docxodus 12.6.4 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/dist/canonical.d.ts.map +1 -1
- package/dist/canonical.js +7 -3
- package/dist/canonical.js.map +1 -1
- package/dist/conversion-options.d.ts +16 -0
- package/dist/conversion-options.d.ts.map +1 -0
- package/dist/conversion-options.js +31 -0
- package/dist/conversion-options.js.map +1 -0
- package/dist/core.d.ts +17 -9
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +23 -24
- package/dist/core.js.map +1 -1
- package/dist/docxodus.worker.js +2 -1073
- package/dist/docxodus.worker.js.map +7 -1
- package/dist/editor.bundle.js +35 -14296
- package/dist/editor.bundle.js.map +7 -0
- package/dist/editor.d.ts +33 -2
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +6739 -4773
- package/dist/editor.js.map +7 -1
- package/dist/embed.bundle.js +159 -18703
- package/dist/embed.bundle.js.map +7 -0
- package/dist/embed.d.ts +1 -1
- package/dist/embed.iife.js +37 -18595
- package/dist/embed.iife.js.map +7 -0
- package/dist/embed.js +1 -1
- package/dist/export-assets.json +27 -27
- package/dist/export-browser.bundle.js +1388 -477
- package/dist/export-browser.d.ts +20 -0
- package/dist/export-browser.d.ts.map +1 -1
- package/dist/export-browser.js +132 -37
- package/dist/export-browser.js.map +1 -1
- package/dist/font-runtime.d.ts.map +1 -1
- package/dist/font-runtime.js +54 -0
- package/dist/font-runtime.js.map +1 -1
- package/dist/line-metrics.d.ts +60 -0
- package/dist/line-metrics.d.ts.map +1 -0
- package/dist/line-metrics.js +343 -0
- package/dist/line-metrics.js.map +1 -0
- package/dist/pagination.bundle.js +3 -3214
- package/dist/pagination.bundle.js.map +7 -0
- package/dist/pagination.d.ts +86 -9
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +358 -55
- package/dist/pagination.js.map +1 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +63 -12
- package/dist/react.js.map +1 -1
- package/dist/render-report-v2.schema.json +29 -0
- package/dist/session.bundle.js +2 -2013
- package/dist/session.bundle.js.map +7 -0
- package/dist/session.d.ts +14 -5
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +62 -29
- package/dist/session.js.map +1 -1
- package/dist/types.d.ts +137 -21
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -1
- package/dist/wasm/_framework/Docxodus.wasm +0 -0
- package/dist/wasm/_framework/Docxodus.wasm.br +0 -0
- package/dist/wasm/_framework/DocxodusWasm.wasm +0 -0
- package/dist/wasm/_framework/DocxodusWasm.wasm.br +0 -0
- package/dist/wasm/_framework/System.Collections.wasm +0 -0
- package/dist/wasm/_framework/System.Collections.wasm.br +0 -0
- package/dist/wasm/_framework/System.IO.Compression.wasm +0 -0
- package/dist/wasm/_framework/System.IO.Compression.wasm.br +0 -0
- package/dist/wasm/_framework/System.Linq.wasm +0 -0
- package/dist/wasm/_framework/System.Linq.wasm.br +0 -0
- package/dist/wasm/_framework/System.Memory.wasm +0 -0
- package/dist/wasm/_framework/System.Memory.wasm.br +0 -0
- package/dist/wasm/_framework/System.Private.CoreLib.wasm +0 -0
- package/dist/wasm/_framework/System.Private.CoreLib.wasm.br +0 -0
- package/dist/wasm/_framework/System.Private.Xml.Linq.wasm +0 -0
- package/dist/wasm/_framework/System.Private.Xml.Linq.wasm.br +0 -0
- package/dist/wasm/_framework/System.Text.RegularExpressions.wasm +0 -0
- package/dist/wasm/_framework/System.Text.RegularExpressions.wasm.br +0 -0
- package/dist/wasm/_framework/dotnet.boot.js +11 -11
- package/dist/wasm/_framework/dotnet.boot.js.br +0 -0
- package/dist/wasm/_framework/dotnet.native.wasm +0 -0
- package/dist/wasm/_framework/dotnet.native.wasm.br +0 -0
- package/dist/word-text.d.ts +14 -0
- package/dist/word-text.d.ts.map +1 -0
- package/dist/word-text.js +377 -0
- package/dist/word-text.js.map +1 -0
- package/dist/worker-proxy.bundle.js +2 -536
- package/dist/worker-proxy.bundle.js.map +7 -0
- package/dist/worker-proxy.d.ts +14 -1
- package/dist/worker-proxy.d.ts.map +1 -1
- package/dist/worker-proxy.js +357 -339
- package/dist/worker-proxy.js.map +1 -1
- package/package.json +13 -12
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../node_modules/bind-event-listener/dist/bind.js", "../node_modules/bind-event-listener/dist/bind-all.js", "../node_modules/bind-event-listener/dist/index.js", "../src/embed.ts", "../src/verification-request.ts", "../src/types.ts", "../src/session.ts", "../src/conversion-options.ts", "../src/external-annotation-wire.ts", "../src/history.ts", "../src/history-checkpoints.ts", "../src/history-indexeddb.ts", "../src/history-controls.ts", "../src/page-number-format.ts", "../src/line-metrics.ts", "../src/page-geometry.ts", "../src/pagination.ts", "../src/viewport.ts", "../src/core.ts", "../src/editor-headerfooter.ts", "../src/editor-comments.ts", "../node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js", "../node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js", "../node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js", "../node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js", "../node_modules/@babel/runtime/helpers/esm/nonIterableRest.js", "../node_modules/@babel/runtime/helpers/esm/slicedToArray.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/adapter/element-adapter.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/honey-pot-fix/honey-pot-data-attribute.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/honey-pot-fix/is-honey-pot-element.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/honey-pot-fix/get-element-from-point-without-honey-pot.js", "../node_modules/@babel/runtime/helpers/esm/typeof.js", "../node_modules/@babel/runtime/helpers/esm/toPrimitive.js", "../node_modules/@babel/runtime/helpers/esm/toPropertyKey.js", "../node_modules/@babel/runtime/helpers/esm/defineProperty.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/honey-pot-fix/make-honey-pot-fix.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/max-z-index.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/popover-reset-styles.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/once.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/supports-popover.js", "../node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js", "../node_modules/@babel/runtime/helpers/esm/iterableToArray.js", "../node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js", "../node_modules/@babel/runtime/helpers/esm/toConsumableArray.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/ledger/lifecycle-manager.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/is-firefox.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/is-safari.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/changing-window/count-events-for-safari.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/changing-window/is-from-another-window.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/changing-window/is-leaving-window.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/detect-broken-drag.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/get-input.js", "../node_modules/raf-schd/dist/raf-schd.esm.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/ledger/dispatch-consumer-event.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/ledger/usage-ledger.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/combine.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/add-attribute.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/make-adapter/make-drop-target.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/make-adapter/make-monitor.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/make-adapter/make-adapter.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/android.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/media-types/text-media-type.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/media-types/url-media-type.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/adapter/element-adapter-native-data-key.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/util/is-safari-on-ios.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/element/custom-native-drag-preview/center-under-pointer.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/element/custom-native-drag-preview/pointer-outside-of-preview.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/engagement-history.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/scheduler.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/over-element/data-attributes.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/configuration.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/can-scroll-on-edge.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/edges.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/axis.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/side.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/get-over-element-hitbox.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/get-percentage-in-range.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/get-scroll-change.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/is-axis-allowed.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/shared/is-within.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/over-element/get-scroll-by.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/over-element/try-scroll.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/over-element/make-api.js", "../node_modules/@atlaskit/pragmatic-drag-and-drop-auto-scroll/dist/esm/entry-point/element.js", "../src/editor-reconcile.ts", "../src/editor-image-patch.ts", "../src/editor.ts", "../src/ribbon-history.ts", "../src/ribbon-chrome.ts", "../src/ribbon.ts"],
|
|
4
|
+
"sourcesContent": ["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.bind = void 0;\nfunction bind(target, _a) {\n var type = _a.type, listener = _a.listener, options = _a.options;\n target.addEventListener(type, listener, options);\n return function unbind() {\n target.removeEventListener(type, listener, options);\n };\n}\nexports.bind = bind;\n", "\"use strict\";\nvar __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.bindAll = void 0;\nvar bind_1 = require(\"./bind\");\nfunction toOptions(value) {\n if (typeof value === 'undefined') {\n return undefined;\n }\n if (typeof value === 'boolean') {\n return {\n capture: value,\n };\n }\n return value;\n}\nfunction getBinding(original, sharedOptions) {\n if (sharedOptions == null) {\n return original;\n }\n var binding = __assign(__assign({}, original), { options: __assign(__assign({}, toOptions(sharedOptions)), toOptions(original.options)) });\n return binding;\n}\nfunction bindAll(target, bindings, sharedOptions) {\n var unbinds = bindings.map(function (original) {\n var binding = getBinding(original, sharedOptions);\n return (0, bind_1.bind)(target, binding);\n });\n return function unbindAll() {\n unbinds.forEach(function (unbind) { return unbind(); });\n };\n}\nexports.bindAll = bindAll;\n", "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.bindAll = exports.bind = void 0;\nvar bind_1 = require(\"./bind\");\nObject.defineProperty(exports, \"bind\", { enumerable: true, get: function () { return bind_1.bind; } });\nvar bind_all_1 = require(\"./bind-all\");\nObject.defineProperty(exports, \"bindAll\", { enumerable: true, get: function () { return bind_all_1.bindAll; } });\n", "/**\n * Embeddable viewer/editor entry point \u2014 the CDN story.\n *\n * This module packages the whole stack behind two one-call factories so a page\n * can embed a DOCX viewer or editor with a single script tag and no build step:\n *\n * ```html\n * <div id=\"doc\"></div>\n * <script type=\"module\">\n * import { createViewer } from \"https://cdn.jsdelivr.net/npm/docxodus@12.6.5/dist/embed.bundle.js\";\n * await createViewer(\"#doc\", \"./contract.docx\");\n * </script>\n * ```\n *\n * It ships in three shapes (see package.json build scripts):\n * - `dist/embed.js` \u2014 plain ESM with relative imports, for bundler users\n * (`import { createEditor } from \"docxodus/embed\"`).\n * Shares module state with the main `docxodus` entry.\n * - `dist/embed.bundle.js` \u2014 self-contained ESM bundle for CDN `<script type=\"module\">`.\n * - `dist/embed.iife.js` \u2014 classic-script bundle exposing `window.Docxodus`.\n *\n * WASM asset resolution: the .NET runtime files live in `wasm/` next to this\n * file (`dist/wasm/` in the published package), which auto-resolves through\n * `import.meta.url` in the ESM shapes. The IIFE shape has no `import.meta`, so\n * it falls back to `document.currentScript.src` captured at load time. An\n * explicit `wasmBasePath` option always wins.\n */\n\nimport {\n initialize,\n getWasmExports,\n convertDocxToHtml,\n openDocxHistory,\n openDocxHistoryArchive,\n} from \"./index.js\";\nimport { DocxEditor } from \"./editor.js\";\nimport type { DocxEditorExports, DocxEditorOptions } from \"./editor.js\";\nimport { mountRibbon } from \"./ribbon.js\";\nimport type { RibbonEditor, RibbonOptions } from \"./ribbon.js\";\nimport type { RibbonHistoryOptions } from './ribbon-history.js';\nimport type { ConversionOptions } from \"./types.js\";\nimport { DocxHistoryError } from './history.js';\nimport type { DocxHistoryClient, DocxHistoryUpdate, HistoryHead, HistoryPosition } from './history.js';\n\n// Everything the main entry exports is re-exported so the CDN bundle is a\n// one-stop surface (convert, compare, diff, sessions, annotations, ...).\nexport * from \"./index.js\";\nexport { DocxEditor } from \"./editor.js\";\nexport type { DocxEditorExports, DocxEditorOptions } from \"./editor.js\";\n\n/**\n * A document to load: raw bytes, a Blob/File (e.g. from an <input type=\"file\">),\n * or a URL string to fetch (must be same-origin or CORS-readable).\n */\nexport type DocumentSource = Uint8Array | ArrayBuffer | Blob | string;\n\n/**\n * `document.currentScript.src`, captured synchronously at module evaluation.\n * Only meaningful for the classic-script (IIFE) shape \u2014 for module scripts\n * `currentScript` is null and `import.meta.url` is used instead.\n */\nconst scriptBase: string = (() => {\n try {\n const el =\n typeof document !== \"undefined\"\n ? (document.currentScript as HTMLScriptElement | null)\n : null;\n if (el?.src) return el.src.substring(0, el.src.lastIndexOf(\"/\") + 1);\n } catch {\n /* non-browser environment */\n }\n return \"\";\n})();\n\n/**\n * The directory this bundle was loaded from: `import.meta.url` for the ESM\n * shapes (esbuild shims it to `{}` in the IIFE build, so the probe fails\n * there), falling back to the captured `currentScript` base for the IIFE.\n */\nfunction moduleBaseDir(): string {\n try {\n const url = import.meta.url;\n if (typeof url === \"string\" && url.length > 0) {\n return url.substring(0, url.lastIndexOf(\"/\") + 1);\n }\n } catch {\n /* shimmed or unavailable */\n }\n return scriptBase;\n}\n\n/**\n * Initialize the WASM runtime for an embed call.\n *\n * An explicit `wasmBasePath` wins. Otherwise probe the two layouts consumers\n * actually have: `wasm/` next to this bundle (the published package layout \u2014\n * `dist/embed.bundle.js` + `dist/wasm/`), then the assets directly next to the\n * bundle (a webroot that serves the wasm directory itself). A failed probe is\n * retryable because `initialize()` clears its cached promise on rejection.\n */\nasync function ensureWasm(wasmBasePath?: string): Promise<void> {\n if (wasmBasePath) return initialize(wasmBasePath);\n const dir = moduleBaseDir();\n if (!dir) return initialize(); // last resort: index.ts's own auto-detection\n try {\n await initialize(dir + \"wasm/\");\n } catch {\n await initialize(dir);\n }\n}\n\nfunction resolveContainer(container: string | HTMLElement): HTMLElement {\n if (typeof container !== \"string\") return container;\n const el = document.querySelector<HTMLElement>(container);\n if (!el) throw new Error(`Docxodus embed: no element matches \"${container}\"`);\n return el;\n}\n\n// A style element nested in a normal DOM container is still document-global.\n// The converter emits selectors such as `body` and `span`, so inserting its\n// stylesheet verbatim would restyle the host page. Embed factories mount into a\n// private inner root and prefix every ordinary selector with that root. This\n// keeps regular DOM/querySelector/contenteditable behavior (unlike Shadow DOM,\n// whose selection boundary is awkward for DocxEditor) without leaking CSS.\nconst EMBED_ROOT_ATTR = \"data-docxodus-embed-root\";\nconst SCOPED_STYLE_ATTR = \"data-docxodus-scoped-style\";\nlet nextEmbedRootId = 0;\n\ninterface ScopedMount {\n root: HTMLElement;\n selector: string;\n}\n\nfunction createScopedMount(container: HTMLElement): ScopedMount {\n let id: string;\n do {\n id = `d${++nextEmbedRootId}`;\n } while (document.querySelector(`[${EMBED_ROOT_ATTR}=\"${id}\"]`));\n\n const root = document.createElement(\"div\");\n root.setAttribute(EMBED_ROOT_ATTR, id);\n container.replaceChildren(root);\n return { root, selector: `[${EMBED_ROOT_ATTR}=\"${id}\"]` };\n}\n\n/** Split a selector list only at top-level commas (not commas inside :is(), attributes, etc.). */\nfunction splitSelectorList(selectorText: string): string[] {\n const selectors: string[] = [];\n let start = 0;\n let parentheses = 0;\n let brackets = 0;\n let quote = \"\";\n let escaped = false;\n\n for (let i = 0; i < selectorText.length; i++) {\n const ch = selectorText[i];\n if (escaped) {\n escaped = false;\n continue;\n }\n if (ch === \"\\\\\") {\n escaped = true;\n continue;\n }\n if (quote) {\n if (ch === quote) quote = \"\";\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n quote = ch;\n continue;\n }\n if (ch === \"(\") parentheses++;\n else if (ch === \")\") parentheses--;\n else if (ch === \"[\") brackets++;\n else if (ch === \"]\") brackets--;\n else if (ch === \",\" && parentheses === 0 && brackets === 0) {\n selectors.push(selectorText.slice(start, i).trim());\n start = i + 1;\n }\n }\n selectors.push(selectorText.slice(start).trim());\n return selectors.filter(Boolean);\n}\n\nfunction scopeSelector(selector: string, rootSelector: string): string {\n let remaining = selector.trim();\n let consumedRoot = false;\n let separated = false;\n\n // The converter's full-document CSS starts at body/:root. In an embed, the\n // private mount root is the equivalent document root. Consume repeated roots\n // too (`html body ...`) before attaching the remainder.\n for (;;) {\n const match = /^(?:html|body|:root)(?=$|[\\s>+~.#[:])/.exec(remaining);\n if (!match) break;\n consumedRoot = true;\n remaining = remaining.slice(match[0].length);\n const whitespace = /^\\s+/.exec(remaining);\n if (whitespace) {\n separated = true;\n remaining = remaining.slice(whitespace[0].length);\n } else {\n separated = false;\n break;\n }\n }\n\n if (!consumedRoot) return `${rootSelector} ${remaining}`;\n if (!remaining) return rootSelector;\n if (separated || /^[>+~]/.test(remaining)) return `${rootSelector} ${remaining}`;\n return `${rootSelector}${remaining}`;\n}\n\ntype MutableCssRules = {\n readonly cssRules: CSSRuleList;\n deleteRule(index: number): void;\n};\n\nfunction scopeCssRules(container: MutableCssRules, rootSelector: string): void {\n // Walk backwards because document-level @page and @import rules are removed.\n // Neither can be selector-scoped; keeping them would let print settings or an\n // imported stylesheet escape into the host page.\n for (let i = container.cssRules.length - 1; i >= 0; i--) {\n const rule = container.cssRules[i];\n if (rule.type === CSSRule.PAGE_RULE || rule.type === CSSRule.IMPORT_RULE) {\n container.deleteRule(i);\n continue;\n }\n if (rule.type === CSSRule.STYLE_RULE) {\n const styleRule = rule as CSSStyleRule;\n styleRule.selectorText = splitSelectorList(styleRule.selectorText)\n .map((selector) => scopeSelector(selector, rootSelector))\n .join(\", \");\n continue;\n }\n const grouping = rule as CSSRule & Partial<MutableCssRules>;\n if (grouping.cssRules && typeof grouping.deleteRule === \"function\") {\n scopeCssRules(grouping as MutableCssRules, rootSelector);\n }\n }\n}\n\nfunction scopeStyleElement(style: HTMLStyleElement, rootSelector: string): void {\n if (style.hasAttribute(SCOPED_STYLE_ATTR)) return;\n\n // Parse through the browser's CSSOM rather than regex-rewriting CSS. `media`\n // keeps this temporary parser stylesheet inert while it is attached, so the\n // unscoped rules never affect layout even for a single frame.\n const parser = document.createElement(\"style\");\n parser.media = \"not all\";\n parser.textContent = style.textContent ?? \"\";\n (document.head ?? document.documentElement).appendChild(parser);\n try {\n const sheet = parser.sheet as CSSStyleSheet | null;\n if (!sheet) throw new Error(\"browser did not expose a CSS stylesheet\");\n scopeCssRules(sheet, rootSelector);\n style.setAttribute(SCOPED_STYLE_ATTR, \"\");\n style.textContent = Array.from(sheet.cssRules, (rule) => rule.cssText).join(\"\\n\");\n } catch (error) {\n throw new Error(`Docxodus embed: failed to scope document CSS: ${String(error)}`);\n } finally {\n parser.remove();\n }\n}\n\nfunction scopeDocumentStyles(fullHtml: string, rootSelector: string): string {\n const parsed = new DOMParser().parseFromString(fullHtml, \"text/html\");\n parsed.querySelectorAll<HTMLStyleElement>(\"style\")\n .forEach((style) => scopeStyleElement(style, rootSelector));\n return `<!doctype html>\\n${parsed.documentElement.outerHTML}`;\n}\n\n/** Scope initial and remount renders synchronously, before DocxEditor inserts their HTML. */\nfunction createScopedEditorExports(\n exports: DocxEditorExports,\n rootSelector: string,\n): DocxEditorExports {\n const convert = exports.DocumentConverter.ConvertDocxToHtmlComplete;\n const bridge = { ...exports.DocxSessionBridge };\n // EVERY whole-document render has to be scoped, not just the first one the editor happened to\n // use: the converter's stylesheet contains `body`/`span` rules, so one unwrapped path is enough\n // to restyle the host page. `RenderHtmlForReview` is the revision-view twin of `RenderHtml` and\n // is what remount prefers when it exists.\n const renderHtml = bridge.RenderHtml;\n if (renderHtml) {\n bridge.RenderHtml = (...args) => scopeDocumentStyles(renderHtml(...args), rootSelector);\n }\n const renderHtmlForReview = bridge.RenderHtmlForReview;\n if (renderHtmlForReview) {\n bridge.RenderHtmlForReview = (...args) =>\n scopeDocumentStyles(renderHtmlForReview(...args), rootSelector);\n }\n // The editor's first paint prefers `RenderEditorHtml` when the bundle has it (it carries the\n // comment markup the plain `RenderHtml` omits). It is a whole-document render too, so its\n // stylesheet's `body`/`span` rules restyle the host page unless it is scoped like the others.\n // The per-block editor renders (`RenderEditorBlockHtml` / `RenderEditorBlocksHtml`) return body\n // fragments without a stylesheet, so they need no scoping.\n const renderEditorHtml = bridge.RenderEditorHtml;\n if (renderEditorHtml) {\n bridge.RenderEditorHtml = (...args) =>\n scopeDocumentStyles(renderEditorHtml(...args), rootSelector);\n }\n return {\n DocxSessionBridge: bridge,\n DocumentConverter: {\n ConvertDocxToHtmlComplete: (...args) =>\n scopeDocumentStyles(convert(...args), rootSelector),\n },\n };\n}\n\n/** Normalize any DocumentSource to bytes. */\nexport async function toDocumentBytes(source: DocumentSource): Promise<Uint8Array> {\n if (source instanceof Uint8Array) return source;\n if (source instanceof ArrayBuffer) return new Uint8Array(source);\n if (typeof Blob !== \"undefined\" && source instanceof Blob) {\n return new Uint8Array(await source.arrayBuffer());\n }\n if (typeof source === \"string\") {\n const response = await fetch(source);\n if (!response.ok) {\n throw new Error(\n `Docxodus embed: failed to fetch document \"${source}\" (HTTP ${response.status})`,\n );\n }\n return new Uint8Array(await response.arrayBuffer());\n }\n throw new Error(\"Docxodus embed: unsupported document source\");\n}\n\nexport interface DocxViewerOptions extends ConversionOptions {\n /** Explicit URL of the wasm assets directory; omit to auto-detect. */\n wasmBasePath?: string;\n}\n\nexport interface DocxViewer {\n /** The container the document was rendered into. */\n readonly element: HTMLElement;\n /** The full HTML document string the converter produced. */\n readonly html: string;\n /** Re-render a (new) document into the same container. */\n reload(source: DocumentSource, options?: ConversionOptions): Promise<void>;\n /** Empty the container. */\n destroy(): void;\n}\n\nfunction scopedDocumentFragment(mount: ScopedMount, html: string): DocumentFragment {\n const parsed = new DOMParser().parseFromString(html, 'text/html');\n const fragment = document.createDocumentFragment();\n parsed.querySelectorAll('style').forEach((sourceStyle) => {\n const style = document.createElement('style');\n style.textContent = sourceStyle.textContent;\n scopeStyleElement(style, mount.selector);\n fragment.appendChild(style);\n });\n const body = document.createElement('template');\n body.innerHTML = parsed.body.innerHTML;\n fragment.appendChild(body.content);\n return fragment;\n}\n\n/**\n * Render a read-only DOCX viewer into `container`.\n *\n * Injects the converter's stylesheet plus the document body into the container\n * (the same mounting the editor uses), so the page's own styles are untouched.\n * Footnotes/endnotes render by default \u2014 they are document content; override\n * any conversion option via `options`.\n */\nexport async function createViewer(\n container: string | HTMLElement,\n source: DocumentSource,\n options: DocxViewerOptions = {},\n): Promise<DocxViewer> {\n const el = resolveContainer(container);\n const { wasmBasePath, ...conversion } = options;\n await ensureWasm(wasmBasePath);\n const mount = createScopedMount(el);\n\n let lastHtml = \"\";\n const render = async (src: DocumentSource, opts: ConversionOptions) => {\n const bytes = await toDocumentBytes(src);\n lastHtml = await convertDocxToHtml(bytes, {\n renderFootnotesAndEndnotes: true,\n ...opts,\n });\n mount.root.replaceChildren(scopedDocumentFragment(mount, lastHtml));\n };\n\n await render(source, conversion);\n return {\n element: el,\n get html() {\n return lastHtml;\n },\n reload: (src, opts) => render(src, { ...conversion, ...opts }),\n destroy: () => {\n el.innerHTML = \"\";\n },\n };\n}\n\nexport interface DocxHistoryViewerOptions extends DocxViewerOptions {\n /** Explicit metadata ancestry budget per refresh/time/sequence lookup; default 10,000. */\n maxEntriesToScan?: number;\n}\n\n/** Read-only live collaboration view. Hosts deliver notifications then call refresh().\n * No network/timer/subscription is created and no editing session is ever replaced. */\nexport interface DocxHistoryViewer {\n readonly element: HTMLElement;\n readonly html: string;\n /** Last verified live head, including while a historical preview remains displayed. */\n readonly head: HistoryHead;\n /** Displayed content sequence (may be earlier than head while previewing). */\n readonly sequence: HistoryPosition;\n readonly following: boolean;\n refresh(): Promise<DocxHistoryUpdate>;\n showSequence(sequence: HistoryPosition): Promise<void>;\n showTime(cutoff: string): Promise<void>;\n resume(): Promise<DocxHistoryUpdate>;\n exportDisplayed(): Uint8Array;\n /** Releases only this view. Await outstanding history calls before closing the shared client. */\n destroy(): void;\n}\n\n/** Render accepted DOCX history and follow host-delivered log notifications.\n * Storage/replay validation stays in the core. A refresh prepares verified bytes and HTML before\n * advancing the displayed head; failures retain the previous frame. Calls serialize in order.\n * Historical previews pause live painting, not log catch-up; resume explicitly returns to live.\n * This coarse path renders full checkpoints, not fine-grained keystrokes or concurrent rebasing. */\nexport async function createHistoryViewer(container: string | HTMLElement, history: DocxHistoryClient,\n documentId: string, options: DocxHistoryViewerOptions = {}): Promise<DocxHistoryViewer> {\n const el = resolveContainer(container);\n const { wasmBasePath, maxEntriesToScan = 10_000, ...conversion } = options;\n if (!Number.isSafeInteger(maxEntriesToScan) || maxEntriesToScan <= 0 || maxEntriesToScan > 0x7fffffff)\n throw new RangeError('Invalid history scan budget.');\n await ensureWasm(wasmBasePath);\n const mount = createScopedMount(el);\n let accepted: DocxHistoryUpdate | null = null;\n let acceptedBytes: Uint8Array | null = null;\n let displayedBytes: Uint8Array | null = null;\n let shownSequence: HistoryPosition = '0';\n let following = true;\n let closed = false;\n let html = '';\n let queue = Promise.resolve();\n const clone = <T>(value: T): T => JSON.parse(JSON.stringify(value));\n const assertOpen = () => {\n if (closed) throw new DocxHistoryError('Closed', 'History viewer is destroyed.');\n };\n const enqueue = <T>(action: () => Promise<T>): Promise<T> => {\n const result = queue.then(() => { assertOpen(); return action(); });\n queue = result.then(() => undefined, () => undefined);\n return result;\n };\n const sameHead = (a: HistoryHead, b: HistoryHead) => a.revision === b.revision\n && a.state.length === b.state.length && a.state.digest.algorithm === b.state.digest.algorithm\n && a.state.digest.value === b.state.digest.value;\n\n const paint = async (bytes: Uint8Array, sequence: HistoryPosition) => {\n const nextHtml = await convertDocxToHtml(bytes, { renderFootnotesAndEndnotes: true, ...conversion });\n assertOpen();\n const fragment = scopedDocumentFragment(mount, nextHtml);\n // The only DOM commit point. No awaits or fallible conversion follows it.\n mount.root.replaceChildren(fragment);\n html = nextHtml; displayedBytes = bytes; shownSequence = sequence;\n };\n const refresh = async (resume = false): Promise<DocxHistoryUpdate> => {\n const update = await history.readChangesSince(documentId, accepted?.view.head ?? null, maxEntriesToScan);\n assertOpen();\n const duplicate = accepted !== null && sameHead(accepted.view.head, update.view.head);\n const bytes = duplicate ? acceptedBytes! : await history.exportVersion(documentId, update.view.version.id);\n assertOpen();\n const wantLive = following || resume;\n const changedContent = accepted === null\n || accepted.view.state.snapshot.contentDigest.value !== update.view.state.snapshot.contentDigest.value\n || accepted.view.state.epoch !== update.view.state.epoch;\n if (wantLive && (changedContent || !following)) await paint(bytes, update.view.state.sequence);\n else if (wantLive) {\n // A tail can return to the same OPC content without an epoch change. The DOM need not\n // change, but its logical position and exact downloadable checkpoint must still advance.\n displayedBytes = bytes; shownSequence = update.view.state.sequence;\n }\n assertOpen();\n accepted = update; acceptedBytes = bytes;\n if (wantLive) following = true;\n return clone(update);\n };\n const showSequence = async (sequence: HistoryPosition) => {\n const bytes = await history.materialize(documentId, sequence, maxEntriesToScan);\n assertOpen();\n await paint(bytes, sequence);\n following = false;\n };\n const viewer: DocxHistoryViewer = {\n element: el,\n get html() { return html; },\n get head() { assertOpen(); return clone(accepted!.view.head); },\n get sequence() { return shownSequence; },\n get following() { return following; },\n refresh: () => enqueue(() => refresh()),\n showSequence: (sequence) => enqueue(() => showSequence(sequence)),\n showTime: (cutoff) => enqueue(async () => {\n const sequence = await history.resolveSequenceAtTime(documentId, cutoff, maxEntriesToScan);\n assertOpen();\n await showSequence(sequence);\n }),\n resume: () => enqueue(() => refresh(true)),\n exportDisplayed: () => { assertOpen(); return displayedBytes!.slice(); },\n destroy: () => {\n if (closed) return;\n closed = true; acceptedBytes = null; displayedBytes = null;\n mount.root.remove();\n },\n };\n try { await viewer.refresh(); return viewer; }\n catch (error) { viewer.destroy(); throw error; }\n}\n\nexport interface CreateEditorOptions extends DocxEditorOptions {\n /** Explicit URL of the wasm assets directory; omit to auto-detect. */\n wasmBasePath?: string;\n}\n\n/**\n * Open an editable DOCX editor in `container`.\n *\n * With a `source`, opens that document; without one, opens a blank \"New\n * document\". Returns the `DocxEditor` instance \u2014 `save()` for the edited\n * bytes, `close()` to release the WASM session, plus the full command surface\n * (formatting, tables, notes, headers/footers, undo/redo).\n */\nexport async function createEditor(\n container: string | HTMLElement,\n source?: DocumentSource | null,\n options: CreateEditorOptions = {},\n): Promise<DocxEditor> {\n const el = resolveContainer(container);\n const { wasmBasePath, ...editorOptions } = options;\n await ensureWasm(wasmBasePath);\n const mount = createScopedMount(el);\n // The runtime object is the real bridge; DocxEditorExports is the editor's\n // narrower view of it, so the cast is safe by construction.\n const exports = createScopedEditorExports(\n getWasmExports() as unknown as DocxEditorExports,\n mount.selector,\n );\n try {\n return source == null\n ? DocxEditor.openBlank(mount.root, exports, editorOptions)\n : DocxEditor.open(mount.root, await toDocumentBytes(source), exports, editorOptions);\n } catch (error) {\n el.replaceChildren();\n throw error;\n }\n}\n\nexport interface CreateRibbonEditorOptions extends Omit<RibbonOptions, 'history'> {\n /** Explicit URL of the wasm assets directory; omit to auto-detect. */\n wasmBasePath?: string;\n /** Show optional version history. Saving is explicit; no autosave or network synchronization. */\n history?: boolean | RibbonHistoryOptions;\n}\n\n/** Best-effort file name from a URL source, so the title bar says something useful. */\nfunction nameFromSource(source: DocumentSource | null | undefined): string | undefined {\n if (typeof source !== \"string\") return undefined;\n try {\n const path = new URL(source, typeof location === \"undefined\" ? undefined : location.href).pathname;\n return decodeURIComponent(path.split(\"/\").pop() ?? \"\") || undefined;\n } catch {\n return source.split(\"/\").pop() || undefined;\n }\n}\n\n/**\n * Open the FULL editor surface \u2014 ribbon chrome, anchor rail and all \u2014 in one call.\n *\n * `createEditor` gives you a bare editable document and leaves the UI to you.\n * This gives you the whole instrument, which is what the shipped demo pages use:\n *\n * ```html\n * <div id=\"app\" style=\"height:100dvh\"></div>\n * <script type=\"module\">\n * import { createRibbonEditor } from \"https://cdn.jsdelivr.net/npm/docxodus/dist/embed.bundle.js\";\n * await createRibbonEditor(\"#app\", \"./contract.docx\");\n * </script>\n * ```\n *\n * The chrome (and its loading overlay) paint immediately; the .NET runtime streams\n * behind them, and the overlay narrates that wait instead of hiding it. Density\n * follows the CONTAINER's width, so the same call serves a full-page editor and a\n * narrow embedded panel.\n */\nexport async function createRibbonEditor(\n container: string | HTMLElement,\n source?: DocumentSource | null,\n options: CreateRibbonEditorOptions = {},\n): Promise<RibbonEditor> {\n const el = resolveContainer(container);\n const { wasmBasePath, history, ...ribbonOptions } = options;\n const mount = createScopedMount(el);\n // The CSS-scoping wrapper sits between the caller's element and the surface, so\n // it has to pass the container's height through \u2014 otherwise a full-height mount\n // (`height:100dvh`) collapses to content height and the surface never scrolls.\n mount.root.style.height = \"100%\";\n mount.root.style.minHeight = \"0\";\n const ribbon = mountRibbon(mount.root, {\n documentName: ribbonOptions.documentName ?? nameFromSource(source),\n // A drop-in embed sits in the middle of someone's page, so it carries its own\n // boundary (rounded card + shadow). Full-bleed hosts pass frame: \"flush\".\n frame: \"card\",\n ...ribbonOptions,\n history: history ? {\n ...(typeof history === 'object' ? history : {}),\n openHistory: openDocxHistory,\n openArchive: openDocxHistoryArchive,\n preview: (container, bytes) => createViewer(container, bytes, { wasmBasePath, renderTrackedChanges: true }),\n } : undefined,\n // Exports arrive after the runtime boots; the loader covers that gap.\n exports: undefined,\n });\n\n try {\n ribbon.loader.stage(0);\n await ensureWasm(wasmBasePath);\n // The document renders inside the ribbon's surface, so that \u2014 not the mount\n // root \u2014 is the scope the converter's document CSS must be confined to.\n ribbon.setExports(\n createScopedEditorExports(\n getWasmExports() as unknown as DocxEditorExports,\n `${mount.selector} [data-dxr-surface]`,\n ),\n );\n\n ribbon.loader.stage(1);\n const bytes = source == null ? null : await toDocumentBytes(source);\n\n ribbon.loader.stage(2);\n if (bytes == null) ribbon.openBlank(ribbonOptions.documentName);\n else ribbon.open(bytes, ribbonOptions.documentName ?? nameFromSource(source));\n await ribbon.history?.resume();\n\n ribbon.loader.stage(3);\n ribbon.loader.done();\n return ribbon;\n } catch (error) {\n ribbon.loader.fail(error);\n throw error;\n }\n}\n", "import type {\n DeliverableVerificationRequest,\n DeliverableCompanionArtifactInput,\n} from \"./types.js\";\n\n/**\n * Serialize the full deliverable-verification request (issue #747) to the wire shape every\n * transport parses: companion bytes become `bytesB64`, everything else passes through. Kept\n * separate from the API modules so the direct API, the session, and the worker proxy share\n * one encoding.\n */\nexport function serializeVerificationRequest(request: DeliverableVerificationRequest): string {\n if (request === null || typeof request !== \"object\" || Array.isArray(request)) {\n throw new RangeError(\"a verification request must be an object\");\n }\n const { companionArtifacts, ...rest } = request;\n const wire: Record<string, unknown> = { ...rest };\n if (companionArtifacts !== undefined) {\n wire.companionArtifacts = companionArtifacts.map(encodeCompanion);\n }\n return JSON.stringify(wire);\n}\n\nfunction encodeCompanion(artifact: DeliverableCompanionArtifactInput): Record<string, unknown> {\n const { bytes, ...rest } = artifact;\n const wire: Record<string, unknown> = { ...rest };\n if (bytes !== undefined) wire.bytesB64 = bytesToBase64(bytes);\n return wire;\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n if (typeof btoa === \"function\") {\n let binary = \"\";\n const chunkSize = 0x8000;\n for (let i = 0; i < bytes.length; i += chunkSize) {\n const chunk = bytes.subarray(i, i + chunkSize);\n binary += String.fromCharCode.apply(null, chunk as unknown as number[]);\n }\n return btoa(binary);\n }\n return Buffer.from(bytes).toString(\"base64\");\n}\n", "/**\n * Which parts of the OOXML package to include in the markdown projection.\n * Bitflags mirroring the .NET `Docxodus.ProjectionScopes` enum.\n */\nexport enum ProjectionScopes {\n Body = 1,\n Headers = 2,\n Footers = 4,\n Footnotes = 8,\n Endnotes = 16,\n Comments = 32,\n All = 63,\n}\n\n/**\n * How anchor markers are rendered in the markdown projection.\n * Mirrors the .NET `Docxodus.AnchorRenderMode` enum.\n */\nexport enum AnchorRenderMode {\n /** Anchor appears on its own line before each block element (default). */\n Block = 0,\n /** Block anchors plus inline `{#\u2026}` markers for spans (comments, hyperlinks). */\n BlockAndInline = 1,\n /** No anchor markers in the output (projection only, no addressing). */\n None = 2,\n}\n\n/**\n * Strategy for rendering `w:tbl` elements that don't fit GFM pipe-table constraints.\n * Mirrors the .NET `Docxodus.TableRenderMode` enum.\n */\nexport enum TableRenderMode {\n /** Emit GFM pipe tables when possible, opaque anchor blocks otherwise (default). */\n GfmWithOpaqueFallback = 0,\n /** Always emit GFM pipe tables, flattening complex structure with possible loss. */\n AlwaysGfm = 1,\n /** Always emit opaque anchor blocks. */\n AlwaysOpaque = 2,\n}\n\n/**\n * How tracked changes are handled in the markdown projection.\n * Mirrors the .NET `Docxodus.TrackedChangeMode` enum.\n */\nexport enum TrackedChangeMode {\n /** Accept all revisions before conversion (default). */\n Accept = 0,\n /** Render insertions and deletions inline as `{+ins+}` / `{-del-}`. */\n RenderInline = 1,\n /** Accept insertions, drop deletions. */\n StripDeletions = 2,\n}\n\n/**\n * How empty paragraphs are rendered. Mirrors the .NET `Docxodus.EmptyParagraphMode` enum.\n */\nexport enum EmptyParagraphMode {\n /** Default: emit the anchor on its own line (`{#p:body:UNID}\\n`). */\n AnchorOnly = 0,\n /** Tag the empty paragraph visibly so agents can pattern-match (`{#p:body:UNID} \u2205`). */\n MarkedEmpty = 1,\n /** Skip empty paragraphs entirely \u2014 they don't appear in the markdown or the anchor index. */\n Suppress = 2,\n}\n\n/**\n * How anchor ids are rendered inside `{#\u2026}` tokens (and keyed in\n * {@link MarkdownProjection.anchorIndex}). Mirrors the .NET\n * `Docxodus.AnchorIdRendering` enum.\n *\n * `Anchor.token` (and any `AnchorRef` returned by `DocxSession` mutations)\n * always carries the full Unid regardless of rendering \u2014 the choice only\n * affects the markdown text. The returned `anchorIndex` is dual-keyed so\n * lookups by either the rendered id or the full Unid work for the\n * `Abbreviated`/`Sequential` modes.\n */\nexport enum AnchorIdRendering {\n /** Full 32-char hex Unid (default; e.g. `{#h:body:a1b2c3d4e5f6789012345678901234ab}`). */\n FullUnid = 0,\n /** Shortest unique prefix per (kind, scope) bucket, 4-char floor (e.g. `{#h:body:a1b2}`).\n * Saves 5-10% of projection-token budget for LLM consumption. */\n Abbreviated = 1,\n /** Sequential numeric ids per (kind, scope) bucket in document order (e.g. `{#h:body:1}`).\n * Maximally token-efficient for one-shot LLM contexts. NOT stable across\n * `project()` calls and must NOT be persisted. */\n Sequential = 2,\n}\n\n/**\n * How far below the target anchor to include in\n * {@link DocxSession.projectAnchor}. Mirrors the .NET\n * `Docxodus.ProjectionDepth` enum.\n */\nexport enum ProjectionDepth {\n /** Just the target block itself (its anchor + its own text). For headings,\n * returns only the heading paragraph, not the section under it. */\n SelfOnly = 0,\n /** Self + descendants. Most useful for `tbl` anchors (returns the whole table);\n * for paragraphs it's the same as `SelfOnly`. */\n Subtree = 1,\n /** Self + descendants + following siblings up to (but not including) the next\n * sibling at the same or higher heading level. For non-heading anchors,\n * equivalent to `Subtree`. Dominant \"give me this section\" case; the default. */\n SubtreeAndFollowingSiblings = 2,\n}\n\n/**\n * Settings controlling the markdown projection. Mirrors the .NET\n * `WmlToMarkdownConverterSettings` class \u2014 see `docs/architecture/markdown_projection.md`.\n */\nexport interface MarkdownProjectionSettings {\n scopes?: ProjectionScopes;\n headingLevelOffset?: number;\n anchorMode?: AnchorRenderMode;\n tableMode?: TableRenderMode;\n tableInlineCellMax?: number;\n trackedChanges?: TrackedChangeMode;\n resolveNumbering?: boolean;\n emptyParagraphs?: EmptyParagraphMode;\n /**\n * How anchor ids are rendered in markdown output. Default `FullUnid`.\n * Set to `Abbreviated` for terse LLM-friendly ids; `Sequential` for\n * 1-based per-scope counters (best for replay logs / human review).\n * `Anchor.token` (and any `AnchorRef`) always reflects the full Unid\n * regardless; this only affects the markdown text. Use the returned\n * {@link MarkdownProjection.anchorIndex} (dual-keyed for Abbreviated /\n * Sequential) to translate rendered ids back to full Unids.\n */\n anchorIdRendering?: AnchorIdRendering;\n}\n\n/**\n * Resolved location of an anchor in the underlying OOXML package \u2014 sufficient to walk\n * back to the source element via the .NET API.\n */\nexport interface MarkdownAnchorTarget {\n id: string;\n kind: string;\n scope: string;\n unid: string;\n partUri: string;\n /** First ~80 characters of the element's flat text \u2014 for previewing/picking anchors. */\n textPreview: string;\n /** Resolved auto-numbering prefix (e.g. \"1.\", \"First\") for paragraphs/headings/list\n * items whose style or `w:numPr` produces numbering. Absent when the element has\n * no numbering. The prefix is NOT included in {@link textPreview} because\n * textPreview reflects only the run text; this field gives callers the value\n * Word actually renders before the element's text. */\n autoNumberPrefix?: string;\n}\n\n/**\n * Output of the markdown projection: rendered text plus the anchor index mapping\n * each `{#\u2026}` token back to a location in the OOXML package.\n */\nexport interface MarkdownProjection {\n markdown: string;\n anchorIndex: Record<string, MarkdownAnchorTarget>;\n}\n\n/**\n * Revision type enum matching the .NET `DocxDiffRevisionType`, as returned by the `docxDiff*`\n * comparison APIs. NOT the shape {@link getRevisions} returns \u2014 that reads a document's own markup\n * and reports the markup-level kind on `RevisionListEntry.type` (`ins`/`del`/`moveFrom`), with the\n * grouped classification on `family`.\n */\nexport enum RevisionType {\n /** Text or content that was added/inserted */\n Inserted = \"Inserted\",\n /** Text or content that was removed/deleted */\n Deleted = \"Deleted\",\n /** Text or content that was relocated within the document */\n Moved = \"Moved\",\n /** Text content unchanged but formatting (bold, italic, etc.) changed */\n FormatChanged = \"FormatChanged\",\n}\n\n\n/**\n * Comment render mode\n * Use -1 (Disabled) to not render comments, or a positive value to enable with that mode\n */\nexport enum CommentRenderMode {\n /** Do not render comments (default) */\n Disabled = -1,\n /** Render comments at the end of the document with bidirectional links (like footnotes) */\n EndnoteStyle = 0,\n /** Render comments as inline tooltips with data attributes */\n Inline = 1,\n /** Render comments in a margin column (CSS-positioned) */\n Margin = 2,\n}\n\n/**\n * Pagination mode for HTML output\n */\nexport enum PaginationMode {\n /** No pagination - content flows continuously (default) */\n None = 0,\n /**\n * Paginated view - outputs page containers with document dimensions\n * and content with data attributes for client-side pagination.\n * Creates a PDF.js-style page preview experience.\n */\n Paginated = 1,\n}\n\n/**\n * How rendered tracked changes look (issue #851). Only used when `renderTrackedChanges` is on.\n */\nexport enum RevisionPresentation {\n /** Docxodus's own review style (default): green/red text with light fills, purple moves, pilcrows. */\n Docxodus = 0,\n /**\n * Close to Word's All Markup print: one colour per author for both insertions (underlined) and\n * deletions (struck through), no fills or pilcrows, green double-lined moves, Word's default cell\n * shading, and one left-margin change bar per changed paragraph. Full renders only.\n */\n Word = 1,\n}\n\n/**\n * Annotation label display mode\n */\nexport enum AnnotationLabelMode {\n /** Floating label positioned above the highlight */\n Above = 0,\n /** Label displayed inline at start of highlight */\n Inline = 1,\n /** Label shown only on hover (tooltip) */\n Tooltip = 2,\n /** No labels displayed, only highlights */\n None = 3,\n}\n\n/**\n * Types of content that cannot be fully converted to HTML.\n * Used for placeholder rendering when unsupported content is encountered.\n */\nexport enum UnsupportedContentType {\n /** Windows Metafile image format (legacy vector graphics) */\n WmfImage = \"WmfImage\",\n /** Enhanced Metafile image format (legacy vector graphics) */\n EmfImage = \"EmfImage\",\n /** SVG image format (not yet supported) */\n SvgImage = \"SvgImage\",\n /** Office Math Markup Language equations */\n MathEquation = \"MathEquation\",\n /** Form field elements (checkboxes, text inputs, dropdowns) */\n FormField = \"FormField\",\n /** Ruby annotations for East Asian text */\n RubyAnnotation = \"RubyAnnotation\",\n /** Embedded OLE objects */\n OleObject = \"OleObject\",\n /** Other unsupported content */\n Other = \"Other\",\n}\n\n/**\n * Options for DOCX to HTML conversion\n */\nexport interface ConversionOptions {\n /** Title for the HTML document (default: \"Document\") */\n pageTitle?: string;\n /** CSS class prefix for generated styles (default: \"docx-\") */\n cssPrefix?: string;\n /** Whether to generate CSS classes (default: true) */\n fabricateClasses?: boolean;\n /** Additional CSS to include in the output */\n additionalCss?: string;\n /** Comment rendering mode: Disabled (-1), EndnoteStyle (0), Inline (1), or Margin (2). Default: Disabled */\n commentRenderMode?: CommentRenderMode;\n /** CSS class prefix for comment elements (default: \"comment-\") */\n commentCssClassPrefix?: string;\n /** Pagination mode: None (0) or Paginated (1). Default: None */\n paginationMode?: PaginationMode;\n /** Scale factor for page rendering in paginated mode (1.0 = 100%). Default: 1.0 */\n paginationScale?: number;\n /** CSS class prefix for pagination elements. Default: \"page-\" */\n paginationCssClassPrefix?: string;\n /** Whether to render custom annotations (default: false) */\n renderAnnotations?: boolean;\n /** How to display annotation labels (default: Above) */\n annotationLabelMode?: AnnotationLabelMode;\n /** CSS class prefix for annotation elements (default: \"annot-\") */\n annotationCssClassPrefix?: string;\n /** Whether to render footnotes and endnotes sections at the end of the document (default: false) */\n renderFootnotesAndEndnotes?: boolean;\n /** Whether to render document headers and footers (default: false) */\n renderHeadersAndFooters?: boolean;\n /** Whether to render tracked changes visually (insertions/deletions) (default: false) */\n renderTrackedChanges?: boolean;\n /** Whether to show deleted content with strikethrough (only when renderTrackedChanges=true, default: true) */\n showDeletedContent?: boolean;\n /** Whether to distinguish move operations from regular insert/delete (only when renderTrackedChanges=true, default: true) */\n renderMoveOperations?: boolean;\n /** How tracked changes look (only when renderTrackedChanges=true, default: RevisionPresentation.Docxodus) */\n revisionPresentation?: RevisionPresentation;\n /**\n * Whether to render placeholders for unsupported content (default: false)\n * When enabled, unsupported content (WMF/EMF images, math equations, form fields, etc.)\n * will display as styled placeholder spans instead of being silently dropped.\n */\n renderUnsupportedContentPlaceholders?: boolean;\n /**\n * Override the document's default language for the HTML lang attribute.\n * If not specified, the language is auto-detected from document settings\n * (w:themeFontLang or default paragraph style), falling back to \"en-US\".\n * Examples: \"en-US\", \"fr-FR\", \"de-DE\", \"ja-JP\"\n */\n documentLanguage?: string;\n /**\n * Stamp block-level elements (p, h1-h6, li, table) with a `data-anchor`\n * attribute carrying the block's stable Unid. Required for the editor to\n * address blocks in the DOM and drive incremental per-block re-render via\n * `renderBlockHtml`. Default: false.\n */\n stampAnchors?: boolean;\n /**\n * Emit Word lists as `<ol>`/`<ul>`/`<li>` instead of paragraphs (issue #895). Adjacent list\n * paragraphs of one list share a list, and a deeper level nests inside the preceding item. CSS\n * draws the marker (`list-style-type`, with `start`/`value` for restarts) only where it\n * reproduces Word's marker exactly; other lists keep the generated marker spans under\n * `list-style-type: none`. Ignored by paginated output. Default: false.\n */\n semanticLists?: boolean;\n}\n\n/**\n * Options for document comparison\n */\nexport interface CompareOptions {\n /** Author name for tracked changes (default: the engine's, \"Docxodus\") */\n authorName?: string;\n /** Whether comparison is case-insensitive (default: false) */\n caseInsensitive?: boolean;\n /**\n * Whether to render tracked changes visually in HTML output (default: true)\n * If true: insertions shown with <ins>, deletions with <del>, styled with colors\n * If false: changes are accepted, output shows final \"clean\" document\n */\n renderTrackedChanges?: boolean;\n}\n\n\n/**\n * Which property container a FormatChanged revision describes.\n * `run` (the default) is an rPr-grade report (bold/italic/fontSize/\u2026); the others are the\n * block-and-above scopes tracked by the block-format-change family: `paragraph` (pPr),\n * `tableCell`/`tableRow`/`table` (tcPr/trPr/tblPr+tblGrid), and `section` (sectPr).\n * Non-`run` scopes are only reported under Fine revision granularity.\n */\nexport type FormatChangeScope =\n | \"run\"\n | \"paragraph\"\n | \"tableCell\"\n | \"tableRow\"\n | \"table\"\n | \"section\";\n\n/**\n * Details about formatting changes for FormatChanged revisions.\n */\nexport interface FormatChangeDetails {\n /**\n * Dictionary of old property names and values.\n * Keys are friendly property names like \"bold\", \"italic\", \"fontSize\".\n */\n oldProperties?: Record<string, string>;\n /**\n * Dictionary of new property names and values.\n */\n newProperties?: Record<string, string>;\n /**\n * List of property names that changed (e.g., \"bold\", \"italic\", \"fontSize\").\n * For the table/section scopes this is a digest-grade marker (`[\"shell\"]`, `[\"grid\"]`).\n */\n changedPropertyNames?: string[];\n /**\n * Which property container this change describes (default `\"run\"`).\n */\n scope?: FormatChangeScope;\n}\n\n// \u2500\u2500\u2500 DocxDiff (IR diff engine) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The structure-aware default comparison engine. Its specialized APIs expose\n// anchor-addressed revisions (`leftAnchor`/`rightAnchor`) and the diff-as-data\n// edit script (`docxDiffGetEditScript`).\n\n/**\n * How `docxDiffGetRevisions` projects the edit script to revisions. Integer\n * values match the .NET `DocxDiffRevisionGranularity` enum positions.\n */\nexport enum DocxDiffRevisionGranularity {\n /** The engine's native one-revision-per-token-span grain (the default). */\n Fine = 0,\n /** Coalesced to the coarser contiguous-region grain the legacy comparer reported. */\n WmlComparerCompatible = 1,\n}\n\n/**\n * How DocxDiff compares run formatting. Integer values match the .NET\n * `DocxDiffFormatComparison` enum positions.\n */\nexport enum DocxDiffFormatComparison {\n /** Compare only the modeled rPr fields (the default). */\n ModeledOnly = 0,\n /** Compare the full run format including the unmodeled rPr digest. */\n Full = 1,\n}\n\n/**\n * Settings for the `docxDiff*` functions. Mirrors the .NET `DocxDiffSettings`;\n * every field is optional and an omitted field uses the engine default.\n */\nexport interface DocxDiffSettings {\n /** Author stamped on revisions and markup (default \"Docxodus\"). */\n authorForRevisions?: string;\n /** Pin revision dates to a fixed epoch for byte-identical output (default true). */\n deterministic?: boolean;\n /** Explicit ISO-8601 revision date; overrides `deterministic` when set. */\n dateTimeForRevisions?: string;\n /**\n * Accept every pre-existing revision on both inputs before comparing (default false).\n * This flattens prior authorship; `preserveInputRevisions` takes precedence when both are set.\n * The consolidate functions (`docxDiffConsolidate` and its siblings) always pre-accept the base\n * and every reviewer, whatever this says: they compare the accepted view, as Word's Compare does.\n */\n preAcceptInputRevisions?: boolean;\n /**\n * Preserve the inputs' existing tracked revisions, as Word's Combine does (default false).\n * Word's Compare pre-accepts them instead (see `preAcceptInputRevisions`).\n * This takes precedence over `preAcceptInputRevisions` when both are set.\n */\n preserveInputRevisions?: boolean;\n /** Case-fold word match keys (default false). */\n caseInsensitive?: boolean;\n /** Culture name (e.g. \"tr-TR\") for case folding when `caseInsensitive` is true; default invariant/ordinal. */\n culture?: string;\n /** Fold NBSP (U+00A0) to ordinary space in match keys (default true). */\n conflateBreakingAndNonbreakingSpaces?: boolean;\n /** Override the word/separator split characters (default: engine's set). */\n wordSeparators?: string;\n /** Report relocations as native move pairs (default true). */\n detectMoves?: boolean;\n /** Jaccard similarity threshold for a fuzzy move 0.0-1.0 (default 0.8). */\n moveSimilarityThreshold?: number;\n /** Minimum word tokens for a fuzzy move (default 3). */\n moveMinimumWordCount?: number;\n /** Revision projection grain (default Fine). */\n revisionGranularity?: DocxDiffRevisionGranularity;\n /** Run-format comparison policy (default ModeledOnly). */\n formatComparison?: DocxDiffFormatComparison;\n /**\n * Compare header/footer stories (default true \u2014 Word Compare's own default).\n * Changed stories get native tracked-changes markup inside their parts;\n * Fine-mode revisions carry `hdr`/`ftr`-scoped anchors; the edit script\n * carries `headerFooterOps`. Set false to ignore header/footer scopes (the\n * pre-campaign behavior: left's headers/footers carried verbatim).\n */\n compareHeadersFooters?: boolean;\n\n /**\n * Track paragraph-and-above property changes (pPr/tcPr/trPr/tblPr/tblGrid/tblPrEx/sectPr) as native\n * Word markup. Default true. Set false to restore the pre-campaign untracked-right-apply behavior.\n * (Consolidate ignores block-format changes regardless.)\n */\n trackBlockFormatChanges?: boolean;\n\n /**\n * Render a run of >=2 adjacent word-matched modified paragraph pairs via a single cross-paragraph\n * word+pilcrow token-stream diff \u2014 the within-run flat-stream shape decoded from Word's compare\n * output (retained words may cross the pilcrow; paragraph marks are ins/del stream tokens; the\n * output paragraph count follows the token-level interleave). Markup (`docxDiffCompare`) only \u2014\n * the revision list and edit-script JSON are unaffected. Default false.\n */\n crossParagraphTokenDiff?: boolean;\n\n /**\n * Record a list item's previous label in `w:numberingChange` when an insertion, deletion or move\n * elsewhere in its list renumbered it. Word's own compare never writes this; set false for output\n * limited to the constructs Word writes. Default true. Consolidate honors it too.\n */\n trackNumberingChanges?: boolean;\n\n /**\n * Track a cell added to or removed from a paired table row with `w:cellIns`/`w:cellDel`. Word's own\n * compare never writes cell-level revisions; set false and such a table is tracked as a whole (the\n * original deleted, the revised inserted), in the markup and the revision list alike. Default true.\n * Consolidate keeps cell-level revisions regardless.\n */\n trackCellInsertionsAndDeletions?: boolean;\n}\n\n/**\n * One revision from `docxDiffGetRevisions`. Mirrors the consumer shape of\n * {@link Revision} and ADDS the block anchors the revision derives from \u2014 the\n * IR engine's differentiator.\n *\n * Anchor presence by `revisionType` \u2014 each type's PRIMARY anchor is ALWAYS\n * present; the opposite anchor MAY also be present for a token-level revision.\n * Inserted \u2192 `rightAnchor` always (plus `leftAnchor` when it is a token-level\n * insert inside a modified block); Deleted \u2192 `leftAnchor` always (plus\n * `rightAnchor` when token-level); FormatChanged \u2192 both; Moved is EXCLUSIVE:\n * source \u2192 `leftAnchor` only, destination \u2192 `rightAnchor` only. A token-level\n * revision (an insert/delete WITHIN a modified paragraph that exists on both\n * sides) carries both enclosing-block anchors; a whole-block insert/delete\n * carries only its primary anchor.\n */\nexport interface DocxDiffRevision {\n /** \"Inserted\" | \"Deleted\" | \"Moved\" | \"FormatChanged\". */\n revisionType: RevisionType | string;\n /** The affected text. */\n text: string;\n /** Author stamped on the revision. */\n author: string;\n /** ISO-8601 revision date. */\n date: string;\n /** For Moved revisions, links source and destination. */\n moveGroupId?: number;\n /** For Moved revisions: true = source, false = destination. */\n isMoveSource?: boolean;\n /** For FormatChanged revisions: what formatting changed. */\n formatChange?: FormatChangeDetails;\n /** The LEFT-document block anchor (`kind:scope:unid`). Always set for Deleted/FormatChanged/Moved-source;\n * also set for a token-level insert inside a modified block; undefined for a whole-block insertion. */\n leftAnchor?: string;\n /** The RIGHT-document block anchor (`kind:scope:unid`). Always set for Inserted/FormatChanged/Moved-dest;\n * also set for a token-level delete inside a modified block; undefined for a whole-block deletion. */\n rightAnchor?: string;\n}\n\n/** A data product selectable in `docxDiffCompareProducts`. */\nexport type DocxDiffProduct = \"redline\" | \"revisions\" | \"editScript\" | \"semanticChanges\";\n\n/**\n * The requested products of ONE memoized comparison pass, from\n * `docxDiffCompareProducts` (issue #594). Unrequested products are undefined.\n * Each present product equals what the corresponding standalone function\n * returns for the same inputs and settings \u2014 except `editScript`, which is\n * handed over parsed (the standalone `docxDiffGetEditScript` returns the\n * serialized string).\n */\nexport interface DocxDiffProducts {\n /** The native tracked-changes redline (what `docxDiffCompare` returns). */\n redline?: Uint8Array;\n /** The anchor-addressed revision list (what `docxDiffGetRevisions` returns). */\n revisions?: DocxDiffRevision[];\n /** The engine's edit script, parsed. */\n editScript?: Record<string, unknown>;\n /** The stable semantic-change schema (what `docxDiffGetSemanticChanges` returns). */\n semanticChanges?: SemanticChangeSet;\n}\n\n/** One candidate of a {@link docxDiffCompareBatch} run: the products of comparing the shared\n * baseline against it, or the error that comparing it produced. */\nexport interface DocxDiffBatchResult extends DocxDiffProducts {\n /** The candidate's name, echoed from the request (its index when none was given). */\n name: string;\n /** Set when this candidate failed; its products are then absent. The rest of the batch is\n * unaffected \u2014 one malformed counterparty markup must not cost the other ninety-nine. */\n error?: string;\n}\n\n/** A candidate document for {@link docxDiffCompareBatch}. */\nexport interface DocxDiffBatchCandidate {\n /** Echoed back on the matching result. Defaults to the candidate's index. */\n name?: string;\n /** The candidate document. */\n document: File | Uint8Array;\n}\n\n/** Stable v1 operation names emitted by the semantic-change schema. */\nexport type SemanticChangeOperation = \"insert\" | \"delete\" | \"move\" | \"modify\";\n\n/** Stable v1 semantic families. New schema versions may append families. */\nexport type SemanticChangeFamily =\n | \"text\"\n | \"block_structure\"\n | \"run_formatting\"\n | \"paragraph_formatting\"\n | \"style\"\n | \"numbering\"\n | \"list\"\n | \"table\"\n | \"table_row\"\n | \"table_cell\"\n | \"table_span\"\n | \"table_width\"\n | \"table_style\"\n | \"section\"\n | \"page_setup\"\n | \"header\"\n | \"footer\"\n | \"field\"\n | \"footnote\"\n | \"endnote\"\n | \"comment\"\n | \"hyperlink\"\n | \"bookmark\"\n | \"content_control\"\n | \"image\"\n | \"media\"\n | \"relationship\"\n | \"revision\"\n | \"annotation\"\n | \"opaque_package_part\";\n\n/**\n * Closed typed value used in {@link SemanticChange.before} and `after`.\n * Schema v1 integers stay within `Number.MIN_SAFE_INTEGER..Number.MAX_SAFE_INTEGER`; a document\n * value outside that range arrives as a decimal `string` rather than a rounded `integer`.\n */\nexport type SemanticValue =\n | { kind: \"absent\" }\n | { kind: \"string\"; value: string }\n | { kind: \"boolean\"; value: boolean }\n | { kind: \"integer\"; value: number }\n | { kind: \"digest\"; algorithm: string; profile: string | null; value: string }\n | { kind: \"object\"; value: Record<string, SemanticValue> }\n | { kind: \"array\"; value: SemanticValue[] };\n\n/** One deterministic, anchor-addressed semantic change. */\nexport interface SemanticChange {\n id: string;\n operation: SemanticChangeOperation;\n family: SemanticChangeFamily;\n partUri: string;\n path: string;\n leftAnchor: string | null;\n rightAnchor: string | null;\n leftScope: string | null;\n rightScope: string | null;\n moveId: string | null;\n before: SemanticValue;\n after: SemanticValue;\n}\n\n/** Public `docxodus.semantic-changes` schema returned by semantic comparison APIs. */\nexport interface SemanticChangeSet {\n schema: \"docxodus.semantic-changes\";\n schemaVersion: 1;\n changeCount: number;\n changes: SemanticChange[];\n}\n\n// \u2500\u2500\u2500 DocxDiff consolidate (composite N-way) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The composite layer over the IR diff engine: merge several reviewers' edits\n// against one shared base DOCX. Mirrors the .NET consolidate surface\n// (`DocxDiff.Consolidate` / `GetConflicts` / `GetConsolidatedRevisions` /\n// `GetConsolidatedEditScriptJson`) \u2014 see `docs/architecture/ir_diff_engine.md`.\n\n/**\n * How overlapping reviewer edits at the same base token span are resolved.\n * Integer values match the .NET `ConflictResolution` enum positions.\n */\nexport enum ConflictResolution {\n /** Keep the base text where reviewers disagree (the default). */\n BaseWins = 0,\n /** The first reviewer (by input order) wins each contested span. */\n FirstReviewerWins = 1,\n /** Stack every reviewer's variant so a human can pick. */\n StackAll = 2,\n}\n\n/** One reviewer's edited copy of the shared base document, plus their name. */\nexport interface DocxDiffReviewer {\n /** The reviewer's edited DOCX bytes. */\n document: Uint8Array;\n /** Author name stamped on this reviewer's revisions in the consolidated output. */\n author: string;\n}\n\n/**\n * Settings for the `docxDiffConsolidate*` functions. Extends {@link DocxDiffSettings}\n * with the conflict-resolution policy; mirrors the .NET `DocxDiffConsolidateSettings`.\n */\nexport interface DocxDiffConsolidateSettings extends DocxDiffSettings {\n /** Policy for overlapping reviewer edits (default {@link ConflictResolution.BaseWins}). */\n conflictResolution?: ConflictResolution;\n}\n\n/** One reviewer's contested variant at a conflict span. */\nexport interface DocxDiffConflictCompetitor {\n /** The reviewer whose variant this is. */\n author: string;\n /** The text this reviewer would produce for the contested span. */\n resultText: string;\n}\n\n/**\n * A single conflict: two or more reviewers edited the same base token span\n * incompatibly. Returned by {@link docxDiffGetConflicts}.\n */\nexport interface DocxDiffConflict {\n /** Stable id for this conflict within the consolidation. */\n id: number;\n /** The base-document block anchor (`kind:scope:unid`) the conflict sits in. */\n baseAnchor: string;\n /** First contested base token index (inclusive). */\n tokenStart: number;\n /** Last contested base token index (exclusive). */\n tokenEnd: number;\n /** The {@link ConflictResolution} policy that was applied to this conflict. */\n policy: ConflictResolution | number;\n /** The competing reviewer variants. */\n competitors: DocxDiffConflictCompetitor[];\n}\n\n/**\n * One revision from {@link docxDiffGetConsolidatedRevisions}. A\n * {@link DocxDiffRevision} plus the id of the conflict it participates in\n * (when it sits in a contested span).\n */\nexport interface DocxDiffConsolidatedRevision extends DocxDiffRevision {\n /** The {@link DocxDiffConflict.id} this revision belongs to, if any. */\n conflictId?: number;\n}\n\n/**\n * Type guard to check if a revision is an insertion.\n * @param revision - The revision to check\n * @returns true if the revision is an insertion\n *\n * @example\n * ```typescript\n * const revisions = await getRevisions(doc);\n * const insertions = revisions.filter(isInsertion);\n * ```\n */\nexport function isInsertion(revision: RevisionListEntry): boolean {\n return revision.family === \"content_insert\";\n}\n\n/**\n * Type guard to check if a revision is a deletion.\n * @param revision - The revision to check\n * @returns true if the revision is a deletion\n *\n * @example\n * ```typescript\n * const revisions = await getRevisions(doc);\n * const deletions = revisions.filter(isDeletion);\n * ```\n */\nexport function isDeletion(revision: RevisionListEntry): boolean {\n return revision.family === \"content_delete\";\n}\n\n/**\n * Type guard to check if a revision is a move operation.\n * @param revision - The revision to check\n * @returns true if the revision is part of a move\n *\n * @example\n * ```typescript\n * const revisions = await getRevisions(doc);\n * const moves = revisions.filter(isMove);\n * ```\n */\nexport function isMove(revision: RevisionListEntry): boolean {\n return revision.family === \"move\";\n}\n\n/**\n * Type guard to check if a revision is a format change.\n * @param revision - The revision to check\n * @returns true if the revision is a format change\n *\n * @example\n * ```typescript\n * const revisions = await getRevisions(doc);\n * const formatChanges = revisions.filter(isFormatChange);\n * for (const rev of formatChanges) {\n * console.log(`Format changed: ${rev.formatChange?.changedPropertyNames?.join(\", \")}`);\n * }\n * ```\n */\nexport function isFormatChange(revision: RevisionListEntry): boolean {\n return revision.family === \"properties_change\";\n}\n\n\n\n\n/**\n * Version information for the library\n */\nexport interface VersionInfo {\n library: string;\n dotnetVersion: string;\n platform: string;\n}\n\n/**\n * Error response from WASM operations\n */\nexport interface ErrorResponse {\n error: string;\n type?: string;\n /**\n * @deprecated Never populated: the engine stopped putting stack traces on the wire (issue #961).\n */\n stackTrace?: string;\n}\n\n/**\n * Result of a comparison operation\n */\nexport interface CompareResult {\n /** The redlined document as a Uint8Array */\n document: Uint8Array;\n /** List of revisions found */\n revisions: RevisionListEntry[];\n}\n\n/** Algorithm-labelled digest in a verification artifact. */\nexport interface VerificationDigest {\n algorithm: string;\n /** Lower-case hexadecimal digest bytes. */\n value: string;\n}\n\n/** Stable package location attached to a verification finding. */\nexport interface ChangeLocation {\n entryUri: string | null;\n ownerUri: string | null;\n relationshipId: string | null;\n targetUri: string | null;\n propertyPath: string | null;\n}\n\nexport type VerificationFindingSeverity = \"info\" | \"warning\" | \"error\";\n\n/** Machine-readable package validation or safety finding. */\nexport interface VerificationFinding {\n code: string;\n severity: VerificationFindingSeverity;\n message: string;\n location: ChangeLocation | null;\n}\n\n/** One physical ZIP entry. Duplicate names remain separate occurrences. */\nexport interface PackageManifestEntry {\n uri: string;\n occurrence: number;\n contentType: string | null;\n contentTypeSource: \"override\" | \"default\" | \"implicit\" | \"unresolved\";\n /** Exact declared uncompressed byte length as a base-10 integer string. */\n size: string;\n /** Exact compressed ZIP byte length as a base-10 integer string. */\n compressedSize: string;\n rawBytesDigest: VerificationDigest | null;\n normalizedXmlDigest: VerificationDigest | null;\n isXml: boolean;\n /** null when central-directory encryption flags could not be parsed authoritatively. */\n isEncrypted: boolean | null;\n}\n\nexport interface PackageContentTypeDeclaration {\n kind: \"default\" | \"override\";\n key: string;\n contentType: string;\n occurrence: number;\n}\n\nexport interface PackageRelationship {\n ownerUri: string;\n id: string;\n type: string;\n target: string;\n targetMode: \"Internal\" | \"External\";\n resolvedTargetUri: string | null;\n isTargetPresent: boolean | null;\n}\n\nexport interface PackageRevisionCounts {\n insertions: number;\n deletions: number;\n moveFrom: number;\n moveTo: number;\n propertyChanges: number;\n /** The `rPrChange` subset of `propertyChanges`; not added into `total`. */\n runPropertyChanges: number;\n structuralChanges: number;\n otherChanges: number;\n total: number;\n}\n\nexport interface PackageAnnotationCounts {\n comments: number;\n commentReplies: number;\n threadedCommentMetadata: number;\n resolvedComments: number;\n people: number;\n docxodusAnnotations: number;\n}\n\nexport interface PackageManifestFacts {\n mainDocumentUri: string | null;\n isStrictOoxml: boolean;\n isMacroEnabled: boolean;\n hasCoreProperties: boolean;\n hasExtendedProperties: boolean;\n hasCustomProperties: boolean;\n sectionCount: number;\n paragraphCount: number;\n tableCount: number;\n headerPartCount: number;\n footerPartCount: number;\n footnoteCount: number;\n endnoteCount: number;\n styleCount: number;\n numberingDefinitionCount: number;\n themePartCount: number;\n mediaPartCount: number;\n customXmlPartCount: number;\n drawingCount: number;\n altChunkCount: number;\n fieldCount: number;\n revisions: PackageRevisionCounts;\n annotations: PackageAnnotationCounts;\n}\n\n/** Deterministic schema-v1 description of a DOCX/OPC package. */\nexport interface PackageManifest {\n schema: \"https://docxodus.dev/schemas/verification/package-manifest/v1\";\n schemaVersion: 1;\n packageKind: \"opc\" | \"zip\" | \"zip-encrypted\" | \"ole-encrypted\" | \"ole\" | \"malformed\";\n isValid: boolean;\n rawPackageBytesDigest: VerificationDigest;\n orderedOpcContentDigest: VerificationDigest | null;\n normalizedSemanticDigest: VerificationDigest | null;\n entries: readonly PackageManifestEntry[];\n contentTypes: readonly PackageContentTypeDeclaration[];\n relationships: readonly PackageRelationship[];\n facts: PackageManifestFacts;\n findings: readonly VerificationFinding[];\n}\n\n// ============================================================================\n// Deliverable verification\n// ============================================================================\n\n/** Policy preset used by the default deliverable gate. */\nexport type DeliverableVerificationMode = \"standard\" | \"strict\" | \"reportOnly\";\n\n/** Final policy decision in a deliverable-verification report. */\nexport type DeliverableVerificationDecision =\n | \"passed\"\n | \"passedWithPreExistingFindings\"\n | \"failed\"\n | \"notEvaluated\";\n\n/** How a delivered finding relates to the exact opening/baseline package. */\nexport type DeliverableFindingDisposition =\n | \"new\"\n | \"preExisting\"\n | \"resolved\"\n | \"unclassified\";\n\nexport type DeliverableFindingCategory =\n | \"package\"\n | \"openXml\"\n | \"relationship\"\n | \"structure\"\n | \"workflow\"\n | \"delta\"\n | \"render\"\n | \"artifact\";\n\nexport type DeliverableCheckStatus =\n | \"completed\"\n | \"skippedPrerequisiteFailed\"\n | \"unavailableEvidence\";\n\nexport type DeliverablePackageChangeKind =\n | \"entryAdded\"\n | \"entryRemoved\"\n | \"entryModified\"\n | \"relationshipAdded\"\n | \"relationshipRemoved\"\n | \"relationshipModified\";\n\nexport type DeliverableArtifactRole =\n | \"html\"\n | \"pdf\"\n | \"pageMap\"\n | \"pageImage\"\n | \"renderReport\"\n | \"other\";\n\nexport type DeliverableArtifactAvailability = \"available\" | \"unavailable\";\n\n/** Camel-case enum values used by the deliverable report's semantic summary. */\nexport type DeliverableSemanticChangeFamily =\n | \"text\"\n | \"blockStructure\"\n | \"runFormatting\"\n | \"paragraphFormatting\"\n | \"style\"\n | \"numbering\"\n | \"list\"\n | \"table\"\n | \"tableRow\"\n | \"tableCell\"\n | \"tableSpan\"\n | \"tableWidth\"\n | \"tableStyle\"\n | \"section\"\n | \"pageSetup\"\n | \"header\"\n | \"footer\"\n | \"field\"\n | \"footnote\"\n | \"endnote\"\n | \"comment\"\n | \"hyperlink\"\n | \"bookmark\"\n | \"contentControl\"\n | \"image\"\n | \"media\"\n | \"relationship\"\n | \"revision\"\n | \"annotation\"\n | \"opaquePackagePart\";\n\nexport interface DeliverablePackageIdentity {\n packageKind: string;\n manifestValid: boolean;\n rawPackageBytesDigest: VerificationDigest;\n orderedOpcContentDigest: VerificationDigest | null;\n normalizedSemanticDigest: VerificationDigest | null;\n}\n\nexport interface DeliverableCheckResult {\n check: string;\n status: DeliverableCheckStatus;\n findingCount: number;\n diagnostic: string | null;\n}\n\nexport interface DeliverableFinding {\n findingId: string;\n code: string;\n category: DeliverableFindingCategory;\n severity: VerificationFindingSeverity;\n disposition: DeliverableFindingDisposition;\n blocksDelivery: boolean;\n message: string;\n owningPartUri: string;\n location: ChangeLocation | null;\n anchorId: string | null;\n scope: string | null;\n xPath: string | null;\n remediation: string;\n}\n\nexport interface DeliverablePackageChange {\n changeId: string;\n kind: DeliverablePackageChangeKind;\n location: ChangeLocation;\n beforeDigest: VerificationDigest | null;\n afterDigest: VerificationDigest | null;\n beforeValue: string | null;\n afterValue: string | null;\n}\n\nexport interface DeliverableSemanticChange {\n changeId: string;\n fingerprint: string;\n operation: SemanticChangeOperation;\n family: DeliverableSemanticChangeFamily;\n partUri: string;\n path: string;\n leftAnchor: string | null;\n rightAnchor: string | null;\n}\n\nexport interface DeliverableSemanticDelta {\n schema: \"docxodus.semantic-changes\";\n schemaVersion: 1;\n changeCount: number;\n canonicalDigest: VerificationDigest;\n changes: readonly DeliverableSemanticChange[];\n}\n\nexport interface DeliverableArtifactMetadata {\n artifactId: string;\n role: DeliverableArtifactRole;\n mediaType: string;\n availability: DeliverableArtifactAvailability;\n byteLength: number | null;\n digest: VerificationDigest | null;\n unavailableReason: string | null;\n pageCount: number | null;\n rendererFingerprint: string | null;\n sourcePackageDigest: VerificationDigest | null;\n pageMapDigest: VerificationDigest | null;\n renderDiagnosticCount: number;\n}\n\n/** Canonical schema-v1 report returned by every default verification transport. */\n/** One recorded artifact's independent re-hash verdict from receipt verification. */\nexport type DeliveryArtifactVerificationStatus =\n | \"verified\"\n | \"unavailable\"\n | \"missing\"\n | \"length_mismatch\"\n | \"digest_mismatch\"\n | \"invalid_record\";\n\nexport interface DeliveryArtifactVerification {\n artifactId: string;\n status: DeliveryArtifactVerificationStatus;\n expectedLength?: number;\n actualLength?: number;\n expectedDigest?: VerificationDigest;\n actualDigest?: VerificationDigest;\n}\n\n/**\n * Portable delivery change receipt verification verdict \u2014 the shared facade wire\n * shape every transport returns (issue #520).\n */\n/** What the session's host-owned delivery evidence recorder holds (issue #748). */\nexport interface DeliveryEvidenceStatus {\n enabled: boolean;\n transactionCount: number;\n lineageEventCount: number;\n /** Version steps applied by direct calls: exact packages, unknown request. */\n unlabeledTransactionCount: number;\n retainedStateCount: number;\n retainedBytes: number;\n sourceVersion: number;\n currentVersion: number;\n /** Null when a complete receipt can be minted; otherwise the first reason it cannot. */\n unavailableReason: string | null;\n}\n\nexport type DeliveryReceiptPrivacyProfile = \"hashOnly\" | \"hashAndSummary\" | \"fullEvidence\";\n\nexport interface DeliveryReceiptBuildOptions {\n privacyProfile?: DeliveryReceiptPrivacyProfile;\n failOnUnexpectedChanges?: boolean;\n}\n\nexport interface DeliveryBundleArtifact {\n artifactId: string;\n kind: string;\n requiredness: \"required\" | \"optional\";\n availability: \"available\" | \"unavailable\";\n relativePath: string;\n mediaType: string;\n /** Present when available. */\n bytes?: Uint8Array;\n /** Present when unavailable. */\n unavailableReason?: string;\n}\n\n/**\n * A delivery bundle as every transport publishes it: the verified manifest, its canonical bytes,\n * and each artifact with its bytes or the reason it is unavailable. `evidence` is the session's\n * recorder status at delivery time.\n */\nexport interface DeliveryBundleResult {\n status: \"complete\" | \"incomplete\" | \"failed\";\n verified: boolean;\n manifest: Record<string, unknown>;\n manifestBytes: Uint8Array;\n artifacts: readonly DeliveryBundleArtifact[];\n evidence?: DeliveryEvidenceStatus;\n}\n\nexport interface DeliveryReceiptVerificationResult {\n isValid: boolean;\n receiptDigestValid: boolean;\n contractValid: boolean;\n citationBindingsValid: boolean;\n artifacts: DeliveryArtifactVerification[];\n findings: string[];\n}\n\n/** One approved package-level delta the deliverable is expected to show (issue #747). */\nexport interface DeliverablePackageChangeExpectation {\n kind: DeliverablePackageChangeKind;\n location: ChangeLocation;\n beforeDigest?: VerificationDigest;\n afterDigest?: VerificationDigest;\n beforeValue?: string;\n afterValue?: string;\n}\n\nexport type DeliverableRenderDiagnosticKind =\n | \"warning\"\n | \"unsupportedContent\"\n | \"missingFont\"\n | \"fontSubstitution\";\n\n/** One render warning or limitation reported by the companion renderer. */\nexport interface DeliverableRenderDiagnostic {\n kind: DeliverableRenderDiagnosticKind;\n message: string;\n severity?: VerificationFindingSeverity;\n code?: string;\n phase?: string;\n}\n\n/** Bytes and renderer/document binding for one companion artifact submitted for verification. */\nexport interface DeliverableCompanionArtifactInput {\n artifactId: string;\n role: DeliverableArtifactRole;\n mediaType: string;\n /** Defaults to `available`. */\n availability?: DeliverableArtifactAvailability;\n bytes?: Uint8Array;\n unavailableReason?: string;\n pageCount?: number;\n rendererFingerprint?: string;\n /** Digest of the exact package the renderer consumed; a mismatch is a stale artifact. */\n sourcePackageDigest?: VerificationDigest;\n pageMapDigest?: VerificationDigest;\n renderDiagnostics?: readonly DeliverableRenderDiagnostic[];\n}\n\n/**\n * Policy and inspection limits for verification (issue #747). Every field is optional; an\n * omitted field takes the verifier's own default. Unknown fields are rejected.\n */\nexport interface DeliverableVerificationPolicyOptions {\n mode?: DeliverableVerificationMode;\n openXmlVersion?: string;\n failOnUnexpectedChanges?: boolean;\n requireNoPlaceholders?: boolean;\n detectBracketedAlternativeClauses?: boolean;\n editorialMarkers?: readonly string[];\n placeholderTokens?: readonly string[];\n maxPackageBytes?: number;\n maxFindings?: number;\n maxDetectorNodes?: number;\n maxDetectorRelationships?: number;\n maxDetectorTextCharacters?: number;\n maxDetectorRegexMatches?: number;\n maxDetectorSteps?: number;\n maxCompanionArtifactBytes?: number;\n maxTotalCompanionArtifactBytes?: number;\n maxCompanionArtifacts?: number;\n maxRenderDiagnostics?: number;\n maxExpectedChanges?: number;\n maxReportedDeltaChanges?: number;\n packageManifest?: {\n maxEntryCount?: number;\n maxEntryUncompressedBytes?: number;\n maxTotalUncompressedBytes?: number;\n maxXmlPartBytes?: number;\n maxCompressionRatio?: number;\n maxUriLength?: number;\n };\n}\n\n/**\n * The full bounded verification request (issue #747): what the typed .NET request adds to the\n * package bytes. Package bytes are passed alongside, never inside, this object.\n */\nexport interface DeliverableVerificationRequest {\n options?: DeliverableVerificationPolicyOptions;\n /** The canonical semantic-changes object (as `getSemanticChanges` returns it). */\n expectedSemanticChanges?: SemanticChangeSet;\n expectedPackageChanges?: readonly DeliverablePackageChangeExpectation[];\n companionArtifacts?: readonly DeliverableCompanionArtifactInput[];\n}\n\nexport interface DeliverableVerificationResult {\n schema: \"https://docxodus.dev/schemas/verification/deliverable-verification/v1\";\n schemaVersion: 1;\n mode: DeliverableVerificationMode;\n decision: DeliverableVerificationDecision;\n analysisCompleted: boolean;\n baselineCompared: boolean;\n baselinePackage: DeliverablePackageIdentity | null;\n deliverablePackage: DeliverablePackageIdentity;\n checks: readonly DeliverableCheckResult[];\n findings: readonly DeliverableFinding[];\n resolvedFindings: readonly DeliverableFinding[];\n semanticDelta: DeliverableSemanticDelta | null;\n packageChanges: readonly DeliverablePackageChange[];\n companionArtifacts: readonly DeliverableArtifactMetadata[];\n}\n\n/** How a revision in a redline relates to the selected baseline. */\nexport type RedlineRevisionDisposition =\n | \"preExisting\"\n | \"intendedFinalPreExisting\"\n | \"generated\"\n | \"conflicted\";\n\n/** Which of the two proof paths a result or finding belongs to. */\nexport type RedlineProofDirection = \"acceptToFinal\" | \"rejectToBaseline\";\n\n/** How a package entry differs from a path's expected document. */\nexport type RedlinePackageDivergenceKind = \"added\" | \"removed\" | \"modified\";\n\n/** Fail-closed resolution status of one native revision \u2014 the session registry's vocabulary. */\nexport type RedlineRevisionResolutionStatus = RevisionResolutionStatus;\n\n/** Coarse family of one native revision. */\nexport type RedlineRevisionFamily =\n | \"contentInsert\"\n | \"contentDelete\"\n | \"move\"\n | \"paragraphMark\"\n | \"rowInsert\"\n | \"rowDelete\"\n | \"cellInsert\"\n | \"cellDelete\"\n | \"cellMerge\"\n | \"contentControlInsert\"\n | \"contentControlDelete\"\n | \"numberingPropertiesInsert\"\n | \"numberingChange\"\n | \"propertiesChange\"\n | \"unsupported\";\n\n/** Why a revision could not be resolved \u2014 the session registry's shape. */\nexport type RedlineRevisionDiagnostic = RevisionDiagnostic;\n\n/** Input or output package identity recorded by the proof. */\nexport interface RedlineProofPackageIdentity {\n rawPackageBytesDigest: VerificationDigest;\n orderedOpcContentDigest: VerificationDigest | null;\n normalizedWholePackageDigest: VerificationDigest | null;\n}\n\n/** A stable, part-qualified identity for one native Word revision. */\nexport interface RedlineRevisionIdentity {\n id: string;\n partUri: string;\n scope: string;\n type: string;\n family: RedlineRevisionFamily;\n constituentIds: readonly string[];\n constituentKeys: readonly string[];\n author: string;\n date: string | null;\n dateUtc: string | null;\n text: string;\n anchorId: string | null;\n affectedAnchorIds: readonly string[];\n resolutionStatus: RedlineRevisionResolutionStatus;\n diagnostic: RedlineRevisionDiagnostic | null;\n}\n\n/** Classification of a baseline/intended-final/redline revision identity triple. */\nexport interface RedlineRevisionClassification {\n disposition: RedlineRevisionDisposition;\n baseline: RedlineRevisionIdentity | null;\n intendedFinal: RedlineRevisionIdentity | null;\n redline: RedlineRevisionIdentity | null;\n reason: string;\n}\n\n/**\n * Modeled semantic comparison for one path. `available` and `changeCount` are explicit so an\n * empty modeled change set is never mistaken for complete package equality.\n */\nexport interface RedlineModeledSemanticComparison {\n available: boolean;\n equivalent: boolean | null;\n schema: string | null;\n changeCount: number | null;\n diagnostic: string | null;\n}\n\n/** One added, removed, or modified package entry on a proof path. */\nexport interface RedlinePackageDivergence {\n kind: RedlinePackageDivergenceKind;\n partUri: string;\n occurrence: number;\n anchorId: string | null;\n applicableRevisionIds: readonly string[];\n expectedRawDigest: VerificationDigest | null;\n actualRawDigest: VerificationDigest | null;\n expectedNormalizedDigest: VerificationDigest | null;\n actualNormalizedDigest: VerificationDigest | null;\n /** Whether the semantic change set reports a modeled change for this part. */\n hasModeledSemanticChange: boolean;\n /**\n * Conservatively true when the normalized difference may contain content outside the modeled\n * semantic projection. A modeled change in one part never proves every change in it was modeled.\n */\n unknownOrUnmodeled: boolean;\n}\n\n/** A structured, actionable proof finding. */\nexport interface RedlineProofFinding {\n code: string;\n severity: VerificationFindingSeverity;\n message: string;\n direction: RedlineProofDirection | null;\n location: ChangeLocation | null;\n anchorId: string | null;\n revisionIds: readonly string[];\n remediation: string | null;\n}\n\n/** Result of accepting or rejecting only the generated revision set. */\nexport interface RedlineProofPathResult {\n direction: RedlineProofDirection;\n completed: boolean;\n equivalent: boolean;\n requestedRevisionIds: readonly string[];\n resolvedRevisionIds: readonly string[];\n implicitlyResolvedRevisionIds: readonly string[];\n survivingPreExistingRevisions: readonly RedlineRevisionIdentity[];\n preExistingRevisionsPreserved: boolean;\n modeledSemantic: RedlineModeledSemanticComparison;\n normalizedWholePackageEquivalent: boolean;\n orderedOpcContentEquivalent: boolean;\n exactPackageBytesEquivalent: boolean;\n /**\n * Whether the complete bounded package delta was available. A false value never exposes a\n * potentially misleading prefix of `divergences`.\n */\n divergenceAnalysisCompleted: boolean;\n expectedPackage: RedlineProofPackageIdentity;\n actualPackage: RedlineProofPackageIdentity | null;\n firstDivergence: RedlinePackageDivergence | null;\n divergences: readonly RedlinePackageDivergence[];\n findings: readonly RedlineProofFinding[];\n}\n\n/**\n * Canonical schema-v1 proof that a redline's generated changes accept to the intended final and\n * reject to the baseline without consuming pre-existing review state.\n */\nexport interface RedlineReversibilityProof {\n schema: \"https://docxodus.dev/schemas/verification/redline-reversibility-proof/v1\";\n schemaVersion: 1;\n success: boolean;\n requireExactPackageBytes: boolean;\n baselinePackage: RedlineProofPackageIdentity;\n intendedFinalPackage: RedlineProofPackageIdentity;\n redlinePackage: RedlineProofPackageIdentity;\n revisionClassifications: readonly RedlineRevisionClassification[];\n acceptToFinal: RedlineProofPathResult | null;\n rejectToBaseline: RedlineProofPathResult | null;\n findings: readonly RedlineProofFinding[];\n}\n\n/** Effective #493 inspection limits applied while the manifest is being generated. */\nexport interface PackageManifestInspectionLimits {\n opcEntries: number;\n expandedOpcBytes: number;\n xmlPartBytes: number;\n opcUriCharacters: number;\n opcCompressionRatio: number;\n}\n\n/**\n * Internal WASM exports structure\n */\nexport interface DocxodusWasmExports {\n /** Available in builds with durable history bindings. */\n HistoryBridge?: import('./history.js').HistoryBridge;\n DocumentConverter: {\n GeneratePackageManifest: (bytes: Uint8Array) => string;\n VerifyDeliverable: (bytes: Uint8Array) => string;\n VerifyDeliverableWithRequest?: (bytes: Uint8Array, requestJson: string) => string;\n VerifyDeliverableWithBaselineAndRequest?: (\n baselineBytes: Uint8Array,\n bytes: Uint8Array,\n requestJson: string,\n ) => string;\n VerifyDeliveryReceipt: (receiptJson: string, artifactsJson: string) => string;\n VerifyDeliverableWithBaseline: (\n baselineBytes: Uint8Array,\n bytes: Uint8Array\n ) => string;\n ProveRedlineReversibility: (\n baselineBytes: Uint8Array,\n intendedFinalBytes: Uint8Array,\n redlineBytes: Uint8Array\n ) => string;\n GeneratePackageManifestWithOptions: (\n bytes: Uint8Array,\n maxEntryCount: number,\n maxTotalUncompressedBytes: number,\n maxXmlPartBytes: number,\n maxCompressionRatio: number,\n maxUriLength: number,\n ) => string;\n ConvertDocxToHtml: (bytes: Uint8Array) => string;\n RenderBlockHtml: (\n bytes: Uint8Array,\n anchorId: string,\n cssPrefix: string,\n fabricateClasses: boolean\n ) => string;\n ConvertDocxToHtmlWithOptions: (\n bytes: Uint8Array,\n pageTitle: string,\n cssPrefix: string,\n fabricateClasses: boolean,\n additionalCss: string,\n commentRenderMode: number,\n commentCssClassPrefix: string\n ) => string;\n ConvertDocxToHtmlWithPagination: (\n bytes: Uint8Array,\n pageTitle: string,\n cssPrefix: string,\n fabricateClasses: boolean,\n additionalCss: string,\n commentRenderMode: number,\n commentCssClassPrefix: string,\n paginationMode: number,\n paginationScale: number,\n paginationCssClassPrefix: string\n ) => string;\n ConvertDocxToHtmlFull: (\n bytes: Uint8Array,\n pageTitle: string,\n cssPrefix: string,\n fabricateClasses: boolean,\n additionalCss: string,\n commentRenderMode: number,\n commentCssClassPrefix: string,\n paginationMode: number,\n paginationScale: number,\n paginationCssClassPrefix: string,\n renderAnnotations: boolean,\n annotationLabelMode: number,\n annotationCssClassPrefix: string\n ) => string;\n ConvertDocxToHtmlComplete: (\n bytes: Uint8Array,\n pageTitle: string,\n cssPrefix: string,\n fabricateClasses: boolean,\n additionalCss: string,\n commentRenderMode: number,\n commentCssClassPrefix: string,\n paginationMode: number,\n paginationScale: number,\n paginationCssClassPrefix: string,\n renderAnnotations: boolean,\n annotationLabelMode: number,\n annotationCssClassPrefix: string,\n renderFootnotesAndEndnotes: boolean,\n renderHeadersAndFooters: boolean,\n renderTrackedChanges: boolean,\n showDeletedContent: boolean,\n renderMoveOperations: boolean,\n renderUnsupportedContentPlaceholders: boolean,\n documentLanguage: string | null,\n stampAnchors: boolean,\n revisionPresentation: number,\n semanticLists?: boolean\n ) => string;\n GetAnnotations: (bytes: Uint8Array) => string;\n AddAnnotation: (bytes: Uint8Array, requestJson: string) => string;\n AddAnnotationWithTarget: (bytes: Uint8Array, requestJson: string) => string;\n RemoveAnnotation: (bytes: Uint8Array, annotationId: string) => string;\n HasAnnotations: (bytes: Uint8Array) => string;\n GetDocumentStructure: (bytes: Uint8Array) => string;\n GetDocumentMetadata: (bytes: Uint8Array) => string;\n ExportToOpenContract: (bytes: Uint8Array) => string;\n ConvertWmlToMarkdown: (bytes: Uint8Array, settingsJson: string) => string;\n GetVersion: () => string;\n // Profiling methods\n ConvertDocxToHtmlProfiled: (bytes: Uint8Array) => string;\n ProfileConversionDetailed: (bytes: Uint8Array) => string;\n // External annotation methods\n ComputeDocumentHash: (bytes: Uint8Array) => string;\n CreateExternalAnnotationSet: (\n bytes: Uint8Array,\n documentId: string\n ) => string;\n ValidateExternalAnnotations: (\n bytes: Uint8Array,\n annotationSetJson: string\n ) => string;\n ConvertDocxToHtmlWithExternalAnnotations: (\n bytes: Uint8Array,\n annotationSetJson: string,\n pageTitle: string,\n cssPrefix: string,\n fabricateClasses: boolean,\n additionalCss: string,\n extAnnotCssClassPrefix: string,\n extAnnotLabelMode: number\n ) => string;\n SearchTextOffsets: (\n bytes: Uint8Array,\n searchText: string,\n maxResults: number\n ) => string;\n // Incremental annotation overlay methods\n ProjectAnnotationsOntoHtml: (\n html: string,\n annotationSetJson: string,\n extAnnotCssClassPrefix: string,\n extAnnotLabelMode: number\n ) => string;\n AddAnnotationToHtml: (\n html: string,\n annotationJson: string,\n labelJson: string,\n extAnnotCssClassPrefix: string,\n extAnnotLabelMode: number\n ) => string;\n RemoveAnnotationFromHtml: (\n html: string,\n annotationId: string,\n extAnnotCssClassPrefix: string\n ) => string;\n GenerateAnnotationVisibilityCss: (\n hiddenLabelIdsJson: string,\n extAnnotCssClassPrefix: string\n ) => string;\n GenerateAnnotationCss: (\n labelsJson: string,\n extAnnotCssClassPrefix: string,\n extAnnotLabelMode: number\n ) => string;\n };\n DocumentComparer: {\n /**\n * Force the comparison code path hot by running a real comparison against\n * tiny in-memory seed documents. Returns \"ok\" or a JSON error object.\n * Idempotent \u2014 assemblies load only once.\n */\n Warmup: () => string;\n CompareDocuments: (\n originalBytes: Uint8Array,\n modifiedBytes: Uint8Array,\n authorName: string | null\n ) => Uint8Array;\n CompareDocumentsToHtml: (\n originalBytes: Uint8Array,\n modifiedBytes: Uint8Array,\n authorName: string | null\n ) => string;\n CompareDocumentsToHtmlWithOptions: (\n originalBytes: Uint8Array,\n modifiedBytes: Uint8Array,\n authorName: string | null,\n renderTrackedChanges: boolean\n ) => string;\n CompareDocumentsToHtmlFull: (\n originalBytes: Uint8Array,\n modifiedBytes: Uint8Array,\n authorName: string | null,\n caseInsensitive: boolean,\n renderTrackedChanges: boolean\n ) => string;\n CompareDocumentsWithOptions: (\n originalBytes: Uint8Array,\n modifiedBytes: Uint8Array,\n authorName: string | null,\n caseInsensitive: boolean\n ) => Uint8Array;\n GetRevisionsJson: (comparedDocBytes: Uint8Array) => string;\n GetCommentsJson: (docBytes: Uint8Array) => string;\n };\n DocxDiffBridge: {\n /** Redlined DOCX bytes (native markup), or empty array on error. */\n Compare: (\n leftBytes: Uint8Array,\n rightBytes: Uint8Array,\n settingsJson: string\n ) => Uint8Array;\n /** `{\"revisions\":[\u2026]}` JSON, or a JSON error object. */\n GetRevisionsJson: (\n leftBytes: Uint8Array,\n rightBytes: Uint8Array,\n settingsJson: string\n ) => string;\n /** Edit-script JSON (diff-as-data), or a JSON error object. */\n GetEditScriptJson: (\n leftBytes: Uint8Array,\n rightBytes: Uint8Array,\n settingsJson: string\n ) => string;\n /** Canonical `docxodus.semantic-changes` JSON, or a JSON error object. */\n GetSemanticChangesJson: (\n leftBytes: Uint8Array,\n rightBytes: Uint8Array,\n settingsJson: string\n ) => string;\n /** One memoized pass, every requested product: `{\"redlineB64\":\u2026, \"revisions\":[\u2026],\n * \"editScript\":\u2026, \"semanticChanges\":\u2026}` JSON (issue #594), or a JSON error object. */\n CompareProductsJson: (\n leftBytes: Uint8Array,\n rightBytes: Uint8Array,\n settingsJson: string,\n productsJson: string\n ) => string;\n /** One baseline read once, compared against many candidates:\n * `{\"results\":[{\"name\":\u2026, \u2026products\u2026}]}` JSON (issue #617), or a JSON error object. */\n CompareBatchJson: (\n baselineBytes: Uint8Array,\n candidatesJson: string,\n settingsJson: string,\n productsJson: string\n ) => string;\n /** Accept all tracked revisions in a redlined DOCX \u2192 \"right\"-side bytes, or empty array on error. */\n AcceptRevisions: (bytes: Uint8Array) => Uint8Array;\n /** Reject all tracked revisions in a redlined DOCX \u2192 \"left\"-side bytes, or empty array on error. */\n RejectRevisions: (bytes: Uint8Array) => Uint8Array;\n /** Consolidated redlined DOCX bytes (native markup), or empty array on error. */\n Consolidate: (\n baseBytes: Uint8Array,\n reviewersJson: string,\n settingsJson: string\n ) => Uint8Array;\n /** `{\"revisions\":[\u2026]}` JSON for the consolidation, or a JSON error object. */\n GetConsolidatedRevisionsJson: (\n baseBytes: Uint8Array,\n reviewersJson: string,\n settingsJson: string\n ) => string;\n /** Consolidated edit-script JSON (diff-as-data), or a JSON error object. */\n GetConsolidatedEditScriptJson: (\n baseBytes: Uint8Array,\n reviewersJson: string,\n settingsJson: string\n ) => string;\n /** `{\"conflicts\":[\u2026]}` JSON for the consolidation, or a JSON error object. */\n GetConflictsJson: (\n baseBytes: Uint8Array,\n reviewersJson: string,\n settingsJson: string\n ) => string;\n };\n DocxSessionBridge: {\n OpenSession: (bytes: Uint8Array, settingsJson: string) => number;\n OpenPreviewSession?: (liveHandle: number) => number;\n CloseSession: (handle: number) => void;\n CreateBlankDocx: () => Uint8Array;\n Project: (handle: number) => string;\n GetVersion: (handle: number) => string;\n RegisterPageMap: (handle: number, pageMapJson: string, expectedRendererFingerprint: string) => string;\n GetPageMapStatus: (handle: number, requestJson: string) => string;\n GetPageCitation: (handle: number, anchorId: string, requestJson: string) => string;\n GetPackageContentHash?: (handle: number) => string;\n BeginMutationTransaction?: (handle: number, transactionId: string, requestJson: string) => string;\n CompleteMutationTransaction?: (handle: number, transactionId: string, serializedResponse: string) => void;\n AbandonMutationTransaction?: (handle: number, transactionId: string) => void;\n RetainPreview?: (shadowHandle: number) => string;\n CommitPreview?: (handle: number, previewId: string) => string;\n GetDeliveryEvidenceStatus?: (handle: number) => string;\n BuildDeliveryReceipt?: (handle: number, optionsJson: string) => string;\n BeginDeliveryEvidence?: (handle: number, operationsJson: string, mode: string, identityJson: string) => boolean;\n CompleteDeliveryEvidence?: (handle: number, stepsJson: string) => void;\n AbandonDeliveryEvidence?: (handle: number) => void;\n GetPackageManifest: (handle: number) => string;\n RenderPreviewHtml?: (handle: number) => string;\n RenderPreviewBlockHtml?: (handle: number, anchorId: string) => string;\n CheckPreconditions: (handle: number, preconditionsJson: string) => string;\n BeginTransaction: (handle: number) => number;\n CommitTransaction: (transactionHandle: number) => void;\n RollbackTransaction: (transactionHandle: number) => void;\n ProjectAnchor: (handle: number, anchorId: string, depth: number | null) => string;\n ProjectAnchorWithCitations: (\n handle: number,\n anchorId: string,\n depth: number | null,\n requestJson: string,\n ) => string;\n /** Ordered top-level render units per scope container (JSON {@link RenderPlan}) \u2014\n * what the editor's incremental reconciler diffs its DOM against. Optional:\n * absent on older WASM bundles. */\n ListBlocks?: (handle: number) => string;\n ListRenderedBlocks?: (handle: number, renderTrackedChanges: boolean) => string;\n /** Citation-ordered footnotes/endnotes (JSON {@link NoteListEntry}[]) \u2014 the\n * id\u2194ordinal authority for renumbering rendered note chrome. Optional:\n * absent on older WASM bundles. */\n ListNotes?: (handle: number, endnotes: boolean) => string;\n /** The anchor index alone as `{\"anchorIndex\":{\u2026}}` \u2014 the editor's per-op\n * anchor-map refresh without marshaling the whole markdown projection.\n * Optional: absent on older WASM bundles. */\n ListAnchors?: (handle: number) => string;\n /** Batch block render: `anchorIdsJson` is a JSON string array; returns a JSON\n * object mapping each id to its HTML element (null when unresolvable), or\n * `{\"error\": \u2026}` on total failure \u2014 parse and check for `error`. One throwaway\n * doc + one converter run for the whole batch, with real sibling context and\n * true list-marker numbers. Optional: absent on older WASM bundles. */\n RenderBlocksHtml?: (\n handle: number,\n anchorIdsJson: string,\n cssPrefix: string,\n fabricateClasses: boolean\n ) => string;\n RenderBlocksHtmlForReview?: (\n handle: number,\n anchorIdsJson: string,\n cssPrefix: string,\n fabricateClasses: boolean,\n renderTrackedChanges: boolean\n ) => string;\n RenderBlockHtml: (\n handle: number,\n anchorId: string,\n cssPrefix: string | null,\n fabricateClasses: boolean | null\n ) => string;\n RenderBlockHtmlForReview?: (\n handle: number,\n anchorId: string,\n cssPrefix: string,\n fabricateClasses: boolean,\n renderTrackedChanges: boolean\n ) => string;\n RenderHtml: (\n handle: number,\n cssPrefix: string,\n fabricateClasses: boolean,\n paginated: boolean,\n scale: number\n ) => string;\n RenderHtmlForReview?: (\n handle: number,\n cssPrefix: string,\n fabricateClasses: boolean,\n paginated: boolean,\n scale: number,\n renderTrackedChanges: boolean\n ) => string;\n /** The editor's comments-aware render profile: `optionsJson` is a serialized\n * {@link EditorRenderOptions}. With `comments: true` the output carries the converter's\n * Inline comment markup (`comment-highlight` spans with `data-comment-id`, `comment-marker`\n * anchors) using the `comment-` class prefix; with `comments: false` it is byte-identical to\n * `RenderHtml` / `RenderHtmlForReview`. Same error convention: HTML starts with '<', an\n * error object with '{'. Optional: absent on older WASM bundles. */\n RenderEditorHtml?: (handle: number, optionsJson: string) => string;\n /** Batch block render with the editor profile \u2014 `RenderBlocksHtml` plus comment markup;\n * same JSON-object result (`{ [anchorId]: html | null }`, or `{\"error\": \u2026}`). */\n RenderEditorBlocksHtml?: (handle: number, anchorIdsJson: string, optionsJson: string) => string;\n RenderEditorChromeHtml?: (handle: number, optionsJson: string) => string;\n RenderEditorRangeHtml?: (handle: number, anchorIdsJson: string, optionsJson: string) => string;\n /** Single-block render with the editor profile \u2014 `RenderBlockHtml` plus comment markup. */\n RenderEditorBlockHtml?: (handle: number, anchorId: string, optionsJson: string) => string;\n ReplaceText: (handle: number, anchor: string, md: string) => string;\n DeleteBlock: (handle: number, anchor: string) => string;\n MoveBlock: (handle: number, sourceAnchor: string, targetAnchor: string, pos: string) => string;\n /** JSON `{anchorId, before, after}[]` \u2014 the blocks a block may legally be moved next to and\n * on which side, which is what a drag UI gates its drop targets on. The two sides are\n * reported separately because a cross-block range or a section break between the blocks can\n * make one legal and the other not. Optional: absent on older WASM bundles. */\n ValidMoveTargets?: (handle: number, sourceAnchor: string) => string;\n DeleteRange: (handle: number, fromAnchorId: string, toAnchorIdExclusive: string) => string;\n DeleteSection: (handle: number, headingAnchorId: string) => string;\n InsertParagraph: (handle: number, anchor: string, pos: string, md: string) => string;\n SplitParagraph: (handle: number, anchor: string, offset: number) => string;\n MergeParagraphs: (handle: number, first: string, second: string) => string;\n InsertHorizontalRule: (handle: number, anchor: string, pos: string, ruleJson: string) => string;\n InsertTable: (handle: number, anchor: string, pos: string, rows: number, cols: number, optionsJson: string) => string;\n GetTableMetadata: (handle: number, tableAnchor: string) => string;\n ResolveTableCellAnchor: (handle: number, cellAnchor: string) => string;\n ResolveTableCellCoordinate: (handle: number, tableAnchor: string, rowIndex: number, columnIndex: number) => string;\n InsertTableRow: (handle: number, cellAnchor: string, pos: string) => string;\n InsertTableColumn: (handle: number, cellAnchor: string, pos: string) => string;\n DeleteTableRow: (handle: number, cellAnchor: string) => string;\n DeleteTableColumn: (handle: number, cellAnchor: string) => string;\n MergeCells: (handle: number, cellAnchor: string, rowSpan: number, colSpan: number, content: string) => string;\n UnmergeCells: (handle: number, cellAnchor: string) => string;\n SetColumnWidths: (handle: number, cellAnchor: string, widthsJson: string) => string;\n SetTableBorders: (handle: number, cellAnchor: string, specJson: string) => string;\n SetCellShading: (handle: number, cellAnchor: string, fill: string, scope: string) => string;\n SetRepeatHeaderRow: (handle: number, cellAnchor: string, repeat: boolean | null) => string;\n SetTableRowOptions: (handle: number, cellAnchor: string, repeatHeader: boolean | null,\n allowBreakAcrossPages: boolean | null, heightTwips: number | null, heightRule: string) => string;\n SetHeaderText: (handle: number, anchor: string, kind: string, markdown: string) => string;\n SetFooterText: (handle: number, anchor: string, kind: string, markdown: string) => string;\n InsertPageNumberField: (handle: number, anchor: string, field: string, format: string) => string;\n SetPageNumbering: (handle: number, anchor: string, opJson: string) => string;\n InsertTableOfContents: (handle: number, anchor: string, pos: string, optionsJson: string) => string;\n InsertTableOfFigures: (handle: number, anchor: string, pos: string, optionsJson: string) => string;\n InsertTableOfAuthorities: (handle: number, anchor: string, pos: string, optionsJson: string) => string;\n ClearPageNumbering: (handle: number, anchor: string) => string;\n EnsureHeaderFooterVisible: (handle: number, anchor: string, kind: string) => string;\n /** Word's \"Different first page\" / \"Different odd & even pages\" checkboxes. `kind` is\n * \"first\" | \"even\"; `enabled: false` removes `w:titlePg` / `w:evenAndOddHeaders` and leaves\n * the story parts in place. Optional: absent on older WASM bundles. */\n SetHeaderFooterKindEnabled?: (handle: number, anchor: string, kind: string, enabled: boolean) => string;\n /** Page size / orientation / margins / header-footer distance of the section owning\n * `anchor`; `opJson` is a serialized {@link PageSetupOp}. Optional: absent on older WASM\n * bundles. */\n SetPageSetup?: (handle: number, anchor: string, opJson: string) => string;\n InsertFootnote: (handle: number, anchor: string, characterOffset: number, markdown: string) => string;\n InsertCrossReference: (\n handle: number,\n anchor: string,\n characterOffset: number,\n bookmarkName: string,\n optionsJson: string\n ) => string;\n InsertEndnote: (handle: number, anchor: string, characterOffset: number, markdown: string) => string;\n // Native Word comment authoring (issue #300). spanJson: \"\" = whole block, else\n // {\"start\":n,\"length\":n}; initials/date: \"\" = absent (date is ISO-8601).\n AddComment: (\n handle: number,\n anchor: string,\n spanJson: string,\n author: string,\n initials: string,\n date: string,\n markdown: string,\n ) => string;\n AddCommentToRevision: (\n handle: number,\n revisionId: string,\n author: string,\n initials: string,\n date: string,\n markdown: string,\n ) => string;\n AddCommentReply: (\n handle: number,\n parentCommentAnchor: string,\n author: string,\n initials: string,\n date: string,\n markdown: string,\n ) => string;\n UpdateComment: (handle: number, commentAnchor: string, markdown: string) => string;\n SetCommentResolved: (handle: number, commentAnchor: string, resolved: boolean) => string;\n RemoveComment: (handle: number, commentAnchor: string) => string;\n ListComments: (handle: number) => string;\n ListHyperlinks: (handle: number, scopes: number) => string;\n AddHyperlink: (handle: number, anchor: string, start: number, length: number, kind: string, target: string) => string;\n UpdateHyperlink: (handle: number, hyperlinkId: string, kind: string, target: string) => string;\n RemoveHyperlink: (handle: number, hyperlinkId: string) => string;\n GetImageCapabilities: () => string;\n ListImages: (handle: number, scopes: number) => string;\n InsertImage: (handle: number, anchor: string, characterOffset: number, imageBase64: string, optionsJson: string) => string;\n ReplaceImage: (handle: number, imageId: string, imageBase64: string) => string;\n EmbedLinkedImage: (handle: number, imageId: string, imageBase64: string) => string;\n SetImageDimensions: (handle: number, imageId: string, dimensionsJson: string) => string;\n SetImageMetadata: (handle: number, imageId: string, altText: string | null, title: string | null) => string;\n SetImageFloatingLayout: (handle: number, imageId: string, layoutJson: string) => string;\n RemoveImage: (handle: number, imageId: string) => string;\n ListContentControls: (handle: number, scopes: number) => string;\n FillContentControlText: (handle: number, anchorId: string, text: string, optionsJson: string) => string;\n FillContentControlRichText: (handle: number, anchorId: string, markdown: string, optionsJson: string) => string;\n SetContentControlChecked: (handle: number, anchorId: string, isChecked: boolean, optionsJson: string) => string;\n SetContentControlDate: (handle: number, anchorId: string, value: string, displayText: string | null, optionsJson: string) => string;\n SelectContentControlItem: (handle: number, anchorId: string, value: string, optionsJson: string) => string;\n FillContentControlPicture: (handle: number, anchorId: string, imageBase64: string, optionsJson: string) => string;\n AddRepeatingSectionItem: (handle: number, sectionAnchorId: string, afterItemAnchorId: string, optionsJson: string) => string;\n RemoveRepeatingSectionItem: (handle: number, itemAnchorId: string) => string;\n ListBookmarks: (handle: number, scopes: number) => string;\n AddBookmark: (handle: number, name: string, startAnchor: string, startOffset: number, endAnchor: string, endOffset: number) => string;\n RenameBookmark: (handle: number, name: string, newName: string) => string;\n MoveBookmark: (handle: number, name: string, startAnchor: string, startOffset: number, endAnchor: string, endOffset: number) => string;\n RemoveBookmark: (handle: number, name: string) => string;\n ListRevisions: (handle: number) => string;\n ListRevisionsFiltered?: (handle: number, filterJson: string) => string;\n ListRevisionRepairs?: (handle: number) => string;\n RepairRevisions?: (handle: number, repairsJson: string) => string;\n AcceptRevision: (handle: number, revisionId: string) => string;\n RejectRevision: (handle: number, revisionId: string) => string;\n AcceptAllRevisions: (handle: number) => string;\n RejectAllRevisions: (handle: number) => string;\n ApplyFormat: (handle: number, anchor: string, spanJson: string, opJson: string) => string;\n ApplyFormatBySubstring: (handle: number, anchor: string, substring: string, opJson: string) => string;\n SetParagraphStyle: (handle: number, anchor: string, styleId: string) => string;\n SetParagraphFormat: (handle: number, anchor: string, opJson: string) => string;\n SetListLevel: (handle: number, anchor: string, delta: number) => string;\n RemoveListMembership: (handle: number, anchor: string) => string;\n ApplyListFormat: (handle: number, anchor: string, kind: string) => string;\n ApplyListFormatRange: (handle: number, firstAnchor: string, lastAnchor: string, kind: string) => string;\n SetListStartOverride: (handle: number, anchor: string, value: number) => string;\n ClearListStartOverride: (handle: number, anchor: string) => string;\n ReplaceCellContent: (handle: number, anchor: string, md: string) => string;\n RawGetXml: (handle: number, anchor: string) => string;\n RawInsertXml: (handle: number, anchor: string, pos: string, xml: string) => string;\n RawReplaceXml: (handle: number, anchor: string, xml: string) => string;\n Grep: (handle: number, pattern: string, optionsJson: string) => string;\n GrepCrossBlock: (handle: number, pattern: string, optionsJson: string) => string;\n ReplaceTextRange: (handle: number, anchor: string, find: string, replace: string, optionsJson: string) => string;\n ReplaceTextAtSpan: (handle: number, anchor: string, spanStart: number, spanLength: number, replace: string) => string;\n ReplaceTextAtSpanWithFormat?: (handle: number, anchor: string, spanStart: number, spanLength: number, replace: string, formatJson: string) => string;\n ReplaceInner: (\n handle: number,\n matchText: string,\n anchor: string,\n spanStart: number,\n spanLength: number,\n newInner: string,\n ) => string;\n FindPlaceholders: (\n handle: number,\n kinds: number | null,\n scope: number | null,\n contextChars: number | null,\n boundary: number | null,\n ) => string;\n FindPlaceholdersWithCitations: (\n handle: number,\n kinds: number | null,\n scope: number | null,\n contextChars: number | null,\n boundary: number | null,\n requestJson: string,\n ) => string;\n GetEditSummary: (handle: number) => string;\n RemainingPlaceholders: (handle: number, kinds: number | null) => string;\n GetDiff: (handle: number, format: number | null) => string;\n GetSemanticChanges: (handle: number) => string;\n VerifyDeliverable: (handle: number) => string;\n VerifyDeliverableWithRequest?: (handle: number, requestJson: string) => string;\n FindByAnnotation: (handle: number, annotationId: string) => string;\n FindByAnnotationWithCitations: (handle: number, annotationId: string, requestJson: string) => string;\n FindByLabel: (handle: number, labelId: string) => string;\n FindByLabelWithCitations: (handle: number, labelId: string, requestJson: string) => string;\n FindByBookmark: (handle: number, bookmarkName: string) => string;\n FindByBookmarkWithCitations: (handle: number, bookmarkName: string, requestJson: string) => string;\n Exists: (handle: number, anchorId: string) => boolean;\n FindByText: (handle: number, needle: string, optionsJson: string) => string;\n FindAllByText: (handle: number, needle: string, optionsJson: string) => string;\n FindByRegex: (handle: number, pattern: string, regexOptions: number | null, optionsJson: string) => string;\n FindByKind: (handle: number, kind: string, scope: string) => string;\n FindByKindWithCitations: (handle: number, kind: string, scope: string, requestJson: string) => string;\n GetAnchorInfo: (handle: number, anchorId: string) => string;\n GetAnchorInfos: (handle: number, anchorIdsJson: string) => string;\n GetBlockMetadata: (handle: number, anchorId: string) => string;\n GetBlockMetadatas: (handle: number, anchorIdsJson: string) => string;\n GetListMembership: (handle: number, anchorId: string) => string;\n GetSectionInfo: (handle: number, anchorId: string) => string;\n ListStyles: (handle: number) => string;\n GetFormatting: (handle: number, anchorId: string) => string;\n ListInlineSpans: (handle: number, anchorId: string) => string;\n ListAnnotations: (handle: number) => string;\n // Session annotation write surface\n AddAnnotation: (\n handle: number,\n anchorId: string,\n spanJson: string,\n annotationJson: string\n ) => string;\n SessionRemoveAnnotation: (handle: number, annotationId: string) => string;\n UpdateAnnotation: (\n handle: number,\n annotationId: string,\n updateJson: string\n ) => string;\n MoveAnnotation: (\n handle: number,\n annotationId: string,\n newAnchorId: string,\n newSpanJson: string\n ) => string;\n Undo: (handle: number) => boolean;\n Redo: (handle: number) => boolean;\n SetTrackedChanges: (handle: number, mode: number) => void;\n SetRevisionAuthor: (handle: number, author: string) => void;\n Save: (handle: number) => Uint8Array;\n /** Save KEEPING the projector's `PtOpenXml:Unid` bookkeeping. Exists for the in-browser\n * editor's remount, which re-renders these bytes and needs the anchors to survive the hop.\n * Roughly 6x the document's size and read by no renderer \u2014 never hand it to a user; a\n * save-to-disk wants {@link Save}. */\n SaveWithAnchorIds: (handle: number) => Uint8Array;\n };\n}\n\n// \u2500\u2500\u2500 DocxSession types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type EditErrorCode =\n | \"anchor_not_found\"\n | \"anchor_wrong_kind\"\n | \"anchors_not_adjacent\"\n | \"session_disposed\"\n | \"malformed_markdown\"\n | \"unsupported_markdown_syntax\"\n | \"table_insert_not_supported\"\n | \"footnote_ref_not_supported\"\n | \"comment_marker_not_supported\"\n | \"image_insert_not_supported\"\n | \"anchor_token_in_payload\"\n | \"offset_out_of_range\"\n | \"invalid_position\"\n | \"text_not_found\"\n | \"unknown_style\"\n | \"invalid_list_level\"\n | \"invalid_list_start_value\"\n | \"invalid_page_numbering\"\n | \"invalid_page_setup\"\n | \"invalid_reference_field\"\n | \"invalid_paragraph_format\"\n | \"invalid_table_styling\"\n | \"invalid_table_merge\"\n | \"table_anchor_migration_required\"\n | \"malformed_xml\"\n | \"disallowed_namespace\"\n | \"incompatible_element_type\"\n | \"validation_failed\"\n | \"nothing_to_undo\"\n | \"nothing_to_redo\"\n | \"duplicate_annotation_id\"\n | \"annotation_not_found\"\n | \"empty_annotation_span\"\n | \"empty_comment_span\"\n | \"revision_not_found\"\n | \"precondition_failed\"\n | \"invalid_batch_step\"\n | \"invalid_transaction\"\n | \"transaction_conflict\"\n | \"transaction_result_evicted\"\n | \"transaction_incomplete\"\n | \"preview_not_found\"\n | \"preview_stale\"\n | \"revision_repair_rejected\"\n | \"hyperlink_not_found\"\n | \"bookmark_not_found\"\n | \"duplicate_bookmark_name\"\n | \"invalid_bookmark_name\"\n | \"invalid_hyperlink_target\"\n | \"missing_bookmark_target\"\n | \"bookmark_in_use\"\n | \"managed_bookmark\"\n | \"empty_hyperlink_span\"\n | \"unsupported_inline_boundary\"\n | \"revision_unsupported\"\n | \"revision_malformed\"\n | \"revision_ambiguous\"\n | \"tracked_operation_unsupported\"\n | \"unresolved_structural_revision\"\n | \"content_control_not_found\"\n | \"content_control_malformed\"\n | \"content_control_unsupported\"\n | \"content_control_locked\"\n | \"content_control_bound\"\n | \"content_control_wrong_type\"\n | \"invalid_content_control_value\"\n | \"content_control_placement_unsupported\"\n | \"content_control_nested_fill_unsupported\"\n | \"repeating_section_constraint\"\n | \"image_not_found\"\n | \"invalid_image_data\"\n | \"unsupported_image_format\"\n | \"image_too_large\"\n | \"invalid_image_dimensions\"\n | \"unsupported_image_markup\"\n | \"linked_image_read_only\"\n | \"invalid_image_layout\"\n | \"internal_error\"\n /** A failed edit's rollback also failed, so the document may be half-changed. Every later\n * mutation is refused with this code; close the session and reopen it from known-good bytes. */\n | \"session_corrupted\";\n\nexport interface AnchorRef {\n id: string;\n kind: string;\n scope: string;\n unid: string;\n}\n\nexport interface EditError {\n code: EditErrorCode;\n message: string;\n anchorId?: string;\n precondition?: PreconditionFailure;\n}\n\nexport interface PreconditionTarget {\n exists: boolean;\n anchorId?: string;\n kind?: string;\n scope?: string;\n contentHash?: string;\n visibleText?: string;\n}\n\nexport interface PreconditionFailure {\n condition: string;\n expected: unknown;\n actual: unknown;\n currentVersion: number;\n currentTarget?: PreconditionTarget;\n}\n\nexport interface TextRangePrecondition {\n start: number;\n length: number;\n text: string;\n}\n\n/** Optimistic guards checked immediately before a mutation. */\nexport interface MutationPreconditions {\n expectedVersion?: number;\n /** Optional explicit target; target-addressed methods infer their own anchor when omitted. */\n anchorId?: string;\n expectedContentHash?: string;\n expectedText?: string;\n expectedTextRange?: TextRangePrecondition;\n expectedKind?: string;\n expectedScope?: string;\n expectedMatchCount?: number;\n}\n\nexport type MutationBatchMode = \"atomic\" | \"best_effort\";\n\n/** One synchronous npm batch step. Atomic is the default execution mode. */\nexport interface MutationBatchStep {\n tool: string;\n action: string;\n mutation: () => EditResult | readonly EditResult[];\n /** Optional read-only validation: all run up front in atomic mode, per-step in best-effort. */\n preflight?: () => EditError | undefined;\n /**\n * The step's request arguments, recorded as the normalized request in delivery evidence\n * (issue #748) when the session captures it. The callback hides them, so name them here.\n */\n args?: Record<string, unknown>;\n}\n\n/** A preview callback receives the isolated shadow session it must mutate/read. */\nexport interface MutationBatchPreviewStep {\n tool: string;\n action: string;\n mutation: (shadow: import(\"./session.js\").DocxSession) => EditResult | readonly EditResult[];\n preflight?: (shadow: import(\"./session.js\").DocxSession) => EditError | undefined;\n}\n\nexport interface MutationBatchPreviewOptions {\n html?: \"none\" | \"scoped\" | \"full\";\n /** Required for scoped HTML. */\n htmlAnchorId?: string;\n /**\n * Keep a successful preview's exact result package so {@link DocxSession.commitPreview} can\n * later make it the live document with the previewed generated ids, timestamps and\n * `packageHash`. The receipt then carries {@link MutationBatchResult.retention}. Retention\n * is bounded (count, bytes and time) and cleared when the session closes.\n */\n retain?: boolean;\n}\n\n/**\n * Identity of a preview retained for a guarded commit (issue #760). `baseVersion` and\n * `basePackageHash` describe the live state the preview was predicted from; the commit refuses\n * once either has moved. `expiresAt` is the ISO-8601 UTC instant after which the entry is gone.\n */\nexport interface MutationPreviewRetention {\n previewId: string;\n baseVersion: number;\n basePackageHash: string;\n expiresAt: string;\n}\n\nexport interface MutationBatchStepResult {\n index: number;\n tool: string;\n action: string;\n success: boolean;\n rolledBack: boolean;\n results: readonly EditResult[];\n}\n\nexport interface MutationBatchFailure {\n index: number;\n tool: string;\n action: string;\n error: EditError;\n rolledBack: boolean;\n}\n\nexport interface MutationBatchChangeSet<T> {\n added: readonly T[];\n removed: readonly T[];\n modified: readonly T[];\n}\n\nexport interface MutationBatchResult {\n mode: MutationBatchMode;\n status: \"ok\" | \"failed\" | \"partial\";\n preview: boolean;\n success: boolean;\n rolledBack: boolean;\n baseVersion: number;\n resultVersion: number;\n /**\n * Canonical SHA-256 of this result package, or `null` when it could not be computed.\n * Exact replay equality is guaranteed only for deterministic batches, so consult\n * {@link MutationBatchResult.warnings} before asserting on it \u2014 and note that `null`\n * never equals `null` for the purposes of a replay assertion: an absent hash proves\n * nothing and must be handled explicitly rather than compared.\n */\n packageHash: string | null;\n steps: readonly MutationBatchStepResult[];\n failure?: MutationBatchFailure;\n revisionChanges: MutationBatchChangeSet<RevisionListEntry>;\n commentChanges: MutationBatchChangeSet<CommentListEntry>;\n annotationChanges: MutationBatchChangeSet<DocumentAnnotation>;\n warnings: readonly string[];\n /** Shadow-only preview HTML when requested; null otherwise. */\n html: string | null;\n /**\n * Present only for a batch executed under a {@link MutationTransaction}: the identity the\n * session's journal bound the request to \u2014 the same on the original call and on a replay.\n */\n transaction?: MutationTransactionIdentity;\n /**\n * Present on a preview retained with {@link MutationBatchPreviewOptions.retain} and on the\n * result of {@link DocxSession.commitPreview}.\n */\n retention?: MutationPreviewRetention;\n}\n\n/** The versioned identity a transaction-aware batch result carries (issue #761). */\nexport interface MutationTransactionIdentity {\n schemaVersion: number;\n transactionId: string;\n /** SHA-256 over the canonical rendering of {@link MutationTransaction.request} plus the mode. */\n requestFingerprint: string;\n}\n\n/**\n * Retry deduplication for {@link DocxSession.executeBatch}. The session's journal replays the\n * original result for an identical retry under the same `transactionId` without executing the\n * steps again, and refuses the id for a different request with `transaction_conflict`. Because\n * the batch is composed from callbacks, `request` is the caller's own serializable description\n * of what the batch does and is what the fingerprint covers: pass the same descriptor on a retry.\n */\nexport interface MutationTransaction {\n /** Non-blank, at most 256 Unicode scalar values; scoped to this open session. */\n transactionId: string;\n /** A JSON object describing the batch (step kinds, targets, payloads). */\n request: Record<string, unknown>;\n}\n\n/** One changed top-level block in a {@link MarkdownPatch}. */\nexport interface MarkdownPatchBlock {\n /** The block's anchor id (`kind:scope:unid`). */\n anchorId: string;\n /** The block it now follows in its scope, or `null` when it is the scope's first block. */\n afterAnchorId: string | null;\n /** The block's own markdown, without the separators the full projection puts between blocks. */\n markdown: string;\n}\n\n/**\n * The projection change one mutation produced. Block-scoped: it carries the markdown of the\n * top-level blocks (body paragraphs/tables, header and footer blocks, note definitions, comments)\n * that changed or were added since the previous patch, and the ids of blocks that are gone.\n * A client keeping one entry per block applies it by deleting `removedAnchorIds`, then, for each\n * of `blocks` in order, deleting that id if present and re-inserting it after `afterAnchorId`.\n *\n * When a block-local patch cannot be exact, `fullDocument` is true and `markdown` is the whole\n * projection: an edit that renumbered a list, changed a style, edited a header or footer, or added,\n * removed or renumbered a story part or a note; the first patch after an op failed and rolled back\n * or a preview was committed; any non-`FullUnid` anchor rendering. `undo()` and `redo()` return no\n * patch: re-read the projection after them; the next patch covers only later changes. Call\n * `project()` for the whole document at any time.\n */\nexport interface MarkdownPatch {\n /** The anchor the op addressed. */\n scopeAnchorId: string;\n /** The changed blocks' markdown in document order, or the whole projection when `fullDocument`. */\n markdown: string;\n /** True when `markdown` is the whole projection; `blocks` and `removedAnchorIds` are then empty. */\n fullDocument: boolean;\n /** Blocks changed or added since the previous patch, in document order. */\n blocks: MarkdownPatchBlock[];\n /** Ids of blocks removed since the previous patch (or whose id changed). */\n removedAnchorIds: string[];\n}\n\nexport interface EditResult {\n success: boolean;\n error?: EditError;\n created: AnchorRef[];\n removed: AnchorRef[];\n modified: AnchorRef[];\n /** Deterministic structural identity map for table shape mutations. */\n tableAnchors?: TableAnchorMapping;\n patch?: MarkdownPatch;\n /** Set by the annotation ops (addAnnotation/removeAnnotation/updateAnnotation/\n * moveAnnotation) with the affected annotation id; absent for every other op. */\n annotationId?: string;\n hyperlinkId?: string;\n bookmarkName?: string;\n imageId?: string;\n}\n\nexport type HyperlinkKind = \"external\" | \"internal\";\n\nexport interface HyperlinkInfo {\n id: string;\n kind: HyperlinkKind;\n owningPartUri: string;\n scope: string;\n anchorId: string;\n span: CharSpan;\n text: string;\n target?: string;\n relationshipId?: string;\n relationshipIsExternal?: boolean;\n isBroken: boolean;\n}\n\nexport type ImageBinaryFormat = \"unknown\" | \"png\" | \"jpeg\" | \"gif\" | \"bmp\" | \"tiff\" | \"webp\";\nexport type ImageMarkupKind = \"modern_drawing\" | \"legacy_vml\" | \"unsupported_drawing\";\nexport type ImagePlacement = \"inline\" | \"floating\";\nexport type ImageWrapMode = \"none\" | \"square\" | \"tight\" | \"through\" | \"top_and_bottom\" | \"unknown\";\nexport type ImageWrapSide = \"both_sides\" | \"left\" | \"right\" | \"largest\" | \"unknown\";\nexport type ImageHorizontalReference = \"page\" | \"margin\" | \"column\" | \"character\" | \"unknown\";\nexport type ImageVerticalReference = \"page\" | \"margin\" | \"paragraph\" | \"line\" | \"unknown\";\nexport type ImageHorizontalAlignment = \"left\" | \"center\" | \"right\" | \"inside\" | \"outside\" | \"unknown\";\nexport type ImageVerticalAlignment = \"top\" | \"center\" | \"bottom\" | \"inside\" | \"outside\" | \"unknown\";\n\n/** One vertex of a tight/through wrap outline in DrawingML's 21600-unit picture space. */\nexport interface ImageWrapPoint { x: number; y: number; }\n\n/**\n * The outline text follows under tight/through wrap: a start vertex plus at least two line\n * segments. Omit it on write to get the picture rectangle; a layout read from the document\n * always carries the outline it holds.\n */\nexport interface ImageWrapPolygon { points: ImageWrapPoint[]; edited?: boolean; }\n\nexport interface FloatingImageLayout {\n horizontalRelativeFrom?: ImageHorizontalReference;\n horizontalOffsetEmu?: number | null;\n horizontalAlignment?: ImageHorizontalAlignment | null;\n verticalRelativeFrom?: ImageVerticalReference;\n verticalOffsetEmu?: number | null;\n verticalAlignment?: ImageVerticalAlignment | null;\n wrapMode?: ImageWrapMode;\n wrapSide?: ImageWrapSide;\n wrapPolygon?: ImageWrapPolygon | null;\n distanceTopEmu?: number;\n distanceBottomEmu?: number;\n distanceLeftEmu?: number;\n distanceRightEmu?: number;\n relativeHeight?: number;\n behindDocument?: boolean;\n locked?: boolean;\n layoutInCell?: boolean;\n allowOverlap?: boolean;\n rawHorizontalReference?: string;\n rawVerticalReference?: string;\n rawHorizontalPosition?: string;\n rawVerticalPosition?: string;\n rawWrapMode?: string;\n rawWrapSide?: string;\n rawRelativeSizeHorizontal?: string;\n rawRelativeSizeVertical?: string;\n rawFlagTokens?: Record<string, string>;\n}\n\nexport interface ImageInsertOptions {\n placement?: ImagePlacement;\n widthPoints?: number;\n heightPoints?: number;\n preserveAspect?: boolean;\n altText?: string | null;\n title?: string | null;\n floatingLayout?: FloatingImageLayout;\n}\n\nexport interface ImageDimensions {\n widthPoints?: number;\n heightPoints?: number;\n preserveAspect?: boolean;\n}\n\n/** Whether one image operation applies to one occurrence in the session's current mode. */\nexport interface ImageOperationSupport { operation: string; canMutate: boolean; reason?: string; }\n\nexport interface ImageOccurrence {\n id: string; markupKind: ImageMarkupKind; placement?: ImagePlacement; canMutate: boolean;\n unsupportedReason?: string; owningPartUri: string; scope: string; anchorId: string; span: CharSpan;\n relationshipId?: string; targetPartUri?: string; linkedRelationshipId?: string; linkedTarget?: string;\n isEmbedded: boolean; isLinked: boolean; isBroken: boolean; mediaFileName?: string; contentType?: string;\n format: ImageBinaryFormat; contentTypeMatchesBytes?: boolean; intrinsicWidthPixels?: number;\n intrinsicHeightPixels?: number; renderedWidthPoints?: number; renderedHeightPoints?: number;\n altText?: string; title?: string; floatingLayout?: FloatingImageLayout; floatingLayoutSupported: boolean;\n /** replace, embed_linked, set_dimensions, set_metadata, set_floating_layout and remove, each answered. */\n operations: ImageOperationSupport[];\n}\n\n/** Which operations one markup family accepts, independent of any occurrence. */\nexport interface ImageMarkupCapability { markup: string; operations: string[]; limitation?: string; }\n\nexport interface ImageFormatCapability {\n format: ImageBinaryFormat; contentType: string; canInspect: boolean; canInsert: boolean;\n canReplace: boolean; limitation?: string;\n}\n\nexport interface ImageCapabilities {\n schemaVersion: number; runtime: string; formats: ImageFormatCapability[]; operations: string[];\n mutableWrapModes: ImageWrapMode[]; horizontalReferences: ImageHorizontalReference[];\n verticalReferences: ImageVerticalReference[]; maxInputBytes: number; maxRenderedPoints: number;\n defaultDpi: number; usesHeaderParsingOnly: boolean; acceptsBinaryBytes: boolean;\n supportsNetworkFetch: boolean; supportsFileIo: boolean;\n markups: ImageMarkupCapability[]; trackedOperations: string[];\n}\n\nexport type ContentControlType = \"plain_text\" | \"rich_text\" | \"checkbox\" | \"date\"\n | \"drop_down_list\" | \"combo_box\" | \"picture\" | \"repeating_section\"\n | \"repeating_section_item\" | \"unsupported\";\nexport type ContentControlPlacement = \"inline\" | \"block\" | \"row\" | \"cell\" | \"unknown\";\nexport type ContentControlBindingPolicy = \"preserve\" | \"detach_target\";\n\n/** How a whole-control fill treats nested controls inside its target (issue #763). */\nexport type ContentControlNestedPolicy = \"refuse\" | \"preserve\" | \"replace\";\n\nexport interface ContentControlFillOptions {\n bindingPolicy?: ContentControlBindingPolicy;\n /**\n * Default `refuse`. `preserve` keeps every nested control in place and replaces only the\n * content outside them; `replace` discards the whole payload, nested controls included\n * (each is reported removed; a locked or data-bound nested control refuses).\n */\n nestedControls?: ContentControlNestedPolicy;\n /**\n * With `preserve`: plain-text fills for nested text/rich-text controls of the target, keyed\n * by their `sdt` anchor, applied in the same operation. A key that is not a nested textual\n * control, or a child that fails its own gates, fails the whole call without mutating.\n */\n childFills?: Record<string, string>;\n}\n\n/** Whether one operation would succeed on a control right now, by the gates the operation applies. */\nexport interface ContentControlOperationSupport {\n operation: \"fill_text\" | \"fill_rich_text\" | \"set_checked\" | \"set_date\" | \"select_item\"\n | \"fill_picture\" | \"add_repeating_item\" | \"remove_repeating_item\";\n /** The nested policy this entry describes, when the target contains nested controls. */\n nestedControls?: ContentControlNestedPolicy;\n canMutate: boolean;\n reason?: string;\n}\n\nexport interface ContentControlBindingInfo {\n storeItemId?: string;\n xpath?: string;\n prefixMappings?: string;\n}\n\nexport interface ContentControlInfo {\n anchorId: string;\n type: ContentControlType;\n placement: ContentControlPlacement;\n nativeId?: string;\n tag?: string;\n alias?: string;\n lock?: string;\n isShowingPlaceholder: boolean;\n isBound: boolean;\n binding?: ContentControlBindingInfo;\n owningPartUri: string;\n scope: string;\n parentAnchorId?: string;\n depth: number;\n hasValidNativeId: boolean;\n hasDuplicateNativeId: boolean;\n canMutate: boolean;\n canDetachTargetBinding: boolean;\n unsupportedReason?: string;\n text: string;\n itemValues: string[];\n /** Anchors of the controls nested anywhere inside this control's payload, in story order. */\n nestedControlAnchorIds: string[];\n /**\n * Per-operation support for this control's family, including nested-policy variants of a\n * fill when the target contains nested controls and the session's tracked-change mode.\n */\n operations: ContentControlOperationSupport[];\n}\n\nexport interface DocumentRange {\n startAnchorId: string;\n startOffset: number;\n endAnchorId: string;\n endOffset: number;\n}\n\nexport interface BookmarkRangeSegment {\n owningPartUri: string;\n scope: string;\n anchorId: string;\n span: CharSpan;\n text: string;\n}\n\nexport interface BookmarkInfo {\n name: string;\n bookmarkId: string;\n startPartUri: string;\n startScope: string;\n endPartUri?: string;\n endScope?: string;\n range?: DocumentRange;\n segments: BookmarkRangeSegment[];\n text: string;\n isPaired: boolean;\n isManaged: boolean;\n isValid: boolean;\n validationError?: string;\n}\n\n/**\n * One native Word comment, in comments-part order \u2014 see {@link DocxSession.listComments}.\n * `anchorId` addresses the definition (kind `cmt`) for updateComment/removeComment;\n * `date` is the raw `w:date` attribute string; `text` is the flattened body.\n * `parentAnchorId` and `resolved` are present when the comment has a\n * `commentsExtended.xml` entry; their absence distinguishes a legacy/flat comment from an\n * explicitly reopened one. `id` is the numeric `w:id` \u2014 the value rendered comment markup\n * carries as `data-comment-id`, which is how a highlight in the DOM is matched back to its\n * entry. Mutations still address comments by `anchorId`.\n */\nexport interface CommentListEntry {\n anchorId: string;\n /** The comment's numeric `w:comment/@w:id`; equals the `data-comment-id` of its rendered\n * highlight spans and marker. */\n id: number;\n author: string;\n initials?: string;\n date?: string;\n text: string;\n parentAnchorId?: string;\n resolved?: boolean;\n}\n\n/** Revision kind in a markup-native revision listing. A `move` entry is a linked\n * move pair \u2014 both sides resolve together. */\nexport type SessionRevisionType = \"insert\" | \"delete\" | \"move\" | \"format\" | \"structure\";\nexport type RevisionFamily =\n | \"content_insert\" | \"content_delete\" | \"move\" | \"paragraph_mark\"\n | \"row_insert\" | \"row_delete\" | \"cell_insert\" | \"cell_delete\" | \"cell_merge\"\n | \"content_control_insert\" | \"content_control_delete\"\n | \"numbering_properties_insert\" | \"numbering_change\" | \"properties_change\"\n | \"unsupported\";\nexport type RevisionResolutionStatus = \"supported\" | \"unsupported\" | \"malformed\" | \"ambiguous\";\n\n/** The explicit repairs the revision registry can perform on markup it refuses to resolve. */\nexport type RevisionRepairKind =\n | \"assign_identity\"\n | \"reattach_numbering_change\"\n | \"reattach_cell_marker\"\n | \"restore_orphan_text\"\n | \"wrap_orphan_text_as_deletion\";\n\n/** One repair the registry offers for one listed entry, and whether it can perform it. */\nexport interface RevisionRepairProposal {\n revisionId: string;\n kind: RevisionRepairKind;\n partUri: string;\n diagnostic: RevisionDiagnostic;\n /** Every native carrier the repair touches, as QName@element-path keys. */\n carriers: readonly string[];\n repairable: boolean;\n /** What the repair does, or why the package's evidence does not permit it. */\n reason: string;\n /** The request must supply `author` and `date`. */\n requiresAuthorship: boolean;\n}\n\nexport interface RevisionRepairRequest {\n revisionId: string;\n kind: RevisionRepairKind;\n author?: string;\n date?: string;\n}\n\n/** One carrier's identity before and after a repair; `newId` is empty when it was moved, not renumbered. */\nexport interface RevisionCarrierIdentity {\n carrier: string;\n oldId: string | null;\n newId: string;\n}\n\nexport interface RevisionRepairOutcome {\n revisionId: string;\n kind: RevisionRepairKind;\n partUri: string;\n identities: readonly RevisionCarrierIdentity[];\n}\n\n/** Atomic, one undo step; repaired entries get new ids, so re-list afterwards. */\nexport interface RevisionRepairResult {\n success: boolean;\n error?: EditError;\n repairs: readonly RevisionRepairOutcome[];\n modified: readonly AnchorRef[];\n}\n\nexport interface RevisionDiagnostic {\n code: string;\n message: string;\n}\n\n/**\n * One part-qualified atomic revision from the live registry. `id` is an opaque,\n * deterministic `rev2-\u2026` identity; `constituentIds` exposes the native Word ids.\n * `family` identifies the exact operation, while `type` is its coarse display class.\n * Unsafe native topology remains listed through `resolutionStatus` and `diagnostic`.\n */\nexport interface RevisionListEntry {\n id: string;\n type: SessionRevisionType;\n family: RevisionFamily;\n constituentIds: string[];\n /**\n * QName-qualified native carrier identities. Unlike `constituentIds`, these\n * distinguish revision roles which legally use the same numeric `w:id` value.\n */\n constituentKeys: string[];\n author: string;\n date?: string;\n /** The `w16du:dateUtc` timestamp, when the markup carries one. */\n dateUtc?: string;\n text: string;\n partUri: string;\n scope: string;\n anchorId?: string;\n affectedAnchors: AnchorRef[];\n resolutionStatus: RevisionResolutionStatus;\n diagnostic?: RevisionDiagnostic;\n}\n\nexport interface CharSpan {\n start: number;\n length: number;\n}\n\nexport interface FormatOp {\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strike?: boolean;\n code?: boolean;\n color?: string;\n runStyle?: string;\n /** Vertical alignment: \"superscript\" | \"subscript\" | \"\" (clear). Omit to leave unchanged. */\n vertAlign?: string;\n /**\n * Font size in **points** (maps to `w:sz`/`w:szCs`, stored as half-points). Omit to leave\n * unchanged; a value <= 0 clears the explicit size. Fractional points round to a half-point.\n */\n fontSizePts?: number;\n /**\n * Run font family (maps to `w:rFonts` ascii/hAnsi/cs). Omit to leave unchanged; `\"\"` clears\n * the explicit font so the run inherits the style/default. Lets a run match a serif filing.\n */\n fontFamily?: string;\n /**\n * Text highlight colour (`w:highlight`) \u2014 one of Word's sixteen `ST_HighlightColor` names:\n * \"yellow\", \"green\", \"cyan\", \"magenta\", \"blue\", \"red\", \"darkBlue\", \"darkCyan\", \"darkGreen\",\n * \"darkMagenta\", \"darkRed\", \"darkYellow\", \"darkGray\", \"lightGray\", \"black\", \"white\". Omit to\n * leave unchanged; `\"\"` or `\"none\"` clears. Any other value fails the op (`internal_error`\n * with the message, like an invalid `vertAlign`) \u2014 Word has no free-form highlight.\n */\n highlight?: string;\n /** All capitals (`w:caps`). `true` sets it and removes `w:smallCaps` (Word's either/or rule);\n * `false` removes it; omit to leave unchanged. */\n caps?: boolean;\n /** Small capitals (`w:smallCaps`). `true` sets it and removes `w:caps`; `false` removes it;\n * omit to leave unchanged. */\n smallCaps?: boolean;\n}\n\n/** One edge of a paragraph border (`w:pBdr` top/bottom) \u2014 drives S-1 horizontal rules. */\nexport interface ParagraphBorderEdge {\n /** Border line style (`w:val`): \"single\",\"double\",\"thick\",\"dotted\",\"dashed\",\u2026 Default \"single\". */\n style?: string;\n /** Weight in eighths of a point (`w:sz`). Default 6 (\u22480.75pt); a heavy rule \u2248 18\u201324. */\n size?: number;\n /** Hex color without '#', or \"auto\". Default \"auto\". */\n color?: string;\n /** Padding between border and text, in points (`w:space`). Default 1. */\n space?: number;\n}\n\n/** List format for `DocxSession.applyListFormat` / `applyListFormatRange`. The plain numbered\n * formats render `1.` / `a.` / `i.` level text; the `*Parenthesis` variants render `(1)` /\n * `(a)` / `(i)` \u2014 same `w:numFmt`, different `w:lvlText` (the legal-drafting presets). */\nexport type ListFormat =\n | \"none\"\n | \"bullet\"\n | \"decimal\"\n | \"lowerLetter\"\n | \"upperLetter\"\n | \"lowerRoman\"\n | \"upperRoman\"\n | \"decimalParenthesis\"\n | \"lowerLetterParenthesis\"\n | \"upperLetterParenthesis\"\n | \"lowerRomanParenthesis\"\n | \"upperRomanParenthesis\";\n\n/** How `ParagraphFormatOp.lineSpacing` is interpreted (`w:spacing/@w:lineRule`): under `\"auto\"`\n * the value is in 240ths of a line (240 = single, 360 = 1.5\u00D7, 480 = double); under\n * `\"exact\"`/`\"atLeast\"` it is a height in twips (20 twips = 1pt). */\nexport type LineSpacingRule = \"auto\" | \"exact\" | \"atLeast\";\n\n/** Paragraph-level formatting for `DocxSession.setParagraphFormat`. Omit a field to leave it unchanged. */\nexport interface ParagraphFormatOp {\n /** Paragraph alignment. */\n alignment?: \"left\" | \"center\" | \"right\" | \"justify\";\n /** Adjust the left indent by this many twips (1440 = 1 inch); clamped at 0. */\n indentDelta?: number;\n /** First-line indent in twips (`w:ind/@w:firstLine`; 1440 = 1 inch). Absolute, not a delta;\n * 0 writes an explicit \"none\". Mutually exclusive with `hangingIndent` (Word's `w:ind` holds\n * one or the other) \u2014 setting this removes any hanging indent, and an op carrying both is\n * rejected with `invalid_paragraph_format`. Negatives are invalid. */\n firstLineIndent?: number;\n /** Hanging indent in twips (`w:ind/@w:hanging`; 1440 = 1 inch) \u2014 every line EXCEPT the first\n * starts this far right of the paragraph's left edge. Mutually exclusive with\n * `firstLineIndent`; setting this removes any first-line indent. Negatives are invalid. */\n hangingIndent?: number;\n /** Space above the paragraph in twips (`w:spacing/@w:before`; 20 twips = 1pt, so 240 = 12pt).\n * Absolute; negatives are invalid. */\n spacingBefore?: number;\n /** Space below the paragraph in twips (`w:spacing/@w:after`; 20 twips = 1pt). Absolute;\n * negatives are invalid. */\n spacingAfter?: number;\n /** Line spacing (`w:spacing/@w:line`). Units depend on `lineSpacingRule`: 240ths of a line\n * under `\"auto\"` (the default when the rule is omitted), twips under `\"exact\"`/`\"atLeast\"`.\n * Negatives are invalid. */\n lineSpacing?: number;\n /** How `lineSpacing` is interpreted. Only meaningful alongside `lineSpacing` \u2014 set without\n * it, the op is rejected with `invalid_paragraph_format`. */\n lineSpacingRule?: LineSpacingRule;\n /** Page-break-before: true to add, false to remove. */\n pageBreakBefore?: boolean;\n /** Top paragraph border (`w:pBdr/w:top`). Omit to leave unchanged. */\n topBorder?: ParagraphBorderEdge;\n /** Bottom paragraph border (`w:pBdr/w:bottom`) \u2014 what an S-1 horizontal rule is. Omit to leave unchanged. */\n bottomBorder?: ParagraphBorderEdge;\n /** Remove all paragraph borders before applying any top/bottom border in this op. */\n clearBorders?: boolean;\n}\n\n/**\n * Which header/footer story `DocxSession.setHeaderText`/`setFooterText` targets, mapping to the\n * OOXML `w:type`: `\"default\"` (all pages), `\"first\"` (first-page-only; sets `w:titlePg`),\n * `\"even\"` (even pages; sets `w:evenAndOddHeaders`).\n */\nexport type HeaderFooterKind = \"default\" | \"first\" | \"even\";\n\n/**\n * Options for {@link DocxSession.insertTableOfContents} (issue #607). Every field is a typed switch\n * on the underlying `TOC` field, so a caller never writes `\\o \"1-3\"` by hand \u2014 a malformed switch\n * string renders as nothing in Word, silently, which is the failure these exist to prevent.\n */\nexport interface TableOfContentsOptions {\n /** Heading levels to list (`\\o`): a level or a range within 1-9, e.g. `\"1-3\"`. Default `\"1-3\"`. */\n levels?: string;\n /** Make each entry a hyperlink to its heading (`\\h`). Default true. */\n hyperlinks?: boolean;\n /** Hide the leader tab and page numbers in Word's web view (`\\z`). Default true. */\n hideTabAndPageNumbersInWeb?: boolean;\n /** Include paragraphs with an outline level but no heading style (`\\u`). Default true. */\n useOutlineLevels?: boolean;\n /** Heading above the table, in Word's `TOCHeading` style. `null` or `\"\"` inserts no heading.\n * Default `\"Contents\"`. */\n title?: string | null;\n /** Right-aligned dot-leader tab stop in twips. Default 9350 (US Letter, one-inch margins). */\n rightTabPos?: number;\n}\n\n/** Options for {@link DocxSession.insertTableOfFigures}. A table of figures is a `TOC` field\n * selecting by caption label rather than outline level \u2014 Word's own encoding. */\nexport interface TableOfFiguresOptions {\n /** The caption label whose captions to list (`\\c`) \u2014 `\"Figure\"`, `\"Table\"`, `\"Exhibit\"`. */\n captionLabel?: string;\n /** Make each entry a hyperlink to its caption (`\\h`). Default true. */\n hyperlinks?: boolean;\n /** Right-aligned dot-leader tab stop in twips. Default 9350. */\n rightTabPos?: number;\n}\n\n/** Word's fixed table-of-authorities categories. */\nexport type AuthorityCategory =\n | \"cases\"\n | \"statutes\"\n | \"other_authorities\"\n | \"rules\"\n | \"treatises\"\n | \"regulations\"\n | \"constitutional_provisions\";\n\n/** Options for {@link DocxSession.insertTableOfAuthorities}. */\nexport interface TableOfAuthoritiesOptions {\n /** Which category of authority to list (`\\c`). Default `\"cases\"`. */\n category?: AuthorityCategory;\n /** Make each entry a hyperlink to its citation (`\\h`). Default true. */\n hyperlinks?: boolean;\n /** Separator between an entry and its page numbers (`\\e`), e.g. a tab. Default: Word's own. */\n entryPageSeparator?: string;\n /** Right-aligned dot-leader tab stop in twips. Default 9350. */\n rightTabPos?: number;\n}\n\n/** Which page-number field `DocxSession.insertPageNumberField` emits: `\"currentPage\"` \u2192 PAGE,\n * `\"totalPages\"` \u2192 NUMPAGES, `\"pageOfTotal\"` \u2192 Word's \"Page X of Y\" gallery entry (the text\n * `Page `, a PAGE field, ` of `, a NUMPAGES field, every run inheriting the paragraph's last run\n * formatting). */\nexport type PageNumberField = \"currentPage\" | \"totalPages\" | \"pageOfTotal\";\n\n/**\n * Section-level page-numbering setup for {@link DocxSession.setPageNumbering} \u2014 the `w:pgNumType`\n * element, which is what Word's *Format Page Numbers\u2026* dialog writes. Each field is tri-state: an\n * omitted field leaves that attribute exactly as it is. Use\n * {@link DocxSession.clearPageNumbering} to remove them.\n *\n * This governs how a **plain** PAGE field renders anywhere in the section, which is the normal way\n * to number pages: set the section once, insert unswitched fields. It is distinct from the\n * per-field `\\*` switch {@link DocxSession.insertPageNumberField} can stamp, which overrides the\n * section for that one field.\n */\nexport interface PageNumberingOp {\n /** The page number this section starts at (`w:start`) \u2014 e.g. `1` to restart at a section break.\n * Omitted leaves it unchanged; absent means the section continues the previous one. */\n start?: number;\n /** This section's page-number format (`w:fmt`) \u2014 e.g. `\"lowerRoman\"` for `i, ii, iii` front\n * matter. Omitted leaves it unchanged; absent means Word's default `1, 2, 3`. `\"bullet\"` is\n * rejected \u2014 pages cannot be bulleted. */\n format?: NumberFormat;\n}\n\n/**\n * Page geometry for {@link DocxSession.setPageSetup} \u2014 the `w:pgSz` / `w:pgMar` of the governing\n * `w:sectPr`, i.e. what Word's *Page Setup* dialog writes. Every field is tri-state: an omitted\n * field leaves that attribute exactly as it is. All values are twips (1440 = 1 inch). Read the\n * current values back from {@link SectionInfo}.\n *\n * Validation runs against the section's effective values after the op: width and height must be\n * positive, margins and header/footer distances non-negative, and `left + right < width`,\n * `top + bottom < height`; a violation fails with `invalid_page_setup` and touches nothing.\n */\nexport interface PageSetupOp {\n /** Page width (`w:pgSz/@w:w`). */\n pageWidthTwips?: number;\n /** Page height (`w:pgSz/@w:h`). */\n pageHeightTwips?: number;\n /** Orientation (`w:pgSz/@w:orient`). `true` writes `landscape` and \u2014 when no explicit size is\n * given and the page is currently taller than wide \u2014 swaps width and height; `false` removes\n * the attribute and swaps back when the page is wider than tall. With an explicit size only\n * the attribute is written. */\n landscape?: boolean;\n /** Top margin (`w:pgMar/@w:top`). */\n marginTopTwips?: number;\n /** Bottom margin (`w:pgMar/@w:bottom`). */\n marginBottomTwips?: number;\n /** Left margin (`w:pgMar/@w:left`). */\n marginLeftTwips?: number;\n /** Right margin (`w:pgMar/@w:right`). */\n marginRightTwips?: number;\n /** Header distance from the page's top edge (`w:pgMar/@w:header`). */\n headerDistanceTwips?: number;\n /** Footer distance from the page's bottom edge (`w:pgMar/@w:footer`). */\n footerDistanceTwips?: number;\n}\n\n/**\n * The browser editor's render profile, passed as one JSON object to the `RenderEditorHtml` /\n * `RenderEditorBlocksHtml` / `RenderEditorBlockHtml` bridge exports. Defaults match the editor's\n * first paint: `\"docx-\"`, no fabricated classes, continuous, scale 1, revisions and comments off.\n */\nexport interface EditorRenderOptions {\n /** CSS class prefix for the document's own classes. Default `\"docx-\"`. */\n cssPrefix?: string;\n /** Emit fabricated per-run CSS classes instead of inline styles. Default false. */\n fabricateClasses?: boolean;\n /** Paginated (page-box) output with headers/footers. Default false. Full-document render only. */\n paginated?: boolean;\n /** Pagination scale. Default 1. Full-document render only. */\n scale?: number;\n /** Render tracked changes as redlines instead of accepting them. Default false. */\n renderTrackedChanges?: boolean;\n /** Render native Word comments inline: `comment-highlight` spans carrying `data-comment-id`\n * around every run inside a comment range, `comment-marker` anchors at each reference. The\n * ids match {@link CommentListEntry.id}. Default false, which renders exactly as the\n * comment-less `RenderHtml` / `RenderBlockHtml` do. */\n comments?: boolean;\n}\n\n/** Options for `DocxSession.insertTable`. */\nexport interface TableInsertOptions {\n /** Emit an invisible layout table (explicit \"none\" borders) \u2014 the S-1 multi-column blocks. */\n borderless?: boolean;\n /** Row-major markdown for each cell (row 0 left\u2192right, then row 1, \u2026). Short/omitted \u21D2 empty cells. */\n cellContents?: string[];\n /** Alignment applied to every cell paragraph (S-1 columns are centered). */\n cellAlignment?: \"left\" | \"center\" | \"right\" | \"justify\";\n /** Per-column widths in twips (one per column, left\u2192right). Omit for equal columns; a list\n * whose length != the column count is rejected. Drives unequal layouts like the S-1's\n * wide-left / narrow-right filing-header row. */\n columnWidths?: number[];\n}\n\nexport type TableVerticalMergeRole = \"none\" | \"restart\" | \"continue\";\nexport type TableAnchorEntityKind = \"table\" | \"row\" | \"column\" | \"cell\";\n\nexport interface TableCellMetadata {\n anchor: AnchorRef;\n tableAnchorId: string;\n rowAnchorId: string;\n rowIndex: number;\n columnIndex: number;\n rowSpan: number;\n columnSpan: number;\n verticalMerge: TableVerticalMergeRole;\n /** Direct cell paragraphs only; nested-table paragraphs belong to their own cells. */\n paragraphAnchors: AnchorRef[];\n}\n\nexport interface TableRowMetadata {\n anchor: AnchorRef;\n tableAnchorId: string;\n rowIndex: number;\n gridBefore: number;\n gridAfter: number;\n cells: TableCellMetadata[];\n}\n\nexport interface TableColumnMetadata {\n anchor: AnchorRef;\n tableAnchorId: string;\n columnIndex: number;\n widthTwips: number;\n /** True when an absent/underspecified tblGrid required a read-only coordinate identity. */\n isVirtual: boolean;\n cellAnchorIds: string[];\n}\n\nexport interface TableMetadata {\n anchor: AnchorRef;\n columns: TableColumnMetadata[];\n rows: TableRowMetadata[];\n}\n\nexport interface TableMetadataResult {\n success: boolean;\n error?: EditError;\n metadata?: TableMetadata;\n}\n\nexport interface TableCellResolutionResult {\n success: boolean;\n error?: EditError;\n cell?: TableCellMetadata;\n}\n\nexport interface TableAnchorLocation {\n anchor: AnchorRef;\n entityKind: TableAnchorEntityKind;\n rowIndex?: number;\n columnIndex?: number;\n rowSpan?: number;\n columnSpan?: number;\n isVirtual?: boolean;\n}\n\nexport interface TableAnchorMapping {\n retained: { before: TableAnchorLocation; after: TableAnchorLocation }[];\n added: TableAnchorLocation[];\n invalidated: TableAnchorLocation[];\n}\n\nexport type TableRowHeightRule = \"auto\" | \"atLeast\" | \"exact\";\n\nexport interface TableRowOptions {\n repeatHeader?: boolean;\n allowBreakAcrossPages?: boolean;\n /** Zero removes an explicit height. */\n heightTwips?: number;\n heightRule?: TableRowHeightRule;\n}\n\n/** Which table edges `DocxSession.setTableBorders` targets: `\"outside\"` = top/left/bottom/right,\n * `\"inside\"` = the inner grid lines (`w:insideH`/`w:insideV`), `\"all\"` = both. */\nexport type TableBorderScope = \"all\" | \"outside\" | \"inside\";\n\n/** Shading granularity for `DocxSession.setCellShading`: the one cell the anchor sits in, or\n * every cell of its row (header-row banding). */\nexport type TableShadingScope = \"cell\" | \"row\";\n\n/** What `DocxSession.mergeCells` does with the content of the cells a merge absorbs:\n * `\"append\"` (default) moves their non-empty blocks into the surviving cell \u2014 lossless;\n * `\"discard\"` drops them; `\"reject\"` fails the merge (`invalid_table_merge`) when any absorbed\n * cell is non-empty. */\nexport type TableMergeContent = \"append\" | \"discard\" | \"reject\";\n\n/** Border specification for `DocxSession.setTableBorders`. Written as explicit `w:tblBorders`\n * edges (overriding style-inherited borders); edges outside `scope` are left untouched. */\nexport interface TableBorderSpec {\n /** Which edges to write. Default `\"all\"`. */\n scope?: TableBorderScope;\n /** Border line style (`w:val`): `\"single\"`, `\"double\"`, `\"thick\"`, `\"dotted\"`, `\"dashed\"`, \u2026 \u2014\n * or `\"none\"` to remove the targeted edges. Default `\"single\"`. */\n style?: string;\n /** Border weight in eighths of a point (`w:sz`). Default 4 (= 0.5pt). */\n size?: number;\n /** Border color as a hex RRGGBB triplet without '#', or `\"auto\"`. Default `\"auto\"`. */\n color?: string;\n}\n\nexport interface DocxSessionSettings {\n /**\n * Maximum undo steps retained. Default 20 (was 50).\n *\n * Each step is a full snapshot of every snapshot-scoped part, so this is a STEP count and not\n * a memory bound \u2014 the cost of one step scales with the document. Use `undoMemoryBudgetBytes`\n * to bound the heap.\n */\n undoDepth?: number;\n /**\n * Approximate ceiling, in bytes, on memory held by undo/redo snapshots. Default 134217728\n * (128 MiB). When exceeded the oldest history is discarded, so on a large document undo may\n * not reach the full `undoDepth`; one step is always retained. Set to 0 to bound by depth\n * alone (the pre-9.10 behavior).\n */\n undoMemoryBudgetBytes?: number;\n validateRawOps?: boolean;\n trackedChanges?: \"accept\" | \"render_inline\" | \"strip_deletions\";\n revisionAuthor?: string;\n /**\n * When false (default), `save()` strips the projector's internal `PtOpenXml:Unid`\n * attributes before serializing \u2014 they aren't OOXML schema, and persisting them\n * bloats large documents significantly (~700 KB on a 100-page DOCX). Set to true\n * only when anchor ids must survive a save/reopen round trip.\n */\n persistAnchorIds?: boolean;\n /**\n * When true, ReplaceText / ReplaceTextRange / ReplaceMatch payloads have ASCII\n * `\"` and `'` converted to typographic curly quotes (`\u201C \u201D \u2018 \u2019`) based on\n * context \u2014 open at start / after whitespace / after open-bracket, close\n * elsewhere. Avoids the cosmetic regression where a replacement lands as\n * straight-quoted text adjacent to surrounding already-curly text. Default false.\n */\n smartQuotes?: boolean;\n /**\n * When false, mutation EditResults omit the markdown patch and skip the per-op\n * scope re-projection that builds it \u2014 the fast path for clients that re-render\n * from HTML (the browser editor) rather than consuming markdown patches.\n * Default true.\n */\n emitMarkdownPatch?: boolean;\n /**\n * When `true` (default), the session projects the document at construction\n * time so {@link DocxSession.getDiff} can compare initial vs. current, and\n * retains the exact opening package for `getSemanticChanges()`.\n * Set to `false` to skip the upfront projection plus package-copy cost if you\n * do not plan to call either comparison API.\n */\n captureInitialProjection?: boolean;\n /**\n * Record the evidence a delivery change receipt needs as edits execute (issue #748): the\n * exact package before and after every version step, each batch's described request,\n * transaction ids, and undo/redo lineage. {@link DocxSession.buildDeliveryReceipt} then mints\n * a verifiable receipt. Default false: every version step serializes a clean package copy\n * and retention holds them (bounded: 256 states / 512 MiB) until delivery. Requires\n * `captureInitialProjection`.\n */\n captureDeliveryEvidence?: boolean;\n}\n\n/** One top-level render unit in a {@link RenderPlan}: a body block (`p`/`h`/`li`),\n * one whole table (`tbl`), or one footnote/endnote definition (`fn`/`en`). */\nexport interface RenderUnit {\n id: string;\n kind: string;\n /** Content signature for change detection (leaf blocks omit it). */\n sig?: string;\n /** Index of the section wrapper (`[data-section-index]`) the unit renders into. */\n section?: number;\n /** Ordinal of the border box the renderer groups adjacent bordered paragraphs into; units\n * sharing a group render inside one wrapper, so a windowed mount never splits one. */\n group?: number;\n}\n\n/** Ordered top-level render units per scope container \u2014 the authority for \"what\n * blocks exist, in what order\" that the incremental reconciler diffs against. */\nexport interface RenderPlan {\n body: RenderUnit[];\n footnotes: RenderUnit[];\n endnotes: RenderUnit[];\n}\n\n/** One footnote/endnote in citation order. `id` is the note's `w:id`; `ordinal`\n * is its 1-based citation position \u2014 which IS its displayed number. */\nexport interface NoteListEntry {\n id: string;\n defAnchorId: string;\n ordinal: number;\n}\n\nexport interface DocxSessionProjection {\n markdown: string;\n anchorIndex: Record<string, {\n partUri: string;\n unid: string;\n kind: string;\n scope: string;\n textPreview: string;\n }>;\n /** Present only when projectAnchor requested citations. */\n pageCitations?: Record<string, PageCitation>;\n}\n\nexport interface PageCitationRequest {\n documentVersion: number;\n rendererFingerprint: string;\n}\n\nexport type PageCitationUnavailableReason =\n | \"no_page_map\"\n | \"continuous_mode\"\n | \"stale_document_version\"\n | \"renderer_fingerprint_mismatch\"\n | \"anchor_not_mapped\";\n\nexport interface PageCitationFragment {\n fragmentId: string;\n anchorId: string;\n fragmentIndex: number;\n pageNumber: number;\n geometry: { x: number; y: number; width: number; height: number };\n story: \"body\" | \"header\" | \"footer\" | \"footnote\" | \"endnote\" | \"comment\";\n inTableCell: boolean;\n}\n\nexport interface PageCitationPage {\n pageNumber: number;\n pageInSection: number;\n width: number;\n height: number;\n sectionIndex?: number;\n pageName: string;\n}\n\nexport interface PageCitation {\n anchorId: string;\n availability: \"available\" | \"unavailable\";\n unavailableReason?: PageCitationUnavailableReason;\n documentVersion: number;\n rendererFingerprint: string;\n pages: PageCitationPage[];\n fragments: PageCitationFragment[];\n}\n\nexport interface PageMapRegistrationResult {\n success: boolean;\n error?: \"unsupported_schema_version\" | \"stale_document_version\" | \"renderer_fingerprint_mismatch\" | \"invalid_map\";\n message?: string;\n}\n\nexport interface PageMapStatus {\n availability: \"available\" | \"unavailable\";\n unavailableReason?: PageCitationUnavailableReason;\n documentVersion: number;\n rendererFingerprint?: string;\n mode?: \"paginated\" | \"continuous\";\n}\n\n/**\n * Per-fragment visible formatting reported by {@link DocxSession.grep}.\n */\nexport interface RunFormatting {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strike: boolean;\n code: boolean;\n color?: string;\n hyperlinkUrl?: string;\n runStyle?: string;\n}\n\n/**\n * One piece of a {@link TextMatch} that came from a single `<w:r>` run.\n */\nexport interface RunFragment {\n /** PtOpenXml:Unid of the `w:r` element this fragment came from. */\n unid: string;\n /** The text from this run that participates in the match. */\n text: string;\n /** Character offset + length of this fragment inside the run's flat text. */\n spanInElement: CharSpan;\n /** Visible formatting of the run this fragment came from. */\n formatting: RunFormatting;\n}\n\n/**\n * A single match returned by {@link DocxSession.grep}. The match always lives\n * within one block-level element.\n */\nexport interface TextMatch {\n text: string;\n enclosingAnchor: AnchorRef;\n span: CharSpan;\n fragments: RunFragment[];\n contextBefore: string;\n contextAfter: string;\n /** Regex capture groups; index 0 is always the whole match. */\n groups: string[];\n /** Present only when grep requested a citation for this exact render. */\n citation?: PageCitation;\n}\n\n/**\n * One block's contribution to a {@link CrossBlockMatch}. The slice's `fragments`\n * list is empty when the match touches an empty paragraph \u2014 the slice is still\n * recorded so callers can see the match crossed the empty block.\n */\nexport interface BlockSlice {\n anchor: AnchorRef;\n /** Character offset + length of the slice within the block's own flat text. */\n spanInBlock: CharSpan;\n /** Run fragments contributing to this slice, in document order. */\n fragments: RunFragment[];\n}\n\n/**\n * A single match returned by {@link DocxSession.grepCrossBlock}. The match may\n * span multiple adjacent block-level elements (paragraphs/headings/list items)\n * under the same parent container. `slices` is the per-block breakdown;\n * `enclosingAnchors` lists every block the match touches, in document order.\n *\n * Block boundaries appear in `text` / `contextBefore` / `contextAfter` as\n * single `\\n` characters.\n */\nexport interface CrossBlockMatch {\n text: string;\n enclosingAnchors: AnchorRef[];\n slices: BlockSlice[];\n contextBefore: string;\n contextAfter: string;\n /** Regex capture groups; index 0 is always the whole match. */\n groups: string[];\n /** One per enclosingAnchors entry when requested. */\n citations?: PageCitation[];\n}\n\n/**\n * Options for {@link DocxSession.insertCrossReference} \u2014 each flag is one of the REF\n * field's switches: `\\r` (reference the target's auto-number), `\\h` (hyperlink),\n * `\\p` (relative position, cached as \"above\"/\"below\").\n */\nexport interface CrossReferenceOptions {\n referenceNumber?: boolean;\n hyperlink?: boolean;\n includePosition?: boolean;\n}\n\n/**\n * Options for {@link DocxSession.replaceTextRange}.\n */\nexport interface ReplaceOptions {\n /** Case-insensitive matching for the literal `find` needle. */\n ignoreCase?: boolean;\n /** Cap the number of replacements; omitted = unlimited. */\n maxReplacements?: number;\n /** Require exactly this many occurrences before applying any replacement. */\n expectedMatchCount?: number;\n /** Optional document/anchor guards evaluated before searching. */\n preconditions?: MutationPreconditions;\n}\n\n/**\n * Categories of bracketed placeholders {@link DocxSession.findPlaceholders} recognizes.\n *\n * - `blank_fill` \u2014 `[___]` or `$[___]` value slots\n * - `alternative_clause` \u2014 `[entire clause text]`\n * - `instruction` \u2014 `[insert X]`, `[specify Y]`, `[*italicized hint*]`\n */\nexport type PlaceholderKind = \"blank_fill\" | \"alternative_clause\" | \"instruction\";\n\n/**\n * Numeric flag layout matching the .NET `PlaceholderKinds` enum. Combine with bitwise OR.\n */\nexport const PlaceholderKinds = {\n BlankFill: 1,\n AlternativeClause: 2,\n Instruction: 4,\n All: 7,\n} as const;\n\n/**\n * Numeric flag layout matching the .NET `DiffFormat` enum. Use with\n * {@link DocxSession.getDiff}.\n *\n * - `Json` (default) \u2014 anchor-keyed structured diff. Returns a `DiffEntry[]`.\n * - `Unified` \u2014 `patch(1)`-compatible unified diff over the markdown projection.\n * Returns a single string (`\"\"` when nothing changed).\n * - `SideBySide` \u2014 two-column human-review diff (`diff -y` style) over the\n * markdown projection. Returns a single string.\n */\nexport const DiffFormat = {\n Json: 0,\n Unified: 1,\n SideBySide: 2,\n} as const;\n\n/**\n * A single anchor-keyed change in the diff between an initial and current projection.\n */\nexport interface DiffEntry {\n op: \"delete\" | \"insert\" | \"modify\";\n anchorId: string;\n /** Pre-change text content for delete/modify; absent for insert. */\n before?: string;\n /** Post-change text content for insert/modify; absent for delete. */\n after?: string;\n}\n\n/**\n * Aggregate snapshot of edit-state introspection signals returned by\n * {@link DocxSession.getEditSummary}.\n */\nexport interface EditSummary {\n totalAnchors: number;\n remainingPlaceholders: TemplatePlaceholder[];\n bareUnderscoreRuns: TextMatch[];\n footnoteCount: number;\n inlineFootnoteRefCount: number;\n commentCount: number;\n}\n\n/**\n * Numeric flag layout matching the .NET `ContextBoundary` enum. Controls\n * how `Grep` / `GrepCrossBlock` / `FindPlaceholders` decide where to stop\n * walking outward when computing `TextMatch.contextBefore` / `contextAfter`.\n *\n * - `Char` (default) \u2014 truncate at `contextChars`. Matches legacy behavior.\n * - `Bracket` \u2014 stop at `[` or `]`. Use for template fills: each placeholder's\n * context is unambiguously its own even when multiple placeholders crowd\n * into one sentence.\n * - `Sentence` \u2014 stop at `.`, `!`, `?`, `:`, `;`.\n * - `Comma` \u2014 stop at `,`. For matches inside enumerations.\n */\nexport const ContextBoundary = {\n Char: 0,\n Bracket: 1,\n Sentence: 2,\n Comma: 3,\n} as const;\n\nexport interface TemplatePlaceholder {\n kind: PlaceholderKind;\n /** For `instruction` placeholders: the inner text with surrounding brackets/asterisks stripped. */\n hint?: string;\n match: TextMatch;\n /**\n * Additional plausible classifications when the primary `kind` is borderline.\n * Empty by default. The classic case is a long bracketed clause that happens\n * to contain a `_______` blank: primary `kind` stays `\"blank_fill\"`\n * (back-compat) and `alternativeKinds` contains `\"alternative_clause\"`.\n */\n alternativeKinds: PlaceholderKind[];\n}\n\n/**\n * Options for {@link DocxSession.fillPlaceholders}.\n */\nexport interface FillOptions {\n /** Which placeholder kinds to fill. Defaults to `PlaceholderKinds.All` so the\n * picker is invoked for every kind in the doc. Narrow with e.g.\n * `PlaceholderKinds.BlankFill | PlaceholderKinds.Instruction` to ignore\n * bracketed alternative clauses. */\n kinds?: number;\n /** Which package parts to scan. Defaults to body (1). */\n scope?: number;\n /** Max iteration passes for multi-pass nested-bracket scenarios. Default 8. */\n maxPasses?: number;\n /** When the match starts with `$` and the picker's return value doesn't,\n * preserve the `$` by prepending it. Default true. */\n preserveDollarPrefix?: boolean;\n /** Cap on `contextBefore` / `contextAfter` length on each side. Default 80. */\n contextChars?: number;\n /** Where to stop walking outward when computing context. Numeric layout\n * matching {@link ContextBoundary}. Default `Char` (0). */\n boundary?: number;\n /** When the picker returns an empty string (and after `$`-prefix preservation\n * has been applied), look at the chars immediately adjacent to the placeholder\n * span and absorb surrounding whitespace / leading-space-before-punctuation /\n * matched-brackets so the dropped placeholder doesn't leave cosmetic\n * artifacts. Default `false` (preserve the literal-delete behavior).\n *\n * Rules: whitespace on both sides collapses to one space; whitespace before\n * and clause-terminating punctuation (`. , ; : ! ?`) after drops the leading\n * space; matched open/close brackets (`()` `[]` `{}`) on either side drop\n * both. NBSP / narrow NBSP / thin space are treated as whitespace.\n *\n * Caveat: `$`-prefix preservation runs first, so a picker returning `\"\"` for\n * `$[xxx]` with `preserveDollarPrefix: true` (default) ends up replacing with\n * `\"$\"` and coalescing is skipped. Set `preserveDollarPrefix: false` when you\n * want the `$` to drop along with the brackets. */\n coalesceWhitespaceAroundEmptyFill?: boolean;\n}\n\n/**\n * Aggregate result returned by {@link DocxSession.fillPlaceholders}.\n *\n * `skipped` counts placeholders the picker returned null for in the first pass\n * that saw them \u2014 it stays > 0 even if later passes finished those same\n * placeholders. Use `stillPresent` (post-loop document state) for the\n * trustworthy \"is the template done?\" check; `skipped > 0 && stillPresent === 0`\n * means \"picker said no the first time but later passes resolved it.\"\n */\nexport interface BulkEditResult {\n filled: number;\n skipped: number;\n /** Number of placeholders matching `options.kinds` in `options.scope` that\n * remain in the document after the final pass. `0` means the template is\n * fully filled for the requested kinds/scope. */\n stillPresent: number;\n passes: number;\n unfilled: TemplatePlaceholder[];\n errors: EditError[];\n}\n\n/**\n * Options for {@link DocxSession.grep}.\n *\n * `regexOptions` and `scope` use the numeric flag layouts of the .NET\n * `System.Text.RegularExpressions.RegexOptions` and `ProjectionScopes` enums.\n * Common values:\n * - `RegexOptions.IgnoreCase = 1`\n * - `RegexOptions.Multiline = 2`\n * - `ProjectionScopes.Body = 1`, `Headers = 2`, `Footers = 4`,\n * `Footnotes = 8`, `Endnotes = 16`, `Comments = 32`, `All = 63`.\n */\nexport interface GrepOptions {\n regexOptions?: number;\n scope?: number;\n contextChars?: number;\n /**\n * Whitespace handling. Numeric layout matching the .NET `WhitespaceMode` enum:\n * - 0 = Preserve (default; match against the document's original characters)\n * - 1 = Normalize (fold NBSP / narrow-NBSP / thin-space to ASCII space before matching)\n */\n whitespace?: number;\n /**\n * Where to stop walking outward when computing `TextMatch.contextBefore` /\n * `contextAfter`. Numeric layout matching the .NET `ContextBoundary` enum;\n * use the {@link ContextBoundary} const. Default `Char` (0) \u2014 truncate at\n * `contextChars`.\n */\n boundary?: number;\n /** Attach citations only if this exact registered layout is still valid. */\n citation?: PageCitationRequest;\n /** Return at most this many matches, in document order. Omitted returns them all. */\n maxResults?: number;\n}\n\n/**\n * Narrows {@link DocxSession.listRevisions} to the entries matching every field set here.\n * `author`, `changeType` (the entry's `type`), `family` and `resolutionStatus` ignore case;\n * `partUri` is exact.\n */\nexport interface RevisionListFilter {\n author?: string;\n changeType?: string;\n family?: string;\n resolutionStatus?: string;\n partUri?: string;\n}\n\n/**\n * Options that tune the `findBy*` helpers on {@link DocxSession}. Mirrors the\n * .NET `FindOptions` record; wire keys are already camelCase, so this object is\n * serialized straight to the bridge. Omit it (or pass `{}`) for the defaults\n * (case-sensitive, whitespace-preserving, all scopes, no kind filter).\n */\nexport interface FindOptions {\n /** Case-insensitive matching. */\n ignoreCase?: boolean;\n /** Fold NBSP / narrow-NBSP / thin-space to ASCII space before matching. */\n ignoreWhitespace?: boolean;\n /** Only return anchors of this kind (e.g. `\"h\"` for headings, `\"p\"` for paragraphs). */\n kindFilter?: string;\n /**\n * Coarse-grained scope flag set (Body / Headers / Footers / Footnotes /\n * Endnotes / Comments). Numeric layout matching the .NET `ProjectionScopes`\n * flags enum; use {@link ProjectionScopes}. Defaults to all scopes.\n */\n scopes?: number;\n /**\n * Target a single named package part (e.g. `\"hdr1\"`). Prefer {@link scopes}\n * for whole-category filtering; this is for the rare single-part case.\n */\n scopeFilter?: string;\n /** Attach citations only if this exact registered layout is still valid. */\n citation?: PageCitationRequest;\n}\n\n/**\n * Resolved location of an anchor \u2014 what {@link DocxSession.findByAnnotation} and\n * the other discovery helpers return. The shape is {@link AnchorRef} plus the\n * `partUri` of the package part the element lives in (useful for callers that\n * walk the underlying OOXML directly).\n */\nexport interface AnchorTargetRef extends AnchorRef {\n partUri: string;\n /** First ~80 characters of the element's flat text \u2014 for previewing/picking anchors. */\n textPreview: string;\n /** Resolved auto-numbering prefix (e.g. \"1.\", \"First\") when the element carries\n * numbering. Absent otherwise. See {@link MarkdownAnchorTarget.autoNumberPrefix}. */\n autoNumberPrefix?: string;\n /** Present only when the discovery call requested an exact page citation. */\n citation?: PageCitation;\n}\n\n/**\n * The shape returned by {@link DocxSession.getAnchorInfo}.\n * Use {@link MarkdownAnchorTarget} when iterating a full projection \u2014 it\n * includes the same fields plus `unid` and `partUri`.\n */\nexport interface AnchorInfo {\n id: string;\n kind: string;\n scope: string;\n textPreview: string;\n /** Exact live subtree hash suitable for expectedContentHash. */\n contentHash: string;\n /** Exact (untruncated) reader-visible text suitable for expectedText. */\n visibleText: string;\n /** Resolved auto-numbering prefix (e.g. \"1.\", \"First\") when the element carries\n * numbering. Absent for un-numbered paragraphs or non-paragraph kinds. */\n autoNumberPrefix?: string;\n}\n\n/** Six list formats supported by the list write surface (decimal, upperLetter,\n * lowerLetter, upperRoman, lowerRoman, bullet). Surfaced on\n * {@link ListMembership.format} as a string union (mirrors the JSON wire format). */\nexport type NumberFormat =\n | \"decimal\"\n | \"upperLetter\"\n | \"lowerLetter\"\n | \"upperRoman\"\n | \"lowerRoman\"\n | \"bullet\";\n\n/** Numbering facts for a list-item paragraph. Returned by\n * {@link DocxSession.getListMembership} and surfaced as {@link BlockMetadata.list}. */\nexport interface ListMembership {\n /** Stable paragraph anchor accepted unchanged by every list mutation method. */\n anchorId: string;\n /** The w:numId the paragraph belongs to (the w:num instance). */\n numId: number;\n /** The w:abstractNumId the paragraph's w:num points at. */\n abstractNumId: number;\n /** The paragraph's level (w:ilvl), 0-8. */\n level: number;\n /** Resolved format for this level. */\n format: NumberFormat;\n /** Always true for a paragraph carrying w:numPr (inline or via style). */\n isAutoNumbered: boolean;\n /** True when the w:numPr is inherited from the paragraph's style chain. */\n fromStyle: boolean;\n /** Start-override from w:lvlOverride/w:startOverride for this level, if any. */\n startOverride?: number;\n /** Level definition's w:start value (1 when omitted). */\n start: number;\n /** Marker template such as \"%1.\" or \"(%2)\". */\n levelText?: string;\n leftIndentTwips?: number;\n rightIndentTwips?: number;\n firstLineIndentTwips?: number;\n hangingIndentTwips?: number;\n /** Resolved label (e.g. \"1.\", \"(a)\") \u2014 same value surfaced via AnchorInfo.autoNumberPrefix. */\n generatedLabel?: string;\n}\n\n/** Block-level structural metadata. Returned by {@link DocxSession.getBlockMetadata}. */\nexport interface BlockMetadata {\n anchorId: string;\n kind: string;\n scope: string;\n styleId?: string;\n styleName?: string;\n /** 0-based outline level (Word convention). */\n outlineLevel?: number;\n list?: ListMembership;\n /** True when any descendant w:r carries a non-empty w:rPr. */\n hasInlineFormatting: boolean;\n}\n\n/**\n * A `w:headerReference`/`w:footerReference` on a section: the story kind it supplies and the\n * URI of the part holding it. Maps a {@link HeaderFooterKind} to a part \u2014 and thence to that\n * part's projection anchors, which carry the same `partUri` \u2014 instead of guessing from\n * part-collection order, which carries no kind information.\n */\nexport interface HeaderFooterRef {\n kind: HeaderFooterKind;\n partUri: string;\n /** True when this section declares no reference of `kind` and the story is INHERITED from the\n * nearest preceding section that does (ECMA-376 \u00A717.6.17). Editing it edits the shared part. */\n inherited: boolean;\n}\n\n/** Page-layout snapshot for the w:sectPr that governs an anchor.\n * Returned by {@link DocxSession.getSectionInfo}. */\nexport interface SectionInfo {\n /** Body anchor used for the lookup; accepted unchanged by section mutation methods. */\n anchorId: string;\n sectionUnid: string;\n pageWidthTwips: number;\n pageHeightTwips: number;\n landscape: boolean;\n marginTopTwips: number;\n marginBottomTwips: number;\n marginLeftTwips: number;\n marginRightTwips: number;\n /** Header distance from the page's top edge (`w:pgMar/@w:header`); Word's default 720 when\n * the attribute is absent. */\n headerDistanceTwips: number;\n /** Footer distance from the page's bottom edge (`w:pgMar/@w:footer`); Word's default 720 when\n * the attribute is absent. */\n footerDistanceTwips: number;\n /** Word's \"Different first page\" flag \u2014 true when the governing `w:sectPr` carries an\n * on-valued `w:titlePg`, so the section's first-page stories actually render. Toggle with\n * {@link DocxSession.setHeaderFooterKindEnabled}. */\n titlePage: boolean;\n /** Word's \"Different odd & even pages\" flag \u2014 true when the settings part carries an\n * on-valued `w:evenAndOddHeaders`. Document-global, so every section reports the same\n * value. Toggle with {@link DocxSession.setHeaderFooterKindEnabled}. */\n evenAndOddHeaders: boolean;\n columns: number;\n headerPartUris: string[];\n footerPartUris: string[];\n /** Header references in declaration order, each with its `w:type`. Describes exactly the\n * parts {@link SectionInfo.headerPartUris} lists, plus the kind each supplies. */\n headerRefs: HeaderFooterRef[];\n /** Footer references in declaration order, each with its `w:type`. Describes exactly the\n * parts {@link SectionInfo.footerPartUris} lists, plus the kind each supplies. */\n footerRefs: HeaderFooterRef[];\n /** The page number this section starts at (`w:pgNumType/@w:start`). Absent when the section\n * continues the previous section's numbering. */\n pageNumberStart?: number;\n /** This section's page-number format (`w:pgNumType/@w:fmt`). Absent means Word's default\n * `1, 2, 3` \u2014 deliberately not reported as `\"decimal\"`, so a UI can tell \"inherits\" from\n * \"explicitly decimal\" and avoid writing an attribute the document never had. */\n pageNumberFormat?: NumberFormat;\n}\n\n/** High-signal paragraph properties. Optional fields are deliberately absent when a\n * direct formatting layer did not write them; effective layers include schema defaults. */\nexport interface ParagraphFormatting {\n styleId?: string;\n alignment?: \"left\" | \"center\" | \"right\" | \"justify\";\n leftIndentTwips?: number;\n rightIndentTwips?: number;\n firstLineIndentTwips?: number;\n hangingIndentTwips?: number;\n spacingBeforeTwips?: number;\n spacingAfterTwips?: number;\n lineSpacing?: number;\n lineSpacingRule?: LineSpacingRule;\n keepNext?: boolean;\n keepLines?: boolean;\n pageBreakBefore?: boolean;\n outlineLevel?: number;\n shadingFill?: string;\n topBorder?: ParagraphBorderEdge;\n bottomBorder?: ParagraphBorderEdge;\n}\n\n/** High-signal character properties. Nullable-at-source fields are optional on the wire so\n * an absent direct property remains distinguishable from an explicit false/zero. */\nexport interface RunFormattingInfo {\n styleId?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n underlineStyle?: string;\n strike?: boolean;\n code?: boolean;\n color?: string;\n highlight?: string;\n vertAlign?: string;\n fontSizePts?: number;\n fontFamily?: string;\n caps?: boolean;\n smallCaps?: boolean;\n hidden?: boolean;\n}\n\nexport interface TableStyleFormatting {\n alignment?: string;\n widthTwips?: number;\n indentTwips?: number;\n layout?: string;\n hasBorders?: boolean;\n cellShadingFill?: string;\n}\n\n/** One explicit document style. `id` is accepted unchanged by paragraph/run style mutations. */\nexport interface StyleInfo {\n id: string;\n name: string;\n type: \"paragraph\" | \"character\" | \"table\" | \"numbering\" | string;\n basedOn?: string;\n next?: string;\n isDefault: boolean;\n isCustom: boolean;\n hasLatentException: boolean;\n uiPriority?: number;\n semiHidden?: boolean;\n unhideWhenUsed?: boolean;\n quickFormat?: boolean;\n locked?: boolean;\n resolvedParagraph?: ParagraphFormatting;\n resolvedRun?: RunFormattingInfo;\n resolvedTable?: TableStyleFormatting;\n}\n\n/** One text-bearing run. `anchorId` + `span` can be passed unchanged to applyFormat. */\nexport interface InlineSpan {\n anchorId: string;\n runUnid: string;\n span: CharSpan;\n text: string;\n direct: RunFormattingInfo;\n effective: RunFormattingInfo;\n /** Outer-to-inner native content controls containing this run. */\n contentControlAnchorIds: string[];\n}\n\n/** Explicitly separated direct and effective formatting for one paragraph anchor. */\nexport interface FormattingInspection {\n anchorId: string;\n directParagraph: ParagraphFormatting;\n effectiveParagraph: ParagraphFormatting;\n runs: InlineSpan[];\n}\n\n/**\n * A custom annotation persisted in the document via Docxodus' annotation system.\n * Returned by {@link DocxSession.listAnnotations}; mirrors the wire-relevant\n * fields of the .NET `DocumentAnnotation` type. The page-info cache fields\n * (`startPage`/`endPage`/`pageInfoStale`/`pageInfoComputedAt`) are omitted to\n * keep the JSON payload compact \u2014 callers that need them can use the .NET API\n * directly. The `metadata` bag is emitted only when non-empty.\n *\n * See `docs/architecture/custom_annotations.md` for the persistence design.\n */\nexport interface DocumentAnnotation {\n /** Unique annotation identifier (caller-supplied at add time). */\n id: string;\n /** Label category/type (e.g. `\"INDEMNIFICATION\"`, `\"CLAUSE_TYPE_A\"`). */\n labelId: string;\n /** Human-readable label text displayed in the UI. */\n label: string;\n /** Highlight color in hex (e.g. `\"#FFEB3B\"`). */\n color: string;\n /** Internal bookmark name in the DOCX (`_Docxodus_Ann_{id}` for managed annotations). */\n bookmarkName: string;\n /** Author who created the annotation, if recorded. */\n author?: string;\n /** Creation timestamp in ISO-8601 (round-trip) format, if recorded. */\n created?: string;\n /** The text content covered by the annotation's bookmark, populated when reading. */\n annotatedText?: string;\n /** Arbitrary string\u2192string metadata bag persisted with the annotation. */\n metadata?: Record<string, string>;\n}\n\n/**\n * Partial-update payload for {@link DocxSession.updateAnnotation}.\n * Null/missing fields leave the existing value unchanged. `metadataPatch`\n * is a per-key merge: a non-null value sets the key, an explicit `null`\n * removes it, a missing key leaves it unchanged.\n */\nexport interface AnnotationUpdate {\n labelId?: string;\n label?: string;\n color?: string;\n author?: string;\n metadataPatch?: Record<string, string | null>;\n}\n\n/**\n * Severity level for comparison log entries.\n */\nexport enum ComparisonLogLevel {\n /** Informational message about the comparison process */\n Info = \"Info\",\n /** Warning about a potential issue that didn't prevent comparison */\n Warning = \"Warning\",\n /** Error that may affect comparison results but didn't stop processing */\n Error = \"Error\",\n}\n\n\n\n\n/**\n * Well-known log entry codes used by the comparison engine.\n */\nexport const ComparisonLogCodes = {\n /** A footnote reference in the document body has no corresponding footnote definition */\n OrphanedFootnoteReference: \"ORPHANED_FOOTNOTE_REFERENCE\",\n /** An endnote reference in the document body has no corresponding endnote definition */\n OrphanedEndnoteReference: \"ORPHANED_ENDNOTE_REFERENCE\",\n /** A style referenced in the document is not defined in styles.xml */\n MissingStyle: \"MISSING_STYLE\",\n /** A numbering definition referenced in the document is missing */\n MissingNumberingDefinition: \"MISSING_NUMBERING_DEFINITION\",\n /** A relationship referenced in the document is missing */\n MissingRelationship: \"MISSING_RELATIONSHIP\",\n /** An image or media file referenced in the document is missing */\n MissingMedia: \"MISSING_MEDIA\",\n /** The document structure contains unexpected or malformed XML */\n MalformedXml: \"MALFORMED_XML\",\n /** A bookmark reference has no corresponding bookmark start/end */\n OrphanedBookmark: \"ORPHANED_BOOKMARK\",\n} as const;\n\n\n/**\n * A custom annotation on a document range.\n */\nexport interface Annotation {\n /** Unique annotation ID */\n id: string;\n /** Label category/type identifier (e.g., \"CLAUSE_TYPE_A\", \"DATE_REF\") */\n labelId: string;\n /** Human-readable label text */\n label: string;\n /** Highlight color in hex format (e.g., \"#FFEB3B\") */\n color: string;\n /** Author who created the annotation */\n author?: string;\n /** Creation timestamp (ISO 8601) */\n created?: string;\n /** Internal bookmark name */\n bookmarkName?: string;\n /** Start page number (if computed) */\n startPage?: number;\n /** End page number (if computed) */\n endPage?: number;\n /** The annotated text content */\n annotatedText?: string;\n /** Custom metadata key-value pairs */\n metadata?: Record<string, string>;\n}\n\n/**\n * Request to add an annotation to a document.\n */\nexport interface AddAnnotationRequest {\n /** Unique annotation ID */\n id: string;\n /** Label category/type identifier */\n labelId: string;\n /** Human-readable label text */\n label: string;\n /** Highlight color in hex format (default: \"#FFEB3B\") */\n color?: string;\n /** Author who created the annotation */\n author?: string;\n /** Text to search for and annotate */\n searchText?: string;\n /** Which occurrence to annotate (1-based, default: 1) */\n occurrence?: number;\n /** Start paragraph index (0-based) */\n startParagraphIndex?: number;\n /** End paragraph index (0-based, inclusive) */\n endParagraphIndex?: number;\n /** Custom metadata key-value pairs */\n metadata?: Record<string, string>;\n}\n\n/**\n * Response from adding an annotation.\n */\nexport interface AddAnnotationResponse {\n /** Whether the operation succeeded */\n success: boolean;\n /** The modified document as base64 string */\n documentBytes: string;\n /** The added annotation details */\n annotation?: Annotation;\n}\n\n/**\n * Response from removing an annotation.\n */\nexport interface RemoveAnnotationResponse {\n /** Whether the operation succeeded */\n success: boolean;\n /** The modified document as base64 string */\n documentBytes: string;\n}\n\n/**\n * Options for annotation rendering in HTML output.\n */\nexport interface AnnotationOptions {\n /** Whether to render annotations (default: false) */\n renderAnnotations?: boolean;\n /** How to display annotation labels (default: Above) */\n annotationLabelMode?: AnnotationLabelMode;\n /** CSS class prefix for annotation elements (default: \"annot-\") */\n annotationCssClassPrefix?: string;\n}\n\n// ============================================================================\n// Document Structure Types (for element-based annotation targeting)\n// ============================================================================\n\n/**\n * Document element types that can be annotated.\n */\nexport enum DocumentElementType {\n /** Root document element */\n Document = \"Document\",\n /** A paragraph (w:p) */\n Paragraph = \"Paragraph\",\n /** A run within a paragraph (w:r) */\n Run = \"Run\",\n /** A table (w:tbl) */\n Table = \"Table\",\n /** A table row (w:tr) */\n TableRow = \"TableRow\",\n /** A table cell (w:tc) */\n TableCell = \"TableCell\",\n /** A virtual table column (not a real OOXML element) */\n TableColumn = \"TableColumn\",\n /** A hyperlink (w:hyperlink) */\n Hyperlink = \"Hyperlink\",\n /** An image/drawing (w:drawing) */\n Image = \"Image\",\n}\n\n/**\n * A document element in the structure tree.\n */\nexport interface DocumentElement {\n /** Unique element ID (path-based, e.g., \"doc/tbl-0/tr-1/tc-2\") */\n id: string;\n /** Canonical session anchor when this element is addressable. */\n anchorId?: string;\n /** Element type */\n type: DocumentElementType | string;\n /** Preview of text content (first ~100 characters) */\n textPreview?: string;\n /** Position index within parent element */\n index: number;\n /** Child elements */\n children: DocumentElement[];\n /** For table rows/cells: the row index */\n rowIndex?: number;\n /** For table cells: the column index */\n columnIndex?: number;\n /** For table cells: number of rows this cell spans */\n rowSpan?: number;\n /** For table cells: number of columns this cell spans */\n columnSpan?: number;\n}\n\n/**\n * Information about a table column.\n */\nexport interface TableColumnInfo {\n /** ID of the table this column belongs to */\n tableId: string;\n /** Canonical `col` anchor. */\n anchorId: string;\n /** Canonical owning `tbl` anchor. */\n tableAnchorId: string;\n isVirtual: boolean;\n /** Zero-based column index */\n columnIndex: number;\n /** IDs of all cells in this column */\n cellIds: string[];\n /** Canonical `tc` anchors for cells covering this column. */\n cellAnchorIds: string[];\n /** Total number of rows in this column */\n rowCount: number;\n}\n\n/**\n * Document structure analysis result.\n */\nexport interface DocumentStructure {\n /** Root document element */\n root: DocumentElement;\n /** All elements indexed by ID for quick lookup */\n elementsById: Record<string, DocumentElement>;\n /** Table column information indexed by column ID */\n tableColumns: Record<string, TableColumnInfo>;\n}\n\n/**\n * Target specification for element-based annotation.\n * Supports multiple targeting modes: element ID, indices, or text search.\n */\nexport interface AnnotationTarget {\n /** Target by element ID (e.g., \"doc/p-0/r-1\") */\n elementId?: string;\n /** Element type for index-based targeting */\n elementType?: DocumentElementType | string;\n /** Paragraph index (0-based) */\n paragraphIndex?: number;\n /** Run index within paragraph (0-based) */\n runIndex?: number;\n /** Table index (0-based) */\n tableIndex?: number;\n /** Row index within table (0-based) */\n rowIndex?: number;\n /** Cell index within row (0-based) */\n cellIndex?: number;\n /** Column index for table column targeting (0-based) */\n columnIndex?: number;\n /** Text to search for (global or within elementId) */\n searchText?: string;\n /** Which occurrence of searchText to target (1-based, default: 1) */\n occurrence?: number;\n /** End paragraph index for range targeting */\n rangeEndParagraphIndex?: number;\n}\n\n/**\n * Request to add an annotation using flexible targeting.\n */\nexport interface AddAnnotationWithTargetRequest {\n /** Unique annotation ID */\n id: string;\n /** Label category/type identifier */\n labelId: string;\n /** Human-readable label text */\n label: string;\n /** Highlight color in hex format (default: \"#FFEB3B\") */\n color?: string;\n /** Author who created the annotation */\n author?: string;\n /** Custom metadata key-value pairs */\n metadata?: Record<string, string>;\n /** Target specification */\n target: AnnotationTarget;\n}\n\n// ============================================================================\n// Helper functions for document structure navigation\n// ============================================================================\n\n/**\n * Find an element by ID in the document structure.\n * @param structure - The document structure\n * @param elementId - The element ID to find\n * @returns The element or undefined if not found\n */\nexport function findElementById(\n structure: DocumentStructure,\n elementId: string\n): DocumentElement | undefined {\n return structure.elementsById[elementId];\n}\n\n/**\n * Find all elements of a specific type in the document structure.\n * @param structure - The document structure\n * @param type - The element type to find\n * @returns Array of matching elements\n */\nexport function findElementsByType(\n structure: DocumentStructure,\n type: DocumentElementType | string\n): DocumentElement[] {\n return Object.values(structure.elementsById).filter(\n (el) => el.type === type\n );\n}\n\n/**\n * Get all paragraphs from the document structure.\n * @param structure - The document structure\n * @returns Array of paragraph elements\n */\nexport function getParagraphs(\n structure: DocumentStructure\n): DocumentElement[] {\n return findElementsByType(structure, DocumentElementType.Paragraph);\n}\n\n/**\n * Get all tables from the document structure.\n * @param structure - The document structure\n * @returns Array of table elements\n */\nexport function getTables(structure: DocumentStructure): DocumentElement[] {\n return findElementsByType(structure, DocumentElementType.Table);\n}\n\n/**\n * Get column information for a specific table.\n * @param structure - The document structure\n * @param tableId - The table ID\n * @returns Array of column info objects sorted by column index\n */\nexport function getTableColumns(\n structure: DocumentStructure,\n tableId: string\n): TableColumnInfo[] {\n return Object.values(structure.tableColumns)\n .filter((col) => col.tableId === tableId)\n .sort((a, b) => a.columnIndex - b.columnIndex);\n}\n\n/**\n * Create an annotation target for an element by ID.\n * @param elementId - The element ID (e.g., \"doc/p-0\", \"doc/tbl-0/tr-1/tc-2\")\n * @returns AnnotationTarget object\n */\nexport function targetElement(elementId: string): AnnotationTarget {\n return { elementId };\n}\n\n/**\n * Create an annotation target for a paragraph by index.\n * @param paragraphIndex - Zero-based paragraph index\n * @returns AnnotationTarget object\n */\nexport function targetParagraph(paragraphIndex: number): AnnotationTarget {\n return {\n elementType: DocumentElementType.Paragraph,\n paragraphIndex,\n };\n}\n\n/**\n * Create an annotation target for a range of paragraphs.\n * @param startIndex - Zero-based start paragraph index\n * @param endIndex - Zero-based end paragraph index\n * @returns AnnotationTarget object\n */\nexport function targetParagraphRange(\n startIndex: number,\n endIndex: number\n): AnnotationTarget {\n return {\n elementType: DocumentElementType.Paragraph,\n paragraphIndex: startIndex,\n rangeEndParagraphIndex: endIndex,\n };\n}\n\n/**\n * Create an annotation target for a specific run within a paragraph.\n * @param paragraphIndex - Zero-based paragraph index\n * @param runIndex - Zero-based run index within the paragraph\n * @returns AnnotationTarget object\n */\nexport function targetRun(\n paragraphIndex: number,\n runIndex: number\n): AnnotationTarget {\n return {\n elementType: DocumentElementType.Run,\n paragraphIndex,\n runIndex,\n };\n}\n\n/**\n * Create an annotation target for a table by index.\n * @param tableIndex - Zero-based table index\n * @returns AnnotationTarget object\n */\nexport function targetTable(tableIndex: number): AnnotationTarget {\n return {\n elementType: DocumentElementType.Table,\n tableIndex,\n };\n}\n\n/**\n * Create an annotation target for a table row.\n * @param tableIndex - Zero-based table index\n * @param rowIndex - Zero-based row index within the table\n * @returns AnnotationTarget object\n */\nexport function targetTableRow(\n tableIndex: number,\n rowIndex: number\n): AnnotationTarget {\n return {\n elementType: DocumentElementType.TableRow,\n tableIndex,\n rowIndex,\n };\n}\n\n/**\n * Create an annotation target for a table cell.\n * @param tableIndex - Zero-based table index\n * @param rowIndex - Zero-based row index\n * @param cellIndex - Zero-based cell index within the row\n * @returns AnnotationTarget object\n */\nexport function targetTableCell(\n tableIndex: number,\n rowIndex: number,\n cellIndex: number\n): AnnotationTarget {\n return {\n elementType: DocumentElementType.TableCell,\n tableIndex,\n rowIndex,\n cellIndex,\n };\n}\n\n/**\n * Create an annotation target for a table column (all cells in that column).\n * @param tableIndex - Zero-based table index\n * @param columnIndex - Zero-based column index\n * @returns AnnotationTarget object\n */\nexport function targetTableColumn(\n tableIndex: number,\n columnIndex: number\n): AnnotationTarget {\n return {\n elementType: DocumentElementType.TableColumn,\n tableIndex,\n columnIndex,\n };\n}\n\n/**\n * Create an annotation target by text search.\n * @param searchText - Text to search for\n * @param occurrence - Which occurrence to target (1-based, default: 1)\n * @returns AnnotationTarget object\n */\nexport function targetSearch(\n searchText: string,\n occurrence: number = 1\n): AnnotationTarget {\n return { searchText, occurrence };\n}\n\n/**\n * Create an annotation target to search text within a specific element.\n * @param elementId - The element ID to search within\n * @param searchText - Text to search for\n * @param occurrence - Which occurrence to target (1-based, default: 1)\n * @returns AnnotationTarget object\n */\nexport function targetSearchInElement(\n elementId: string,\n searchText: string,\n occurrence: number = 1\n): AnnotationTarget {\n return { elementId, searchText, occurrence };\n}\n\n// ============================================================================\n// Document Metadata Types (Phase 3: Lazy Loading)\n// ============================================================================\n\n/**\n * Metadata for a single section in the document.\n *\n * ## Units\n * All dimension values are in **points** (1 point = 1/72 inch).\n *\n * Common page sizes in points:\n * - **US Letter**: 612 \u00D7 792 pt (8.5\" \u00D7 11\")\n * - **A4**: 595 \u00D7 842 pt (210mm \u00D7 297mm)\n * - **Legal**: 612 \u00D7 1008 pt (8.5\" \u00D7 14\")\n *\n * To convert points to other units:\n * - Points to inches: `pt / 72`\n * - Points to mm: `pt / 72 * 25.4`\n * - Points to pixels (96 DPI): `pt * 96 / 72` (or `pt * 1.333...`)\n *\n * @example\n * ```typescript\n * const section = metadata.sections[0];\n * // US Letter: pageWidthPt = 612, pageHeightPt = 792\n *\n * // Convert to inches\n * const widthInches = section.pageWidthPt / 72; // 8.5\n *\n * // Convert to pixels at 96 DPI\n * const widthPx = section.pageWidthPt * 96 / 72; // 816\n * ```\n */\nexport interface SectionMetadata {\n /** Section index (0-based, sequential across document) */\n sectionIndex: number;\n /** Page width in points (1 pt = 1/72 inch). US Letter = 612pt, A4 \u2248 595pt */\n pageWidthPt: number;\n /** Page height in points (1 pt = 1/72 inch). US Letter = 792pt, A4 \u2248 842pt */\n pageHeightPt: number;\n /** Top margin in points. Default is typically 72pt (1 inch) */\n marginTopPt: number;\n /** Right margin in points. Default is typically 72pt (1 inch) */\n marginRightPt: number;\n /** Bottom margin in points. Default is typically 72pt (1 inch) */\n marginBottomPt: number;\n /** Left margin in points. Default is typically 72pt (1 inch) */\n marginLeftPt: number;\n /** Content width in points (pageWidthPt - marginLeftPt - marginRightPt) */\n contentWidthPt: number;\n /** Content height in points (pageHeightPt - marginTopPt - marginBottomPt) */\n contentHeightPt: number;\n /** Header distance from page top in points. Default is typically 36pt (0.5 inch) */\n headerPt: number;\n /** Footer distance from page bottom in points. Default is typically 36pt (0.5 inch) */\n footerPt: number;\n /** Number of paragraphs in this section (includes paragraphs inside tables) */\n paragraphCount: number;\n /** Number of top-level tables in this section */\n tableCount: number;\n /** Whether this section has a default header (w:headerReference type=\"default\") */\n hasHeader: boolean;\n /** Whether this section has a default footer (w:footerReference type=\"default\") */\n hasFooter: boolean;\n /** Whether this section has a first page header (requires titlePg element) */\n hasFirstPageHeader: boolean;\n /** Whether this section has a first page footer (requires titlePg element) */\n hasFirstPageFooter: boolean;\n /** Whether this section has an even page header (for different even/odd headers) */\n hasEvenPageHeader: boolean;\n /** Whether this section has an even page footer (for different even/odd footers) */\n hasEvenPageFooter: boolean;\n /** Start paragraph index (0-based, global across document). Inclusive. */\n startParagraphIndex: number;\n /** End paragraph index (global across document). Exclusive - use `endParagraphIndex - startParagraphIndex` for count. */\n endParagraphIndex: number;\n /** Start table index (0-based, global across document). Inclusive. */\n startTableIndex: number;\n /** End table index (global across document). Exclusive - use `endTableIndex - startTableIndex` for count. */\n endTableIndex: number;\n}\n\n/**\n * Document metadata for lazy loading pagination.\n * Provides fast access to document structure without full HTML rendering.\n *\n * This is significantly faster than full HTML conversion and is designed for:\n * - Lazy loading / virtual scrolling of large documents\n * - Pre-calculating pagination layouts\n * - Document feature detection before rendering\n *\n * @example\n * ```typescript\n * const metadata = await getDocumentMetadata(docxFile);\n *\n * // Check document features before rendering\n * if (metadata.hasTrackedChanges) {\n * console.log('Document has tracked changes');\n * }\n *\n * // Calculate total content for lazy loading\n * const totalSections = metadata.sections.length;\n * const firstPageWidth = metadata.sections[0].pageWidthPt;\n *\n * // Paragraph count includes paragraphs inside tables\n * console.log(`${metadata.totalParagraphs} paragraphs, ${metadata.totalTables} tables`);\n * ```\n *\n * @remarks\n * **Limitations:**\n * - Section breaks inside tables or text boxes are not detected (see GitHub issue #51)\n * - Estimated page count is heuristic-based and may not match actual rendered pages\n * - Maximum document size is 100MB\n */\nexport interface DocumentMetadata {\n /** List of sections with their metadata. Documents always have at least one section. */\n sections: SectionMetadata[];\n /** Total number of paragraphs in the document (includes paragraphs inside tables) */\n totalParagraphs: number;\n /** Total number of top-level tables in the document */\n totalTables: number;\n /** Whether the document has any footnotes (excludes separator/continuationSeparator) */\n hasFootnotes: boolean;\n /** Whether the document has any endnotes (excludes separator/continuationSeparator) */\n hasEndnotes: boolean;\n /** Whether the document has tracked changes (w:ins, w:del, w:moveFrom, w:moveTo) */\n hasTrackedChanges: boolean;\n /** Whether the document has comments (w:comment elements with content) */\n hasComments: boolean;\n /** Estimated total page count (heuristic based on content volume and page sizes) */\n estimatedPageCount: number;\n /** Explicit provenance: always \"heuristic\"; use PageMap for authoritative pages. */\n estimatedPageCountSource: \"heuristic\";\n}\n\n// ============================================================================\n// Web Worker Types (Phase 2: Non-blocking WASM operations)\n// ============================================================================\n\n/**\n * Message types sent from main thread to worker.\n */\nexport type WorkerRequestType =\n | \"init\"\n | \"generatePackageManifest\"\n | \"verifyDeliverable\"\n | \"proveRedlineReversibility\"\n | \"projectReviewProfile\"\n | \"convertDocxToHtml\"\n | \"compareDocuments\"\n | \"compareDocumentsToHtml\"\n | \"getSemanticChanges\"\n | \"createExternalAnnotationSet\"\n | \"validateExternalAnnotations\"\n | \"projectAnnotationsOntoHtml\"\n | \"convertDocxToHtmlWithExternalAnnotations\"\n | \"exportToOpenContract\"\n | \"getRevisions\"\n | \"getComments\"\n | \"getDocumentMetadata\"\n | \"getVersion\"\n | \"prepare\"\n | \"sessionOpen\"\n | \"sessionGetPackageManifest\"\n | \"sessionGetSemanticChanges\"\n | \"sessionVerifyDeliverable\"\n | \"sessionClose\"\n | \"sessionAddAnnotation\"\n | \"sessionRemoveAnnotation\"\n | \"sessionUpdateAnnotation\"\n | \"sessionMoveAnnotation\";\n\n/**\n * Base structure for worker requests.\n */\nexport interface WorkerRequestBase {\n /** Unique request ID for correlating responses */\n id: string;\n /** The operation type */\n type: WorkerRequestType;\n}\n\n/**\n * Initialize the worker with WASM base path.\n */\nexport interface WorkerInitRequest extends WorkerRequestBase {\n type: \"init\";\n /** Base URL for loading WASM files (e.g., \"/wasm/\") */\n wasmBasePath: string;\n}\n\n/**\n * Convert DOCX to HTML request.\n */\nexport interface WorkerConvertRequest extends WorkerRequestBase {\n type: \"convertDocxToHtml\";\n /** Private exact-view copy of the caller's document bytes, transferred to the worker. */\n documentBytes: Uint8Array;\n /** Conversion options */\n options?: ConversionOptions;\n /** Optional main-thread admission ceiling for the UTF-8 response. */\n maximumOutputBytes?: number;\n}\n\n/** Generate a deterministic package manifest without opening a live session. */\nexport interface WorkerGeneratePackageManifestRequest extends WorkerRequestBase {\n type: \"generatePackageManifest\";\n documentBytes: Uint8Array;\n /** When present, these lower ceilings constrain #493 inspection itself. */\n limits?: PackageManifestInspectionLimits;\n /**\n * Which representation the caller needs. A manifest near the entry ceiling is multi-megabyte,\n * so returning both costs a parse plus a structured clone nobody reads. Defaults to `\"both\"`.\n */\n representation?: \"object\" | \"json\" | \"both\";\n}\n\n/** Derive exact final/original package bytes before conversion. */\nexport interface WorkerProjectReviewProfileRequest extends WorkerRequestBase {\n type: \"projectReviewProfile\";\n documentBytes: Uint8Array;\n profile: \"final\" | \"original\";\n /** Do not transfer a derived package larger than this many bytes. */\n maximumOutputBytes?: number;\n}\n\n/** Run the default deliverable gate directly over exact supplied bytes. */\nexport interface WorkerVerifyDeliverableRequest extends WorkerRequestBase {\n type: \"verifyDeliverable\";\n documentBytes: Uint8Array;\n baselineBytes?: Uint8Array;\n /** The serialized full request (issue #747); absent means the default policy. */\n requestJson?: string;\n}\n\n/**\n * Prove redline accept/reject reversibility off the main thread. Three packages are inspected and\n * two are rebuilt, so this is the heaviest verification request the worker serves.\n */\nexport interface WorkerProveRedlineReversibilityRequest extends WorkerRequestBase {\n type: \"proveRedlineReversibility\";\n baselineBytes: Uint8Array;\n intendedFinalBytes: Uint8Array;\n redlineBytes: Uint8Array;\n}\n\n/**\n * Compare two documents request.\n */\nexport interface WorkerCompareRequest extends WorkerRequestBase {\n type: \"compareDocuments\";\n /** Original document bytes */\n originalBytes: Uint8Array;\n /** Modified document bytes */\n modifiedBytes: Uint8Array;\n /** Comparison options */\n options?: CompareOptions;\n}\n\n/**\n * Compare documents and return HTML request.\n */\nexport interface WorkerCompareToHtmlRequest extends WorkerRequestBase {\n type: \"compareDocumentsToHtml\";\n /** Original document bytes */\n originalBytes: Uint8Array;\n /** Modified document bytes */\n modifiedBytes: Uint8Array;\n /** Comparison options */\n options?: CompareOptions;\n}\n\n/** Compare two packages into the stable, versioned semantic-change schema. */\nexport interface WorkerGetSemanticChangesRequest extends WorkerRequestBase {\n type: \"getSemanticChanges\";\n leftBytes: Uint8Array;\n rightBytes: Uint8Array;\n settings?: DocxDiffSettings;\n}\n\n/** Create an empty external annotation set bound to a document's hash (issue #775). */\nexport interface WorkerCreateExternalAnnotationSetRequest extends WorkerRequestBase {\n type: \"createExternalAnnotationSet\";\n documentBytes: Uint8Array;\n documentId: string;\n}\n\n/** Validate an external annotation set against a document. */\nexport interface WorkerValidateExternalAnnotationsRequest extends WorkerRequestBase {\n type: \"validateExternalAnnotations\";\n documentBytes: Uint8Array;\n annotationSet: ExternalAnnotationSet;\n}\n\n/** Project an annotation set onto already-rendered (XML-well-formed) HTML. */\nexport interface WorkerProjectAnnotationsOntoHtmlRequest extends WorkerRequestBase {\n type: \"projectAnnotationsOntoHtml\";\n html: string;\n annotationSet: ExternalAnnotationSet;\n projectionOptions?: ExternalAnnotationProjectionSettings;\n}\n\n/** Convert a document and project an annotation set onto it in one round trip. */\nexport interface WorkerConvertWithExternalAnnotationsRequest extends WorkerRequestBase {\n type: \"convertDocxToHtmlWithExternalAnnotations\";\n documentBytes: Uint8Array;\n annotationSet: ExternalAnnotationSet;\n conversionOptions?: ConversionOptions;\n projectionOptions?: ExternalAnnotationProjectionSettings;\n}\n\n/** Export a document to the OpenContracts format. */\nexport interface WorkerExportToOpenContractRequest extends WorkerRequestBase {\n type: \"exportToOpenContract\";\n documentBytes: Uint8Array;\n}\n\n/**\n * Get revisions from a document request.\n */\nexport interface WorkerGetRevisionsRequest extends WorkerRequestBase {\n type: \"getRevisions\";\n /** Document bytes */\n documentBytes: Uint8Array;\n}\n\n/**\n * Get comments from a document request.\n */\nexport interface WorkerGetCommentsRequest extends WorkerRequestBase {\n type: \"getComments\";\n /** Document bytes */\n documentBytes: Uint8Array;\n}\n\n/**\n * Get document metadata for lazy loading request.\n */\nexport interface WorkerGetDocumentMetadataRequest extends WorkerRequestBase {\n type: \"getDocumentMetadata\";\n /** Document bytes */\n documentBytes: Uint8Array;\n}\n\n/**\n * Get library version request.\n */\nexport interface WorkerGetVersionRequest extends WorkerRequestBase {\n type: \"getVersion\";\n}\n\n/**\n * Warm up the comparison code path so the next compare triggers no further\n * WASM assembly fetches. Carries no payload.\n */\nexport interface WorkerPrepareRequest extends WorkerRequestBase {\n type: \"prepare\";\n}\n\n/**\n * Open a DocxSession in the worker.\n */\nexport interface WorkerSessionOpenRequest extends WorkerRequestBase {\n type: \"sessionOpen\";\n /** Private exact-view copy of the caller's document bytes, transferred to the worker. */\n documentBytes: Uint8Array;\n /** Session settings as JSON */\n settingsJson?: string;\n}\n\n/** Generate a manifest from the current logical checkpoint of a worker session. */\nexport interface WorkerSessionGetPackageManifestRequest extends WorkerRequestBase {\n type: \"sessionGetPackageManifest\";\n handle: number;\n}\n\n/** Compare a worker session's current checkpoint with its opening package. */\nexport interface WorkerSessionGetSemanticChangesRequest extends WorkerRequestBase {\n type: \"sessionGetSemanticChanges\";\n handle: number;\n}\n\n/** Run the default deliverable gate over a worker session's clean-save checkpoint. */\nexport interface WorkerSessionVerifyDeliverableRequest extends WorkerRequestBase {\n type: \"sessionVerifyDeliverable\";\n handle: number;\n /** The serialized full request (issue #747); absent means the default policy. */\n requestJson?: string;\n}\n\n/**\n * Close a worker DocxSession.\n */\nexport interface WorkerSessionCloseRequest extends WorkerRequestBase {\n type: \"sessionClose\";\n /** Session handle returned by sessionOpen */\n handle: number;\n}\n\n/**\n * Add an annotation via a worker DocxSession.\n */\nexport interface WorkerSessionAddAnnotationRequest extends WorkerRequestBase {\n type: \"sessionAddAnnotation\";\n handle: number;\n anchorId: string;\n /** CharSpan as JSON, or empty string for block-level */\n spanJson: string;\n annotationJson: string;\n}\n\n/**\n * Remove an annotation via a worker DocxSession.\n */\nexport interface WorkerSessionRemoveAnnotationRequest extends WorkerRequestBase {\n type: \"sessionRemoveAnnotation\";\n handle: number;\n annotationId: string;\n}\n\n/**\n * Update an annotation via a worker DocxSession.\n */\nexport interface WorkerSessionUpdateAnnotationRequest extends WorkerRequestBase {\n type: \"sessionUpdateAnnotation\";\n handle: number;\n annotationId: string;\n updateJson: string;\n}\n\n/**\n * Move an annotation via a worker DocxSession.\n */\nexport interface WorkerSessionMoveAnnotationRequest extends WorkerRequestBase {\n type: \"sessionMoveAnnotation\";\n handle: number;\n annotationId: string;\n newAnchorId: string;\n /** CharSpan as JSON, or empty string for block-level */\n newSpanJson: string;\n}\n\n/**\n * Union type of all possible worker requests.\n */\nexport type WorkerRequest =\n | WorkerInitRequest\n | WorkerGeneratePackageManifestRequest\n | WorkerVerifyDeliverableRequest\n | WorkerProveRedlineReversibilityRequest\n | WorkerProjectReviewProfileRequest\n | WorkerConvertRequest\n | WorkerCompareRequest\n | WorkerCompareToHtmlRequest\n | WorkerGetSemanticChangesRequest\n | WorkerCreateExternalAnnotationSetRequest\n | WorkerValidateExternalAnnotationsRequest\n | WorkerProjectAnnotationsOntoHtmlRequest\n | WorkerConvertWithExternalAnnotationsRequest\n | WorkerExportToOpenContractRequest\n | WorkerGetRevisionsRequest\n | WorkerGetCommentsRequest\n | WorkerGetDocumentMetadataRequest\n | WorkerGetVersionRequest\n | WorkerPrepareRequest\n | WorkerSessionOpenRequest\n | WorkerSessionGetPackageManifestRequest\n | WorkerSessionGetSemanticChangesRequest\n | WorkerSessionVerifyDeliverableRequest\n | WorkerSessionCloseRequest\n | WorkerSessionAddAnnotationRequest\n | WorkerSessionRemoveAnnotationRequest\n | WorkerSessionUpdateAnnotationRequest\n | WorkerSessionMoveAnnotationRequest;\n\n/**\n * Base structure for worker responses.\n */\nexport interface WorkerResponseBase {\n /** Request ID this response corresponds to */\n id: string;\n /** Whether the operation succeeded */\n success: boolean;\n /** Error message if success is false */\n error?: string;\n /**\n * Machine-readable cause when success is false. Callers classify failures from this\n * rather than by matching `error`, whose wording is not a contract.\n */\n errorCode?: WorkerErrorCode;\n}\n\n/**\n * Closed set of machine-readable worker failure causes.\n *\n * - `resource_limit`: the operation exceeded a configured size or work limit.\n * - `internal_error`: the worker threw an unexpected error while handling the request.\n * - `timeout`: the request outlived its `timeoutMs` / `requestTimeoutMs` deadline.\n * - `aborted`: the request's `AbortSignal` fired.\n * - `message_error`: a worker response could not be deserialized (`messageerror`); every request\n * in flight is rejected with this code, because the lost response cannot be matched to its request.\n * - `missing_result`: the worker reported success but sent no payload.\n */\nexport type WorkerErrorCode =\n | \"resource_limit\"\n | \"internal_error\"\n | \"timeout\"\n | \"aborted\"\n | \"message_error\"\n | \"missing_result\";\n\n/**\n * Response from init request.\n */\nexport interface WorkerInitResponse extends WorkerResponseBase {\n type: \"init\";\n}\n\n/**\n * Response from convertDocxToHtml request.\n */\nexport interface WorkerConvertResponse extends WorkerResponseBase {\n type: \"convertDocxToHtml\";\n /** The converted HTML string */\n html?: string;\n}\n\nexport interface WorkerGeneratePackageManifestResponse extends WorkerResponseBase {\n type: \"generatePackageManifest\";\n manifest?: PackageManifest;\n /** Exact canonical JSON, retained for strict duplicate-property/schema validation. */\n manifestJson?: string;\n}\n\nexport interface WorkerProjectReviewProfileResponse extends WorkerResponseBase {\n type: \"projectReviewProfile\";\n documentBytes?: Uint8Array;\n}\n\nexport interface WorkerVerifyDeliverableResponse extends WorkerResponseBase {\n type: \"verifyDeliverable\";\n verification?: DeliverableVerificationResult;\n}\n\nexport interface WorkerProveRedlineReversibilityResponse extends WorkerResponseBase {\n type: \"proveRedlineReversibility\";\n proof?: RedlineReversibilityProof;\n}\n\n/**\n * Response from compareDocuments request.\n */\nexport interface WorkerCompareResponse extends WorkerResponseBase {\n type: \"compareDocuments\";\n /** The redlined document bytes */\n documentBytes?: Uint8Array;\n}\n\n/**\n * Response from compareDocumentsToHtml request.\n */\nexport interface WorkerCompareToHtmlResponse extends WorkerResponseBase {\n type: \"compareDocumentsToHtml\";\n /** The HTML string with redlines */\n html?: string;\n}\n\n/** Response containing the public semantic-change schema. */\nexport interface WorkerGetSemanticChangesResponse extends WorkerResponseBase {\n type: \"getSemanticChanges\";\n semanticChanges?: SemanticChangeSet;\n}\n\nexport interface WorkerCreateExternalAnnotationSetResponse extends WorkerResponseBase {\n type: \"createExternalAnnotationSet\";\n annotationSet?: ExternalAnnotationSet;\n}\n\nexport interface WorkerValidateExternalAnnotationsResponse extends WorkerResponseBase {\n type: \"validateExternalAnnotations\";\n validation?: ExternalAnnotationValidationResult;\n}\n\nexport interface WorkerProjectAnnotationsOntoHtmlResponse extends WorkerResponseBase {\n type: \"projectAnnotationsOntoHtml\";\n html?: string;\n}\n\nexport interface WorkerConvertWithExternalAnnotationsResponse extends WorkerResponseBase {\n type: \"convertDocxToHtmlWithExternalAnnotations\";\n html?: string;\n}\n\nexport interface WorkerExportToOpenContractResponse extends WorkerResponseBase {\n type: \"exportToOpenContract\";\n export?: OpenContractDocExport;\n}\n\n/**\n * Response from getRevisions request.\n */\nexport interface WorkerGetRevisionsResponse extends WorkerResponseBase {\n type: \"getRevisions\";\n /** Array of revisions */\n revisions?: RevisionListEntry[];\n}\n\n/**\n * Response from getComments request.\n */\nexport interface WorkerGetCommentsResponse extends WorkerResponseBase {\n type: \"getComments\";\n /** Array of comments */\n comments?: CommentListEntry[];\n}\n\n/**\n * Response from getDocumentMetadata request.\n */\nexport interface WorkerGetDocumentMetadataResponse extends WorkerResponseBase {\n type: \"getDocumentMetadata\";\n /** Document metadata */\n metadata?: DocumentMetadata;\n}\n\n/**\n * Response from getVersion request.\n */\nexport interface WorkerGetVersionResponse extends WorkerResponseBase {\n type: \"getVersion\";\n /** Version information */\n version?: VersionInfo;\n}\n\n/**\n * Response from prepare request. Carries no payload beyond success/error.\n */\nexport interface WorkerPrepareResponse extends WorkerResponseBase {\n type: \"prepare\";\n}\n\n/**\n * Response from sessionOpen request.\n */\nexport interface WorkerSessionOpenResponse extends WorkerResponseBase {\n type: \"sessionOpen\";\n /** Integer handle identifying the session in the worker */\n handle?: number;\n}\n\n/** Response containing the current worker-session package manifest. */\nexport interface WorkerSessionGetPackageManifestResponse extends WorkerResponseBase {\n type: \"sessionGetPackageManifest\";\n manifest?: PackageManifest;\n}\n\n/** Response containing a session's public semantic-change schema. */\nexport interface WorkerSessionGetSemanticChangesResponse extends WorkerResponseBase {\n type: \"sessionGetSemanticChanges\";\n semanticChanges?: SemanticChangeSet;\n}\n\nexport interface WorkerSessionVerifyDeliverableResponse extends WorkerResponseBase {\n type: \"sessionVerifyDeliverable\";\n verification?: DeliverableVerificationResult;\n}\n\n/**\n * Response from sessionClose request.\n */\nexport interface WorkerSessionCloseResponse extends WorkerResponseBase {\n type: \"sessionClose\";\n}\n\n/**\n * Response from session annotation write operations.\n * The `result` field is the serialised EditResult from the WASM bridge.\n */\nexport interface WorkerSessionEditResponse extends WorkerResponseBase {\n type:\n | \"sessionAddAnnotation\"\n | \"sessionRemoveAnnotation\"\n | \"sessionUpdateAnnotation\"\n | \"sessionMoveAnnotation\";\n /** EditResult returned by the session operation */\n result?: EditResult;\n}\n\n/**\n * Union type of all possible worker responses.\n */\nexport type WorkerResponse =\n | WorkerInitResponse\n | WorkerGeneratePackageManifestResponse\n | WorkerVerifyDeliverableResponse\n | WorkerProveRedlineReversibilityResponse\n | WorkerProjectReviewProfileResponse\n | WorkerConvertResponse\n | WorkerCompareResponse\n | WorkerCompareToHtmlResponse\n | WorkerGetSemanticChangesResponse\n | WorkerCreateExternalAnnotationSetResponse\n | WorkerValidateExternalAnnotationsResponse\n | WorkerProjectAnnotationsOntoHtmlResponse\n | WorkerConvertWithExternalAnnotationsResponse\n | WorkerExportToOpenContractResponse\n | WorkerGetRevisionsResponse\n | WorkerGetCommentsResponse\n | WorkerGetDocumentMetadataResponse\n | WorkerGetVersionResponse\n | WorkerPrepareResponse\n | WorkerSessionOpenResponse\n | WorkerSessionGetPackageManifestResponse\n | WorkerSessionGetSemanticChangesResponse\n | WorkerSessionVerifyDeliverableResponse\n | WorkerSessionCloseResponse\n | WorkerSessionEditResponse;\n\n/**\n * Options for creating a worker-based Docxodus instance.\n */\nexport interface WorkerDocxodusOptions {\n /**\n * Base URL for loading WASM files.\n * Defaults to auto-detection from module URL.\n */\n wasmBasePath?: string;\n /** Abort the owned worker, including an initialization that has not completed. */\n signal?: AbortSignal;\n /**\n * Reject any request, including initialization, that has not answered within this many\n * milliseconds, with a `timeout` {@link WorkerErrorCode}. Off by default: large documents can\n * legitimately take a long time. A timed-out initialization stops the worker. Any other\n * timed-out request is most likely still running on the worker's single thread, and later\n * requests queue behind it; call `terminate()` to stop it.\n */\n requestTimeoutMs?: number;\n}\n\n/** Per-request options for a `WorkerDocxodus.withRequestOptions` view. */\nexport interface WorkerRequestOptions {\n /** Rejects each pending request of the view with an `aborted` {@link WorkerErrorCode} when it fires. */\n signal?: AbortSignal;\n /** A deadline in milliseconds that overrides the instance's `requestTimeoutMs`. */\n timeoutMs?: number;\n}\n\n// ============================================================================\n// OpenContracts Export Types (Issue #56)\n// ============================================================================\n\n/**\n * OpenContracts document export format.\n * Compatible with the OpenContracts ecosystem for document analysis.\n *\n * @example\n * ```typescript\n * const export = await exportToOpenContract(docxFile);\n * console.log(`Title: ${export.title}`);\n * console.log(`Content length: ${export.content.length} characters`);\n * console.log(`Pages: ${export.pageCount}`);\n * console.log(`Structural annotations: ${export.labelledText.filter(a => a.structural).length}`);\n * ```\n */\nexport interface OpenContractDocExport {\n /** Document title (from core properties or filename) */\n title: string;\n /** Complete document text content - ALL text from the document */\n content: string;\n /** Optional document description */\n description?: string;\n /** Estimated page count */\n pageCount: number;\n /** PAWLS-format page layout information with token positions */\n pawlsFileContent: PawlsPage[];\n /** Document-level labels (categories applied to the whole document) */\n docLabels: string[];\n /** Annotations/labeled text spans in the document */\n labelledText: OpenContractsAnnotation[];\n /** Relationships between annotations */\n relationships?: OpenContractsRelationship[];\n}\n\n/**\n * PAWLS page containing page boundary and token information.\n * PAWLS (Page-Aware Layout Segmentation) is a format for document layout data.\n */\nexport interface PawlsPage {\n /** Page boundary information (dimensions and index) */\n page: PawlsPageBoundary;\n /** Tokens on this page with position information */\n tokens: PawlsToken[];\n}\n\n/**\n * Page boundary information for PAWLS format.\n */\nexport interface PawlsPageBoundary {\n /** Page width in points (1pt = 1/72 inch) */\n width: number;\n /** Page height in points */\n height: number;\n /** Zero-based page index */\n index: number;\n}\n\n/**\n * Token with position information for PAWLS format.\n * Each token represents a word or text fragment with its bounding box.\n */\nexport interface PawlsToken {\n /** X coordinate (left edge) in points */\n x: number;\n /** Y coordinate (top edge) in points */\n y: number;\n /** Token width in points */\n width: number;\n /** Token height in points */\n height: number;\n /** The text content of this token */\n text: string;\n}\n\n/**\n * OpenContracts annotation format.\n * Used for both user annotations and structural elements.\n */\nexport interface OpenContractsAnnotation {\n /** Unique annotation identifier */\n id?: string;\n /** Label/category for this annotation (e.g., \"SECTION\", \"PARAGRAPH\", \"CLAUSE_TYPE_A\") */\n annotationLabel: string;\n /** The raw text content of the annotation */\n rawText: string;\n /** Starting page number (0-indexed) */\n page: number;\n /**\n * Position data for the annotation. Can be either:\n * - A TextSpan with start/end character offsets\n * - A dictionary of page indices to single-page annotation data\n */\n annotationJson?: TextSpan | Record<string, OpenContractsSinglePageAnnotation>;\n /** Parent annotation ID for hierarchical annotations */\n parentId?: string;\n /** Type of annotation (e.g., \"text\", \"structural\") */\n annotationType?: string;\n /** Whether this is a structural element (section, heading, table, etc.) */\n structural: boolean;\n}\n\n/**\n * Per-page annotation position data.\n * Used when an annotation spans multiple pages.\n */\nexport interface OpenContractsSinglePageAnnotation {\n /** Bounding box for the annotation on this page */\n bounds: BoundingBox;\n /** Token indices that make up this annotation on this page */\n tokensJsons: TokenId[];\n /** Raw text content on this page */\n rawText: string;\n}\n\n/**\n * Bounding box coordinates in points.\n */\nexport interface BoundingBox {\n /** Top edge coordinate */\n top: number;\n /** Bottom edge coordinate */\n bottom: number;\n /** Left edge coordinate */\n left: number;\n /** Right edge coordinate */\n right: number;\n}\n\n/**\n * Token identifier referencing a specific token on a specific page.\n */\nexport interface TokenId {\n /** Zero-based page index */\n pageIndex: number;\n /** Zero-based token index within the page */\n tokenIndex: number;\n}\n\n/**\n * Text span with character offsets for annotation positioning.\n * This is the simpler form of annotation_json for single-page annotations.\n */\nexport interface TextSpan {\n /** Optional span identifier */\n id?: string;\n /** Start character offset (0-indexed, inclusive) */\n start: number;\n /** End character offset (exclusive) */\n end: number;\n /** The text content of this span */\n text: string;\n}\n\n/**\n * Relationship between annotations.\n * Used to express hierarchical or semantic connections between annotations.\n */\nexport interface OpenContractsRelationship {\n /** Unique relationship identifier */\n id?: string;\n /** Label describing the relationship type (e.g., \"CONTAINS\", \"REFERENCES\") */\n relationshipLabel: string;\n /** IDs of source annotations */\n sourceAnnotationIds: string[];\n /** IDs of target annotations */\n targetAnnotationIds: string[];\n /** Whether this is a structural relationship */\n structural: boolean;\n}\n\n// ============================================================================\n// External Annotation Types (Issue #57)\n// ============================================================================\n\n/**\n * Annotation label definition matching OpenContracts AnnotationLabelPythonType.\n */\nexport interface AnnotationLabel {\n /** Unique label identifier */\n id: string;\n /** Color in hex format (e.g., \"#FFEB3B\") */\n color: string;\n /** Description of what this label represents */\n description: string;\n /** Optional icon name */\n icon: string;\n /** Display name for the label */\n text: string;\n /** Type of label: \"text\", \"doc\", or \"metadata\" */\n labelType: \"text\" | \"doc\" | \"metadata\";\n}\n\n/**\n * External annotation set - extends OpenContractDocExport with binding/validation.\n * This allows storing annotations externally (in JSON/database) without modifying the DOCX.\n *\n * @example\n * ```typescript\n * // Create an annotation set from a document\n * const set = await createExternalAnnotationSet(docxFile, \"my-doc-123\");\n *\n * // Add a label definition\n * set.textLabels[\"IMPORTANT\"] = {\n * id: \"IMPORTANT\",\n * text: \"Important\",\n * color: \"#FF0000\",\n * description: \"Important text that needs attention\",\n * icon: \"\",\n * labelType: \"text\"\n * };\n *\n * // Create an annotation\n * const annotation = createAnnotationFromSearch(\n * \"ann-001\", \"IMPORTANT\", set.content, \"contract term\"\n * );\n * if (annotation) {\n * set.labelledText.push(annotation);\n * }\n *\n * // Validate and project onto HTML\n * const result = await validateExternalAnnotations(docxFile, set);\n * if (result.isValid) {\n * const html = await convertDocxToHtmlWithExternalAnnotations(docxFile, set);\n * }\n * ```\n */\nexport interface ExternalAnnotationSet extends OpenContractDocExport {\n /** Unique identifier for the source document (filename, UUID, or external reference) */\n documentId: string;\n /** SHA256 hash of the source document for integrity validation */\n documentHash: string;\n /** ISO 8601 timestamp when this annotation set was created */\n createdAt: string;\n /** ISO 8601 timestamp when this annotation set was last modified */\n updatedAt: string;\n /** Version of the external annotation format (for future migrations) */\n version: string;\n /** Text label definitions keyed by label ID */\n textLabels: Record<string, AnnotationLabel>;\n /** Document label definitions keyed by label ID */\n docLabelDefinitions: Record<string, AnnotationLabel>;\n}\n\n/**\n * Result of validating an external annotation set against a document.\n */\nexport interface ExternalAnnotationValidationResult {\n /** True if the annotation set is valid for the document */\n isValid: boolean;\n /** True if the document hash doesn't match, indicating the document may have been modified */\n hashMismatch: boolean;\n /** List of specific issues found during validation */\n issues: ExternalAnnotationValidationIssue[];\n}\n\n/**\n * A single validation issue found when validating an external annotation set.\n */\nexport interface ExternalAnnotationValidationIssue {\n /** ID of the annotation with the issue */\n annotationId: string;\n /** Type of issue: \"TextMismatch\", \"OutOfBounds\", or \"MissingLabel\" */\n issueType: \"TextMismatch\" | \"OutOfBounds\" | \"MissingLabel\";\n /** Human-readable description of the issue */\n description: string;\n /** For TextMismatch: the text that was expected (stored in annotation) */\n expectedText?: string;\n /** For TextMismatch: the actual text found at the annotation's offsets */\n actualText?: string;\n}\n\n/**\n * Settings for projecting external annotations onto HTML.\n */\nexport interface ExternalAnnotationProjectionSettings {\n /** CSS class prefix for annotation elements (default: \"ext-annot-\") */\n cssClassPrefix?: string;\n /** How to display annotation labels (default: Above) */\n labelMode?: AnnotationLabelMode;\n /** Whether to include annotation metadata as data attributes (default: true) */\n includeMetadata?: boolean;\n /** Whether to validate annotations before projection (default: true) */\n validateBeforeProjection?: boolean;\n}\n", "// Copyright (c) John Scrudato IV. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport type {\n AnchorInfo,\n AnchorRef,\n AnchorTargetRef,\n AnnotationUpdate,\n BlockMetadata,\n BookmarkInfo,\n BulkEditResult,\n CharSpan,\n CommentListEntry,\n ContentControlFillOptions,\n ContentControlInfo,\n CrossBlockMatch,\n DiffEntry,\n DocumentAnnotation,\n DocumentRange,\n DeliverableVerificationResult,\n DeliverableVerificationRequest,\n DocxodusWasmExports,\n DocxSessionProjection,\n DocxSessionSettings,\n EditError,\n EditResult,\n EditSummary,\n FillOptions,\n FindOptions,\n FormatOp,\n FormattingInspection,\n HeaderFooterKind,\n HyperlinkInfo,\n HyperlinkKind,\n ImageCapabilities,\n ImageDimensions,\n ImageInsertOptions,\n ImageOccurrence,\n FloatingImageLayout,\n InlineSpan,\n NoteListEntry,\n NumberFormat,\n PageNumberField,\n PageNumberingOp,\n PageSetupOp,\n TableOfAuthoritiesOptions,\n TableOfContentsOptions,\n TableOfFiguresOptions,\n PageCitation,\n PageCitationRequest,\n PageMapRegistrationResult,\n PageMapStatus,\n PackageManifest,\n ParagraphBorderEdge,\n ParagraphFormatOp,\n TableBorderSpec,\n TableInsertOptions,\n TableMetadataResult,\n TableCellResolutionResult,\n TableMergeContent,\n TableRowOptions,\n TableShadingScope,\n ListFormat,\n GrepOptions,\n ListMembership,\n MutationBatchFailure,\n MutationBatchChangeSet,\n MutationBatchMode,\n MutationBatchPreviewOptions,\n MutationBatchPreviewStep,\n MutationBatchResult,\n MutationBatchStep,\n MutationTransaction,\n MutationTransactionIdentity,\n MutationPreviewRetention,\n DeliveryBundleResult,\n DeliveryEvidenceStatus,\n DeliveryReceiptBuildOptions,\n MutationBatchStepResult,\n MutationPreconditions,\n CrossReferenceOptions,\n ReplaceOptions,\n RevisionListEntry,\n RevisionListFilter,\n RevisionRepairProposal,\n RevisionRepairRequest,\n RevisionRepairResult,\n SectionInfo,\n SemanticChangeSet,\n StyleInfo,\n TemplatePlaceholder,\n TextMatch,\n} from \"./types.js\";\nimport { serializeVerificationRequest } from \"./verification-request.js\";\nimport type { PageMap } from \"./pagination.js\";\nimport { ContextBoundary, DiffFormat, PlaceholderKinds, ProjectionDepth, ProjectionScopes, TrackedChangeMode } from \"./types.js\";\n\nfunction mutationBatchChangeSet<T>(\n before: readonly T[],\n after: readonly T[],\n key: (value: T) => string,\n): MutationBatchChangeSet<T> {\n const beforeGroups = new Map<string, number[]>();\n const afterGroups = new Map<string, number[]>();\n const group = (items: readonly T[], target: Map<string, number[]>): void => {\n items.forEach((item, index) => {\n const identity = key(item);\n const indices = target.get(identity) ?? [];\n indices.push(index);\n target.set(identity, indices);\n });\n };\n group(before, beforeGroups);\n group(after, afterGroups);\n\n const beforeMatched = before.map(() => false);\n const afterMatched = after.map(() => false);\n const modified = after.map(() => false);\n for (const [identity, afterIndices] of afterGroups) {\n const beforeIndices = beforeGroups.get(identity) ?? [];\n for (const afterIndex of afterIndices) {\n const beforeIndex = beforeIndices.find(index =>\n !beforeMatched[index] && JSON.stringify(before[index]) === JSON.stringify(after[afterIndex]));\n if (beforeIndex === undefined) continue;\n beforeMatched[beforeIndex] = true;\n afterMatched[afterIndex] = true;\n }\n const remainingBefore = beforeIndices.filter(index => !beforeMatched[index]);\n const remainingAfter = afterIndices.filter(index => !afterMatched[index]);\n const modifiedCount = Math.min(remainingBefore.length, remainingAfter.length);\n for (let index = 0; index < modifiedCount; index++) {\n beforeMatched[remainingBefore[index]!] = true;\n afterMatched[remainingAfter[index]!] = true;\n modified[remainingAfter[index]!] = true;\n }\n }\n return {\n added: after.filter((_, index) => !afterMatched[index]),\n removed: before.filter((_, index) => !beforeMatched[index]),\n modified: after.filter((_, index) => modified[index]),\n };\n}\n\n/**\n * Stateful in-memory DOCX editing session keyed by markdown-projection anchor ids.\n * Mirror of the .NET `DocxSession` surface. See\n * `docs/architecture/docx_mutation_api.md` for the surface contract,\n * anchor lifecycle, error catalog, and supported markdown subset.\n *\n * Sessions are not eligible for JS-side garbage collection \u2014 call {@link close}\n * (or use a `using` block under TypeScript 5.2+) when done.\n */\n/**\n * Receipt warnings that say a fresh execution may regenerate ids or timestamps \u2014 the same\n * text the .NET receipt attaches. {@link DocxSession.commitPreview} removes them, because a\n * commit restores the previewed bytes rather than executing afresh.\n */\nconst BATCH_REPLAY_CAVEATS = {\n revisionDates: \"Tracked-revision date attributes may use the execution clock; compare revision ids, authors, types, text, and anchors across separate executions.\",\n commentDates: \"Comment date attributes may be generated from the execution clock; supply dates explicitly when byte-identical replay is required.\",\n annotationMetadata: \"Auto-generated annotation ids or creation timestamps are execution metadata; supply id and created explicitly when byte-identical replay is required.\",\n createdAnchors: \"Created anchors and related OOXML ids may be generated independently on replay; preview/apply equivalence is semantic and packageHash or anchor ids may differ.\",\n} as const;\nconst BATCH_REPLAY_CAVEAT_TEXTS: ReadonlySet<string> = new Set(Object.values(BATCH_REPLAY_CAVEATS));\n\ntype DeliveryBundleArtifactWire = Omit<DeliveryBundleResult[\"artifacts\"][number], \"bytes\"> & { bytes?: string };\n\n/** Mirrors the .NET retained-preview count bound, so this client-side receipt map cannot outgrow it. */\nconst RETAINED_PREVIEW_RECEIPTS = 8;\n\nexport class DocxSession {\n private readonly handle: number;\n private readonly wasm: DocxodusWasmExports[\"DocxSessionBridge\"];\n /**\n * The receipts this client composed for previews it retained, keyed by previewId. The host\n * keeps the package and the binding; the step receipts live only here, so a commit can return\n * the previewed steps and change sets without the host re-parsing a client-composed result.\n */\n private readonly retainedPreviewReceipts = new Map<string, MutationBatchResult>();\n\n /** @internal */\n constructor(handle: number, wasm: DocxodusWasmExports[\"DocxSessionBridge\"]) {\n this.handle = handle;\n this.wasm = wasm;\n }\n\n // \u2500\u2500\u2500 View \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n project(): DocxSessionProjection {\n return JSON.parse(this.wasm.Project(this.handle)) as DocxSessionProjection;\n }\n\n /** Monotonic document version (0 at open; +1 per committed mutation/undo/redo). */\n getVersion(): number {\n return (JSON.parse(this.wasm.GetVersion(this.handle)) as { version: number }).version;\n }\n\n /**\n * Verification manifest for the current logical checkpoint. Unsaved edits are included and\n * the read does not mutate package bytes, caches, history, or the document version.\n */\n getPackageManifest(): PackageManifest {\n return JSON.parse(this.wasm.GetPackageManifest(this.handle)) as PackageManifest;\n }\n\n /** Register a browser-materialized PageMap without changing the document version. */\n registerPageMap(pageMap: PageMap, expectedRendererFingerprint?: string): PageMapRegistrationResult {\n return JSON.parse(this.wasm.RegisterPageMap(\n this.handle,\n JSON.stringify(pageMap),\n expectedRendererFingerprint ?? \"\",\n )) as PageMapRegistrationResult;\n }\n\n getPageMapStatus(request?: PageCitationRequest): PageMapStatus {\n return JSON.parse(this.wasm.GetPageMapStatus(\n this.handle,\n request ? JSON.stringify(request) : \"\",\n )) as PageMapStatus;\n }\n\n getPageCitation(anchorId: string, request: PageCitationRequest): PageCitation {\n return JSON.parse(this.wasm.GetPageCitation(\n this.handle,\n anchorId,\n JSON.stringify(request),\n )) as PageCitation;\n }\n\n /** Evaluate optimistic guards without mutating or advancing the version. */\n checkPreconditions(preconditions: MutationPreconditions): EditResult {\n return JSON.parse(\n this.wasm.CheckPreconditions(this.handle, JSON.stringify(preconditions)),\n ) as EditResult;\n }\n\n /**\n * Guard any synchronous mutation. WASM calls are synchronous and single-threaded, so the\n * check and callback form one uninterrupted client-side operation. Prefer a method's native\n * `preconditions` option where it has one (notably replaceTextRange's match-count guard).\n */\n runWithPreconditions(\n preconditions: MutationPreconditions,\n mutation: () => EditResult,\n ): EditResult {\n const checked = this.checkPreconditions(preconditions);\n return checked.success ? mutation() : checked;\n }\n\n /**\n * Execute synchronous mutations atomically by default. Atomic success is one undo/version\n * unit; any failed or thrown step restores the exact package and history checkpoint.\n */\n executeBatch(\n steps: readonly MutationBatchStep[],\n mode: MutationBatchMode = \"atomic\",\n transaction?: MutationTransaction,\n ): MutationBatchResult {\n if (mode !== \"atomic\" && mode !== \"best_effort\") {\n throw new RangeError(`unknown mutation batch mode: ${String(mode)}`);\n }\n if (transaction === undefined) return this.recorded(steps, mode, undefined, () => this.runBatch(steps, mode));\n return this.runTransactional(transaction, mode,\n identity => this.recorded(steps, mode, identity, () => this.runBatch(steps, mode)));\n }\n\n /**\n * What the session's host-owned delivery evidence recorder holds (issue #748). `enabled` is\n * false, with the reason, unless the session was opened with `captureDeliveryEvidence`.\n */\n getDeliveryEvidenceStatus(): DeliveryEvidenceStatus {\n if (!this.wasm.GetDeliveryEvidenceStatus) {\n throw new Error(\"This WASM bundle predates delivery evidence; rebuild docxodus.\");\n }\n return JSON.parse(this.wasm.GetDeliveryEvidenceStatus(this.handle)) as DeliveryEvidenceStatus;\n }\n\n /**\n * Build the receipt-bearing delivery of this session through the shared bundle service: the\n * clean current package (`final-docx`), the source-to-delivered semantic delta, and the change\n * receipt (`change-receipt`) minted from the captured evidence \u2014 verifiable with\n * `verifyDeliveryReceipt` against the returned artifact bytes. A history that cannot be\n * attested yields an `incomplete` bundle whose receipt artifact carries the reason, and\n * `evidence.unavailableReason` says why.\n */\n buildDeliveryReceipt(options?: DeliveryReceiptBuildOptions): DeliveryBundleResult {\n if (!this.wasm.BuildDeliveryReceipt) {\n throw new Error(\"This WASM bundle predates delivery evidence; rebuild docxodus.\");\n }\n const wire = JSON.parse(this.wasm.BuildDeliveryReceipt(this.handle, JSON.stringify(options ?? {}))) as {\n status: DeliveryBundleResult[\"status\"];\n verified: boolean;\n manifest: Record<string, unknown>;\n manifestBytes: string;\n artifacts: readonly (Omit<DeliveryBundleArtifactWire, \"bytes\"> & { bytes?: string })[];\n evidence?: DeliveryEvidenceStatus;\n };\n const decode = (base64: string): Uint8Array => Uint8Array.from(atob(base64), c => c.charCodeAt(0));\n return {\n status: wire.status,\n verified: wire.verified,\n manifest: wire.manifest,\n manifestBytes: decode(wire.manifestBytes),\n artifacts: wire.artifacts.map(artifact => {\n const { bytes, ...rest } = artifact;\n return bytes === undefined ? rest : { ...rest, bytes: decode(bytes) };\n }),\n ...(wire.evidence ? { evidence: wire.evidence } : {}),\n };\n }\n\n /**\n * Describe a batch to the session's delivery evidence recorder before running it, and hand\n * it the step results afterwards, so the version steps the batch produced are recorded under\n * this description rather than as unlabeled mutations. A bundle without the recorder, or a\n * session not capturing evidence, simply runs the batch.\n */\n private recorded(\n steps: readonly MutationBatchStep[],\n mode: MutationBatchMode,\n identity: MutationTransactionIdentity | undefined,\n run: () => MutationBatchResult,\n ): MutationBatchResult {\n if (!this.wasm.BeginDeliveryEvidence || !this.wasm.CompleteDeliveryEvidence\n || !this.wasm.AbandonDeliveryEvidence) {\n return run();\n }\n const described = this.wasm.BeginDeliveryEvidence(\n this.handle,\n JSON.stringify(steps.map(step => step.args === undefined\n ? { tool: step.tool, action: step.action }\n : { tool: step.tool, action: step.action, args: step.args })),\n mode,\n identity ? JSON.stringify({ transactionId: identity.transactionId, requestFingerprint: identity.requestFingerprint }) : \"\",\n );\n if (!described) return run();\n let result: MutationBatchResult | undefined;\n try {\n result = run();\n return result;\n } finally {\n if (result) this.wasm.CompleteDeliveryEvidence(this.handle, JSON.stringify(result.steps));\n else this.wasm.AbandonDeliveryEvidence(this.handle);\n }\n }\n\n /**\n * Make a preview retained by {@link previewBatch} (`retain: true`) the live document exactly\n * as previewed: the previewed package is restored byte-for-byte as one undo step, so the\n * generated anchor ids, timestamps and `packageHash` are exactly those the preview reported.\n * The commit is guarded \u2014 it refuses with `preview_stale`, editing nothing, when the session's\n * version, package content, tracked-changes mode or revision author moved since the preview,\n * and with `preview_not_found` once the preview expired, was evicted, or was already\n * committed. A `transaction` makes a retry after a lost response safe, as for\n * {@link executeBatch}.\n */\n commitPreview(previewId: string, transaction?: MutationTransaction): MutationBatchResult {\n if (!this.wasm.CommitPreview) {\n throw new Error(\"This WASM bundle predates retained previews; rebuild docxodus.\");\n }\n const commit = (): MutationBatchResult => {\n const envelope = JSON.parse(this.wasm.CommitPreview!(this.handle, previewId)) as MutationBatchResult;\n if (!envelope.success) {\n if (envelope.failure?.error.code === \"preview_not_found\") this.retainedPreviewReceipts.delete(previewId);\n return envelope;\n }\n const receipt = this.retainedPreviewReceipts.get(previewId);\n this.retainedPreviewReceipts.delete(previewId);\n // No receipt means another client of this handle retained the preview; the host's\n // envelope (versions, hash, retention) is still exact, only the step receipts are unknown.\n if (!receipt) return envelope;\n return {\n ...receipt,\n preview: false,\n html: null,\n baseVersion: envelope.baseVersion,\n resultVersion: envelope.resultVersion,\n packageHash: envelope.packageHash,\n warnings: receipt.warnings.filter(warning => !BATCH_REPLAY_CAVEAT_TEXTS.has(warning)),\n retention: envelope.retention,\n };\n };\n if (transaction === undefined) return commit();\n return this.runTransactional(transaction, \"atomic\", () => commit());\n }\n\n private runTransactional(\n transaction: MutationTransaction,\n mode: MutationBatchMode,\n body: (identity: MutationTransactionIdentity) => MutationBatchResult,\n ): MutationBatchResult {\n // The batch is composed here from callbacks, so the session's journal (shared with every\n // other transport) is driven in three steps: resolve the id, run, retain the result.\n if (!this.wasm.BeginMutationTransaction\n || !this.wasm.CompleteMutationTransaction\n || !this.wasm.AbandonMutationTransaction) {\n throw new Error(\"This WASM bundle predates mutation transactions; rebuild docxodus.\");\n }\n if (typeof transaction.transactionId !== \"string\") {\n throw new RangeError(\"transactionId must be a string\");\n }\n if (transaction.request === null || typeof transaction.request !== \"object\"\n || Array.isArray(transaction.request)) {\n throw new RangeError(\"a mutation transaction needs a request object describing the batch\");\n }\n const decision = JSON.parse(this.wasm.BeginMutationTransaction(\n this.handle,\n transaction.transactionId,\n JSON.stringify({ ...transaction.request, mode }),\n )) as { kind: string; transaction: MutationTransactionIdentity; response: string | null };\n if (decision.response !== null) {\n return JSON.parse(decision.response) as MutationBatchResult;\n }\n let completed = false;\n try {\n const result: MutationBatchResult = {\n ...body(decision.transaction),\n transaction: decision.transaction,\n };\n this.wasm.CompleteMutationTransaction(\n this.handle, transaction.transactionId, JSON.stringify(result));\n completed = true;\n return result;\n } finally {\n if (!completed) this.wasm.AbandonMutationTransaction(this.handle, transaction.transactionId);\n }\n }\n\n private runBatch(\n steps: readonly MutationBatchStep[],\n mode: MutationBatchMode,\n ): MutationBatchResult {\n const baseVersion = this.getVersion();\n const observationWarnings: string[] = [];\n const inspect = <T>(label: string, read: () => T, fallback: T): T => {\n try { return read(); } catch (error) {\n observationWarnings.push(`${label} unavailable: ${error instanceof Error ? error.message : String(error)}`);\n return fallback;\n }\n };\n const beforeRevisions = inspect(\"Revision delta inspection\", () => this.listRevisions(), []);\n const beforeComments = inspect(\"Comment delta inspection\", () => this.listComments(), []);\n const beforeAnnotations = inspect(\"Annotation delta inspection\", () => this.listAnnotations(), []);\n const complete = (result: {\n mode: MutationBatchMode;\n status: \"ok\" | \"failed\" | \"partial\";\n success: boolean;\n rolledBack: boolean;\n steps: readonly MutationBatchStepResult[];\n failure?: MutationBatchFailure;\n }): MutationBatchResult => {\n try {\n const revisionChanges = mutationBatchChangeSet(\n beforeRevisions,\n inspect(\"Revision delta inspection\", () => this.listRevisions(), beforeRevisions),\n revision => revision.id,\n );\n const commentChanges = mutationBatchChangeSet(\n beforeComments,\n inspect(\"Comment delta inspection\", () => this.listComments(), beforeComments),\n comment => comment.anchorId,\n );\n const annotationChanges = mutationBatchChangeSet(\n beforeAnnotations,\n inspect(\"Annotation delta inspection\", () => this.listAnnotations(), beforeAnnotations),\n annotation => annotation.id ?? \"\",\n );\n const resultVersion = inspect(\n \"Result version inspection\", () => this.getVersion(), baseVersion,\n );\n const warnings: string[] = [...observationWarnings];\n if ([...revisionChanges.added, ...revisionChanges.modified]\n .some(revision => revision.date !== undefined && revision.date !== null)) {\n warnings.push(BATCH_REPLAY_CAVEATS.revisionDates);\n }\n if ([...commentChanges.added, ...commentChanges.modified]\n .some(comment => comment.date !== undefined && comment.date !== null)) {\n warnings.push(BATCH_REPLAY_CAVEATS.commentDates);\n }\n // Same predicate as the .NET receipt (`annotation.Created.HasValue`): the warning is\n // about an execution CLOCK, so an annotation added with no created timestamp is\n // deterministic and must not raise it on one surface and not the other.\n if (annotationChanges.added\n .some(annotation => annotation.created !== undefined && annotation.created !== null)) {\n warnings.push(BATCH_REPLAY_CAVEATS.annotationMetadata);\n }\n if (result.steps.some(step => step.results.some(edit => edit.created.length > 0))) {\n warnings.push(BATCH_REPLAY_CAVEATS.createdAnchors);\n }\n if (mode === \"best_effort\" && !result.success) {\n warnings.push(\"Best-effort execution retains every successful step despite later failures.\");\n }\n // null, never \"\": an absent hash must not compare equal to another absent hash, or a\n // naive `preview.packageHash === applied.packageHash` replay assertion passes vacuously.\n let packageHash: string | null = null;\n if (!this.wasm.GetPackageContentHash) {\n warnings.push(\"This WASM bundle predates package equivalence hashes; packageHash is unavailable.\");\n } else {\n try { packageHash = this.wasm.GetPackageContentHash(this.handle); } catch (error) {\n warnings.push(`Package equivalence hash unavailable: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n return {\n ...result,\n preview: false,\n baseVersion,\n resultVersion,\n packageHash,\n revisionChanges,\n commentChanges,\n annotationChanges,\n warnings,\n html: null,\n };\n } catch (error) {\n return {\n ...result,\n preview: false,\n baseVersion,\n resultVersion: inspect(\"Result version inspection\", () => this.getVersion(), baseVersion),\n packageHash: null,\n revisionChanges: { added: [], removed: [], modified: [] },\n commentChanges: { added: [], removed: [], modified: [] },\n annotationChanges: { added: [], removed: [], modified: [] },\n warnings: [\n ...observationWarnings,\n `Batch receipt enrichment unavailable: ${error instanceof Error ? error.message : String(error)}`,\n ],\n html: null,\n };\n }\n };\n const internalFailure = (value: unknown): EditResult => ({\n success: false,\n error: { code: \"internal_error\", message: value instanceof Error ? value.message : String(value) },\n created: [], removed: [], modified: [],\n });\n const run = (step: MutationBatchStep): readonly EditResult[] => {\n try {\n const value = step.mutation();\n const results = Array.isArray(value) ? value : [value];\n if (results.some(result =>\n result === null || typeof result !== \"object\" || typeof result.success !== \"boolean\")) {\n return [internalFailure(\"batch mutation returned invalid edit results\")];\n }\n // An empty list is a successful no-op step, matching the core contract.\n return results;\n } catch (error) {\n return [internalFailure(error)];\n }\n };\n const failureOf = (\n step: MutationBatchStepResult,\n rolledBack: boolean,\n ): MutationBatchFailure => ({\n index: step.index,\n tool: step.tool,\n action: step.action,\n error: step.results.find(result => !result.success)?.error\n ?? { code: \"internal_error\", message: \"batch step failed without an error\" },\n rolledBack,\n });\n\n const preflightOne = (step: MutationBatchStep): EditError | undefined => {\n try { return step.preflight?.(); } catch (error) { return internalFailure(error).error; }\n };\n if (mode === \"atomic\") {\n const preflight = steps.map(preflightOne);\n const failedPreflight = preflight.findIndex(error => error !== undefined);\n if (failedPreflight >= 0) {\n const source = steps[failedPreflight]!;\n const failed: MutationBatchStepResult = {\n index: failedPreflight, tool: source.tool, action: source.action,\n success: false, rolledBack: true,\n results: [{ success: false, error: preflight[failedPreflight]!, created: [], removed: [], modified: [] }],\n };\n return complete({ mode, status: \"failed\", success: false, rolledBack: true,\n steps: [failed], failure: failureOf(failed, true) });\n }\n\n const transaction = this.wasm.BeginTransaction(this.handle);\n const completed: MutationBatchStepResult[] = [];\n try {\n for (let index = 0; index < steps.length; index++) {\n const source = steps[index]!;\n const results = run(source);\n const step: MutationBatchStepResult = {\n index, tool: source.tool, action: source.action,\n success: results.every(result => result.success), rolledBack: false, results,\n };\n completed.push(step);\n if (!step.success) {\n this.wasm.RollbackTransaction(transaction);\n const rolledBack = completed.map(value => ({ ...value, rolledBack: true }));\n const failed = rolledBack[rolledBack.length - 1]!;\n return complete({ mode, status: \"failed\", success: false, rolledBack: true,\n steps: rolledBack, failure: failureOf(failed, true) });\n }\n }\n this.wasm.CommitTransaction(transaction);\n return complete({ mode, status: \"ok\", success: true, rolledBack: false, steps: completed });\n } catch (error) {\n try { this.wasm.RollbackTransaction(transaction); } catch { /* preserve the original */ }\n throw error;\n }\n }\n\n // Preserve sequential best-effort semantics: a later preflight can observe state created by\n // an earlier successful step, so run it immediately before that step rather than up front.\n const completed: MutationBatchStepResult[] = steps.map((source, index) => {\n const preflight = preflightOne(source);\n const results = preflight\n ? [{ success: false, error: preflight, created: [], removed: [], modified: [] }]\n : run(source);\n return {\n index, tool: source.tool, action: source.action,\n success: results.every(result => result.success), rolledBack: false, results,\n };\n });\n const failed = completed.find(step => !step.success);\n return complete({\n mode,\n status: failed ? (completed.some(step => step.success) ? \"partial\" : \"failed\") : \"ok\",\n success: failed === undefined,\n rolledBack: false,\n steps: completed,\n failure: failed ? failureOf(failed, false) : undefined,\n });\n }\n\n /**\n * Execute the same callback batch algorithm against a complete isolated package clone.\n * Callbacks receive the shadow session explicitly; mutate that argument. The live session's\n * package, caches, version, configuration, and undo/redo history are never execution targets.\n */\n previewBatch(\n steps: readonly MutationBatchPreviewStep[],\n mode: MutationBatchMode = \"atomic\",\n options?: MutationBatchPreviewOptions,\n ): MutationBatchResult {\n if (mode !== \"atomic\" && mode !== \"best_effort\") {\n throw new RangeError(`unknown mutation batch mode: ${String(mode)}`);\n }\n const htmlMode = options?.html ?? \"none\";\n if (htmlMode !== \"none\" && htmlMode !== \"scoped\" && htmlMode !== \"full\") {\n throw new RangeError(`unknown preview HTML mode: ${String(htmlMode)}`);\n }\n if (!this.wasm.OpenPreviewSession) {\n throw new Error(\"This WASM bundle does not support isolated mutation previews.\");\n }\n\n const shadow = new DocxSession(this.wasm.OpenPreviewSession(this.handle), this.wasm);\n try {\n const result = shadow.executeBatch(\n steps.map(step => ({\n tool: step.tool,\n action: step.action,\n mutation: () => step.mutation(shadow),\n preflight: step.preflight ? () => step.preflight!(shadow) : undefined,\n })),\n mode,\n );\n const warnings = [...result.warnings];\n let html: string | null = null;\n // A rendered document always starts with '<'; a leading '{' is the bridge's error object.\n const unwrapRendered = (rendered: string): string | null => {\n if (rendered.trimStart().startsWith(\"{\")) {\n const envelope = JSON.parse(rendered) as { error?: string };\n if (envelope.error) {\n warnings.push(`Preview HTML could not be generated: ${envelope.error}`);\n return null;\n }\n }\n return rendered;\n };\n // Preview HTML MUST come from the fa\u00E7ade's preview profile (DocxSessionOps.RenderPreview*),\n // not the editor's authoring profile: the editor render hides comments, annotations and\n // headers/footers, so routing a preview through it would show this surface a materially\n // different document than the stdio/Python/MCP surfaces show for the identical batch.\n const legacyProfileWarning =\n \"This WASM bundle predates the shared preview HTML profile; preview HTML omits comments, \" +\n \"annotations and headers/footers and may differ from other surfaces.\";\n try {\n if (htmlMode === \"scoped\") {\n if (!options?.htmlAnchorId) {\n warnings.push(\"Scoped HTML was requested without htmlAnchorId; no HTML was generated.\");\n } else if (this.wasm.RenderPreviewBlockHtml) {\n html = unwrapRendered(\n this.wasm.RenderPreviewBlockHtml(shadow.handle, options.htmlAnchorId));\n } else {\n warnings.push(legacyProfileWarning);\n html = shadow.renderBlock(options.htmlAnchorId);\n }\n } else if (htmlMode === \"full\") {\n if (this.wasm.RenderPreviewHtml) {\n html = unwrapRendered(this.wasm.RenderPreviewHtml(shadow.handle));\n } else {\n warnings.push(legacyProfileWarning);\n html = unwrapRendered(this.wasm.RenderHtmlForReview\n ? this.wasm.RenderHtmlForReview(shadow.handle, \"docx-\", false, false, 1, true)\n : this.wasm.RenderHtml(shadow.handle, \"docx-\", false, false, 1));\n }\n }\n } catch (error) {\n warnings.push(`Preview HTML could not be generated: ${error instanceof Error ? error.message : String(error)}`);\n }\n let retention: MutationPreviewRetention | undefined;\n if (options?.retain) {\n if (!this.wasm.RetainPreview) {\n throw new Error(\"This WASM bundle predates retained previews; rebuild docxodus.\");\n }\n if (!result.success) {\n warnings.push(\"The preview did not succeed, so it was not retained for commit.\");\n } else {\n const retained = JSON.parse(this.wasm.RetainPreview(shadow.handle)) as {\n retention: MutationPreviewRetention | null;\n warnings: readonly string[];\n };\n warnings.push(...retained.warnings);\n retention = retained.retention ?? undefined;\n }\n }\n const preview: MutationBatchResult = retention\n ? { ...result, preview: true, warnings, html, retention }\n : { ...result, preview: true, warnings, html };\n if (retention) {\n if (this.retainedPreviewReceipts.size >= RETAINED_PREVIEW_RECEIPTS) {\n this.retainedPreviewReceipts.delete(this.retainedPreviewReceipts.keys().next().value!);\n }\n this.retainedPreviewReceipts.set(retention.previewId, { ...preview, html: null });\n }\n return preview;\n } finally {\n shadow.close();\n }\n }\n\n /**\n * Project a slice of the document keyed off an anchor \u2014 useful for showing\n * one section to an LLM at a time without paying the cost of projecting the\n * whole document.\n *\n * - `ProjectionDepth.SelfOnly` \u2014 just the addressed block (one paragraph,\n * row, etc.).\n * - `ProjectionDepth.Subtree` \u2014 the block + descendants (e.g. a table with\n * all its rows/cells, but no following content).\n * - `ProjectionDepth.SubtreeAndFollowingSiblings` (default) \u2014 for headings\n * this returns the whole section (heading + content up to the next same-\n * or-higher heading); for non-headings it behaves like `Subtree`.\n *\n * @see docs/architecture/docx_mutation_api.md\n */\n projectAnchor(\n anchorId: string,\n depth?: ProjectionDepth,\n citation?: PageCitationRequest,\n ): DocxSessionProjection {\n // An omitted depth takes the engine's default (SubtreeAndFollowingSiblings), declared once in\n // DocxSessionOps.\n return JSON.parse(\n citation\n ? this.wasm.ProjectAnchorWithCitations(this.handle, anchorId, depth ?? null, JSON.stringify(citation))\n : this.wasm.ProjectAnchor(this.handle, anchorId, depth ?? null),\n ) as DocxSessionProjection;\n }\n\n /**\n * Render a single block to faithful HTML from the live session \u2014 the editor's\n * incremental per-block re-render after an edit. Resolves against the in-memory\n * document (no Save round-trip). `anchorId` is a block anchor (`kind:scope:unid`)\n * or the bare unid carried by a `data-anchor` attribute. Returns the block's HTML\n * element (no `<html>`/`<head>` wrapper).\n */\n renderBlock(\n anchorId: string,\n options?: { cssPrefix?: string; fabricateClasses?: boolean },\n ): string {\n // Omitted options take the engine's defaults (\"docx-\", no fabricated classes), declared once\n // in DocxSessionOps.\n const html = this.wasm.RenderBlockHtml(\n this.handle,\n anchorId,\n options?.cssPrefix ?? null,\n options?.fabricateClasses ?? null,\n );\n // Rendered HTML always begins with '<'; a leading '{' signals an error object.\n if (html.charCodeAt(0) === 0x7b /* '{' */) {\n const err = JSON.parse(html) as { error?: string };\n throw new Error(`renderBlock failed: ${err.error ?? \"unknown error\"}`);\n }\n return html;\n }\n\n // \u2500\u2500\u2500 Tier A: text CRUD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n replaceText(\n anchorId: string,\n markdown: string,\n preconditions?: MutationPreconditions,\n ): EditResult {\n const apply = () => JSON.parse(\n this.wasm.ReplaceText(this.handle, anchorId, markdown),\n ) as EditResult;\n return preconditions\n ? this.runWithPreconditions(\n { ...preconditions, anchorId: preconditions.anchorId ?? anchorId }, apply)\n : apply();\n }\n\n deleteBlock(anchorId: string, preconditions?: MutationPreconditions): EditResult {\n const apply = () => JSON.parse(this.wasm.DeleteBlock(this.handle, anchorId)) as EditResult;\n return preconditions\n ? this.runWithPreconditions(\n { ...preconditions, anchorId: preconditions.anchorId ?? anchorId }, apply)\n : apply();\n }\n\n /** Reorder one top-level paragraph/heading/list/table block relative to another. */\n moveBlock(sourceAnchorId: string, targetAnchorId: string, position: \"before\" | \"after\"): EditResult {\n return JSON.parse(\n this.wasm.MoveBlock(this.handle, sourceAnchorId, targetAnchorId, position),\n ) as EditResult;\n }\n\n /**\n * Delete every top-level block-level sibling between `fromAnchorId` (inclusive)\n * and `toAnchorIdExclusive` (exclusive). Both anchors must share a direct\n * parent and live in the same package part. Returns a single `EditResult`\n * whose `removed` lists every anchor that was deleted.\n *\n * Records ONE undo snapshot \u2014 `undo()` restores the entire range.\n *\n * @see docs/architecture/docx_mutation_api.md#deleterange\n */\n deleteRange(fromAnchorId: string, toAnchorIdExclusive: string): EditResult {\n return JSON.parse(this.wasm.DeleteRange(this.handle, fromAnchorId, toAnchorIdExclusive)) as EditResult;\n }\n\n /**\n * Delete a heading and everything below it up to (but not including) the next\n * heading at the same or higher level. The heading anchor must have `kind === \"h\"`.\n *\n * If the target is the last heading in its parent, the section extends to the\n * end of the parent (heading + everything after).\n *\n * @see docs/architecture/docx_mutation_api.md#deletesection\n */\n deleteSection(headingAnchorId: string): EditResult {\n return JSON.parse(this.wasm.DeleteSection(this.handle, headingAnchorId)) as EditResult;\n }\n\n // \u2500\u2500\u2500 Tier B: structural \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n insertParagraph(anchorId: string, position: \"before\" | \"after\", markdown: string): EditResult {\n return JSON.parse(this.wasm.InsertParagraph(this.handle, anchorId, position, markdown)) as EditResult;\n }\n\n splitParagraph(anchorId: string, characterOffset: number): EditResult {\n return JSON.parse(this.wasm.SplitParagraph(this.handle, anchorId, characterOffset)) as EditResult;\n }\n\n mergeParagraphs(firstAnchorId: string, secondAnchorId: string): EditResult {\n return JSON.parse(this.wasm.MergeParagraphs(this.handle, firstAnchorId, secondAnchorId)) as EditResult;\n }\n\n /**\n * Insert an empty paragraph carrying a bottom border \u2014 an S-1-style horizontal rule \u2014\n * before/after the block. `rule` styles the line (default: a single \u22481.5pt black rule).\n */\n insertHorizontalRule(\n anchorId: string,\n position: \"before\" | \"after\",\n rule?: ParagraphBorderEdge,\n ): EditResult {\n const ruleJson = rule ? JSON.stringify(rule) : \"\";\n return JSON.parse(\n this.wasm.InsertHorizontalRule(this.handle, anchorId, position, ruleJson),\n ) as EditResult;\n }\n\n /**\n * Insert a `rows`\u00D7`cols` table before/after the block. `options` controls borders, row-major\n * cell markdown, and cell alignment. The returned `EditResult.created` lists canonical `tc`\n * anchors (row-major), so each cell can then be addressed to fill/format.\n */\n insertTable(\n anchorId: string,\n position: \"before\" | \"after\",\n rows: number,\n cols: number,\n options?: TableInsertOptions,\n ): EditResult {\n const optionsJson = options ? JSON.stringify(options) : \"\";\n return JSON.parse(\n this.wasm.InsertTable(this.handle, anchorId, position, rows, cols, optionsJson),\n ) as EditResult;\n }\n\n /** Resolve a canonical `tbl` anchor to explicit table/row/column/cell identities. */\n getTableMetadata(tableAnchorId: string): TableMetadataResult {\n return JSON.parse(this.wasm.GetTableMetadata(this.handle, tableAnchorId)) as TableMetadataResult;\n }\n\n /** Resolve a canonical `tc` anchor to its zero-based table-grid coordinate and spans. */\n resolveTableCellAnchor(cellAnchorId: string): TableCellResolutionResult {\n return JSON.parse(\n this.wasm.ResolveTableCellAnchor(this.handle, cellAnchorId),\n ) as TableCellResolutionResult;\n }\n\n /** Resolve a zero-based table-grid coordinate to the physical `tc` covering it. */\n resolveTableCellCoordinate(\n tableAnchorId: string,\n rowIndex: number,\n columnIndex: number,\n ): TableCellResolutionResult {\n return JSON.parse(\n this.wasm.ResolveTableCellCoordinate(this.handle, tableAnchorId, rowIndex, columnIndex),\n ) as TableCellResolutionResult;\n }\n\n /**\n * Table row/column editing, addressed by the canonical `tc` anchor returned from\n * {@link insertTable}'s `created` or table metadata. Insert clones the reference row/column's\n * widths and starts empty (`created` lists new `tc` anchors); delete of the last row/column removes\n * the whole table. All four are grid-aware: inserting across a merge extends it, deleting\n * through one narrows it, and deleting a vertical merge's lead row promotes the next row to\n * carry it \u2014 the grid is never left ragged.\n */\n insertTableRow(cellAnchorId: string, position: \"before\" | \"after\"): EditResult {\n return JSON.parse(this.wasm.InsertTableRow(this.handle, cellAnchorId, position)) as EditResult;\n }\n\n insertTableColumn(cellAnchorId: string, position: \"before\" | \"after\"): EditResult {\n return JSON.parse(this.wasm.InsertTableColumn(this.handle, cellAnchorId, position)) as EditResult;\n }\n\n deleteTableRow(cellAnchorId: string): EditResult {\n return JSON.parse(this.wasm.DeleteTableRow(this.handle, cellAnchorId)) as EditResult;\n }\n\n deleteTableColumn(cellAnchorId: string): EditResult {\n return JSON.parse(this.wasm.DeleteTableColumn(this.handle, cellAnchorId)) as EditResult;\n }\n\n /**\n * Merge the rectangle of cells anchored at `cellAnchorId` running `rowSpan` rows down \u00D7\n * `colSpan` cells right (Word's *Merge Cells*): `w:gridSpan` for the horizontal extent,\n * `w:vMerge` restart/continue for the vertical one. The rectangle must tile the same whole grid\n * columns in every row it covers and must not clip a vertical merge entering from above or\n * continuing below \u2014 a partial overlap fails with `invalid_table_merge` instead of tearing the\n * grid. `content` decides what happens to the absorbed cells' content (default `\"append\"`).\n */\n mergeCells(\n cellAnchorId: string,\n rowSpan: number,\n colSpan: number,\n content: TableMergeContent = \"append\",\n ): EditResult {\n return JSON.parse(\n this.wasm.MergeCells(this.handle, cellAnchorId, rowSpan, colSpan, content),\n ) as EditResult;\n }\n\n /**\n * Split the merged cell at `cellAnchorId` back into unit cells, dropping its `w:gridSpan` and\n * `w:vMerge` markup and restoring one cell per grid column (each taking its `w:tblGrid` width).\n * Addressing a vertical-merge continuation unmerges the whole run. A cell with no merge markup\n * fails with `invalid_table_merge`.\n */\n unmergeCells(cellAnchorId: string): EditResult {\n return JSON.parse(this.wasm.UnmergeCells(this.handle, cellAnchorId)) as EditResult;\n }\n\n /**\n * Table styling, addressed by a canonical `tc` anchor \u2014 the post-insert counterpart of\n * {@link insertTable}'s options (issue #315 Stage A). `setColumnWidths` retunes `w:tblGrid` +\n * every row's cell width (one positive twip value per column) and pins the table to fixed\n * layout, exactly as inserting with explicit `columnWidths` would.\n */\n setColumnWidths(cellAnchorId: string, widthsTwips: number[]): EditResult {\n return JSON.parse(\n this.wasm.SetColumnWidths(this.handle, cellAnchorId, JSON.stringify(widthsTwips)),\n ) as EditResult;\n }\n\n /**\n * Set the table-level borders (`w:tblPr/w:tblBorders`) of the table containing the anchor.\n * Only the edges named by `spec.scope` are written; the rest are left untouched. Style\n * `\"none\"` removes the targeted edges. Omitting `spec` writes a thin single border all round.\n */\n setTableBorders(cellAnchorId: string, spec?: TableBorderSpec): EditResult {\n return JSON.parse(\n this.wasm.SetTableBorders(this.handle, cellAnchorId, spec ? JSON.stringify(spec) : \"\"),\n ) as EditResult;\n }\n\n /**\n * Shade the cell containing the anchor \u2014 or, with scope `\"row\"`, every cell of its row\n * (header-row banding). `fill` is a hex RRGGBB triplet (leading '#' tolerated) or `\"auto\"`;\n * `null` removes the shading.\n */\n setCellShading(\n cellAnchorId: string,\n fill: string | null,\n scope?: TableShadingScope,\n ): EditResult {\n // An omitted scope takes the engine's default (\"cell\"), declared once in the facade.\n return JSON.parse(\n this.wasm.SetCellShading(this.handle, cellAnchorId, fill ?? \"\", scope ?? \"\"),\n ) as EditResult;\n }\n\n /**\n * Mark (or unmark) the row containing the anchor as a repeating header row\n * (`w:trPr/w:tblHeader`), so a multi-page table re-shows it on every page. Word only honors\n * the flag on a run of rows starting at the table's first row. An omitted `repeat` marks the\n * row (the engine's default, `true`).\n */\n setRepeatHeaderRow(cellAnchorId: string, repeat?: boolean): EditResult {\n return JSON.parse(\n this.wasm.SetRepeatHeaderRow(this.handle, cellAnchorId, repeat ?? null),\n ) as EditResult;\n }\n\n /** Apply row layout options to the row containing the canonical cell anchor. */\n setTableRowOptions(cellAnchorId: string, options: TableRowOptions): EditResult {\n return JSON.parse(\n this.wasm.SetTableRowOptions(\n this.handle,\n cellAnchorId,\n options.repeatHeader ?? null,\n options.allowBreakAcrossPages ?? null,\n options.heightTwips ?? null,\n options.heightRule ?? \"atLeast\",\n ),\n ) as EditResult;\n }\n\n // \u2500\u2500\u2500 Headers / footers / page numbers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Set the running header story for the section that owns `anchorId` (any body block in that\n * section) to `markdown`. Creates the header part + `w:headerReference` if the story of `kind`\n * doesn't exist yet, else replaces its content. The created header-paragraph anchors (scope\n * `hdr{N}`) come back in `EditResult.created` \u2014 insert a page number into one with\n * {@link insertPageNumberField}. `\"first\"` sets the section's title-page flag; `\"even\"` sets the\n * document's even/odd-headers flag.\n */\n setHeaderText(anchorId: string, kind: HeaderFooterKind, markdown: string): EditResult {\n return JSON.parse(this.wasm.SetHeaderText(this.handle, anchorId, kind, markdown)) as EditResult;\n }\n\n /** Set the running footer story for the section that owns `anchorId` \u2014 see {@link setHeaderText};\n * the created footer-paragraph anchors (scope `ftr{N}`) come back in `EditResult.created`. */\n setFooterText(anchorId: string, kind: HeaderFooterKind, markdown: string): EditResult {\n return JSON.parse(this.wasm.SetFooterText(this.handle, anchorId, kind, markdown)) as EditResult;\n }\n\n /**\n * Append a page-number field to the paragraph `anchorId` \u2014 typically a header/footer paragraph\n * returned by {@link setFooterText}/{@link setHeaderText}. `\"currentPage\"` emits a PAGE field,\n * `\"totalPages\"` a NUMPAGES field (native complex field with a cached result), and\n * `\"pageOfTotal\"` Word's \"Page X of Y\" gallery entry \u2014 the text `Page `, a PAGE field, the text\n * ` of ` and a NUMPAGES field, every run inheriting the paragraph's last run formatting (the\n * pieces cannot be composed from the single-field form: text after a field cannot be appended\n * without rewriting the field's result). Center it by setting the paragraph alignment\n * ({@link setParagraphFormat}). Returns the paragraph anchor in `modified`.\n *\n * `format` writes the field's own `\\*` general-formatting switch (`PAGE \\* roman` \u2192 `i, ii, iii`).\n * Omitting it \u2014 the default \u2014 emits a plain field, which is what Word inserts and what follows the\n * SECTION's format ({@link setPageNumbering}). Prefer the section setting for ordinary page\n * numbering: a switch here overrides it for this one field and keeps overriding it if the section\n * later changes.\n */\n insertPageNumberField(\n anchorId: string,\n field?: PageNumberField,\n format?: NumberFormat\n ): EditResult {\n // An omitted field takes the engine's default (\"currentPage\"), declared once in DocxSessionOps.\n return JSON.parse(\n this.wasm.InsertPageNumberField(this.handle, anchorId, field ?? \"\", format ?? \"\")\n ) as EditResult;\n }\n\n /**\n * Set the page-numbering properties (`w:pgNumType`) of the section that owns `anchorId` (any body\n * block in that section) \u2014 Word's *Format Page Numbers\u2026* dialog: which number the section starts\n * at and which format its pages use. Omitted fields on `op` are left unchanged, so the start can\n * be set without disturbing the format and vice versa. Creates the element, and a trailing\n * `w:sectPr`, if absent.\n *\n * Applying values the section already has is a successful no-op that does NOT consume undo\n * history \u2014 safe to call from a dropdown's change handler.\n */\n setPageNumbering(anchorId: string, op: PageNumberingOp): EditResult {\n return JSON.parse(\n this.wasm.SetPageNumbering(this.handle, anchorId, JSON.stringify(op))\n ) as EditResult;\n }\n\n /**\n * Insert a **table of contents** before or after `anchorId` (issue #607). The field is written\n * dirty and the document asks for a field update on open, so Word paginates and fills the table\n * itself \u2014 nothing here ships a cached result that is stale the moment anything above it moves.\n *\n * The table is wrapped in the `w:sdt` content control Word puts around one, which is what gives\n * it the *Update Table* control in Word's UI. Word's `TOCHeading` and `TOC1` styles are\n * find-or-created; a document that already defines them keeps its own.\n *\n * Body anchors only, and refused under tracked-change recording: a generated table is regenerated\n * wholesale on every field update, so there is no reversible way to redline it.\n */\n insertTableOfContents(\n anchorId: string,\n pos?: \"before\" | \"after\",\n options?: TableOfContentsOptions\n ): EditResult {\n // An omitted position takes the engine's default for reference fields (\"before\").\n return JSON.parse(\n this.wasm.InsertTableOfContents(\n this.handle, anchorId, pos ?? \"\", options ? JSON.stringify(options) : \"\")\n ) as EditResult;\n }\n\n /**\n * Insert a **table of figures** \u2014 the captions carrying `options.captionLabel` and their page\n * numbers. Same field mechanics as {@link insertTableOfContents}; Word writes this one as a bare\n * paragraph rather than inside a content control, so this does too.\n */\n insertTableOfFigures(\n anchorId: string,\n pos?: \"before\" | \"after\",\n options?: TableOfFiguresOptions\n ): EditResult {\n // An omitted position takes the engine's default for reference fields (\"before\").\n return JSON.parse(\n this.wasm.InsertTableOfFigures(\n this.handle, anchorId, pos ?? \"\", options ? JSON.stringify(options) : \"\")\n ) as EditResult;\n }\n\n /**\n * Insert a **table of authorities** \u2014 the cases, statutes or other authorities marked in the\n * document, grouped by `options.category`. The table lists entries the document has MARKED with\n * `TA` fields; a document with no marked citations produces a table that is correct and empty.\n */\n insertTableOfAuthorities(\n anchorId: string,\n pos?: \"before\" | \"after\",\n options?: TableOfAuthoritiesOptions\n ): EditResult {\n // An omitted position takes the engine's default for reference fields (\"before\").\n return JSON.parse(\n this.wasm.InsertTableOfAuthorities(\n this.handle, anchorId, pos ?? \"\", options ? JSON.stringify(options) : \"\")\n ) as EditResult;\n }\n\n /**\n * Remove the section's page-numbering start/format: it reverts to continuing the previous\n * section's numbering in Word's default `1, 2, 3`. Chapter-numbering attributes\n * (`w:chapStyle`/`w:chapSep`) are preserved. A section with nothing to clear is a no-op.\n */\n clearPageNumbering(anchorId: string): EditResult {\n return JSON.parse(this.wasm.ClearPageNumbering(this.handle, anchorId)) as EditResult;\n }\n\n /**\n * Make the `kind` header/footer stories of the section that owns `anchorId` actually RENDER:\n * `\"first\"` sets `w:titlePg`, `\"even\"` sets the document-global `w:evenAndOddHeaders`;\n * `\"default\"` needs no flag and succeeds as a no-op. Idempotent.\n *\n * {@link setHeaderText}/{@link setFooterText} set these flags while writing content, which covers\n * authoring a story from scratch \u2014 but NOT a document that already carries a first/even reference\n * with the flag absent (Word leaves exactly that behind when \"Different first page\" is switched\n * off). Editing such a story through the text ops otherwise yields header content that is present\n * but invisible. Note the `\"even\"` caveat from {@link setHeaderText}: the flag is document-global\n * and governs footers too.\n */\n ensureHeaderFooterVisible(anchorId: string, kind: HeaderFooterKind): EditResult {\n return JSON.parse(this.wasm.EnsureHeaderFooterVisible(this.handle, anchorId, kind)) as EditResult;\n }\n\n /**\n * Word's \"Different first page\" / \"Different odd & even pages\" checkboxes as one verb: switch\n * the `kind` story of the section that owns `anchorId` (any body block in it) on or off.\n * `enabled: true` is exactly {@link ensureHeaderFooterVisible}; `enabled: false` removes the\n * flag that selects the story \u2014 `w:titlePg` from the governing `w:sectPr` for `\"first\"`, the\n * document-global `w:evenAndOddHeaders` for `\"even\"` \u2014 and leaves the story parts in place,\n * which is what Word does when the checkbox is cleared (re-enabling brings the content straight\n * back). Disabling `\"default\"` fails with `invalid_page_setup`: that story has no flag.\n *\n * A flag already in the requested state is a successful no-op that records NO undo step, so a\n * checkbox handler can call this unconditionally. Read the current state from\n * {@link SectionInfo.titlePage} / {@link SectionInfo.evenAndOddHeaders}.\n */\n setHeaderFooterKindEnabled(anchorId: string, kind: HeaderFooterKind, enabled: boolean): EditResult {\n if (!this.wasm.SetHeaderFooterKindEnabled) {\n throw new Error(\"SetHeaderFooterKindEnabled is not available in this WASM build\");\n }\n return JSON.parse(\n this.wasm.SetHeaderFooterKindEnabled(this.handle, anchorId, kind, enabled)\n ) as EditResult;\n }\n\n /**\n * Set the page geometry (`w:pgSz` / `w:pgMar`) of the section that owns `anchorId` \u2014 Word's\n * *Page Setup* dialog: page size, orientation, margins and header/footer distance. Omitted\n * fields on `op` are left unchanged; the elements are created in schema order when absent, as\n * is a trailing `w:sectPr` for a body that has none. Read the result back with\n * {@link getSectionInfo}.\n *\n * `landscape: true` without an explicit size swaps a portrait-shaped page's width and height\n * (and `false` swaps back), matching Word's orientation toggle. Invalid geometry \u2014 a\n * non-positive size, a negative margin, or opposing margins that leave no room \u2014 fails with\n * `invalid_page_setup` and touches nothing. Values the section already has are a successful\n * no-op that consumes no undo history.\n */\n setPageSetup(anchorId: string, op: PageSetupOp): EditResult {\n if (!this.wasm.SetPageSetup) {\n throw new Error(\"SetPageSetup is not available in this WASM build\");\n }\n return JSON.parse(\n this.wasm.SetPageSetup(this.handle, anchorId, JSON.stringify(op))\n ) as EditResult;\n }\n\n // \u2500\u2500\u2500 Footnotes / endnotes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Create a footnote whose body is `markdown` and cite it from the body paragraph `anchorId`, at\n * `characterOffset` characters into that paragraph's text (0 = before all text, text length =\n * after all of it). On a document with no footnotes yet this also creates the footnotes part,\n * Word's two reserved separator notes, the `FootnoteText`/`FootnoteReference` styles and the\n * `w:footnotePr` settings declaration; otherwise the existing part is reused. The note id is\n * allocated above every id already used in the package, so non-contiguous ids can't collide.\n *\n * Returns the created note anchors in `EditResult.created` \u2014 the definition (kind `fn`) and its\n * paragraphs (kind `p`, scope `fn`) \u2014 so the note can immediately be edited with\n * {@link replaceText} or removed with {@link deleteBlock} (which also drops the body reference).\n *\n * Body paragraphs only: Word does not allow a note reference inside a header/footer story or\n * inside another note, so a non-body anchor fails with `anchorWrongKind`.\n */\n insertFootnote(anchorId: string, characterOffset: number, markdown: string): EditResult {\n return JSON.parse(\n this.wasm.InsertFootnote(this.handle, anchorId, characterOffset, markdown),\n ) as EditResult;\n }\n\n /**\n * Insert a Word-faithful internal cross-reference \u2014 a `REF` field targeting an existing\n * bookmark \u2014 at a character offset (issue #545). The field carries a cached result run\n * (the bookmarked text, or the target's auto-number under `referenceNumber`), so\n * renderers that do not recompute fields show a faithful snapshot and Word updates it\n * like a hand-authored cross-reference. A missing or incoherent bookmark fails with\n * `missing_bookmark_target`.\n */\n insertCrossReference(\n anchorId: string,\n characterOffset: number,\n bookmarkName: string,\n options?: CrossReferenceOptions,\n ): EditResult {\n return JSON.parse(\n this.wasm.InsertCrossReference(\n this.handle, anchorId, characterOffset, bookmarkName,\n options ? JSON.stringify(options) : \"\",\n ),\n ) as EditResult;\n }\n\n /**\n * The document's footnotes (`endnotes` false) or endnotes (`endnotes` true) in citation order.\n * Each entry is the note's `w:id`, its definition anchor (kind `fn`/`en`, the anchor\n * {@link replaceText} and {@link deleteBlock} take) and its 1-based `ordinal`, which is the\n * number Word displays for it. Notes are found through their body references, so Word's\n * separator notes and a note nothing cites are not listed.\n */\n listNotes(endnotes: boolean): NoteListEntry[] {\n if (!this.wasm.ListNotes) {\n throw new Error(\"ListNotes is not available in this WASM build\");\n }\n return JSON.parse(this.wasm.ListNotes(this.handle, endnotes)) as NoteListEntry[];\n }\n\n /** Create an endnote \u2014 see {@link insertFootnote}; writes the endnotes part and a\n * `w:endnoteReference`, and the created definition anchor has kind `en`. */\n insertEndnote(anchorId: string, characterOffset: number, markdown: string): EditResult {\n return JSON.parse(\n this.wasm.InsertEndnote(this.handle, anchorId, characterOffset, markdown),\n ) as EditResult;\n }\n\n // \u2500\u2500\u2500 Comments (issue #300) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Add a **native Word comment** (real `w:comment` markup, visible in Word/Google\n * Docs/LibreOffice's Reviewing pane \u2014 not the {@link addAnnotation} overlay) on the body\n * paragraph `anchorId`. `span` selects the commented character range; `null` comments the\n * whole block. On a document with no comments yet this also creates the comments part and\n * the `CommentText`/`CommentReference` styles. `opts.date` (ISO-8601) is written only when\n * provided, keeping output deterministic by default.\n *\n * Returns the created definition anchor (kind `cmt`) and its paragraph anchors (kind `p`,\n * scope `cmt`) in `EditResult.created`, so the comment can immediately be edited with\n * {@link updateComment} or removed with {@link removeComment}.\n *\n * Body paragraphs only (Word has no comments-on-comments); a non-body anchor fails with\n * `anchor_wrong_kind`, a zero-length span with `empty_comment_span`.\n */\n addComment(\n anchorId: string,\n span: CharSpan | null,\n author: string,\n markdown: string,\n opts?: { initials?: string; date?: string },\n ): EditResult {\n const spanJson = span ? JSON.stringify(span) : \"\";\n return JSON.parse(\n this.wasm.AddComment(\n this.handle,\n anchorId,\n spanJson,\n author,\n opts?.initials ?? \"\",\n opts?.date ?? \"\",\n markdown,\n ),\n ) as EditResult;\n }\n\n /** Add a native Word comment around the exact live extent of a tracked revision returned by\n * {@link listRevisions}. Accepting/rejecting the revision keeps the comment and either leaves\n * its range on surviving text or collapses it to a point. */\n addCommentToRevision(\n revisionId: string,\n author: string,\n markdown: string,\n opts?: { initials?: string; date?: string },\n ): EditResult {\n return JSON.parse(\n this.wasm.AddCommentToRevision(\n this.handle,\n revisionId,\n author,\n opts?.initials ?? \"\",\n opts?.date ?? \"\",\n markdown,\n ),\n ) as EditResult;\n }\n\n /**\n * Add a native Word reply to `parentCommentAnchorId`. It adds an adjacent reference and\n * inherits the thread root's range through `w15:paraIdParent`; the required\n * `commentsExtended.xml` and `commentsIds.xml` parts are created when the parent was flat.\n */\n addCommentReply(\n parentCommentAnchorId: string,\n author: string,\n markdown: string,\n opts?: { initials?: string; date?: string },\n ): EditResult {\n return JSON.parse(\n this.wasm.AddCommentReply(\n this.handle,\n parentCommentAnchorId,\n author,\n opts?.initials ?? \"\",\n opts?.date ?? \"\",\n markdown,\n ),\n ) as EditResult;\n }\n\n /** Replace a comment's body text, addressed by its definition anchor (kind `cmt`); the\n * comment's author/initials/date are preserved, as is the last paragraph's `w14:paraId`\n * (Word's reply-threading key). */\n updateComment(commentAnchorId: string, markdown: string): EditResult {\n return JSON.parse(this.wasm.UpdateComment(this.handle, commentAnchorId, markdown)) as EditResult;\n }\n\n /** Resolve or reopen one comment (`false` reopens it). Flat comments are upgraded with the\n * paraId-keyed metadata Word uses, and the operation is undoable. */\n setCommentResolved(commentAnchorId: string, resolved: boolean): EditResult {\n return JSON.parse(\n this.wasm.SetCommentResolved(this.handle, commentAnchorId, resolved),\n ) as EditResult;\n }\n\n /** Remove a comment: the definition, its body marker triple everywhere in the package, and\n * any `commentsExtended`/`commentsIds` threading entries keyed by it. */\n removeComment(commentAnchorId: string): EditResult {\n return JSON.parse(this.wasm.RemoveComment(this.handle, commentAnchorId)) as EditResult;\n }\n\n /** The document's native Word comments in comments-part order. */\n listComments(): CommentListEntry[] {\n return JSON.parse(this.wasm.ListComments(this.handle)) as CommentListEntry[];\n }\n\n listHyperlinks(scopes: ProjectionScopes = ProjectionScopes.All): HyperlinkInfo[] {\n return JSON.parse(this.wasm.ListHyperlinks(this.handle, scopes)) as HyperlinkInfo[];\n }\n\n addHyperlink(anchorId: string, span: CharSpan, kind: HyperlinkKind, target: string): EditResult {\n return JSON.parse(this.wasm.AddHyperlink(\n this.handle, anchorId, span.start, span.length, kind, target,\n )) as EditResult;\n }\n\n updateHyperlink(hyperlinkId: string, kind: HyperlinkKind, target: string): EditResult {\n return JSON.parse(this.wasm.UpdateHyperlink(this.handle, hyperlinkId, kind, target)) as EditResult;\n }\n\n removeHyperlink(hyperlinkId: string): EditResult {\n return JSON.parse(this.wasm.RemoveHyperlink(this.handle, hyperlinkId)) as EditResult;\n }\n\n /** Versioned operational facts for native image inspection/mutation in this runtime. */\n getImageCapabilities(): ImageCapabilities {\n return JSON.parse(this.wasm.GetImageCapabilities()) as ImageCapabilities;\n }\n\n listImages(scopes: ProjectionScopes = ProjectionScopes.All): ImageOccurrence[] {\n return JSON.parse(this.wasm.ListImages(this.handle, scopes)) as ImageOccurrence[];\n }\n\n insertImage(anchorId: string, characterOffset: number, bytes: Uint8Array,\n options: ImageInsertOptions = {}): EditResult {\n return JSON.parse(this.wasm.InsertImage(this.handle, anchorId, characterOffset,\n imageBytesToBase64(bytes), JSON.stringify(options))) as EditResult;\n }\n\n replaceImage(imageId: string, bytes: Uint8Array): EditResult {\n return JSON.parse(this.wasm.ReplaceImage(\n this.handle, imageId, imageBytesToBase64(bytes))) as EditResult;\n }\n\n /**\n * Convert an external linked picture into an embedded one using bytes the caller fetched;\n * the engine never reaches the network itself. Refused for pictures that already embed\n * their media \u2014 see `ImageOccurrence.operations`.\n */\n embedLinkedImage(imageId: string, bytes: Uint8Array): EditResult {\n return JSON.parse(this.wasm.EmbedLinkedImage(\n this.handle, imageId, imageBytesToBase64(bytes))) as EditResult;\n }\n\n setImageDimensions(imageId: string, dimensions: ImageDimensions): EditResult {\n return JSON.parse(this.wasm.SetImageDimensions(\n this.handle, imageId, JSON.stringify(dimensions))) as EditResult;\n }\n\n setImageMetadata(imageId: string, altText: string | null, title: string | null): EditResult {\n return JSON.parse(this.wasm.SetImageMetadata(\n this.handle, imageId, altText, title)) as EditResult;\n }\n\n setImageFloatingLayout(imageId: string, layout: FloatingImageLayout): EditResult {\n return JSON.parse(this.wasm.SetImageFloatingLayout(\n this.handle, imageId, JSON.stringify(layout))) as EditResult;\n }\n\n removeImage(imageId: string): EditResult {\n return JSON.parse(this.wasm.RemoveImage(this.handle, imageId)) as EditResult;\n }\n\n /** Native Word structured-document tags, in outer-before-inner story order. */\n listContentControls(scopes: ProjectionScopes = ProjectionScopes.All): ContentControlInfo[] {\n return JSON.parse(this.wasm.ListContentControls(this.handle, scopes)) as ContentControlInfo[];\n }\n\n fillContentControlText(anchorId: string, text: string,\n options: ContentControlFillOptions = {}): EditResult {\n return JSON.parse(this.wasm.FillContentControlText(\n this.handle, anchorId, text, JSON.stringify(options))) as EditResult;\n }\n\n fillContentControlRichText(anchorId: string, markdown: string,\n options: ContentControlFillOptions = {}): EditResult {\n return JSON.parse(this.wasm.FillContentControlRichText(\n this.handle, anchorId, markdown, JSON.stringify(options))) as EditResult;\n }\n\n setContentControlChecked(anchorId: string, isChecked: boolean,\n options: ContentControlFillOptions = {}): EditResult {\n return JSON.parse(this.wasm.SetContentControlChecked(\n this.handle, anchorId, isChecked, JSON.stringify(options))) as EditResult;\n }\n\n setContentControlDate(anchorId: string, value: string | Date, displayText?: string,\n options: ContentControlFillOptions = {}): EditResult {\n const timestamp = value instanceof Date ? value.toISOString() : value;\n return JSON.parse(this.wasm.SetContentControlDate(\n this.handle, anchorId, timestamp, displayText ?? null, JSON.stringify(options))) as EditResult;\n }\n\n selectContentControlItem(anchorId: string, value: string,\n options: ContentControlFillOptions = {}): EditResult {\n return JSON.parse(this.wasm.SelectContentControlItem(\n this.handle, anchorId, value, JSON.stringify(options))) as EditResult;\n }\n\n fillContentControlPicture(anchorId: string, bytes: Uint8Array,\n options: ContentControlFillOptions = {}): EditResult {\n return JSON.parse(this.wasm.FillContentControlPicture(\n this.handle, anchorId, imageBytesToBase64(bytes), JSON.stringify(options))) as EditResult;\n }\n\n addRepeatingSectionItem(sectionAnchorId: string, afterItemAnchorId?: string,\n options: ContentControlFillOptions = {}): EditResult {\n return JSON.parse(this.wasm.AddRepeatingSectionItem(\n this.handle, sectionAnchorId, afterItemAnchorId ?? \"\", JSON.stringify(options))) as EditResult;\n }\n\n removeRepeatingSectionItem(itemAnchorId: string): EditResult {\n return JSON.parse(this.wasm.RemoveRepeatingSectionItem(\n this.handle, itemAnchorId)) as EditResult;\n }\n\n listBookmarks(scopes: ProjectionScopes = ProjectionScopes.All): BookmarkInfo[] {\n return JSON.parse(this.wasm.ListBookmarks(this.handle, scopes)) as BookmarkInfo[];\n }\n\n addBookmark(name: string, range: DocumentRange): EditResult {\n return JSON.parse(this.wasm.AddBookmark(this.handle, name,\n range.startAnchorId, range.startOffset, range.endAnchorId, range.endOffset)) as EditResult;\n }\n\n renameBookmark(name: string, newName: string): EditResult {\n return JSON.parse(this.wasm.RenameBookmark(this.handle, name, newName)) as EditResult;\n }\n\n moveBookmark(name: string, range: DocumentRange): EditResult {\n return JSON.parse(this.wasm.MoveBookmark(this.handle, name,\n range.startAnchorId, range.startOffset, range.endAnchorId, range.endOffset)) as EditResult;\n }\n\n removeBookmark(name: string): EditResult {\n return JSON.parse(this.wasm.RemoveBookmark(this.handle, name)) as EditResult;\n }\n\n // \u2500\u2500\u2500 Tracked revisions (issue #318) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Markup-native tracked-revision listing, in document order across body, headers,\n * footers, footnotes, and endnotes. Ids are stable while the underlying markup\n * exists and address {@link acceptRevision}/{@link rejectRevision}; authors/dates\n * are the markup's own (no accept/reject re-diff). */\n listRevisions(filter?: RevisionListFilter): RevisionListEntry[] {\n if (filter && Object.values(filter).some((v) => v != null)) {\n if (!this.wasm.ListRevisionsFiltered) {\n throw new Error(\"This WASM bundle predates filtered revision listing; rebuild docxodus.\");\n }\n return JSON.parse(\n this.wasm.ListRevisionsFiltered(this.handle, JSON.stringify(filter)),\n ) as RevisionListEntry[];\n }\n return JSON.parse(this.wasm.ListRevisions(this.handle)) as RevisionListEntry[];\n }\n\n /**\n * The explicit repairs the registry offers for entries it refuses to resolve (issues\n * #754\u2013#758): which carriers are defective, whether a unique repair exists, and what it\n * would do. Read-only; listing, accept and reject never repair.\n */\n listRevisionRepairs(): RevisionRepairProposal[] {\n if (!this.wasm.ListRevisionRepairs) {\n throw new Error(\"This WASM bundle predates revision repairs; rebuild docxodus.\");\n }\n return JSON.parse(this.wasm.ListRevisionRepairs(this.handle)) as RevisionRepairProposal[];\n }\n\n /**\n * Perform requested repairs atomically as one undo step. A kind the registry did not offer,\n * a non-repairable proposal, or a wrap-as-deletion without author and date refuses the whole\n * call (`revision_repair_rejected`) with nothing mutated. Repaired entries get new ids.\n */\n repairRevisions(repairs: readonly RevisionRepairRequest[]): RevisionRepairResult {\n if (!this.wasm.RepairRevisions) {\n throw new Error(\"This WASM bundle predates revision repairs; rebuild docxodus.\");\n }\n return JSON.parse(this.wasm.RepairRevisions(this.handle, JSON.stringify(repairs))) as RevisionRepairResult;\n }\n\n /** Accept ONE revision by the id {@link listRevisions} reported \u2014 insertions keep\n * their content, deletions are carried out, a move materializes at its destination,\n * a format change keeps the new properties. Undoable. */\n acceptRevision(revisionId: string): EditResult {\n return JSON.parse(this.wasm.AcceptRevision(this.handle, revisionId)) as EditResult;\n }\n\n /** Reject ONE revision by id \u2014 the inverse of {@link acceptRevision}: insertions are\n * removed, deleted content is restored, a move stays at its source, a format change\n * restores the stored old properties. Undoable. */\n rejectRevision(revisionId: string): EditResult {\n return JSON.parse(this.wasm.RejectRevision(this.handle, revisionId)) as EditResult;\n }\n\n /**\n * Accept every live revision as one undoable session mutation.\n *\n * Fails closed: an unsupported, malformed, or ambiguous registry entry aborts the whole\n * operation (`revisionUnsupported`/`revisionMalformed`/`revisionAmbiguous`) and nothing is\n * mutated. There is no force mode \u2014 call {@link listRevisions} and read each entry's\n * `diagnostic` to see what blocks it.\n */\n acceptAllRevisions(): EditResult {\n return JSON.parse(this.wasm.AcceptAllRevisions(this.handle)) as EditResult;\n }\n\n /** Reject every live revision as one undoable session mutation. Fails closed exactly like\n * {@link acceptAllRevisions}. */\n rejectAllRevisions(): EditResult {\n return JSON.parse(this.wasm.RejectAllRevisions(this.handle)) as EditResult;\n }\n\n // \u2500\u2500\u2500 Tier C: formatting \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n applyFormat(anchorId: string, span: CharSpan | null, op: FormatOp): EditResult {\n const spanJson = span ? JSON.stringify(span) : \"\";\n return JSON.parse(this.wasm.ApplyFormat(this.handle, anchorId, spanJson, JSON.stringify(op))) as EditResult;\n }\n\n /**\n * Convenience: find `substring` in the anchor's flat text and apply `op` to the\n * first occurrence. Eliminates the offset-arithmetic trap from #138 \u2014 caller passes\n * the visible text they want formatted, the WASM-side resolves it to a CharSpan.\n */\n applyFormatBySubstring(anchorId: string, substring: string, op: FormatOp): EditResult {\n return JSON.parse(\n this.wasm.ApplyFormatBySubstring(this.handle, anchorId, substring, JSON.stringify(op))\n ) as EditResult;\n }\n\n /**\n * Convenience: apply `op` to the exact span of a {@link TextMatch} (typically from\n * {@link grep}). The match's `enclosingAnchor.id` + `span` address one specific\n * occurrence even when several identical needles share the same block.\n */\n applyFormatToMatch(match: TextMatch, op: FormatOp): EditResult {\n const span: CharSpan = { start: match.span.start, length: match.span.length };\n return this.applyFormat(match.enclosingAnchor.id, span, op);\n }\n\n setParagraphStyle(anchorId: string, styleId: string): EditResult {\n return JSON.parse(this.wasm.SetParagraphStyle(this.handle, anchorId, styleId)) as EditResult;\n }\n\n /** Set paragraph alignment / indent / page-break-before (omitted fields are left unchanged). */\n setParagraphFormat(anchorId: string, op: ParagraphFormatOp): EditResult {\n return JSON.parse(this.wasm.SetParagraphFormat(this.handle, anchorId, JSON.stringify(op))) as EditResult;\n }\n\n setListLevel(anchorId: string, levelDelta: number): EditResult {\n return JSON.parse(this.wasm.SetListLevel(this.handle, anchorId, levelDelta)) as EditResult;\n }\n\n removeListMembership(anchorId: string): EditResult {\n return JSON.parse(this.wasm.RemoveListMembership(this.handle, anchorId)) as EditResult;\n }\n\n /** Make the paragraph a bullet/numbered list item, or remove list membership (\"none\"). */\n applyListFormat(anchorId: string, kind: ListFormat): EditResult {\n return JSON.parse(this.wasm.ApplyListFormat(this.handle, anchorId, kind)) as EditResult;\n }\n\n /** Apply one list format across the contiguous sibling run from `firstAnchorId` to\n * `lastAnchorId` inclusive (either document order). Every member shares one `w:num`\n * instance so the numbering sequence stays intact; the whole range is a single undo step. */\n applyListFormatRange(firstAnchorId: string, lastAnchorId: string, kind: ListFormat): EditResult {\n return JSON.parse(\n this.wasm.ApplyListFormatRange(this.handle, firstAnchorId, lastAnchorId, kind),\n ) as EditResult;\n }\n\n /** Restart the anchored list item's numbering at `value` \u2014 Word's *Set Numbering Value\u2026*.\n * Writes a `w:startOverride` on a dedicated `w:num` instance and repoints the anchored item\n * plus every following member of its sequence, so a mid-list restart splits the sequence\n * exactly like Word (earlier items keep their numbers, the tail continues from `value`). */\n setListStartOverride(anchorId: string, value: number): EditResult {\n return JSON.parse(this.wasm.SetListStartOverride(this.handle, anchorId, value)) as EditResult;\n }\n\n /** Remove the numbering restart from the anchored item's whole sequence (the inverse of\n * {@link setListStartOverride}); the sequence reverts to the definition's own start. A\n * sequence with no override at the item's level is a successful no-op. */\n clearListStartOverride(anchorId: string): EditResult {\n return JSON.parse(this.wasm.ClearListStartOverride(this.handle, anchorId)) as EditResult;\n }\n\n // \u2500\u2500\u2500 Tier D: cell content \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n replaceCellContent(cellAnchorId: string, markdown: string): EditResult {\n return JSON.parse(this.wasm.ReplaceCellContent(this.handle, cellAnchorId, markdown)) as EditResult;\n }\n\n // \u2500\u2500\u2500 Raw escape hatch \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n readonly raw = {\n getXml: (anchorId: string): string => this.wasm.RawGetXml(this.handle, anchorId),\n insertXml: (anchorId: string, position: \"before\" | \"after\", xml: string): EditResult =>\n JSON.parse(this.wasm.RawInsertXml(this.handle, anchorId, position, xml)) as EditResult,\n replaceXml: (anchorId: string, xml: string): EditResult =>\n JSON.parse(this.wasm.RawReplaceXml(this.handle, anchorId, xml)) as EditResult,\n };\n\n // \u2500\u2500\u2500 Search \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Searches the flat text of every paragraph/heading/list-item in scope for\n * matches of `pattern`, returning them in document order with the run\n * fragments each match spans. Lets callers rewrite a match in place while\n * preserving each fragment's formatting (bold/italic/hyperlink/etc.).\n *\n * `pattern` is a regular expression \u2014 use plain string equivalents wrapped\n * in `^` / `$` or pass literal text escaped via a helper.\n *\n * @see docs/architecture/docx_mutation_api.md#grep\n */\n grep(pattern: string, options?: GrepOptions): TextMatch[] {\n return JSON.parse(this.wasm.Grep(this.handle, pattern, options ? JSON.stringify(options) : \"\")) as TextMatch[];\n }\n\n /**\n * Like {@link grep}, but lets a single match span adjacent block-level\n * siblings (paragraphs/headings/list items) under the same parent. Block\n * boundaries appear in the matched text as `\\n`, so `^`/`$` with the\n * Multiline flag anchor at boundaries and `.` won't cross unless Singleline\n * is set.\n *\n * Matches never cross OOXML package parts, container boundaries (body \u2192\n * table cell), or non-paragraph siblings (a table between two paragraphs\n * breaks the run). Returned superset of {@link grep}: single-block matches\n * still appear with one slice. Filter `slices.length > 1` for cross-block only.\n *\n * @see docs/architecture/docx_mutation_api.md#grepcrossblock\n */\n grepCrossBlock(pattern: string, options?: GrepOptions): CrossBlockMatch[] {\n return JSON.parse(\n this.wasm.GrepCrossBlock(this.handle, pattern, options ? JSON.stringify(options) : \"\")\n ) as CrossBlockMatch[];\n }\n\n /**\n * Finds every literal occurrence of `find` in the anchor's flat text and\n * replaces it with `replace`, preserving the surrounding run formatting that\n * the match didn't touch. Returns one `EditResult` per attempted match.\n *\n * A `find` that matches nothing fails with a single `text_not_found` result\n * naming the anchor and the needle \u2014 never an empty array. Pass\n * `expectedMatchCount: 0` to assert absence as a successful no-op instead.\n *\n * Run-formatting contract: the replacement text inherits the formatting of\n * the FIRST run the match spanned. Middle/trailing runs keep their `w:rPr`\n * but lose the slice of text the match consumed.\n *\n * @see docs/architecture/docx_mutation_api.md#replacetextrange\n */\n replaceTextRange(anchorId: string, find: string, replace: string, options?: ReplaceOptions): EditResult[] {\n return JSON.parse(\n this.wasm.ReplaceTextRange(this.handle, anchorId, find, replace, options ? JSON.stringify(options) : \"\")\n ) as EditResult[];\n }\n\n /**\n * Replaces a specific Grep match in place \u2014 addresses the exact span by\n * `enclosingAnchor.id` + `span.{start,length}`, so identical needles in the\n * same paragraph (the template-fill case where five `[___]` placeholders\n * each get a different value) don't collide.\n *\n * Pass `format` to replace text and format exactly the replacement atomically, with one\n * undo/version unit. This interactive path returns an ordinary EditResult and avoids the\n * package checkpoint/hash required by executeBatch's receipt. Empty replacements only delete.\n */\n replaceMatch(match: TextMatch, replace: string, format?: FormatOp): EditResult {\n if (format !== undefined) {\n if (!this.wasm.ReplaceTextAtSpanWithFormat) {\n throw new Error(\"This WASM bundle predates atomic text-plus-format edits; rebuild docxodus.\");\n }\n return JSON.parse(this.wasm.ReplaceTextAtSpanWithFormat(\n this.handle, match.enclosingAnchor.id, match.span.start, match.span.length, replace,\n JSON.stringify(format),\n )) as EditResult;\n }\n return JSON.parse(\n this.wasm.ReplaceTextAtSpan(this.handle, match.enclosingAnchor.id, match.span.start, match.span.length, replace)\n ) as EditResult;\n }\n\n /**\n * Helper for {@link fillPlaceholders} `coalesceWhitespaceAroundEmptyFill` path \u2014\n * mirrors the .NET `ReplaceMatchCoalescingNeighbors` rules. Inspects the chars\n * immediately surrounding the match via `match.contextBefore` / `contextAfter`\n * (so the option requires `contextChars >= 1`, the default) and expands the\n * deletion span to absorb whitespace / leading-space-before-punctuation /\n * matched-brackets where the patterns match. Falls back to literal-delete\n * when no neighbor pattern applies.\n *\n * Note: with `boundary: ContextBoundary.Bracket`, neighbor brackets are not\n * captured in context, so the bracket-coalesce rule won't fire on the JS side.\n * The .NET implementation reads flat text directly and handles that case;\n * callers who care should leave `boundary` at the default `Char`.\n */\n private replaceMatchCoalescingNeighbors(match: TextMatch): EditResult {\n // Fold NBSP / narrow NBSP / thin space to ASCII space so e.g. an NBSP on\n // either side still gets treated as whitespace by the rules below.\n const fold = (c: string | undefined): string | undefined => {\n if (c === \"\u00A0\" || c === \"\u202F\" || c === \"\u2009\") return \" \";\n return c;\n };\n const l = fold(match.contextBefore.length > 0 ? match.contextBefore[match.contextBefore.length - 1] : undefined);\n const r = fold(match.contextAfter.length > 0 ? match.contextAfter[0] : undefined);\n\n const isSpace = (c: string | undefined): boolean => c === \" \" || c === \"\\t\";\n const isClauseTerm = (c: string | undefined): boolean =>\n c === \".\" || c === \",\" || c === \";\" || c === \":\" || c === \"!\" || c === \"?\";\n const isOpen = (c: string | undefined): boolean => c === \"(\" || c === \"[\" || c === \"{\";\n const isClose = (c: string | undefined): boolean => c === \")\" || c === \"]\" || c === \"}\";\n\n let extendLeft = 0;\n let extendRight = 0;\n if (isSpace(l) && isSpace(r)) {\n extendRight = 1;\n } else if (isSpace(l) && isClauseTerm(r)) {\n extendLeft = 1;\n } else if (isOpen(l) && isClose(r)) {\n extendLeft = 1;\n extendRight = 1;\n }\n\n if (extendLeft === 0 && extendRight === 0) {\n return this.replaceMatch(match, \"\");\n }\n\n return JSON.parse(\n this.wasm.ReplaceTextAtSpan(\n this.handle,\n match.enclosingAnchor.id,\n match.span.start - extendLeft,\n match.span.length + extendLeft + extendRight,\n \"\",\n ),\n ) as EditResult;\n }\n\n /**\n * Replace the bracketed portion of a `TextMatch` with `newInner`, preserving any\n * prefix or suffix outside the brackets. Designed for `findPlaceholders` matches\n * like `$[___]` where the regex `\\$?\\[\u2026\\]` captures a leading `$`:\n * `replaceInner(match, \"0.20\")` yields `$0.20`, not `0.20`.\n *\n * Returns `MalformedMarkdown` if the match text does not contain balanced brackets.\n */\n replaceInner(match: TextMatch, newInner: string): EditResult {\n return JSON.parse(this.wasm.ReplaceInner(\n this.handle,\n match.text,\n match.enclosingAnchor.id,\n match.span.start,\n match.span.length,\n newInner,\n )) as EditResult;\n }\n\n /**\n * Picker-driven template fill. For every placeholder matching `options.kinds`,\n * calls `picker`; if the picker returns a non-null string, the placeholder is\n * replaced (with optional `$`-prefix preservation). Iterates until no more\n * placeholders match (or `maxPasses` is reached, or a pass makes zero changes)\n * \u2014 handles nested brackets that surface only after the inner ones are stripped.\n *\n * The TypeScript implementation mirrors the .NET `DocxSession.FillPlaceholders`\n * exactly.\n *\n * The picker is invoked synchronously by this loop on the JS side (it does\n * NOT run inside the WASM module). Async pickers are not supported: returning\n * a `Promise` will cause a `TypeError` at runtime inside the `$`-prefix\n * preservation branch (`Promise.startsWith is not a function`). For async\n * data, pre-build a lookup map before calling and have the picker read from\n * it synchronously.\n */\n fillPlaceholders(\n picker: (p: TemplatePlaceholder) => string | null | undefined,\n options?: FillOptions,\n ): BulkEditResult {\n const opts = options ?? {};\n // Default Kinds = All so the picker is invoked for every kind the doc contains.\n // Callers that want to ignore AlternativeClause matches should narrow this to\n // `PlaceholderKinds.BlankFill | PlaceholderKinds.Instruction`.\n const kinds = opts.kinds ?? PlaceholderKinds.All;\n const scope = opts.scope ?? 1; // Body\n const maxPasses = opts.maxPasses ?? 8;\n const preserveDollarPrefix = opts.preserveDollarPrefix ?? true;\n const contextChars = opts.contextChars;\n const boundary = opts.boundary ?? ContextBoundary.Char;\n const coalesceEmpty = opts.coalesceWhitespaceAroundEmptyFill ?? false;\n\n if (maxPasses <= 0) {\n throw new RangeError(\"FillOptions.maxPasses must be > 0\");\n }\n\n let filled = 0;\n let workPasses = 0;\n const errors: EditError[] = [];\n const unfilled: TemplatePlaceholder[] = [];\n const seenSkipKeys = new Set<string>();\n\n for (let pass = 1; pass <= maxPasses; pass++) {\n const placeholders = this.findPlaceholders(kinds, scope, contextChars, boundary)\n .sort((a, b) => {\n const cmp = b.match.enclosingAnchor.id.localeCompare(a.match.enclosingAnchor.id);\n if (cmp !== 0) return cmp;\n return b.match.span.start - a.match.span.start;\n });\n if (placeholders.length === 0) break;\n\n let passChanges = 0;\n for (const p of placeholders) {\n const pick = picker(p);\n if (pick == null) {\n const key = `${p.match.enclosingAnchor.id}:${p.match.span.start}:${p.match.span.length}`;\n if (!seenSkipKeys.has(key)) {\n seenSkipKeys.add(key);\n unfilled.push(p);\n }\n continue;\n }\n\n let replacement = pick;\n if (preserveDollarPrefix && p.match.text.startsWith(\"$\") && !replacement.startsWith(\"$\")) {\n replacement = \"$\" + replacement;\n }\n\n const r = coalesceEmpty && replacement.length === 0\n ? this.replaceMatchCoalescingNeighbors(p.match)\n : this.replaceMatch(p.match, replacement);\n if (r.success) {\n filled++;\n passChanges++;\n } else if (r.error) {\n errors.push(r.error);\n }\n }\n\n if (passChanges > 0) workPasses = pass;\n if (passChanges === 0) break;\n }\n\n const stillPresent = this.findPlaceholders(kinds, scope).length;\n\n return {\n filled,\n skipped: unfilled.length,\n stillPresent,\n passes: workPasses,\n unfilled,\n errors,\n };\n }\n\n /**\n * Enumerate template placeholders in the document. Thin classifier over\n * {@link grep}: distinguishes `[___]` value blanks (`blank_fill`),\n * `[bracketed alternative clauses]` (`alternative_clause`), and\n * `[insert X]` / `[*italic hint*]` instructions (`instruction`).\n *\n * Combine kinds with bitwise OR: `PlaceholderKinds.BlankFill | PlaceholderKinds.Instruction`.\n * Default is `PlaceholderKinds.All`; default scope is body only (1).\n *\n * @see docs/architecture/docx_mutation_api.md#findplaceholders\n */\n findPlaceholders(\n kinds?: number,\n scope?: number,\n contextChars?: number,\n boundary?: number,\n citation?: PageCitationRequest,\n ): TemplatePlaceholder[] {\n // Omitted arguments take the engine's defaults (all kinds, the body, 80 characters, cut at a\n // character), declared once in DocxSessionOps and DocxSession.\n const json = citation\n ? this.wasm.FindPlaceholdersWithCitations(\n this.handle, kinds ?? null, scope ?? null, contextChars ?? null, boundary ?? null,\n JSON.stringify(citation),\n )\n : this.wasm.FindPlaceholders(\n this.handle, kinds ?? null, scope ?? null, contextChars ?? null, boundary ?? null);\n return JSON.parse(json) as TemplatePlaceholder[];\n }\n\n /**\n * Returns a snapshot of edit-state introspection signals \u2014 placeholder counts,\n * underscore-run leftovers, footnote/comment counts. Useful for \"am I done?\"\n * verification at the end of an edit pipeline.\n */\n getEditSummary(): EditSummary {\n return JSON.parse(this.wasm.GetEditSummary(this.handle)) as EditSummary;\n }\n\n /**\n * Discoverability alias for {@link findPlaceholders}. Same return shape.\n */\n remainingPlaceholders(kinds?: number): TemplatePlaceholder[] {\n return JSON.parse(this.wasm.RemainingPlaceholders(this.handle, kinds ?? null)) as TemplatePlaceholder[];\n }\n\n /**\n * Diff the document's current projection against the projection captured at\n * session construction time.\n *\n * Requires `captureInitialProjection: true` in {@link DocxSessionSettings}\n * (the default). Throws if not enabled.\n *\n * The return type depends on `format`:\n * - `DiffFormat.Json` (default) \u2014 structured anchor-keyed `DiffEntry[]`.\n * - `DiffFormat.Unified` \u2014 `patch(1)`-compatible unified-diff text;\n * empty string when nothing has changed.\n * - `DiffFormat.SideBySide` \u2014 two-column human-review text\n * (`diff -y` style).\n */\n getDiff(format?: typeof DiffFormat.Json): DiffEntry[];\n getDiff(format: typeof DiffFormat.Unified | typeof DiffFormat.SideBySide): string;\n getDiff(format?: number): DiffEntry[] | string {\n // An omitted format reaches the engine as null and takes its default (JSON, declared once in\n // DocxSessionOps); the overloads above promise the parsed form for it.\n const raw = this.wasm.GetDiff(this.handle, format ?? null);\n if (format == null || format === DiffFormat.Json) {\n return JSON.parse(raw) as DiffEntry[];\n }\n return raw;\n }\n\n /**\n * Return stable semantic changes from the package opened for this session to\n * its current state. Requires `captureInitialProjection` (enabled by default).\n */\n getSemanticChanges(): SemanticChangeSet {\n return JSON.parse(this.wasm.GetSemanticChanges(this.handle)) as SemanticChangeSet;\n }\n\n /**\n * Run the default deliverable gate on this session's normal clean-save checkpoint.\n * With initial projection capture enabled (the default), exact opening bytes are the\n * baseline used for dispositions and semantic/package deltas.\n */\n verifyDeliverable(request?: DeliverableVerificationRequest): DeliverableVerificationResult {\n if (request !== undefined) {\n // The full request (issue #747): policy/limit options, expected deltas, companions.\n if (!this.wasm.VerifyDeliverableWithRequest) {\n throw new Error(\"This WASM bundle predates full verification requests; rebuild docxodus.\");\n }\n return JSON.parse(this.wasm.VerifyDeliverableWithRequest(\n this.handle, serializeVerificationRequest(request))) as DeliverableVerificationResult;\n }\n return JSON.parse(\n this.wasm.VerifyDeliverable(this.handle),\n ) as DeliverableVerificationResult;\n }\n\n // \u2500\u2500\u2500 Annotation-based anchor discovery (#132) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Resolves an annotation's range to the block-level markdown anchors covering\n * it, in document order. The bridge between Docxodus' read-side annotation API\n * and the write-side session: an agent that wants to edit \"the indemnification\n * clause\" looks the annotation up by id and gets the anchors it can hand to\n * {@link replaceText} / {@link deleteBlock} / {@link raw}. Returns an empty\n * list when the id is unknown or its bookmark is missing.\n *\n * v1 returns the enclosing block anchors \u2014 every paragraph/heading/list-item/\n * cell/row/table whose subtree overlaps the bookmark range. Filter by\n * `kind === \"p\" | \"h\" | \"li\"` when you want only text-bearing blocks.\n *\n * @see docs/architecture/docx_mutation_api.md#findbyannotation\n */\n findByAnnotation(annotationId: string, citation?: PageCitationRequest): AnchorTargetRef[] {\n const json = citation\n ? this.wasm.FindByAnnotationWithCitations(this.handle, annotationId, JSON.stringify(citation))\n : this.wasm.FindByAnnotation(this.handle, annotationId);\n return JSON.parse(json) as AnchorTargetRef[];\n }\n\n /**\n * Finds every annotation whose `labelId` matches and resolves each of their\n * ranges. The result is keyed by annotation id so callers can disambiguate\n * when the same label is applied to multiple regions (three \"WARRANTY\"\n * annotations on different paragraphs become three entries). Annotations\n * whose bookmark resolves to no anchors are omitted from the result.\n */\n findByLabel(labelId: string, citation?: PageCitationRequest): Record<string, AnchorTargetRef[]> {\n const json = citation\n ? this.wasm.FindByLabelWithCitations(this.handle, labelId, JSON.stringify(citation))\n : this.wasm.FindByLabel(this.handle, labelId);\n return JSON.parse(json) as Record<string, AnchorTargetRef[]>;\n }\n\n /**\n * Resolves any bookmark in the main document part (Docxodus-managed or\n * user-authored) to the block-level anchors covering its range, in document\n * order. Empty when the bookmark name is unknown. Use this for raw bookmark\n * names that didn't come from the annotation system.\n */\n findByBookmark(bookmarkName: string, citation?: PageCitationRequest): AnchorTargetRef[] {\n const json = citation\n ? this.wasm.FindByBookmarkWithCitations(this.handle, bookmarkName, JSON.stringify(citation))\n : this.wasm.FindByBookmark(this.handle, bookmarkName);\n return JSON.parse(json) as AnchorTargetRef[];\n }\n\n // \u2500\u2500\u2500 Text/kind-based anchor discovery (#171) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * True when `anchorId` resolves to a live element in the current session.\n * Cheap existence probe \u2014 use it to guard an anchor obtained from an earlier\n * projection before handing it to a mutation (anchors can be invalidated by\n * intervening edits; see the anchor lifecycle table in the mutation docs).\n */\n exists(anchorId: string): boolean {\n return this.wasm.Exists(this.handle, anchorId);\n }\n\n /**\n * Find the first block-level anchor (in document order) whose flat text\n * contains `needle`, or `null` when nothing matches. `options` tune case /\n * whitespace handling and narrow the search by kind or scope. For all\n * matches use {@link findAllByText}.\n */\n findByText(needle: string, options?: FindOptions): AnchorTargetRef | null {\n return JSON.parse(\n this.wasm.FindByText(this.handle, needle, options ? JSON.stringify(options) : \"\"),\n ) as AnchorTargetRef | null;\n }\n\n /**\n * Like {@link findByText} but returns every matching anchor in document\n * order (empty when nothing matches).\n */\n findAllByText(needle: string, options?: FindOptions): AnchorTargetRef[] {\n return JSON.parse(\n this.wasm.FindAllByText(this.handle, needle, options ? JSON.stringify(options) : \"\"),\n ) as AnchorTargetRef[];\n }\n\n /**\n * Find every block-level anchor whose flat text matches the regular\n * expression `pattern`, in document order. `regexOptions` uses the numeric\n * layout of .NET `RegexOptions` (e.g. `1` = IgnoreCase); `options` is the\n * same shape as {@link findByText} (its `ignoreCase` composes with the regex\n * flag). Defaults to `regexOptions = 0` (none).\n */\n findByRegex(pattern: string, regexOptions?: number, options?: FindOptions): AnchorTargetRef[] {\n return JSON.parse(\n this.wasm.FindByRegex(\n this.handle, pattern, regexOptions ?? null, options ? JSON.stringify(options) : \"\"),\n ) as AnchorTargetRef[];\n }\n\n /**\n * Return every anchor of the given `kind` \u2014 one of `\"p\"`, `\"h\"`, `\"li\"`,\n * `\"tbl\"`, `\"tr\"`, `\"tc\"`, `\"col\"`, `\"sdt\"`, `\"sec\"`, `\"fn\"`, `\"en\"`,\n * `\"cmt\"`, `\"unk\"` \u2014 in document order. Matching is an exact string comparison;\n * in particular the row and cell tokens are `\"tr\"` and `\"tc\"`, never\n * `\"row\"`/`\"cell\"`. Unknown strings are not parsed or rejected: they simply\n * return an empty array. `\"img\"` and `\"drw\"` likewise return empty because the\n * projection never assigns those reserved kinds; address images through the\n * image surface instead. Reads the projection's anchor\n * index directly \u2014 no text scan. Pass `scope` (e.g. `\"body\"`) to restrict to\n * a single part; omit it to span all scopes.\n */\n findByKind(kind: string, scope?: string, citation?: PageCitationRequest): AnchorTargetRef[] {\n const json = citation\n ? this.wasm.FindByKindWithCitations(\n this.handle, kind, scope ?? \"\", JSON.stringify(citation),\n )\n : this.wasm.FindByKind(this.handle, kind, scope ?? \"\");\n return JSON.parse(json) as AnchorTargetRef[];\n }\n\n /**\n * Look up a single anchor's preview info \u2014 `{ id, kind, scope, textPreview }`.\n * Returns null when the anchor id is unknown.\n *\n * For iterating many anchors at once, prefer reading `textPreview` directly\n * off the {@link MarkdownProjection.anchorIndex} entries (cheaper \u2014 no extra\n * WASM round trip), or use {@link getAnchorInfos} for batched lookups.\n */\n getAnchorInfo(anchorId: string): AnchorInfo | null {\n const raw = this.wasm.GetAnchorInfo(this.handle, anchorId);\n return JSON.parse(raw) as AnchorInfo | null;\n }\n\n /**\n * Bulk variant of {@link getAnchorInfo}: takes an array of anchor ids,\n * returns a record where each unknown id maps to `null`.\n */\n getAnchorInfos(anchorIds: readonly string[]): Record<string, AnchorInfo | null> {\n const raw = this.wasm.GetAnchorInfos(this.handle, JSON.stringify(anchorIds));\n return JSON.parse(raw) as Record<string, AnchorInfo | null>;\n }\n\n /**\n * Resolve block-level metadata (style id+name, outline level, list membership,\n * formatting probe) for an anchor. Returns null when the anchor doesn't exist.\n */\n getBlockMetadata(anchorId: string): BlockMetadata | null {\n const raw = this.wasm.GetBlockMetadata(this.handle, anchorId);\n return JSON.parse(raw) as BlockMetadata | null;\n }\n\n /**\n * Bulk variant of {@link getBlockMetadata}. Unknown ids map to null;\n * duplicates are deduped.\n */\n getBlockMetadatas(anchorIds: readonly string[]): Record<string, BlockMetadata | null> {\n const raw = this.wasm.GetBlockMetadatas(this.handle, JSON.stringify(anchorIds));\n return JSON.parse(raw) as Record<string, BlockMetadata | null>;\n }\n\n /**\n * Resolve the numbering facts for a list-item paragraph; returns null when\n * the anchor has no w:numPr.\n */\n getListMembership(anchorId: string): ListMembership | null {\n const raw = this.wasm.GetListMembership(this.handle, anchorId);\n return JSON.parse(raw) as ListMembership | null;\n }\n\n /**\n * Resolve page-layout info for the w:sectPr that governs an anchor.\n * Returns null for anchors outside the body part.\n */\n getSectionInfo(anchorId: string): SectionInfo | null {\n const raw = this.wasm.GetSectionInfo(this.handle, anchorId);\n return JSON.parse(raw) as SectionInfo | null;\n }\n\n /** Enumerate the document's explicit style catalog with resolved high-signal properties. */\n listStyles(): StyleInfo[] {\n return JSON.parse(this.wasm.ListStyles(this.handle)) as StyleInfo[];\n }\n\n /** Inspect direct and effective paragraph/run formatting for one paragraph anchor. */\n getFormatting(anchorId: string): FormattingInspection | null {\n return JSON.parse(this.wasm.GetFormatting(this.handle, anchorId)) as FormattingInspection | null;\n }\n\n /** Enumerate text-bearing runs as mutation-compatible anchor/span pairs. */\n listInlineSpans(anchorId: string): InlineSpan[] {\n return JSON.parse(this.wasm.ListInlineSpans(this.handle, anchorId)) as InlineSpan[];\n }\n\n /**\n * Enumerates every annotation persisted in the document. Lets an agent prime\n * itself with \"here are the labeled regions you can target\" before committing\n * to a specific id.\n */\n listAnnotations(): DocumentAnnotation[] {\n return JSON.parse(this.wasm.ListAnnotations(this.handle)) as DocumentAnnotation[];\n }\n\n // \u2500\u2500\u2500 Annotation write surface \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Annotate a range inside `anchorId`. When `span` is `null`/`undefined`\n * the annotation wraps every inline run of the block. When\n * `annotation.id` is `undefined`, a 16-char hex id is auto-generated and\n * returned in `EditResult.annotationId`.\n */\n addAnnotation(\n anchorId: string,\n span: CharSpan | null,\n annotation: DocumentAnnotation,\n ): EditResult {\n const spanJson = span ? JSON.stringify(span) : \"\";\n return JSON.parse(\n this.wasm.AddAnnotation(this.handle, anchorId, spanJson, JSON.stringify(annotation)),\n ) as EditResult;\n }\n\n removeAnnotation(annotationId: string): EditResult {\n return JSON.parse(this.wasm.SessionRemoveAnnotation(this.handle, annotationId)) as EditResult;\n }\n\n updateAnnotation(annotationId: string, update: AnnotationUpdate): EditResult {\n return JSON.parse(\n this.wasm.UpdateAnnotation(this.handle, annotationId, JSON.stringify(update)),\n ) as EditResult;\n }\n\n moveAnnotation(\n annotationId: string,\n newAnchorId: string,\n newSpan: CharSpan | null,\n ): EditResult {\n const spanJson = newSpan ? JSON.stringify(newSpan) : \"\";\n return JSON.parse(\n this.wasm.MoveAnnotation(this.handle, annotationId, newAnchorId, spanJson),\n ) as EditResult;\n }\n\n // \u2500\u2500\u2500 Lifecycle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Switch how subsequent mutations are recorded (issue #304). Session configuration,\n * not a document mutation: not undoable, and already-applied markup is never touched.\n */\n setTrackedChanges(mode: TrackedChangeMode): void {\n this.wasm.SetTrackedChanges(this.handle, mode);\n }\n\n /** Author stamped on subsequent tracked-change markup; `null` restores the \"docxodus\" default. */\n setRevisionAuthor(author: string | null): void {\n this.wasm.SetRevisionAuthor(this.handle, author ?? \"\");\n }\n\n undo(): boolean {\n return this.wasm.Undo(this.handle);\n }\n\n redo(): boolean {\n return this.wasm.Redo(this.handle);\n }\n\n save(): Uint8Array {\n return this.wasm.Save(this.handle);\n }\n\n close(): void {\n this.retainedPreviewReceipts.clear();\n this.wasm.CloseSession(this.handle);\n }\n\n // TypeScript 5.2+ disposable protocol\n [Symbol.dispose]?(): void {\n this.close();\n }\n}\n\nfunction imageBytesToBase64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let offset = 0; offset < bytes.length; offset += 0x8000) {\n binary += String.fromCharCode(...bytes.subarray(offset, offset + 0x8000));\n }\n return globalThis.btoa(binary);\n}\n\n/**\n * Opens a new {@link DocxSession} over the supplied DOCX bytes.\n * The returned session holds its document in WASM memory until you call\n * {@link DocxSession.close} (or it is disposed).\n */\nexport function openDocxSession(\n bytes: Uint8Array,\n wasmExports: DocxodusWasmExports,\n settings?: DocxSessionSettings,\n): DocxSession {\n const bridge = wasmExports.DocxSessionBridge;\n const handle = bridge.OpenSession(bytes, settings ? JSON.stringify(settings) : \"\");\n return new DocxSession(handle, bridge);\n}\n\nexport type { AnchorInfo, AnchorRef, AnchorTargetRef, BlockSlice, CharSpan, CommentListEntry, CrossBlockMatch, CrossReferenceOptions, DocumentAnnotation, DocxSessionProjection, DocxSessionSettings, EditError, EditErrorCode, EditResult, FindOptions, FormatOp, FormattingInspection, GrepOptions, InlineSpan, MarkdownPatch, MarkdownPatchBlock, MutationBatchChangeSet, MutationBatchFailure, MutationBatchMode, MutationBatchPreviewOptions, MutationBatchPreviewStep, MutationBatchResult, MutationBatchStep, MutationBatchStepResult, MutationPreconditions, PageCitation, PageCitationRequest, PageMapRegistrationResult, PageMapStatus, ParagraphFormatting, PlaceholderKind, PreconditionFailure, PreconditionTarget, ReplaceOptions, RunFormatting, RunFormattingInfo, RunFragment, StyleInfo, TableStyleFormatting, TemplatePlaceholder, TextMatch, TextRangePrecondition } from \"./types.js\";\nexport { ContextBoundary, PlaceholderKinds } from \"./types.js\";\n", "import type { ConversionOptions } from \"./types.js\";\n\n/**\n * The conversion options only the complete WASM entry point\n * (`DocumentConverter.ConvertDocxToHtmlComplete`) accepts. Setting any of them, even to its\n * default, routes a conversion there; the plain and pagination entry points would drop it.\n *\n * The main-thread `convertDocxToHtml` and the worker's both read this list, so a new\n * complete-only option is added here once rather than to two copies that can drift.\n */\nexport const COMPLETE_ONLY_CONVERSION_OPTIONS = [\n \"renderFootnotesAndEndnotes\",\n \"renderHeadersAndFooters\",\n \"renderTrackedChanges\",\n \"showDeletedContent\",\n \"renderMoveOperations\",\n \"renderUnsupportedContentPlaceholders\",\n \"documentLanguage\",\n \"stampAnchors\",\n \"revisionPresentation\",\n \"semanticLists\",\n] as const satisfies readonly (keyof ConversionOptions)[];\n\n/**\n * Whether a conversion must use the complete entry point: any complete-only option is set,\n * or annotations are rendered.\n */\nexport function needsCompleteConversion(options: ConversionOptions | undefined): boolean {\n if (!options) return false;\n return options.renderAnnotations === true ||\n COMPLETE_ONLY_CONVERSION_OPTIONS.some(key => options[key] !== undefined);\n}\n", "/**\n * Wire-shape readers for the external annotation family.\n *\n * The engine serializes these results with PascalCase property names (and older builds with\n * camelCase), so every consumer has to normalize them once. The main-thread entry points in\n * `core.ts` and the Web Worker (`docxodus.worker.ts`) both read through here, which is what\n * lets the worker hand back the same typed objects the main thread would without a second\n * copy of the mapping.\n */\n\nimport type {\n AnnotationLabel,\n ExternalAnnotationSet,\n ExternalAnnotationValidationResult,\n OpenContractDocExport,\n OpenContractsAnnotation,\n OpenContractsRelationship,\n OpenContractsSinglePageAnnotation,\n PawlsPage,\n TextSpan,\n} from \"./types.js\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nfunction readPawlsPage(p: any): PawlsPage {\n return {\n page: {\n width: p.Page?.Width ?? p.page?.width,\n height: p.Page?.Height ?? p.page?.height,\n index: p.Page?.Index ?? p.page?.index,\n },\n tokens: (p.Tokens || p.tokens || []).map((t: any) => ({\n x: t.X ?? t.x,\n y: t.Y ?? t.y,\n width: t.Width ?? t.width,\n height: t.Height ?? t.height,\n text: t.Text ?? t.text,\n })),\n };\n}\n\nfunction readAnnotationJson(\n json: any,\n): TextSpan | Record<string, OpenContractsSinglePageAnnotation> | undefined {\n if (!json) return undefined;\n\n // A text span carries offsets; anything else is a page-keyed dictionary.\n if (json.Start !== undefined || json.start !== undefined) {\n return {\n id: json.Id ?? json.id,\n start: json.Start ?? json.start,\n end: json.End ?? json.end,\n text: json.Text ?? json.text,\n };\n }\n\n const result: Record<string, OpenContractsSinglePageAnnotation> = {};\n for (const [key, value] of Object.entries(json)) {\n const v = value as any;\n result[key] = {\n bounds: {\n top: v.Bounds?.Top ?? v.bounds?.top,\n bottom: v.Bounds?.Bottom ?? v.bounds?.bottom,\n left: v.Bounds?.Left ?? v.bounds?.left,\n right: v.Bounds?.Right ?? v.bounds?.right,\n },\n tokensJsons: (v.TokensJsons || v.tokensJsons || []).map((t: any) => ({\n pageIndex: t.PageIndex ?? t.pageIndex,\n tokenIndex: t.TokenIndex ?? t.tokenIndex,\n })),\n rawText: v.RawText ?? v.rawText,\n };\n }\n return result;\n}\n\nfunction readAnnotation(a: any): OpenContractsAnnotation {\n return {\n id: a.Id ?? a.id,\n annotationLabel: a.AnnotationLabel ?? a.annotationLabel,\n rawText: a.RawText ?? a.rawText,\n page: a.Page ?? a.page,\n annotationJson: readAnnotationJson(a.AnnotationJson ?? a.annotationJson),\n parentId: a.ParentId ?? a.parentId,\n annotationType: a.AnnotationType ?? a.annotationType,\n structural: a.Structural ?? a.structural,\n };\n}\n\nfunction readRelationship(r: any): OpenContractsRelationship {\n return {\n id: r.Id ?? r.id,\n relationshipLabel: r.RelationshipLabel ?? r.relationshipLabel,\n sourceAnnotationIds: r.SourceAnnotationIds ?? r.sourceAnnotationIds ?? [],\n targetAnnotationIds: r.TargetAnnotationIds ?? r.targetAnnotationIds ?? [],\n structural: r.Structural ?? r.structural,\n };\n}\n\nfunction readLabel(l: any): AnnotationLabel {\n return {\n id: l.Id ?? l.id,\n color: l.Color ?? l.color,\n description: l.Description ?? l.description ?? \"\",\n icon: l.Icon ?? l.icon ?? \"\",\n text: l.Text ?? l.text,\n labelType: l.LabelType ?? l.labelType ?? \"text\",\n };\n}\n\nfunction readLabels(raw: any): Record<string, AnnotationLabel> {\n const labels: Record<string, AnnotationLabel> = {};\n for (const [key, value] of Object.entries(raw || {})) labels[key] = readLabel(value);\n return labels;\n}\n\n/** Read an OpenContracts document export from the engine's parsed JSON. */\nexport function readOpenContractExport(parsed: any): OpenContractDocExport {\n return {\n title: parsed.Title ?? parsed.title,\n content: parsed.Content ?? parsed.content,\n description: parsed.Description ?? parsed.description,\n pageCount: parsed.PageCount ?? parsed.pageCount,\n pawlsFileContent: (parsed.PawlsFileContent || parsed.pawlsFileContent || []).map(readPawlsPage),\n docLabels: parsed.DocLabels ?? parsed.docLabels ?? [],\n labelledText: (parsed.LabelledText || parsed.labelledText || []).map(readAnnotation),\n relationships: (parsed.Relationships || parsed.relationships)?.map(readRelationship),\n };\n}\n\n/** Read an external annotation set \u2014 an OpenContracts export plus identity and label tables. */\nexport function readExternalAnnotationSet(parsed: any): ExternalAnnotationSet {\n return {\n documentId: parsed.DocumentId ?? parsed.documentId,\n documentHash: parsed.DocumentHash ?? parsed.documentHash,\n createdAt: parsed.CreatedAt ?? parsed.createdAt,\n updatedAt: parsed.UpdatedAt ?? parsed.updatedAt,\n version: parsed.Version ?? parsed.version,\n ...readOpenContractExport(parsed),\n textLabels: readLabels(parsed.TextLabels || parsed.textLabels),\n docLabelDefinitions: readLabels(parsed.DocLabelDefinitions || parsed.docLabelDefinitions),\n };\n}\n\n/** Read the result of validating an annotation set against a document. */\nexport function readExternalAnnotationValidation(parsed: any): ExternalAnnotationValidationResult {\n return {\n isValid: parsed.IsValid ?? parsed.isValid,\n hashMismatch: parsed.HashMismatch ?? parsed.hashMismatch,\n issues: (parsed.Issues || parsed.issues || []).map((i: any) => ({\n annotationId: i.AnnotationId ?? i.annotationId,\n issueType: i.IssueType ?? i.issueType,\n description: i.Description ?? i.description,\n expectedText: i.ExpectedText ?? i.expectedText,\n actualText: i.ActualText ?? i.actualText,\n })),\n };\n}\n\n/** The engine wraps projected HTML in a small JSON envelope; unwrap it. */\nexport function readProjectedHtml(parsed: any): string {\n return parsed.Html ?? parsed.html;\n}\n", "import type { VerificationDigest } from './types.js';\n\n/** Nonnegative Int64 decimal string, never a JS number. Sequence orders content; time does not. */\nexport type HistoryPosition = string;\nexport interface HistoryBlobReference { digest: VerificationDigest; length: number }\nexport interface HistoryHead { revision: HistoryPosition; state: HistoryBlobReference }\nexport interface HistoryHeadInitializationResult { initialized: boolean; head: HistoryHead }\nexport interface DocxHistoryArchiveInfo { documentId: string; head: HistoryHead; blobCount: number; totalBlobBytes: HistoryPosition }\nexport interface DocxHistoryImportResult { archive: DocxHistoryArchiveInfo; view: DocxHistoryView; alreadyPresent: boolean }\nexport const MAX_HISTORY_ARCHIVE_BYTES = 64 * 1024 * 1024;\nexport interface HistoryRequestIdentity { id: string; fingerprint: VerificationDigest }\nexport interface HistoryRequestJournal {\n documentId: string;\n revision: HistoryPosition;\n index: HistoryBlobReference | null;\n current: HistoryRequestIdentity | null;\n}\nexport interface DocxSnapshotReference { blob: HistoryBlobReference; contentDigest: VerificationDigest }\nexport interface DocxVersionMetadata {\n author: string;\n createdAt: string;\n label?: string | null;\n message?: string | null;\n applicationMetadata?: Readonly<Record<string, string>>;\n}\nexport interface DocxVersionRecord {\n documentId: string;\n metadata: DocxVersionMetadata;\n nonce: string;\n parent: HistoryBlobReference | null;\n restoredFrom: HistoryBlobReference | null;\n sequence: HistoryPosition;\n snapshot: DocxSnapshotReference;\n}\nexport interface DocxStoredVersion { id: HistoryBlobReference; record: DocxVersionRecord }\nexport interface DocxHistoryState {\n requests?: HistoryRequestJournal;\n parentPublication?: HistoryHead;\n operation?: HistoryBlobReference;\n commit: HistoryBlobReference | null;\n documentId: string;\n epoch: HistoryPosition;\n initialSnapshot: DocxSnapshotReference;\n sequence: HistoryPosition;\n snapshot: DocxSnapshotReference;\n version: HistoryBlobReference;\n}\nexport interface DocxHistoryView { head: HistoryHead; state: DocxHistoryState; version: DocxStoredVersion }\nexport interface DocxVersionPage { versions: DocxStoredVersion[]; next: HistoryBlobReference | null }\nexport interface PackageHistoryCommit {\n after: DocxSnapshotReference;\n before: DocxSnapshotReference;\n contribution: HistoryBlobReference | null;\n documentId: string;\n epoch: HistoryPosition;\n kind: 'import' | 'restore';\n parent: HistoryBlobReference | null;\n sequence: HistoryPosition;\n version: HistoryBlobReference;\n}\nexport interface DocxHistoryLogEntry { id: HistoryBlobReference; commit: PackageHistoryCommit; metadata: DocxVersionMetadata }\nexport interface DocxHistoryUpdate {\n after: HistoryHead | null;\n view: DocxHistoryView;\n entries: DocxHistoryLogEntry[];\n reset: boolean;\n}\nexport interface DocxTextSplice { partUri: string; textNode: number; offset: number; deleteCount: number; insert: string }\nexport interface DocxOperationRequest {\n requestId: string; base: HistoryHead; kind: 'text' | 'package' | 'discard'; metadata: DocxVersionMetadata;\n text: DocxTextSplice | null; readParts: string[]; resolves: HistoryBlobReference | null;\n}\nexport interface DocxOperationInput { documentId: string; request: DocxOperationRequest; candidate: HistoryBlobReference | null }\nexport interface DocxOperationRecord {\n documentId: string; input: HistoryBlobReference; parent: HistoryBlobReference | null; revision: HistoryPosition;\n before: HistoryHead; proposedSnapshot: DocxSnapshotReference; afterSnapshot: DocxSnapshotReference;\n version: HistoryBlobReference; contentCommit: HistoryBlobReference | null; status: 'accepted' | 'conflict';\n conflict: string | null; appliedText: DocxTextSplice | null;\n}\nexport interface DocxStoredOperation { id: HistoryBlobReference; record: DocxOperationRecord; input: DocxOperationInput }\nexport interface DocxOperationUpdate { after: HistoryHead | null; view: DocxHistoryView; operations: DocxStoredOperation[] }\n\n/** Host-owned storage. Persist blobs before returning; advanceHead must be an atomic CAS.\n * References and returned bytes are verified in the core. Methods must settle their promises.\n * No fetching, subscription, timer, authorization or retention policy is supplied by this API. */\nexport interface HistoryStorage {\n readBlob(reference: HistoryBlobReference): Promise<Uint8Array | null>;\n putBlob(reference: HistoryBlobReference, bytes: Uint8Array): Promise<void>;\n readHead(documentId: string): Promise<HistoryHead | null>;\n advanceHead(documentId: string, expected: HistoryHead | null, state: HistoryBlobReference): Promise<HistoryHead | null>;\n /** Optional import capability. Atomically insert the exact head only if absent; otherwise return\n * the unchanged existing head. Must share exclusion with advanceHead, never overwrite/revise it. */\n initializeHead?(documentId: string, head: HistoryHead): Promise<HistoryHeadInitializationResult>;\n}\n\nexport interface HistoryBridge {\n Open(adapterId: number): number;\n OpenWithInitialization?(adapterId: number): number;\n OpenArchive?(bytes: Uint8Array): Promise<string>;\n Close(handle: number): void;\n Invoke(handle: number, requestJson: string, bytes: Uint8Array): Promise<string>;\n}\n\nexport class DocxHistoryError extends Error {\n constructor(public readonly code: string, message: string) { super(message); this.name = 'DocxHistoryError'; }\n}\n\ninterface Result {\n handle: number | null;\n archive: DocxHistoryArchiveInfo | null;\n import: DocxHistoryImportResult | null;\n success: boolean;\n errorCode: string | null;\n message: string | null;\n view: DocxHistoryView | null;\n version: DocxStoredVersion | null;\n page: DocxVersionPage | null;\n sequence: HistoryPosition | null;\n bytes: string | null;\n update: DocxHistoryUpdate | null;\n operationUpdate: DocxOperationUpdate | null;\n operation: DocxStoredOperation | null;\n}\n\nconst adapters = new Map<number, HistoryStorage>();\nlet nextAdapter = 0;\nfunction adapter(id: number): HistoryStorage {\n const store = adapters.get(id);\n if (!store) throw new DocxHistoryError('Closed', 'History storage adapter is closed.');\n return store;\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n let binary = '';\n for (let offset = 0; offset < bytes.length; offset += 0x8000)\n binary += String.fromCharCode(...bytes.subarray(offset, offset + 0x8000));\n return btoa(binary);\n}\nfunction fromBase64(encoded: string): Uint8Array {\n const binary = atob(encoded);\n return Uint8Array.from(binary, c => c.charCodeAt(0));\n}\n\n/** For custom WASM loaders. initialize() installs these automatically. */\nexport function installHistoryStorageImports(setModuleImports: (name: string, imports: object) => void): void {\n setModuleImports('docxodus.history', {\n readBlob: async (id: number, json: string): Promise<string> => {\n const reference: HistoryBlobReference = JSON.parse(json);\n const bytes = await adapter(id).readBlob(reference);\n if (bytes === null) return '';\n if (bytes.length !== reference.length) throw new DocxHistoryError('PayloadMismatch', 'Stored blob length differs from its reference.');\n return bytes.length === 0 ? '=' : toBase64(bytes);\n },\n putBlob: async (id: number, json: string, bytes: Uint8Array): Promise<void> =>\n adapter(id).putBlob(JSON.parse(json), bytes.slice()),\n readHead: async (id: number, documentId: string): Promise<string> =>\n JSON.stringify(await adapter(id).readHead(documentId)),\n advanceHead: async (id: number, documentId: string, expected: string, state: string): Promise<string> =>\n JSON.stringify(await adapter(id).advanceHead(documentId, JSON.parse(expected), JSON.parse(state))),\n initializeHead: async (id: number, documentId: string, head: string): Promise<string> => {\n const storage = adapter(id);\n if (!storage.initializeHead) throw new DocxHistoryError('InitializationUnsupported', 'Storage cannot import an exact head.');\n return JSON.stringify(await storage.initializeHead(documentId, JSON.parse(head)));\n },\n });\n}\n\n/** Durable package-history client. Reopening over the same adapters preserves history.\n * Await active calls before close(); it releases handles but never deletes host data. */\nexport class DocxHistoryClient {\n private readonly adapterId: number;\n private readonly handle: number;\n private closed = false;\n\n constructor(private readonly bridge: HistoryBridge, storage: HistoryStorage) {\n if (nextAdapter >= 0x7fffffff) throw new Error('History adapter identifiers exhausted.');\n this.adapterId = ++nextAdapter;\n adapters.set(this.adapterId, storage);\n try { this.handle = storage.initializeHead && bridge.OpenWithInitialization\n ? bridge.OpenWithInitialization(this.adapterId) : bridge.Open(this.adapterId); }\n catch (error) { adapters.delete(this.adapterId); throw error; }\n }\n\n close(): void {\n if (this.closed) return;\n this.bridge.Close(this.handle);\n adapters.delete(this.adapterId);\n this.closed = true;\n }\n\n /** Bind an identity without reading, creating a version, or taking ownership of this client. */\n document(documentId: string): DocxHistoryDocument {\n return new DocxHistoryDocument(documentId, (operation, fields, bytes) => this.call(operation, documentId, fields, bytes));\n }\n\n async exportHistoryArchive(documentId: string): Promise<Uint8Array> {\n return fromBase64((await this.call('exportArchive', documentId)).bytes!);\n }\n async importHistoryArchive(bytes: Uint8Array): Promise<DocxHistoryImportResult> {\n checkArchiveSize(bytes);\n return (await this.call('importArchive', '', {}, bytes)).import!;\n }\n\n async read(documentId: string): Promise<DocxHistoryView | null> {\n return (await this.call('read', documentId)).view;\n }\n /** Host-triggered validated metadata tail; first join starts at the latest checkpoint. */\n async readChangesSince(documentId: string, after: HistoryHead | null, maxEntriesToScan = 10_000): Promise<DocxHistoryUpdate> {\n return (await this.call('updates', documentId, { expectedHead: after, maxEntriesToScan })).update!;\n }\n async readOperationsSince(documentId: string, after: HistoryHead | null, maxEntriesToScan = 10_000): Promise<DocxOperationUpdate> {\n return (await this.call('operations', documentId, { expectedHead: after, maxEntriesToScan })).operationUpdate!;\n }\n async getOperation(documentId: string, operationId: HistoryBlobReference): Promise<DocxStoredOperation> {\n return (await this.call('getOperation', documentId, { operationId })).operation!;\n }\n async exportOperationProposal(documentId: string, operationId: HistoryBlobReference): Promise<Uint8Array> {\n return fromBase64((await this.call('exportOperationProposal', documentId, { operationId })).bytes!);\n }\n async compareVersions(documentId: string, beforeVersionId: HistoryBlobReference, afterVersionId: HistoryBlobReference): Promise<Uint8Array> {\n return fromBase64((await this.call('compare', documentId, { beforeVersionId, afterVersionId })).bytes!);\n }\n async createVersion(documentId: string, expectedHead: HistoryHead | null, bytes: Uint8Array,\n metadata: DocxVersionMetadata, requestId?: string): Promise<DocxHistoryView> {\n return (await this.call('create', documentId, { expectedHead, metadata, requestId }, bytes)).view!;\n }\n async listVersions(documentId: string, cursor: HistoryBlobReference | null = null, limit = 25): Promise<DocxVersionPage> {\n return (await this.call('list', documentId, { versionId: cursor, limit })).page!;\n }\n async getVersion(documentId: string, versionId: HistoryBlobReference): Promise<DocxStoredVersion> {\n return (await this.call('get', documentId, { versionId })).version!;\n }\n async exportVersion(documentId: string, versionId: HistoryBlobReference): Promise<Uint8Array> {\n return fromBase64((await this.call('export', documentId, { versionId })).bytes!);\n }\n async materialize(documentId: string, sequence: HistoryPosition, maxEntriesToScan = 10_000): Promise<Uint8Array> {\n return fromBase64((await this.call('materialize', documentId, { sequence, maxEntriesToScan })).bytes!);\n }\n async replay(documentId: string, sequence: HistoryPosition, maxEntriesToScan = 10_000): Promise<Uint8Array> {\n return fromBase64((await this.call('replay', documentId, { sequence, maxEntriesToScan })).bytes!);\n }\n async resolveSequenceAtTime(documentId: string, cutoff: string, maxEntriesToScan = 10_000): Promise<HistoryPosition> {\n return (await this.call('resolveTime', documentId, { cutoff, maxEntriesToScan })).sequence!;\n }\n async restoreVersion(documentId: string, expectedHead: HistoryHead, versionId: HistoryBlobReference,\n metadata: DocxVersionMetadata, requestId?: string): Promise<DocxHistoryView> {\n return (await this.call('restore', documentId, { expectedHead, versionId, metadata, requestId })).view!;\n }\n\n private async call(operation: string, documentId: string, fields: object = {}, bytes: Uint8Array = new Uint8Array()): Promise<Result> {\n if (this.closed) throw new DocxHistoryError('Closed', 'History client is closed.');\n return parseResult(await this.bridge.Invoke(this.handle,\n JSON.stringify({ schemaVersion: 1, operation, documentId, ...fields }), bytes));\n }\n}\n\ntype HistoryCall = (operation: string, fields?: object, bytes?: Uint8Array) => Promise<Result>;\n\n/** Document-scoped reads. No method publishes or changes an editor. */\nexport class DocxHistoryReader {\n readonly #documentId: string;\n get documentId(): string { return this.#documentId; }\n /** @internal Obtain through client.document() or openDocxHistoryArchive(). */\n constructor(documentId: string, protected readonly call: HistoryCall) { this.#documentId = documentId; }\n async read(): Promise<DocxHistoryView | null> { return (await this.call('read')).view; }\n async listVersions(cursor: HistoryBlobReference | null = null, limit = 25): Promise<DocxVersionPage> {\n return (await this.call('list', { versionId: cursor, limit })).page!;\n }\n async getVersion(versionId: HistoryBlobReference): Promise<DocxStoredVersion> {\n return (await this.call('get', { versionId })).version!;\n }\n /** Omit versionId for latest; pass an ID to keep a UI operation pinned to a captured version. */\n async exportDocx(versionId: HistoryBlobReference | null = null): Promise<Uint8Array> {\n return fromBase64((await this.call('exportDocx', { versionId })).bytes!);\n }\n async exportHistoryArchive(): Promise<Uint8Array> { return fromBase64((await this.call('exportArchive')).bytes!); }\n async materialize(sequence: HistoryPosition, maxEntriesToScan = 10_000): Promise<Uint8Array> {\n return fromBase64((await this.call('materialize', { sequence, maxEntriesToScan })).bytes!);\n }\n async replay(sequence: HistoryPosition, maxEntriesToScan = 10_000): Promise<Uint8Array> {\n return fromBase64((await this.call('replay', { sequence, maxEntriesToScan })).bytes!);\n }\n async resolveSequenceAtTime(cutoff: string, maxEntriesToScan = 10_000): Promise<HistoryPosition> {\n return (await this.call('resolveTime', { cutoff, maxEntriesToScan })).sequence!;\n }\n async readChangesSince(after: HistoryHead | null, maxEntriesToScan = 10_000): Promise<DocxHistoryUpdate> {\n return (await this.call('updates', { expectedHead: after, maxEntriesToScan })).update!;\n }\n async readOperationsSince(after: HistoryHead | null, maxEntriesToScan = 10_000): Promise<DocxOperationUpdate> {\n return (await this.call('operations', { expectedHead: after, maxEntriesToScan })).operationUpdate!;\n }\n async getOperation(operationId: HistoryBlobReference): Promise<DocxStoredOperation> {\n return (await this.call('getOperation', { operationId })).operation!;\n }\n async exportOperationProposal(operationId: HistoryBlobReference): Promise<Uint8Array> {\n return fromBase64((await this.call('exportOperationProposal', { operationId })).bytes!);\n }\n /** Redlined DOCX through DocxCompare's existing accepted-input revision policy. */\n async compareVersions(beforeVersionId: HistoryBlobReference, afterVersionId: HistoryBlobReference): Promise<Uint8Array> {\n return fromBase64((await this.call('compare', { beforeVersionId, afterVersionId })).bytes!);\n }\n}\n\n/** Explicit checkpoint/restore controls over host-owned storage; request IDs are required here. */\nexport class DocxHistoryDocument extends DocxHistoryReader {\n async createVersion(expectedHead: HistoryHead | null, bytes: Uint8Array, metadata: DocxVersionMetadata,\n requestId: string): Promise<DocxHistoryView> {\n requireRequestId(requestId);\n return (await this.call('create', { expectedHead, metadata, requestId }, bytes)).view!;\n }\n async restoreVersion(expectedHead: HistoryHead, versionId: HistoryBlobReference, metadata: DocxVersionMetadata,\n requestId: string): Promise<DocxHistoryView> {\n requireRequestId(requestId);\n return (await this.call('restore', { expectedHead, versionId, metadata, requestId })).view!;\n }\n}\n\n/** Standalone readonly file. Owns its handle and captured bytes; await calls before close(). */\nexport class DocxHistoryArchive extends DocxHistoryReader {\n private closed = false;\n private constructor(private readonly bridge: HistoryBridge, private readonly handle: number,\n public readonly info: DocxHistoryArchiveInfo) {\n super(info.documentId, async (operation, fields = {}, bytes = new Uint8Array()) => {\n if (this.closed) throw new DocxHistoryError('Closed', 'History archive is closed.');\n return parseResult(await bridge.Invoke(handle,\n JSON.stringify({ schemaVersion: 1, operation, documentId: this.documentId, ...fields }), bytes));\n });\n }\n /** For custom loaders; normal callers use openDocxHistoryArchive(). */\n static async open(bridge: HistoryBridge, bytes: Uint8Array): Promise<DocxHistoryArchive> {\n checkArchiveSize(bytes);\n if (!bridge.OpenArchive) throw new Error('This WASM build does not include portable history.');\n const result = parseResult(await bridge.OpenArchive(bytes));\n return new DocxHistoryArchive(bridge, result.handle!, result.archive!);\n }\n close(): void {\n if (this.closed) return;\n this.bridge.Close(this.handle); this.closed = true;\n }\n}\n\nfunction parseResult(json: string): Result {\n const result: Result = JSON.parse(json);\n if (!result.success) throw new DocxHistoryError(result.errorCode!, result.message!);\n return result;\n}\nfunction checkArchiveSize(bytes: Uint8Array): void {\n if (bytes.length > MAX_HISTORY_ARCHIVE_BYTES) throw new DocxHistoryError('ResourceLimit', 'History archive exceeds 64 MiB.');\n}\nfunction requireRequestId(requestId: string): void {\n if (typeof requestId !== 'string' || !requestId.trim()) throw new DocxHistoryError('InvalidRequest', 'A durable requestId is required.');\n}\n\n/** Reference process-local storage. Share one instance among local clients; it is not durable\n * across a page/process restart. Every incoming blob is copied and SHA-256 verified. */\nexport function createMemoryHistoryStorage(maxBlobBytes = 256 * 1024 * 1024): HistoryStorage {\n if (!Number.isSafeInteger(maxBlobBytes) || maxBlobBytes <= 0) throw new RangeError('Invalid blob byte limit.');\n const blobs = new Map<string, Uint8Array>();\n const heads = new Map<string, HistoryHead>();\n const copy = <T>(value: T): T => JSON.parse(JSON.stringify(value));\n const key = (reference: HistoryBlobReference): string => {\n if (reference.digest.algorithm !== 'SHA-256' || !/^[a-f0-9]{64}$/.test(reference.digest.value)\n || !Number.isSafeInteger(reference.length) || reference.length < 0 || reference.length > maxBlobBytes)\n throw new DocxHistoryError('InvalidRequest', 'Invalid blob reference or byte limit.');\n return `${reference.digest.value}:${reference.length}`;\n };\n const equalReference = (a: HistoryBlobReference, b: HistoryBlobReference): boolean =>\n a.length === b.length && a.digest.algorithm === b.digest.algorithm && a.digest.value === b.digest.value;\n const equalHead = (a: HistoryHead | null, b: HistoryHead | null): boolean => a === null || b === null\n ? a === b : a.revision === b.revision && equalReference(a.state, b.state);\n return {\n async readBlob(reference) { return blobs.get(key(reference))?.slice() ?? null; },\n async putBlob(reference, bytes) {\n const blobKey = key(reference);\n const captured = bytes.slice();\n if (captured.length !== reference.length) throw new DocxHistoryError('PayloadMismatch', 'Blob length mismatch.');\n const digest = Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256', captured)),\n n => n.toString(16).padStart(2, '0')).join('');\n if (digest !== blobKey.split(':')[0]) throw new DocxHistoryError('PayloadMismatch', 'Blob digest mismatch.');\n if (!blobs.has(blobKey)) blobs.set(blobKey, captured);\n },\n async readHead(documentId) { return copy(heads.get(documentId) ?? null); },\n async advanceHead(documentId, expected, state) {\n key(state);\n const current = heads.get(documentId) ?? null;\n if (!equalHead(current, expected)) return null;\n const revision = BigInt(current?.revision ?? '0') + 1n;\n if (revision > 9223372036854775807n) throw new RangeError('History revision exhausted.');\n const head = { revision: String(revision), state: copy(state) };\n // No awaits inside the compare/publication critical section, even under concurrent callers.\n heads.set(documentId, head);\n return copy(head);\n },\n async initializeHead(documentId, head) {\n key(head.state);\n if (typeof head.revision !== 'string' || !/^[1-9][0-9]*$/.test(head.revision) || BigInt(head.revision) > 9223372036854775807n)\n throw new DocxHistoryError('InvalidRequest', 'Imported head revision must be a positive Int64 string.');\n const existing = heads.get(documentId);\n if (existing) return { initialized: false, head: copy(existing) };\n // Same synchronous critical section as advanceHead; exact revision, no await/increment.\n const captured = copy(head); heads.set(documentId, captured);\n return { initialized: true, head: copy(captured) };\n },\n };\n}\n", "import { DocxHistoryError } from './history.js';\nimport type { DocxHistoryDocument, DocxHistoryView, DocxVersionMetadata, HistoryBlobReference, HistoryHead } from './history.js';\n\n/** Persist the entire request before publication. Bytes are structured-cloneable, not JSON. */\nexport type HistoryCheckpointRequest = {\n id: string;\n documentId: string;\n metadata: DocxVersionMetadata;\n} & ({ kind: 'save'; head: HistoryHead | null; bytes: Uint8Array }\n | { kind: 'restore'; head: HistoryHead; target: HistoryBlobReference });\n\n/** Host-owned durable outbox, scoped to one document. Methods resolve only after commit.\n * put must atomically return the existing request or insert and return the supplied one.\n * Existing inputs must never change, even for the same ID. remove must match the ID.\n * Share exclusion between tabs/clients. Never clear an uncertain publication to start another. */\nexport interface HistoryCheckpointJournal {\n read(): Promise<HistoryCheckpointRequest | null>;\n put(request: HistoryCheckpointRequest): Promise<HistoryCheckpointRequest>;\n remove(requestId: string): Promise<void>;\n}\n\n/** Explicit checkpoint commands. No editor ownership, timers, automatic retries or subscriptions.\n * Keep this instance for the document's editing session; refresh only when the user requests it. */\nexport class HistoryCheckpoints {\n private current: DocxHistoryView | null = null;\n private request: HistoryCheckpointRequest | null = null;\n private running = false;\n private stale = false;\n\n private constructor(readonly document: DocxHistoryDocument, private readonly journal: HistoryCheckpointJournal) {}\n\n /** Pass an already captured view when opening its exact version in an editor (for example, after import). */\n static async open(document: DocxHistoryDocument, journal: HistoryCheckpointJournal,\n view?: DocxHistoryView | null): Promise<HistoryCheckpoints> {\n const controls = new HistoryCheckpoints(document, journal);\n controls.request = structuredClone(await journal.read());\n if (controls.request && controls.request.documentId !== document.documentId)\n throw new DocxHistoryError('InvalidRequest', 'The pending checkpoint belongs to another document.');\n controls.current = view === undefined ? await document.read() : structuredClone(view);\n if (controls.current && controls.current.state.documentId !== document.documentId)\n throw new DocxHistoryError('InvalidRequest', 'The captured view belongs to another document.');\n return controls;\n }\n\n get view(): DocxHistoryView | null { return structuredClone(this.current); }\n get hasPending(): boolean { return this.request !== null; }\n /** Snapshot of the exact request a retry will recover, including its original operation kind. */\n get pendingRequest(): HistoryCheckpointRequest | null { return structuredClone(this.request); }\n get needsRefresh(): boolean { return this.stale; }\n\n async refresh(): Promise<DocxHistoryView | null> {\n return this.exclusive(async () => {\n this.current = await this.document.read();\n this.stale = false;\n return this.view;\n });\n }\n\n async save(bytes: Uint8Array, metadata: DocxVersionMetadata): Promise<DocxHistoryView> {\n return this.start({ kind: 'save', head: this.current?.head ?? null, bytes,\n id: crypto.randomUUID(), documentId: this.document.documentId, metadata });\n }\n\n async restore(target: HistoryBlobReference, metadata: DocxVersionMetadata): Promise<DocxHistoryView> {\n if (!this.current) throw new DocxHistoryError('NotFound', 'Save a checkpoint before restoring a version.');\n return this.start({ kind: 'restore', head: this.current.head, target,\n id: crypto.randomUUID(), documentId: this.document.documentId, metadata });\n }\n\n async retry(): Promise<DocxHistoryView> {\n return this.exclusive(async () => {\n if (!this.request) throw new DocxHistoryError('InvalidRequest', 'There is no pending checkpoint.');\n return this.publish();\n });\n }\n\n private async start(request: HistoryCheckpointRequest): Promise<DocxHistoryView> {\n return this.exclusive(async () => {\n if (this.request) throw new DocxHistoryError('PendingRequest', 'Retry the pending checkpoint first.');\n if (this.stale) throw new DocxHistoryError('StaleHead', 'Refresh history before saving again.');\n this.request = structuredClone(request);\n return this.publish();\n });\n }\n\n private async publish(): Promise<DocxHistoryView> {\n const intended = this.request!;\n // Retry persistence too: an outbox acknowledgement can be lost independently of publication.\n const request = await this.journal.put(structuredClone(intended));\n this.request = structuredClone(request);\n if (request.id !== intended.id)\n throw new DocxHistoryError('PendingRequest', 'Another tab has a pending checkpoint. Retry it before saving your draft.');\n let view: DocxHistoryView;\n try {\n view = request.kind === 'save'\n ? await this.document.createVersion(request.head, request.bytes, request.metadata, request.id)\n : await this.document.restoreVersion(request.head, request.target, request.metadata, request.id);\n } catch (error) {\n if (error instanceof DocxHistoryError && error.code === 'StaleHead') {\n this.stale = true;\n await this.journal.remove(request.id);\n this.request = null;\n }\n throw error;\n }\n // Idempotent retries may return an older version. Retain that exact view, never substitute latest.\n this.current = view;\n await this.journal.remove(request.id);\n this.request = null;\n return this.view!;\n }\n\n private async exclusive<T>(action: () => Promise<T>): Promise<T> {\n if (this.running) throw new DocxHistoryError('Busy', 'A history command is still running.');\n this.running = true;\n try { return await action(); } finally { this.running = false; }\n }\n}\n", "import { DocxHistoryError } from './history.js';\nimport type { HistoryBlobReference, HistoryHead, HistoryHeadInitializationResult, HistoryStorage } from './history.js';\nimport type { HistoryCheckpointJournal, HistoryCheckpointRequest } from './history-checkpoints.js';\n\nexport interface IndexedDbHistoryStore {\n readonly storage: HistoryStorage;\n journal(documentId: string): HistoryCheckpointJournal;\n /** Await active history calls first. Stored documents and pending requests are retained. */\n close(): void;\n}\n\n/** Optional browser-local persistence. Call explicitly; no storage, autosave or retention\n * policy is installed by mounting controls. Browser site-data clearing removes this store. */\nexport async function openIndexedDbHistoryStore(name: string): Promise<IndexedDbHistoryStore> {\n const db = await new Promise<IDBDatabase>((resolve, reject) => {\n let blocked = false;\n const request = indexedDB.open(name, 1);\n request.onupgradeneeded = () => {\n for (const store of ['blobs', 'heads', 'requests']) request.result.createObjectStore(store);\n };\n request.onsuccess = () => { if (blocked) request.result.close(); else resolve(request.result); };\n request.onerror = () => reject(request.error);\n request.onblocked = () => {\n blocked = true;\n reject(new Error('Close other tabs using this history store, then try again.'));\n };\n });\n db.onversionchange = () => db.close();\n\n function transaction<T>(name: string, mode: IDBTransactionMode,\n action: (store: IDBObjectStore, result: (value: T) => void) => void): Promise<T> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(name, mode);\n let value: T;\n tx.oncomplete = () => resolve(value);\n tx.onabort = () => reject(tx.error ?? new Error('History storage transaction was aborted.'));\n try { action(tx.objectStore(name), result => { value = result; }); }\n catch (error) { tx.abort(); reject(error); }\n });\n }\n\n const storage: HistoryStorage = {\n readBlob(reference) {\n const key = referenceKey(reference);\n return transaction<Uint8Array | null>('blobs', 'readonly', (store, result) => {\n store.get(key).onsuccess = event => result((event.target as IDBRequest<Uint8Array>).result ?? null);\n });\n },\n async putBlob(reference, bytes) {\n const key = referenceKey(reference);\n const captured = bytes.slice();\n if (captured.length !== reference.length) throw new DocxHistoryError('PayloadMismatch', 'Stored document length does not match its reference.');\n const hash = Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256', captured)),\n byte => byte.toString(16).padStart(2, '0')).join('');\n if (hash !== key.split(':')[0])\n throw new DocxHistoryError('PayloadMismatch', 'Stored document bytes do not match their reference.');\n await transaction<void>('blobs', 'readwrite', (store, result) => {\n store.put(captured, key); result();\n });\n },\n readHead(documentId) {\n return transaction<HistoryHead | null>('heads', 'readonly', (store, result) => {\n store.get(documentId).onsuccess = event => result((event.target as IDBRequest<HistoryHead>).result ?? null);\n });\n },\n advanceHead(documentId, expected, state) {\n referenceKey(state);\n const captured = structuredClone({ expected, state });\n if (expected) validateHead(expected);\n const revision = BigInt(expected?.revision ?? '0') + 1n;\n if (revision > 9223372036854775807n) throw new RangeError('History revision exhausted.');\n return transaction<HistoryHead | null>('heads', 'readwrite', (store, result) => {\n store.get(documentId).onsuccess = event => {\n const current = (event.target as IDBRequest<HistoryHead>).result ?? null;\n if (!equalHead(current, captured.expected)) { result(null); return; }\n const head = { revision: String(revision), state: captured.state };\n store.put(head, documentId); result(head);\n };\n });\n },\n initializeHead(documentId, head) {\n validateHead(head);\n const captured = structuredClone(head);\n // Both publication paths lock the same object store for the entire read/write transaction.\n return transaction<HistoryHeadInitializationResult>('heads', 'readwrite', (store, result) => {\n store.get(documentId).onsuccess = event => {\n const existing = (event.target as IDBRequest<HistoryHead>).result;\n if (existing) { result({ initialized: false, head: existing }); return; }\n store.put(captured, documentId); result({ initialized: true, head: captured });\n };\n });\n },\n };\n\n return {\n storage,\n journal(documentId) {\n return {\n read: () => transaction<HistoryCheckpointRequest | null>('requests', 'readonly', (store, result) => {\n store.get(documentId).onsuccess = event => result((event.target as IDBRequest<HistoryCheckpointRequest>).result ?? null);\n }),\n put(request) {\n if (request.documentId !== documentId) throw new Error('Checkpoint document identity does not match.');\n const captured = structuredClone(request);\n return transaction<HistoryCheckpointRequest>('requests', 'readwrite', (store, result) => {\n store.get(documentId).onsuccess = event => {\n const existing = (event.target as IDBRequest<HistoryCheckpointRequest>).result;\n if (existing) { result(existing); return; }\n store.put(captured, documentId); result(captured);\n };\n });\n },\n remove(requestId) {\n return transaction<void>('requests', 'readwrite', (store, result) => {\n store.get(documentId).onsuccess = event => {\n if ((event.target as IDBRequest<HistoryCheckpointRequest>).result?.id === requestId) store.delete(documentId);\n result();\n };\n });\n },\n };\n },\n close: () => db.close(),\n };\n}\n\nfunction referenceKey(reference: HistoryBlobReference): string {\n if (reference.digest.algorithm !== 'SHA-256' || !/^[a-f0-9]{64}$/.test(reference.digest.value)\n || !Number.isSafeInteger(reference.length) || reference.length < 0)\n throw new DocxHistoryError('InvalidRequest', 'Invalid history blob reference.');\n return `${reference.digest.value}:${reference.length}`;\n}\nfunction validateHead(head: HistoryHead): void {\n referenceKey(head.state);\n if (typeof head.revision !== 'string' || !/^[1-9][0-9]*$/.test(head.revision) || BigInt(head.revision) > 9223372036854775807n)\n throw new DocxHistoryError('InvalidRequest', 'Invalid history revision.');\n}\nfunction equalHead(a: HistoryHead | null, b: HistoryHead | null): boolean {\n return a === null || b === null ? a === b\n : a.revision === b.revision && a.state.length === b.state.length\n && a.state.digest.algorithm === b.state.digest.algorithm && a.state.digest.value === b.state.digest.value;\n}\n", "import { DocxHistoryError } from './history.js';\nimport type { DocxHistoryReader, DocxHistoryView, DocxStoredOperation, DocxStoredVersion, HistoryBlobReference } from './history.js';\nimport type { HistoryCheckpoints, HistoryCheckpointRequest } from './history-checkpoints.js';\n\nexport interface HistoryControlsOptions {\n reader: DocxHistoryReader;\n /** Omit for a read-only archive. Must belong to reader. */\n checkpoints?: HistoryCheckpoints;\n /** Capture the open draft on Save only. The panel never replaces editor content. */\n capture?: () => Uint8Array | Promise<Uint8Array>;\n author?: string;\n documentName?: string;\n /** Render in a separate preview; reject on failure, preserving the previous document. */\n preview: (bytes: Uint8Array, title: string) => void | Promise<void>;\n /** Defaults to a browser download. */\n download?: (bytes: Uint8Array, filename: string) => void | Promise<void>;\n /** Called after acknowledgement. A retry includes its original request and may return an older view. */\n onCheckpoint?: (view: DocxHistoryView, action: 'save' | 'restore' | 'retry', retriedRequest?: HistoryCheckpointRequest) => void | Promise<void>;\n /** Hosts that replace the draft on restore provide a matching confirmation and acknowledgement. */\n confirmRestore?: (title: string) => boolean | Promise<boolean>;\n restoreUpdatesDraft?: boolean;\n pageSize?: number;\n}\n\nexport interface HistoryControls {\n readonly element: HTMLElement;\n /** Initial metadata load. No document export or checkpoint is implicit. */\n readonly ready: Promise<void>;\n refresh(): Promise<void>;\n /** Removes controls and awaits their active call. The host may then close its reader/client. */\n destroy(): Promise<void>;\n}\n\n/** Mount explicit document-history controls. Persistence and preview/editor ownership stay with the host. */\nexport function mountHistoryControls(container: HTMLElement, options: HistoryControlsOptions): HistoryControls {\n const pageSize = options.pageSize ?? 25;\n if (!Number.isInteger(pageSize) || pageSize < 1 || pageSize > 100) throw new RangeError('History page size must be 1\u2013100.');\n if (options.checkpoints && options.checkpoints.document !== options.reader)\n throw new Error('History controls and checkpoints must use the same document.');\n return new HistoryPanel(container, options, pageSize);\n}\n\nclass HistoryPanel implements HistoryControls {\n readonly element: HTMLElement;\n readonly ready: Promise<void>;\n private readonly fieldset: HTMLFieldSetElement;\n private readonly status: HTMLElement;\n private readonly versions: HTMLSelectElement;\n private readonly before: HTMLSelectElement;\n private readonly detail: HTMLElement;\n private readonly author: HTMLInputElement;\n private readonly label: HTMLInputElement;\n private readonly actions = new Map<string, HTMLButtonElement>();\n private readonly events = new AbortController();\n private records: DocxStoredVersion[] = [];\n private next: HistoryBlobReference | null = null;\n private view: DocxHistoryView | null = null;\n private active: Promise<void> | null = null;\n private destroyed = false;\n\n constructor(container: HTMLElement, private readonly options: HistoryControlsOptions, private readonly pageSize: number) {\n const doc = container.ownerDocument;\n this.element = doc.createElement('section');\n this.element.className = 'dx-history';\n this.element.setAttribute('aria-label', 'Version history');\n const style = doc.createElement('style'); style.textContent = HISTORY_CSS;\n const title = doc.createElement('h2'); title.textContent = 'Version history';\n this.status = doc.createElement('p'); this.status.setAttribute('role', 'status'); this.status.setAttribute('aria-live', 'polite');\n this.fieldset = doc.createElement('fieldset');\n const legend = doc.createElement('legend'); legend.textContent = 'Saved versions'; this.fieldset.append(legend);\n this.element.append(style, title, this.status, this.fieldset); container.append(this.element);\n const note = doc.createElement('p');\n note.dataset.historyExisting = '';\n note.textContent = options.checkpoints ? 'Browse saved versions without changing your draft.' : 'Read-only history. Preview or download any saved version.';\n this.fieldset.append(note);\n this.button('refresh', 'Refresh history', () => this.load(true));\n this.button('latest', 'Preview latest', async () => this.preview(await options.reader.exportDocx(), 'Latest saved version'));\n this.versions = this.select('Version'); this.versions.size = 6;\n this.detail = doc.createElement('p'); this.fieldset.append(this.detail);\n this.versions.addEventListener('change', () => this.update(), { signal: this.events.signal });\n this.button('preview', 'Preview selected', async () => this.preview(await options.reader.exportDocx(this.selected().id), versionTitle(this.selected())));\n this.button('download', 'Download selected', async () => this.download(await options.reader.exportDocx(this.selected().id), `version-${this.selected().record.sequence}.docx`));\n const comparison = this.disclosure('Compare versions');\n this.before = this.select('Compare from', comparison);\n this.before.addEventListener('change', () => this.update(), { signal: this.events.signal });\n const compareNote = doc.createElement('p'); compareNote.textContent = 'Compare from this version to the selected version above.'; comparison.append(compareNote);\n this.button('compare', 'Compare versions', async () => {\n const before = this.records[Number(this.before.value)];\n await this.preview(await options.reader.compareVersions(before.id, this.selected().id), 'Comparison with tracked changes');\n }, comparison);\n this.button('more', 'Load older versions', async () => { if (this.next) await this.page(this.next, false); });\n const saveGroup = doc.createElement('div'); saveGroup.className = 'dx-history-save';\n this.fieldset.insertBefore(saveGroup, note);\n const attribution = doc.createElement('details');\n const attributionTitle = doc.createElement('summary'); attributionTitle.textContent = 'Saved by'; attribution.append(attributionTitle);\n saveGroup.append(attribution);\n this.author = this.input('Your name', 'text', options.author ?? 'You', attribution);\n this.label = this.input('Version name (optional)', 'text', '', saveGroup);\n saveGroup.hidden = !options.checkpoints;\n this.author.parentElement!.hidden = this.label.parentElement!.hidden = !options.checkpoints;\n this.button('save', 'Save version', async () => {\n const view = await options.checkpoints!.save(await options.capture!(), this.metadata());\n await options.onCheckpoint?.(view, 'save');\n await this.load(false); this.label.value = '';\n this.status.textContent = 'Version saved. Your draft remains open.';\n }, saveGroup);\n saveGroup.append(attribution);\n this.button('restore', 'Restore selected', async () => {\n const version = this.selected();\n const confirmed = options.confirmRestore ? await options.confirmRestore(versionTitle(version))\n : doc.defaultView?.confirm(`Restore ${versionTitle(version)} as a new saved version?\\n\\nYour current draft and all later versions will be kept.`);\n if (!confirmed) {\n this.status.textContent = 'Restore canceled. Your draft and history are unchanged.';\n return;\n }\n const view = await options.checkpoints!.restore(version.id, this.metadata());\n await options.onCheckpoint?.(view, 'restore');\n await this.load(false);\n this.status.textContent = options.restoreUpdatesDraft ? 'Version restored. All saved versions are kept.' : 'Restored as a new saved version. Your draft and later versions are kept.';\n });\n const restoreNote = doc.createElement('p'); restoreNote.hidden = !options.checkpoints;\n if (options.checkpoints) restoreNote.dataset.historyExisting = '';\n restoreNote.textContent = options.restoreUpdatesDraft ? 'Restore returns your document to this version and keeps every saved version.' : 'Restore creates a new saved version. Preview latest to view it; your draft stays open.'; this.fieldset.append(restoreNote);\n this.button('retry', 'Retry save', async () => {\n const request = options.checkpoints!.pendingRequest;\n if (request?.kind === 'restore' && options.confirmRestore) {\n const target = await options.reader.getVersion(request.target);\n if (!await options.confirmRestore(versionTitle(target))) {\n this.status.textContent = 'Restore retry canceled. Your draft is unchanged; the saved action still needs recovery.';\n return;\n }\n }\n const view = await options.checkpoints!.retry();\n await options.onCheckpoint?.(view, 'retry', request ?? undefined); await this.load(false);\n this.status.textContent = request?.kind === 'restore' && options.restoreUpdatesDraft\n ? 'Version restored. All saved versions are kept. Refresh history to check for newer versions.'\n : 'Saved version recovered. Your draft remains open. Refresh history to check for newer versions.';\n });\n const sharing = this.disclosure('Download with history');\n const sharingNote = doc.createElement('p');\n sharingNote.textContent = 'Includes retained drafts and collaboration proposals. Share this file only when you want to include that history. A DOCX download keeps existing Word comments and revisions, without external history.';\n sharing.append(sharingNote);\n this.button('archive', 'Download with version history', async () => this.download(await options.reader.exportHistoryArchive(), 'docxhistory'), sharing);\n const portability = doc.createElement('p'); portability.textContent = 'Saved versions stay on this device. Download a history file to keep a portable copy; clearing browser data removes local versions.'; sharing.append(portability);\n const time = this.disclosure('Find a version by time');\n const cutoff = this.input('Saved at or before (local time)', 'datetime-local', '', time);\n this.button('time', 'Preview at time', async () => {\n if (!cutoff.value) throw new DocxHistoryError('InvalidRequest', 'Choose a date and time first.');\n const sequence = await options.reader.resolveSequenceAtTime(new Date(cutoff.value).toISOString());\n await this.preview(await options.reader.materialize(sequence), 'Version at selected time');\n }, time);\n const activity = this.disclosure('Recorded collaboration');\n const decisions = doc.createElement('ol');\n let showOlderActivity = () => {};\n this.button('activity', 'Load activity', async () => {\n const { operations } = await options.reader.readOperationsSince(null);\n const resolved = new Set(operations.filter(op => op.record.status === 'accepted').map(op => op.input.request.resolves?.digest.value));\n let shown = 0;\n showOlderActivity = () => {\n const page = operations.slice(Math.max(0, operations.length - shown - this.pageSize), operations.length - shown).reverse();\n decisions.append(...page.map(op => this.activityItem(op, resolved.has(op.id.digest.value)))); shown += page.length;\n this.actions.get('activity-more')!.hidden = shown >= operations.length;\n };\n decisions.replaceChildren(); showOlderActivity();\n this.status.textContent = operations.length ? 'Recorded activity loaded.' : 'No recorded collaboration.';\n }, activity);\n activity.append(decisions);\n this.button('activity-more', 'Load older activity', async () => showOlderActivity(), activity);\n this.actions.get('activity-more')!.hidden = true;\n this.ready = this.run('Loading history', () => this.load(false));\n }\n\n refresh(): Promise<void> { return this.run('Loading history', () => this.load(true)); }\n\n async destroy(): Promise<void> {\n this.destroyed = true; this.events.abort(); this.element.remove();\n await this.active?.catch(() => {});\n }\n\n private async load(refresh: boolean): Promise<void> {\n this.view = this.options.checkpoints\n ? refresh ? await this.options.checkpoints.refresh() : this.options.checkpoints.view\n : await this.options.reader.read();\n if (this.view) await this.page(this.view.version.id, true);\n else { this.records = []; this.next = null; this.versions.replaceChildren(); this.before.replaceChildren(); }\n this.status.textContent = this.options.checkpoints?.hasPending\n ? 'A save needs recovery. Retry it before saving more changes.'\n : this.view ? 'Select a version to preview, download or restore.' : 'No saved versions yet. Save your first version when you are ready.';\n }\n\n private async page(cursor: HistoryBlobReference, reset: boolean): Promise<void> {\n const page = await this.options.reader.listVersions(cursor, this.pageSize);\n if (reset) { this.records = []; this.versions.replaceChildren(); this.before.replaceChildren(); }\n const start = this.records.length;\n this.records.push(...page.versions); this.next = page.next;\n for (let index = start; index < this.records.length; index++) {\n for (const select of [this.versions, this.before]) {\n const option = select.ownerDocument.createElement('option'); option.value = String(index);\n option.textContent = option.title = versionTitle(this.records[index]); select.append(option);\n }\n }\n if (reset) { this.versions.value = '0'; this.before.value = this.records.length > 1 ? '1' : '0'; }\n }\n\n private update(): void {\n const hasVersion = this.records.length > 0;\n const pending = this.options.checkpoints?.hasPending ?? false;\n const stale = this.options.checkpoints?.needsRefresh ?? false;\n for (const key of ['latest', 'preview', 'download', 'archive', 'time', 'activity']) this.actions.get(key)!.disabled = !hasVersion;\n this.actions.get('more')!.hidden = !this.next;\n this.actions.get('compare')!.disabled = !hasVersion || this.before.value === this.versions.value;\n this.actions.get('save')!.hidden = !this.options.checkpoints || !this.options.capture;\n this.actions.get('save')!.disabled = pending || stale;\n this.actions.get('restore')!.hidden = !this.options.checkpoints;\n this.actions.get('restore')!.disabled = !hasVersion || pending || stale;\n this.actions.get('retry')!.hidden = !pending;\n this.versions.parentElement!.hidden = this.detail.hidden = !hasVersion;\n this.versions.size = Math.max(2, Math.min(6, this.records.length));\n for (const key of ['latest', 'preview', 'download']) this.actions.get(key)!.hidden = !hasVersion;\n this.actions.get('restore')!.hidden = !hasVersion || !this.options.checkpoints;\n for (const element of Array.from(this.element.querySelectorAll<HTMLElement>('[data-history-existing]'))) element.hidden = !hasVersion;\n this.detail.textContent = hasVersion ? [versionTitle(this.selected()), this.selected().record.metadata.message,\n this.selected().record.restoredFrom ? 'Restored from an earlier version.' : ''].filter(Boolean).join(' \u2014 ') : '';\n }\n\n private selected(): DocxStoredVersion { return this.records[Number(this.versions.value)]; }\n private activityItem(op: DocxStoredOperation, resolved: boolean): HTMLLIElement {\n const doc = this.element.ownerDocument;\n const item = doc.createElement('li');\n const state = op.record.status === 'accepted' ? 'Accepted' : resolved ? 'Conflict resolved' : 'Conflict needs review';\n const label = doc.createElement('p');\n label.textContent = `${op.input.request.metadata.author} \u00B7 ${state} \u00B7 ${formatTime(op.input.request.metadata.createdAt)}`;\n item.append(label);\n const description = doc.createElement('p');\n this.commandButton('View decision', async () => {\n const decision = await this.options.reader.getOperation(op.id);\n const { kind, metadata } = decision.input.request;\n description.textContent = [{ text: 'Text edit', package: 'Document edit', discard: 'Discarded proposal' }[kind],\n metadata.label, metadata.message, decision.record.conflict].filter(Boolean).join(' \u2014 ');\n }, item);\n item.append(description);\n this.commandButton('Download proposal', async () => {\n await this.download(await this.options.reader.exportOperationProposal(op.id), `proposal-${op.record.revision}.docx`);\n }, item);\n return item;\n }\n private metadata() { return { author: this.author.value.trim() || 'You', createdAt: new Date().toISOString(), label: this.label.value.trim() || undefined }; }\n private async preview(bytes: Uint8Array, title: string): Promise<void> {\n if (!this.destroyed) await this.options.preview(bytes, title);\n }\n private async download(bytes: Uint8Array, suffix: string): Promise<void> {\n if (this.destroyed) return;\n const stem = (this.options.documentName ?? 'document').replace(/\\.(docx|docxhistory)$/i, '');\n const name = suffix === 'docxhistory' ? `${stem}.docxhistory` : `${stem}-${suffix}`;\n if (this.options.download) { await this.options.download(bytes, name); return; }\n const url = URL.createObjectURL(new Blob([bytes.slice()], { type: suffix === 'docxhistory' ? 'application/octet-stream' : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }));\n const link = this.element.ownerDocument.createElement('a'); link.href = url; link.download = name;\n link.click(); setTimeout(() => URL.revokeObjectURL(url), 1000);\n }\n\n private async run(label: string, action: () => Promise<void>): Promise<void> {\n if (this.destroyed) throw new DocxHistoryError('Closed', 'History controls are closed.');\n if (this.active) throw new DocxHistoryError('Busy', 'A history command is still running.');\n this.fieldset.disabled = true; this.element.setAttribute('aria-busy', 'true'); this.status.textContent = `${label}\u2026`;\n const work = Promise.resolve().then(action); this.active = work;\n try { await work; if (this.status.textContent === `${label}\u2026`) this.status.textContent = 'Ready.'; }\n catch (error) {\n if (!this.destroyed) this.status.textContent = historyControlError(error, this.options.checkpoints?.hasPending);\n throw error;\n } finally {\n this.active = null;\n if (!this.destroyed) { this.fieldset.disabled = false; this.element.setAttribute('aria-busy', 'false'); this.update(); }\n }\n }\n\n private button(key: string, title: string, action: () => Promise<void>, parent: HTMLElement = this.fieldset): void {\n const button = this.commandButton(title, action, parent); button.dataset.historyAction = key;\n this.actions.set(key, button);\n }\n private commandButton(title: string, action: () => Promise<void>, parent: HTMLElement): HTMLButtonElement {\n const button = parent.ownerDocument.createElement('button'); button.type = 'button'; button.textContent = title;\n button.addEventListener('click', () => { void this.run(title, action).catch(() => {}); }, { signal: this.events.signal });\n parent.append(button); return button;\n }\n private select(title: string, parent: HTMLElement = this.fieldset): HTMLSelectElement {\n const label = this.fieldset.ownerDocument.createElement('label'); label.textContent = title;\n const select = label.ownerDocument.createElement('select'); select.setAttribute('aria-label', title);\n label.append(select); parent.append(label); return select;\n }\n private input(title: string, type: string, value = '', parent: HTMLElement = this.fieldset): HTMLInputElement {\n const label = parent.ownerDocument.createElement('label'); label.textContent = title;\n const input = label.ownerDocument.createElement('input'); input.type = type; input.value = value;\n label.append(input); parent.append(label); return input;\n }\n private disclosure(title: string): HTMLDetailsElement {\n const details = this.fieldset.ownerDocument.createElement('details');\n details.dataset.historyExisting = '';\n const summary = details.ownerDocument.createElement('summary'); summary.textContent = title;\n details.append(summary); this.fieldset.append(details); return details;\n }\n}\n\nexport function historyControlError(error: unknown, pending = false): string {\n const code = error instanceof DocxHistoryError ? error.code : '';\n if (code === 'StaleHead') return 'A newer saved version exists. Your draft is safe. Refresh history, review the newer version, then save again.';\n if (code === 'ImportConflict') return 'A different local history already exists. Open this file read-only to explore it.';\n if (code === 'InitializationUnsupported') return 'This storage cannot import history. Open read-only or choose storage that supports importing.';\n if (pending) return 'The save could not be confirmed. Your draft is safe. Retry save to recover your saved version.';\n if (code === 'ResourceLimit') return 'This history file exceeds browser processing limits, which can apply even below 64 MiB. Your document is unchanged.';\n if (code === 'UnsupportedVersion') return 'This history file uses an unsupported version. Open it with a newer app. Your document is unchanged.';\n if (code === 'InvalidManifest') return 'This history file is damaged or incomplete. Choose another copy. Your document is unchanged.';\n return `History could not be loaded. Your document is unchanged. ${error instanceof Error ? error.message : 'Please try again.'}`;\n}\n\nfunction versionTitle(version: DocxStoredVersion): string {\n const { metadata } = version.record;\n return `${metadata.label || 'Saved version'} \u00B7 ${metadata.author} \u00B7 ${formatTime(metadata.createdAt)}`;\n}\nfunction formatTime(value: string): string {\n const time = new Date(value);\n return Number.isNaN(time.getTime()) ? value : new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short' }).format(time);\n}\n\nconst HISTORY_CSS = `\n.dx-history{font:14px/1.5 system-ui,sans-serif;color:#203047;background:#fff;border:1px solid #cbd5e1;border-radius:12px;padding:18px;min-width:0}\n.dx-history *{box-sizing:border-box}.dx-history h2{font-size:20px;margin:0 0 8px}.dx-history p{margin:8px 0;overflow-wrap:anywhere}\n.dx-history fieldset{border:0;padding:0;margin:0;min-width:0}.dx-history legend{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}\n.dx-history label{display:block;font-weight:600;margin:12px 0 6px}.dx-history input,.dx-history select{display:block;width:100%;max-width:100%;margin-top:4px;font:inherit;color:inherit;border:1px solid #94a3b8;border-radius:6px;padding:8px;background:#fff}\n.dx-history button{min-height:40px;margin:4px 6px 4px 0;padding:7px 12px;border:1px solid #94a3b8;border-radius:6px;background:#f8fafc;color:inherit;font:inherit;cursor:pointer}\n.dx-history button:disabled{opacity:.5;cursor:wait}.dx-history :focus-visible{outline:3px solid #2563eb;outline-offset:2px}.dx-history [hidden]{display:none}\n.dx-history details{margin-top:16px;border-top:1px solid #e2e8f0;padding-top:12px}.dx-history summary{cursor:pointer;font-weight:600;padding:4px 0}\n.dx-history [role=status]{min-height:42px}.dx-history ol{padding-left:22px}.dx-history option{padding:6px}\n`;\n", "/**\n * Rendering a page number in an OOXML number format \u2014 the browser-side counterpart of the .NET\n * `NumberFormats.Render`, used by the paginator to fill in `[data-field]` page-number markers.\n *\n * Two vocabularies reach this module and both are handled here so callers never have to know which\n * one they hold:\n *\n * - `ST_NumberFormat` tokens (`\"lowerRoman\"`, \u2026), from a section's `w:pgNumType/@w:fmt` \u2014\n * stamped on the section wrapper as `data-page-num-fmt`.\n * - Field `\\*` general-formatting switch arguments (`\"roman\"`, `\"ROMAN\"`, `\"alphabetic\"`,\n * `\"ALPHABETIC\"`, `\"Arabic\"`), from a field's own instruction \u2014 stamped as `data-field-format`.\n * Case is load-bearing: `roman` is `i, ii, iii` and `ROMAN` is `I, II, III`.\n *\n * An unrecognized token renders as decimal, matching how Word treats a format it does not\n * implement \u2014 a page number that reads \"12\" is wrong in style; one that reads \"\" is a hole.\n */\n\n/** Formats this module renders. Anything else falls back to decimal. */\ntype Renderer = (value: number) => string;\n\nconst ROMAN_ONES = [\"\", \"i\", \"ii\", \"iii\", \"iv\", \"v\", \"vi\", \"vii\", \"viii\", \"ix\"];\nconst ROMAN_TENS = [\"\", \"x\", \"xx\", \"xxx\", \"xl\", \"l\", \"lx\", \"lxx\", \"lxxx\", \"xc\"];\nconst ROMAN_HUNDREDS = [\"\", \"c\", \"cc\", \"ccc\", \"cd\", \"d\", \"dc\", \"dcc\", \"dccc\", \"cm\"];\nconst ROMAN_THOUSANDS = [\"\", \"m\", \"mm\", \"mmm\"];\n\nfunction toRoman(value: number): string {\n // Word renders anything outside the classical range as a plain number rather than nothing.\n if (value <= 0 || value >= 4000) return String(value);\n return (\n ROMAN_THOUSANDS[Math.floor(value / 1000)] +\n ROMAN_HUNDREDS[Math.floor((value % 1000) / 100)] +\n ROMAN_TENS[Math.floor((value % 100) / 10)] +\n ROMAN_ONES[value % 10]\n );\n}\n\n/** `1 \u2192 a`, `26 \u2192 z`, `27 \u2192 aa` \u2014 Word repeats the letter rather than carrying like a base-26 number. */\nfunction toLetter(value: number): string {\n if (value <= 0) return String(value);\n const wrapped = value % 780 === 0 ? 780 : value % 780;\n const repeats = Math.floor((wrapped - 1) / 26) + 1;\n return \"abcdefghijklmnopqrstuvwxyz\".charAt((wrapped - 1) % 26).repeat(repeats);\n}\n\nconst RENDERERS: Record<string, Renderer> = {\n // ST_NumberFormat tokens (w:pgNumType/@w:fmt, w:numFmt).\n decimal: (v) => String(v),\n lowerRoman: toRoman,\n upperRoman: (v) => toRoman(v).toUpperCase(),\n lowerLetter: toLetter,\n upperLetter: (v) => toLetter(v).toUpperCase(),\n // Field `\\*` general-formatting switch arguments.\n Arabic: (v) => String(v),\n roman: toRoman,\n ROMAN: (v) => toRoman(v).toUpperCase(),\n alphabetic: toLetter,\n ALPHABETIC: (v) => toLetter(v).toUpperCase(),\n};\n\n/**\n * Render `value` in `format`. `format` may be an `ST_NumberFormat` token or a `\\*` switch argument;\n * an absent or unrecognized one renders as decimal.\n */\nexport function formatPageNumber(value: number, format?: string | null): string {\n const renderer = format ? RENDERERS[format] : undefined;\n return (renderer ?? RENDERERS.decimal)(value);\n}\n", "/**\n * Unrounded natural line heights for the paginated export (issue #850).\n *\n * Chromium lays a `line-height: normal` line out at the font's natural line height \u2014 ascent +\n * descent + line gap from its metrics \u2014 but first rounds that to a whole CSS pixel (0.75 pt). The\n * converter relies on `normal` for single spacing and on `calc(1lh * m)` for Word's `auto`\n * multiples, so every line inherits the rounding: 11 pt Carlito advances 18 px instead of\n * 17.90 px, and the error accumulates down the page and moves page breaks. An explicit length keeps\n * Chromium's 1/64-pixel layout precision, so this pass replaces each `normal` with the same font's\n * natural height measured where rounding is negligible.\n */\n\n/** Font size the natural line height is probed at: rounding to a pixel there is < 0.0005 em. */\nconst PROBE_FONT_SIZE_PX = 1000;\n\n/** Probe text for an element whose own text the primary font covers (Latin, through U+024F). */\nconst LATIN_PROBE = \"Hg\";\n\n/** At most this many distinct characters of an element's own text go into its probe. */\nconst MAX_PROBE_CHARACTERS = 256;\n\n/**\n * What to measure an element's natural line height with. Under `normal`, Chromium also grows a line\n * for the fallback fonts its text needs (a CJK run in a Calibri paragraph lays out taller than Latin\n * text), so an element whose own text goes beyond Latin is probed with those characters themselves.\n */\nfunction probeText(element: Element): string {\n const characters = new Set<string>();\n for (const node of Array.from(element.childNodes)) {\n if (node.nodeType !== 3) continue;\n for (const character of node.textContent ?? \"\") {\n if (/\\s/.test(character)) continue;\n characters.add(character);\n if (characters.size >= MAX_PROBE_CHARACTERS) break;\n }\n }\n const beyondLatin = Array.from(characters).filter((character) => character.codePointAt(0)! > 0x024f);\n return beyondLatin.length === 0 ? LATIN_PROBE : LATIN_PROBE + beyondLatin.sort().join(\"\");\n}\n\n/**\n * A cached measure of a font's natural line height as a fraction of its size, probed at\n * {@link PROBE_FONT_SIZE_PX} with the given text.\n */\nfunction naturalLineHeightRatios(document: Document): (style: CSSStyleDeclaration, text: string) => number {\n const ratios = new Map<string, number>();\n return (style, text) => {\n const key = `${style.fontStyle}|${style.fontWeight}|${style.fontStretch}|${style.fontFamily}|${text}`;\n let ratio = ratios.get(key);\n if (ratio === undefined) {\n const probe = document.createElement(\"span\");\n probe.setAttribute(\"aria-hidden\", \"true\");\n probe.style.cssText = \"position:absolute;left:-100000px;top:0;visibility:hidden;\"\n + \"display:inline-block;white-space:nowrap;line-height:normal;margin:0;padding:0;border:0;\";\n probe.style.fontFamily = style.fontFamily;\n probe.style.fontStyle = style.fontStyle;\n probe.style.fontWeight = style.fontWeight;\n probe.style.fontStretch = style.fontStretch;\n probe.style.fontSize = `${PROBE_FONT_SIZE_PX}px`;\n probe.textContent = text;\n (document.body ?? document.documentElement).appendChild(probe);\n ratio = probe.getBoundingClientRect().height / PROBE_FONT_SIZE_PX;\n probe.remove();\n ratios.set(key, ratio);\n }\n return ratio;\n };\n}\n\n/**\n * Give every element under `root` whose computed `line-height` is `normal` an explicit line height\n * equal to its own font's unrounded natural line height (including any fallback font its own text\n * needs). Elements are collected before any is\n * changed, because an explicit value on a parent would otherwise be inherited by children that\n * should keep sizing their lines from their own font. Returns how many elements changed.\n */\nexport function applyUnroundedNormalLineHeights(root: Element): number {\n const document = root.ownerDocument;\n const view = document.defaultView;\n if (!view) return 0;\n const ratioFor = naturalLineHeightRatios(document);\n\n const targets: Array<{ element: HTMLElement; lineHeight: number }> = [];\n for (const element of [root, ...Array.from(root.querySelectorAll(\"*\"))]) {\n if (!(element instanceof view.HTMLElement)) continue;\n const style = view.getComputedStyle(element);\n if (style.lineHeight !== \"normal\") continue;\n const fontSize = Number.parseFloat(style.fontSize);\n const ratio = ratioFor(style, probeText(element));\n if (!(fontSize > 0) || !(ratio > 0)) continue;\n targets.push({ element, lineHeight: ratio * fontSize });\n }\n for (const { element, lineHeight } of targets) {\n element.style.setProperty(\"line-height\", `${lineHeight.toFixed(4)}px`);\n }\n return targets.length;\n}\n\n/** The elements the converter writes a Word paragraph as. */\nconst PARAGRAPH_SELECTOR = \"p, h1, h2, h3, h4, h5, h6\";\n\n/** How far Chromium puts the first baseline below the top of a paragraph shaped like this one. */\nfunction baselineOffsets(document: Document): (paragraph: CSSStyleDeclaration, child: CSSStyleDeclaration) => number {\n const offsets = new Map<string, number>();\n const host = document.body ?? document.documentElement;\n return (paragraph, child) => {\n const key = [paragraph.fontStyle, paragraph.fontWeight, paragraph.fontStretch, paragraph.fontFamily,\n paragraph.fontSize, paragraph.lineHeight, child.fontStyle, child.fontWeight, child.fontStretch,\n child.fontFamily, child.fontSize, child.lineHeight, child.verticalAlign, child.top].join(\"|\");\n let offset = offsets.get(key);\n if (offset === undefined) {\n const probe = document.createElement(\"div\");\n probe.setAttribute(\"aria-hidden\", \"true\");\n probe.style.cssText = \"position:absolute;left:-100000px;top:0;visibility:hidden;width:max-content;\"\n + \"margin:0;padding:0;border:0;white-space:nowrap;\";\n for (const property of [\"font-family\", \"font-style\", \"font-weight\", \"font-stretch\", \"font-size\", \"line-height\"])\n probe.style.setProperty(property, paragraph.getPropertyValue(property));\n const span = document.createElement(\"span\");\n for (const property of [\"font-family\", \"font-style\", \"font-weight\", \"font-stretch\", \"font-size\", \"line-height\",\n \"vertical-align\", \"position\", \"top\"])\n span.style.setProperty(property, child.getPropertyValue(property));\n const marker = document.createElement(\"span\");\n marker.style.cssText = \"display:inline-block;width:0;height:0;vertical-align:baseline;margin:0;padding:0;border:0;\";\n span.append(marker, LATIN_PROBE);\n probe.append(span);\n host.appendChild(probe);\n offset = marker.getBoundingClientRect().bottom - probe.getBoundingClientRect().top;\n probe.remove();\n offsets.set(key, offset);\n }\n return offset;\n };\n}\n\n/**\n * Word places an exact-spaced line's baseline at 80% of its height, independent of font size\n * (issue #882; fixtures/exact-line-spacing/word.json). Move each run by its own font's offset,\n * retaining the converter's top alignment so mixed font sizes cannot enlarge the line boxes.\n */\nexport function alignExactLineBaselines(root: Element): void {\n const view = root.ownerDocument.defaultView;\n if (!view) return;\n const offsetFor = baselineOffsets(root.ownerDocument);\n for (const run of Array.from(root.querySelectorAll<HTMLElement>(\"[data-docx-exact-run]\"))) {\n const paragraph = run.closest(PARAGRAPH_SELECTOR);\n if (!paragraph || !movable(run, view)) continue;\n const style = view.getComputedStyle(paragraph);\n if (!style.getPropertyValue(\"--docx-exact-line-height\")) continue;\n const height = Number.parseFloat(style.lineHeight);\n const runStyle = view.getComputedStyle(run);\n if (!(height > 0) || runStyle.display !== \"inline\" || runStyle.verticalAlign !== \"top\") continue;\n const top = Number.parseFloat(runStyle.top) || 0;\n const offset = offsetFor(style, runStyle) - top;\n const shift = height * 0.8 - offset;\n if (!Number.isFinite(shift)) continue;\n run.style.position = \"relative\";\n run.style.top = `${(top + shift).toFixed(4)}px`;\n }\n}\n\nconst EXACT_INK_ATTRIBUTE = \"data-docx-exact-ink\";\n\n/**\n * Exact line boxes still occupy their declared height when their glyphs extend outside them.\n * Word lets that ink enter the margins. Expand only the paint clip, after placement, for plain\n * inline text whose paragraph fits its band and whose ink cannot enter a running story or leave\n * the paper. Block geometry and pagination budgets remain unchanged.\n */\nexport function preserveExactLineInk(content: HTMLElement, topLimit: number, bottomLimit: number, paper: DOMRect): void {\n const view = content.ownerDocument.defaultView;\n if (!view) return;\n const band = content.getBoundingClientRect();\n const scale = band.width / content.offsetWidth || 1;\n let above = 0;\n let below = 0;\n for (const paragraph of Array.from(content.querySelectorAll<HTMLElement>(PARAGRAPH_SELECTOR))) {\n if (!view.getComputedStyle(paragraph).getPropertyValue(\"--docx-exact-line-height\")) continue;\n const box = paragraph.getBoundingClientRect();\n if (box.top < band.top - 0.5 || box.bottom > band.bottom + 0.5) continue;\n if (!paragraph.querySelector(\"[data-docx-exact-run]\") || paragraph.querySelector(\"img, svg, canvas, video, object, iframe\"))\n continue;\n if (Array.from(paragraph.querySelectorAll<HTMLElement>(\"*\")).some(element => {\n const style = view.getComputedStyle(element);\n return style.display !== \"inline\" || ![\"static\", \"relative\"].includes(style.position);\n })) continue;\n const range = content.ownerDocument.createRange();\n range.selectNodeContents(paragraph);\n const rects = Array.from(range.getClientRects()).filter(rect => rect.width > 0 && rect.height > 0);\n if (rects.length === 0) continue;\n const top = Math.min(...rects.map(rect => rect.top));\n const bottom = Math.max(...rects.map(rect => rect.bottom));\n if (top < topLimit || bottom > bottomLimit) continue;\n const extra = Math.max(0, band.top - top, bottom - band.bottom);\n if (extra === 0) continue;\n paragraph.setAttribute(EXACT_INK_ATTRIBUTE, \"true\");\n above = Math.max(above, band.top - top);\n below = Math.max(below, bottom - band.bottom);\n }\n if (above > 0 || below > 0) {\n const up = Math.ceil(above / scale * 64) / 64;\n const down = Math.ceil(below / scale * 64) / 64;\n // overflow-clip-margin is ignored by Chromium when the other axis stays visible. A pixel\n // inset clips each vertical edge independently and keeps horizontal clipping at the paper.\n content.style.overflowY = \"visible\";\n content.style.clipPath = `inset(${-up}px ${(band.right - paper.right) / scale}px ${-down}px ${(paper.left - band.left) / scale}px)`;\n }\n}\n\n/** Read the pixel inset used for the exact-text paint clip, including CSS's 1-4 value shorthand. */\nexport function insetClipBounds(value: string, box: DOMRect, scale: number):\n { top: number; right: number; bottom: number; left: number } | null {\n const match = /^inset\\(((?:-?\\d+(?:\\.\\d+)?px\\s*){1,4})\\)$/.exec(value);\n if (!match) return null;\n const parts = match[1].trim().split(/\\s+/).map(Number.parseFloat);\n const [top, right = top, bottom = top, left = right] = parts;\n return { top: box.top + top * scale, right: box.right - right * scale,\n bottom: box.bottom - bottom * scale, left: box.left + left * scale };\n}\n\n/** Only inline ink in a fitting exact-spaced paragraph may use the expanded paint clip. */\nexport function isPreservedExactLineInk(element: HTMLElement, content: HTMLElement): boolean {\n const paragraph = element.closest<HTMLElement>(`[${EXACT_INK_ATTRIBUTE}]`);\n const view = content.ownerDocument.defaultView;\n if (!paragraph || !view || element === paragraph || !content.contains(paragraph)) return false;\n if (view.getComputedStyle(element).display !== \"inline\") return false;\n const band = content.getBoundingClientRect();\n const box = paragraph.getBoundingClientRect();\n const clip = insetClipBounds(view.getComputedStyle(content).clipPath, band, band.width / content.offsetWidth || 1);\n const ink = element.getBoundingClientRect();\n return clip !== null && box.top >= band.top - 0.5 && box.bottom <= band.bottom + 0.5\n && ink.top >= clip.top - 0.02 && ink.bottom <= clip.bottom + 0.02;\n}\n\n/**\n * Put every exported baseline where Word puts it, to a fraction of a pixel (issue #942).\n *\n * Word sets a line's baseline its natural line height less the font's descent below the line's top: the\n * font's ascent, with any line gap above it. Chromium instead rounds the ascent and descent to whole pixels\n * and floors half the remaining leading, so the baseline lands up to a pixel off; for 11 pt Calibri and 12 pt\n * Arial it is one pixel high. Word also puts a font's line gap above the text where CSS splits it, which moves\n * Arial's baseline a little further. That offset is the same on every line of a paragraph, whatever its position, so\n * it is measured once per paragraph shape in a probe and taken back with relative positioning, which moves the\n * glyphs without changing any line box: pagination and line pitch are untouched.\n *\n * Each direct inline child of a paragraph is moved, composing with a `top` it already has. A child positioned\n * some other way, or holding an image, an SVG or an absolutely positioned element (for which a relative child\n * would become the containing block), is left alone. Run once the page tree is final: the moved boxes count\n * toward a page band's overflow, which the export's clipping check must not see.\n * Returns how many children moved.\n */\nexport function alignBaselinesToWord(root: Element): number {\n const document = root.ownerDocument;\n const view = document.defaultView;\n if (!view) return 0;\n const descents = new Map<string, number>();\n const ratioFor = naturalLineHeightRatios(document);\n const chromiumOffset = baselineOffsets(document);\n\n /** The font's descent as a fraction of its size, read where rounding is negligible. */\n const descentRatio = (style: CSSStyleDeclaration): number => {\n // The canvas font shorthand takes no percentage stretch (computed styles give one), and ignores a value it\n // cannot parse, so the stretch is left out and an assignment that did not take counts as unmeasurable.\n const font = `${style.fontStyle} ${style.fontWeight} ${PROBE_FONT_SIZE_PX}px ${style.fontFamily}`;\n let ratio = descents.get(font);\n if (ratio === undefined) {\n const context = document.createElement(\"canvas\").getContext(\"2d\");\n ratio = Number.NaN;\n if (context) {\n context.font = font;\n if (context.font.includes(`${PROBE_FONT_SIZE_PX}px`))\n ratio = context.measureText(LATIN_PROBE).fontBoundingBoxDescent / PROBE_FONT_SIZE_PX;\n }\n descents.set(font, ratio);\n }\n return ratio;\n };\n\n const moves: Array<{ element: HTMLElement; top: number }> = [];\n for (const paragraph of Array.from(root.querySelectorAll(PARAGRAPH_SELECTOR))) {\n if (!(paragraph instanceof view.HTMLElement)) continue;\n const style = view.getComputedStyle(paragraph);\n // Probe with a child that sits on the baseline (not a raised or lowered run), preferably in the\n // paragraph's own font rather than, say, a list marker's.\n const candidates = Array.from(paragraph.children).filter((child): child is HTMLElement =>\n child instanceof view.HTMLElement && (child.textContent ?? \"\").trim() !== \"\" && movable(child, view) &&\n view.getComputedStyle(child).display === \"inline\" && view.getComputedStyle(child).verticalAlign === \"baseline\");\n const first = candidates.find((child) => view.getComputedStyle(child).fontFamily === style.fontFamily) ??\n candidates[0];\n if (!first) continue;\n const lineHeight = Number.parseFloat(style.lineHeight);\n const fontSize = Number.parseFloat(style.fontSize);\n // Word's placement is recorded for natural line heights (single spacing and auto multiples, which the\n // converter builds on the paragraph's natural height), not for exact or at-least ones.\n if (!(lineHeight > 0) || !(fontSize > 0) ||\n Math.abs(lineHeight - ratioFor(style, LATIN_PROBE) * fontSize) > 0.01) continue;\n const descent = descentRatio(style);\n if (!(descent > 0)) continue;\n const childStyle = view.getComputedStyle(first);\n // Word: the extra height of a multiple goes below the text (issue #908), so the baseline is one natural\n // line height less the descent below the line's top, however tall the line is.\n const shift = (lineHeight - descent * fontSize) - chromiumOffset(style, childStyle);\n // The correction is Chromium's rounding plus the half of any line gap it puts below the text, which Word\n // puts above: a fraction of the line. Half a line or more means the font does not follow this model.\n if (!Number.isFinite(shift) || Math.abs(shift) < 1 / 64 || Math.abs(shift) >= lineHeight / 2) continue;\n for (const child of Array.from(paragraph.children))\n if (child instanceof view.HTMLElement && movable(child, view)) {\n // Compose with the offset the child already has (a run's w:position, or the lift of an auto multiple),\n // which may come from a stylesheet rule rather than its own style attribute.\n const top = Number.parseFloat(view.getComputedStyle(child).top);\n moves.push({ element: child, top: (Number.isFinite(top) ? top : 0) + shift });\n }\n }\n for (const { element, top } of moves) {\n element.style.setProperty(\"position\", \"relative\");\n element.style.setProperty(\"top\", `${top.toFixed(4)}px`);\n }\n return moves.length;\n}\n\n/** Whether relative positioning can move a paragraph child without disturbing anything laid out from it. */\nfunction movable(element: HTMLElement, view: Window & typeof globalThis): boolean {\n const position = view.getComputedStyle(element).position;\n if (position !== \"static\" && position !== \"relative\") return false;\n // Inline boxes share the line's baseline; tab stops and leaders are inline-blocks on the same line.\n if (![\"inline\", \"inline-block\"].includes(view.getComputedStyle(element).display)) return false;\n if (element.querySelector(\"img, svg\")) return false;\n for (const descendant of Array.from(element.querySelectorAll(\"*\")))\n if ([\"absolute\", \"fixed\"].includes(view.getComputedStyle(descendant).position)) return false;\n return true;\n}\n", "/**\n * Page geometry \u2014 the document's own page setup, and the scaling a view applies to show it.\n *\n * A Word document's line breaking is authored against ONE width: the text column its\n * `w:sectPr` defines (page size minus margins). That width is a property of the document,\n * not of the device showing it, which is why the converter emits it on every section wrapper\n * (`data-page-width`, `data-content-width`, the four margins, \u2026) in every render mode.\n *\n * A view that instead sizes the column from the viewport gets a different line-breaking\n * result on every screen, and \u2014 once a run is enlarged past what the narrowed column can\n * hold \u2014 content that no longer fits the page at all. Word and LibreOffice never do that:\n * they keep the column fixed and ZOOM the page to fit the window. This module is the shared\n * owner of both halves \u2014 reading the geometry, and computing/applying that zoom \u2014 so the\n * paginated view (`pagination.ts`) and the continuous view (`editor.ts` via `viewport.ts`)\n * agree on what a page is instead of each inventing its own.\n */\n\n/** Page dimensions extracted from a section wrapper's data attributes (in points). */\nexport interface PageDimensions {\n /** Page width in points */\n pageWidth: number;\n /** Page height in points */\n pageHeight: number;\n /** Content area width (page minus margins) in points */\n contentWidth: number;\n /** Content area height (page minus margins) in points */\n contentHeight: number;\n /** Top margin in points */\n marginTop: number;\n /** Right margin in points */\n marginRight: number;\n /** Bottom margin in points */\n marginBottom: number;\n /** Left margin in points */\n marginLeft: number;\n /** `w:pgMar/@w:header` \u2014 page top edge to the TOP of the header story, in points. */\n headerDistance: number;\n /** `w:pgMar/@w:footer` \u2014 page bottom edge to the BOTTOM of the footer story, in points. */\n footerDistance: number;\n /** @deprecated Misnamed alias of {@link headerDistance} \u2014 it never held a height. */\n headerHeight: number;\n /** @deprecated Misnamed alias of {@link footerDistance} \u2014 it never held a height. */\n footerHeight: number;\n}\n\n/** US Letter portrait \u2014 Word's default, and this module's fallback for an unstamped section. */\nexport const DEFAULT_PAGE_WIDTH = 612;\nexport const DEFAULT_PAGE_HEIGHT = 792;\nexport const DEFAULT_MARGIN = 72; // 1 inch\n/** Default header/footer distance from the paper edge (0.5 inch). */\nexport const DEFAULT_HEADER_FOOTER_DISTANCE = 36;\n/** @deprecated Misnamed alias of {@link DEFAULT_HEADER_FOOTER_DISTANCE}. */\nexport const DEFAULT_HEADER_FOOTER_HEIGHT = DEFAULT_HEADER_FOOTER_DISTANCE;\n\n/** Converts pixels to points (assuming 96 DPI screen). */\nexport function pxToPt(px: number): number {\n return px * 0.75; // 72 points / 96 pixels\n}\n\n/** Converts points to pixels (assuming 96 DPI screen). */\nexport function ptToPx(pt: number): number {\n return pt / 0.75;\n}\n\nfunction finiteDataNumber(value: string | undefined, fallback: number): number {\n if (value === undefined || value.trim() === \"\") return fallback;\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : fallback;\n}\n\nfunction positiveDataNumber(value: string | undefined, fallback: number): number {\n const parsed = finiteDataNumber(value, fallback);\n return parsed > 0 ? parsed : fallback;\n}\n\nfunction nonNegativeDataNumber(value: string | undefined, fallback: number): number {\n const parsed = finiteDataNumber(value, fallback);\n return parsed >= 0 ? parsed : fallback;\n}\n\nfunction positiveFinite(value: number, fallback: number): number {\n return Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\n/**\n * Parses page dimensions from a section wrapper's data attributes.\n *\n * Zero is meaningful for margins and header/footer distances, so truthiness-based parsing would\n * silently replace a valid edge-to-edge section with one-inch defaults. Number() also rejects\n * partial numeric strings (for example `612evil`) instead of letting malformed staging markup\n * leak non-deterministic CSS geometry into pagination.\n */\nexport function parseSectionDimensions(section: HTMLElement): PageDimensions {\n const pageWidth = positiveDataNumber(section.dataset.pageWidth, DEFAULT_PAGE_WIDTH);\n const pageHeight = positiveDataNumber(section.dataset.pageHeight, DEFAULT_PAGE_HEIGHT);\n const marginTop = finiteDataNumber(section.dataset.marginTop, DEFAULT_MARGIN);\n const marginRight = finiteDataNumber(section.dataset.marginRight, DEFAULT_MARGIN);\n const marginBottom = finiteDataNumber(section.dataset.marginBottom, DEFAULT_MARGIN);\n const marginLeft = finiteDataNumber(section.dataset.marginLeft, DEFAULT_MARGIN);\n const derivedContentWidth = positiveFinite(pageWidth - marginLeft - marginRight, pageWidth);\n const derivedContentHeight = positiveFinite(pageHeight - marginTop - marginBottom, pageHeight);\n const contentWidth = positiveDataNumber(section.dataset.contentWidth, derivedContentWidth);\n const contentHeight = positiveDataNumber(section.dataset.contentHeight, derivedContentHeight);\n // `data-header-height`/`data-footer-height` carry `w:pgMar/@w:header` and `@w:footer`, which\n // are distances from the paper edge \u2014 the attribute names predate that being understood.\n const headerDistance = nonNegativeDataNumber(\n section.dataset.headerHeight,\n DEFAULT_HEADER_FOOTER_DISTANCE,\n );\n const footerDistance = nonNegativeDataNumber(\n section.dataset.footerHeight,\n DEFAULT_HEADER_FOOTER_DISTANCE,\n );\n\n return {\n pageWidth,\n pageHeight,\n contentWidth,\n contentHeight,\n marginTop,\n marginRight,\n marginBottom,\n marginLeft,\n headerDistance,\n footerDistance,\n headerHeight: headerDistance,\n footerHeight: footerDistance,\n };\n}\n\n/**\n * Where a page's three bands sit, in points measured from the page's TOP edge.\n *\n * Resolved by {@link resolvePageBands} from the section's page setup plus the measured\n * height of the running content actually selected for that page.\n */\nexport interface PageBands {\n /** Top of the header band; it grows downward from here. */\n headerTop: number;\n /** Height of the header band (the measured header story, clipped to the body's top). */\n headerHeight: number;\n /** Top of the body text band. */\n bodyTop: number;\n /** Height of the body text band. */\n bodyHeight: number;\n /** Top of the footer band; it grows upward, so its BOTTOM is the fixed edge. */\n footerTop: number;\n /** Height of the footer band (the measured footer story, clipped to the body's bottom). */\n footerHeight: number;\n}\n\n/**\n * A body band this short cannot hold a single line, and a page that can hold nothing sends\n * every block down the oversized-block path. Running content may push the body \u2014 Word does\n * that \u2014 but it may not delete it, so a pathological header/footer gives this much back.\n */\nexport const MIN_BODY_BAND_PT = 12;\n\n/**\n * Word's page band model.\n *\n * `w:header`/`w:footer` are DISTANCES from the paper edge to the running content, and\n * `w:top`/`w:bottom` are distances from the paper edge to the body text \u2014 four independent\n * numbers, not two nested boxes. The header is laid out from `headerDistance` downward and\n * the footer from `footerDistance` upward; the body then starts at the top margin unless the\n * header has already run past it, and ends at the bottom margin unless the footer has\n * already climbed above it.\n *\n * Anchoring the bands to the margins instead \u2014 header bottom-aligned to `marginTop`, footer\n * top-aligned to `pageHeight - marginBottom` \u2014 collapses both toward the body by exactly\n * `margin - distance`, which is what this function replaced.\n */\nexport function resolvePageBands(\n dims: PageDimensions,\n headerContentHeight: number,\n footerContentHeight: number,\n): PageBands {\n const headerTop = dims.headerDistance;\n const footerBottom = dims.pageHeight - dims.footerDistance;\n\n // A page with NO running story has nothing below the paper edge to push the body: the\n // distance alone reserves no space. (Word's own empty header is still a story \u2014 one empty\n // paragraph with a real line height \u2014 so zero here means absent, not blank.)\n const headerReach = headerContentHeight > 0 ? headerTop + headerContentHeight : 0;\n const footerReach = footerContentHeight > 0 ? footerBottom - footerContentHeight : dims.pageHeight;\n\n let bodyTop = Math.max(dims.marginTop, headerReach);\n let bodyBottom = Math.min(dims.pageHeight - dims.marginBottom, footerReach);\n\n // Hand back whatever the bands over-claimed, in proportion to how far each grew past its\n // own margin, so a tall header does not silently consume the whole page.\n const shortfall = MIN_BODY_BAND_PT - (bodyBottom - bodyTop);\n if (shortfall > 0) {\n const headerGrowth = bodyTop - dims.marginTop;\n const footerGrowth = dims.pageHeight - dims.marginBottom - bodyBottom;\n const growth = headerGrowth + footerGrowth;\n if (growth > 0) {\n bodyTop -= (shortfall * headerGrowth) / growth;\n bodyBottom += (shortfall * footerGrowth) / growth;\n }\n }\n\n return {\n headerTop,\n headerHeight: Math.max(0, Math.min(headerContentHeight, bodyTop - headerTop)),\n bodyTop,\n bodyHeight: Math.max(0, bodyBottom - bodyTop),\n footerTop: footerBottom - Math.max(0, Math.min(footerContentHeight, footerBottom - bodyBottom)),\n footerHeight: Math.max(0, Math.min(footerContentHeight, footerBottom - bodyBottom)),\n };\n}\n\n/** Every section wrapper under `root`, or `root` itself when the render stamped none. */\nexport function sectionWrappers(root: HTMLElement): HTMLElement[] {\n const sections = Array.from(root.querySelectorAll<HTMLElement>(\"[data-section-index]\"));\n return sections.length > 0 ? sections : [root];\n}\n\n/**\n * The zoom that fits `naturalPt` of document into `availablePx` of window, never magnifying\n * past `max`. Below `MIN_FIT_SCALE` the text would be unreadable, so the view stops shrinking\n * and lets the surface scroll horizontally instead \u2014 the same trade a word processor makes.\n */\nexport const MIN_FIT_SCALE = 0.25;\n\nexport function fitScale(availablePx: number, naturalPt: number, max = 1): number {\n if (!(availablePx > 0) || !(naturalPt > 0)) return max;\n const naturalPx = ptToPx(naturalPt);\n if (naturalPx <= availablePx) return max;\n return Math.max(MIN_FIT_SCALE, Math.min(max, availablePx / naturalPx));\n}\n\n/**\n * Applies a zoom factor to `el`.\n *\n * Prefers CSS `zoom`, which participates in layout \u2014 so the element's own box shrinks, the\n * page keeps its scrollbars honest, and caret/hit-testing geometry stays correct inside a\n * `contenteditable`. `transform: scale()` is the fallback for engines without `zoom`; it does\n * not affect layout, so the caller must compensate for the space the unscaled box still\n * reserves, which is what `naturalPt` is for.\n */\nexport function applyZoom(\n el: HTMLElement,\n scale: number,\n naturalPt?: { width: number; height: number },\n): void {\n if (scale === 1) {\n el.style.removeProperty(\"zoom\");\n el.style.removeProperty(\"transform\");\n el.style.removeProperty(\"transform-origin\");\n el.style.removeProperty(\"margin-right\");\n el.style.removeProperty(\"margin-bottom\");\n return;\n }\n const zoomSupported =\n typeof CSS !== \"undefined\" && typeof CSS.supports === \"function\" && CSS.supports(\"zoom\", \"0.5\");\n if (zoomSupported) {\n el.style.zoom = String(scale);\n return;\n }\n el.style.transform = `scale(${scale})`;\n el.style.transformOrigin = \"top left\";\n if (naturalPt) {\n el.style.marginRight = `-${ptToPx(naturalPt.width * (1 - scale))}px`;\n el.style.marginBottom = `-${ptToPx(naturalPt.height * (1 - scale))}px`;\n }\n}\n", "/**\n * Pagination engine for creating a PDF.js-style paginated view from HTML output.\n *\n * This module provides client-side pagination that measures rendered content\n * and flows it across fixed-size page containers based on document dimensions.\n */\n\nimport { formatPageNumber } from \"./page-number-format.js\";\nimport { alignExactLineBaselines, insetClipBounds, preserveExactLineInk } from \"./line-metrics.js\";\nimport {\n DEFAULT_MARGIN,\n DEFAULT_PAGE_HEIGHT,\n DEFAULT_PAGE_WIDTH,\n parseSectionDimensions,\n ptToPx,\n pxToPt,\n resolvePageBands,\n} from \"./page-geometry.js\";\nimport type { PageBands, PageDimensions } from \"./page-geometry.js\";\n\nexport type { PageBands, PageDimensions } from \"./page-geometry.js\";\n\n/**\n * Whether two sections describe the same physical page box. A continuous section\n * break is only honorable when it does \u2014 a changed page size or margin set forces\n * a real page break, which is Word's behavior too.\n */\nfunction samePageBox(a: PageDimensions, b: PageDimensions): boolean {\n return (\n a.pageWidth === b.pageWidth &&\n a.pageHeight === b.pageHeight &&\n a.marginTop === b.marginTop &&\n a.marginRight === b.marginRight &&\n a.marginBottom === b.marginBottom &&\n a.marginLeft === b.marginLeft\n );\n}\n\n/**\n * Headers and footers for a specific section.\n */\nexport interface SectionHeaderFooter {\n /** Default header (used for odd pages or all pages) */\n headerDefault?: HTMLElement;\n /** First page header */\n headerFirst?: HTMLElement;\n /** Even page header */\n headerEven?: HTMLElement;\n /** Default footer (used for odd pages or all pages) */\n footerDefault?: HTMLElement;\n /** First page footer */\n footerFirst?: HTMLElement;\n /** Even page footer */\n footerEven?: HTMLElement;\n\n // Pre-measured heights (populated during registry parsing for lazy-loading compatibility)\n /** Measured height of default header in points */\n headerDefaultHeight?: number;\n /** Measured height of first page header in points */\n headerFirstHeight?: number;\n /** Measured height of even page header in points */\n headerEvenHeight?: number;\n /** Measured height of default footer in points */\n footerDefaultHeight?: number;\n /** Measured height of first page footer in points */\n footerFirstHeight?: number;\n /** Measured height of even page footer in points */\n footerEvenHeight?: number;\n}\n\n/**\n * Registry of headers and footers by section index.\n */\nexport type HeaderFooterRegistry = Map<number, SectionHeaderFooter>;\n\n/**\n * A measured content block with metadata for pagination decisions.\n */\nexport interface MeasuredBlock {\n /** The DOM element */\n element: HTMLElement;\n /** Section whose body owns this block after a continuous section transition. */\n sectionIndex: number;\n /** Measured height in points (content + padding + border, excluding margins) */\n heightPt: number;\n /** Top margin in points */\n marginTopPt: number;\n /** Bottom margin in points */\n marginBottomPt: number;\n /** Whether to keep this block with the next one */\n keepWithNext: boolean;\n /** Whether to keep all lines of this block together */\n keepLines: boolean;\n /** Whether to force a page break before this block */\n pageBreakBefore: boolean;\n /** Whether this is a page break marker */\n isPageBreak: boolean;\n /** Whether the block is a Word paragraph whose top margin represents paragraph space-before */\n isWordParagraph?: boolean;\n}\n\n/**\n * Information about a rendered page.\n */\nexport interface PageInfo {\n /** 1-based page number */\n pageNumber: number;\n /** Section index this page belongs to */\n sectionIndex: number;\n /** Page dimensions */\n dimensions: PageDimensions;\n /** The page container element */\n element: HTMLElement;\n}\n\n/**\n * Result of pagination operation.\n */\nexport interface PaginationResult {\n /** Total number of pages */\n totalPages: number;\n /** Array of page information */\n pages: PageInfo[];\n /** Present only when the caller supplied an exact layoutToken. */\n pageMap?: PageMap;\n}\n\nexport type PageMapMode = \"paginated\" | \"continuous\";\nexport type PageMapAvailability = \"available\" | \"unavailable\";\nexport type PageMapStory = \"body\" | \"header\" | \"footer\" | \"footnote\" | \"endnote\" | \"comment\";\n\nexport interface PageMapRect {\n /** Page-relative points, independent of viewer zoom/transform. */\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface PageMapPage {\n pageNumber: number;\n pageInSection: number;\n width: number;\n height: number;\n sectionIndex?: number;\n pageName: string;\n}\n\nexport interface PageMapFragment {\n fragmentId: string;\n /** Canonical collision-safe `kind:scope:unid`, never the bare editor Unid. */\n anchorId: string;\n fragmentIndex: number;\n pageNumber: number;\n geometry: PageMapRect;\n story: PageMapStory;\n /** Table-cell ownership is orthogonal to story (e.g. a body or footnote table cell). */\n inTableCell: boolean;\n}\n\n/** Versioned portable layout contract consumed by DocxSession and remote agent surfaces. */\nexport interface PageMap {\n schemaVersion: 1;\n mode: PageMapMode;\n availability: PageMapAvailability;\n documentVersion: number;\n rendererFingerprint: string;\n pages: PageMapPage[];\n fragments: PageMapFragment[];\n}\n\n/** Explicit no-pages contract for a continuous viewer. It never estimates page numbers. */\nexport function createUnavailablePageMap(\n documentVersion: number,\n rendererFingerprint: string,\n mode: \"continuous\" = \"continuous\",\n): PageMap {\n if (!rendererFingerprint) throw new Error(\"rendererFingerprint must be non-empty\");\n return {\n schemaVersion: 1,\n mode,\n availability: \"unavailable\",\n documentVersion,\n rendererFingerprint,\n pages: [],\n fragments: [],\n };\n}\n\nexport interface PageCitationNavigation {\n navigated: boolean;\n target?: HTMLElement;\n pageNumber?: number;\n fragmentId?: string;\n unavailableReason?: \"citation_unavailable\" | \"fragment_not_found\";\n}\n\ninterface PageCitationHighlightState {\n target: HTMLElement;\n highlightClass?: string;\n addedClass?: boolean;\n inlineStyles?: Array<{ name: string; value: string; priority: string }>;\n}\n\nconst activePageCitationHighlights = new WeakMap<ParentNode, PageCitationHighlightState>();\n\n/** Remove the citation highlight previously applied within this paginated root. */\nexport function clearPageCitationHighlight(root: ParentNode): void {\n const active = activePageCitationHighlights.get(root);\n if (!active) return;\n if (active.highlightClass && active.addedClass) {\n active.target.classList.remove(active.highlightClass);\n }\n for (const style of active.inlineStyles ?? []) {\n if (style.value) {\n active.target.style.setProperty(style.name, style.value, style.priority);\n } else {\n active.target.style.removeProperty(style.name);\n }\n }\n activePageCitationHighlights.delete(root);\n}\n\n/**\n * Navigate an exact citation over an already-paginated DOM. The page-qualified fragment id is\n * authoritative; page + canonical source identity is a compatibility fallback for older v1 DOMs.\n */\nexport function navigateToPageCitation(\n root: ParentNode,\n citation: {\n availability: PageMapAvailability;\n anchorId: string;\n fragments: Array<{ fragmentId: string; pageNumber: number }>;\n },\n options: {\n highlightClass?: string;\n /** Apply a visible inline highlight when no class is supplied. Default true. */\n highlight?: boolean;\n behavior?: ScrollBehavior;\n block?: ScrollLogicalPosition;\n } = {},\n): PageCitationNavigation {\n clearPageCitationHighlight(root);\n if (citation.availability !== \"available\" || citation.fragments.length === 0) {\n return { navigated: false, unavailableReason: \"citation_unavailable\" };\n }\n\n const byAttribute = (name: string, value: string, within: ParentNode = root): HTMLElement | null => {\n for (const node of Array.from(within.querySelectorAll<HTMLElement>(`[${name}]`))) {\n if (node.getAttribute(name) === value) return node;\n }\n return null;\n };\n\n const fragment = citation.fragments[0];\n let target = byAttribute(\"data-page-fragment-id\", fragment.fragmentId);\n if (!target) {\n const page = byAttribute(\"data-page-number\", String(fragment.pageNumber));\n if (page) target = byAttribute(\"data-source-anchor-id\", citation.anchorId, page) ?? page;\n }\n if (!target) {\n return {\n navigated: false,\n pageNumber: fragment.pageNumber,\n fragmentId: fragment.fragmentId,\n unavailableReason: \"fragment_not_found\",\n };\n }\n\n if (options.highlightClass) {\n const addedClass = !target.classList.contains(options.highlightClass);\n target.classList.add(options.highlightClass);\n activePageCitationHighlights.set(root, {\n target,\n highlightClass: options.highlightClass,\n addedClass,\n });\n } else if (options.highlight !== false) {\n const names = [\"outline\", \"outline-offset\", \"background-color\"];\n const inlineStyles = names.map((name) => ({\n name,\n value: target.style.getPropertyValue(name),\n priority: target.style.getPropertyPriority(name),\n }));\n target.style.setProperty(\"outline\", \"3px solid #f4b400\", \"important\");\n target.style.setProperty(\"outline-offset\", \"2px\", \"important\");\n target.style.setProperty(\"background-color\", \"rgba(255, 235, 59, .18)\", \"important\");\n activePageCitationHighlights.set(root, { target, inlineStyles });\n }\n target.scrollIntoView({\n behavior: options.behavior ?? \"smooth\",\n block: options.block ?? \"center\",\n });\n return {\n navigated: true,\n target,\n pageNumber: fragment.pageNumber,\n fragmentId: fragment.fragmentId,\n };\n}\n\n/**\n * Options for the pagination engine.\n */\nexport interface PaginationOptions {\n /** Scale factor for rendering (1.0 = 100%). Default: 1 */\n scale?: number;\n /** CSS class prefix used in the HTML. Default: \"page-\" */\n cssPrefix?: string;\n /** Whether to show page numbers. Default: true */\n showPageNumbers?: boolean;\n /** Gap between pages in pixels. Default: 20 */\n pageGap?: number;\n /**\n * Whether ordinary paragraphs may be fragmented across page boundaries.\n * Defaults to false for direct PaginationEngine callers; read-only viewer\n * entry points opt in explicitly.\n */\n fragmentParagraphs?: boolean;\n /** Cooperative checkpoint for bounded non-yielding browser layout work. */\n checkCancellation?: () => void;\n /**\n * Skip fragment-identity stamping at the end of paginate(). Callers that mutate the page tree\n * afterwards (running-story placement) and then call normalizePageMapFragmentIdentities() would\n * otherwise pay the whole forced-layout pass twice and discard the first result. Default: false.\n */\n deferFragmentIdentities?: boolean;\n /**\n * Points to withhold from the body height available to specific physical pages (1-based page\n * number \u2192 pt). Only the fitting budget shrinks; the page's rendered bands do not move. The\n * standalone export uses it for its bounded corrective pass: when a finished page still clips\n * its body \u2014 its layout ran a few points past what the placement model predicted \u2014 the export\n * lays the document out again from pristine HTML with that page's budget reduced by the\n * overflow, so the offending block moves or splits onto the next page (issue #848).\n */\n bodyBudgetReductionsPt?: Readonly<Record<number, number>>;\n /**\n * Incremental admission check invoked immediately before each physical page is allocated.\n * Export callers use this to enforce `finalPages` without constructing an over-limit DOM first.\n */\n checkPageCount?: (prospectivePageCount: number) => void;\n /** Exact invalidation tokens used to materialize an authoritative PageMap with the result. */\n layoutToken?: { documentVersion: number; rendererFingerprint: string };\n}\n\n// Default letter size in points (612 x 792 = 8.5\" x 11\")\n// Maximum percentage of content height that footnotes can occupy\n// This allows footnotes to expand upward into body content space when needed\nconst MAX_FOOTNOTE_AREA_RATIO = 0.6; // 60% of content height\n// Hidden measurement and final absolutely-positioned note bands differ by sub-pixel border/margin\n// rounding in Chromium. Reserve a small physical-unit guard so the last baseline stays visible.\nconst FOOTNOTE_MEASUREMENT_GUARD_PT = 2;\n/** Internal provenance retained only while a note element waits between pages. */\nconst FOOTNOTE_SOURCE_POSITION_ATTR = \"data-pagination-footnote-source-position\";\n\n/**\n * Pagination engine that converts HTML with pagination metadata\n * into a paginated view with fixed-size page containers.\n */\n/**\n * Registry of footnotes by ID for per-page distribution.\n */\nexport type FootnoteRegistry = Map<string, HTMLElement>;\n\n/**\n * Tracks footnote content that needs to continue on the next page.\n */\ninterface FootnoteContinuation {\n /** The footnote ID being continued */\n footnoteId: string;\n /** Canonical fn:* definition identity from the registry wrapper. */\n sourceAnchorId?: string;\n /** Remaining paragraphs/elements that didn't fit */\n remainingElements: HTMLElement[];\n}\n\n/**\n * Tracks a partial footnote that was split on a page.\n */\ninterface PartialFootnote {\n /** The footnote ID */\n footnoteId: string;\n /** Elements that fit on this page */\n fittingElements: HTMLElement[];\n}\n\n/** Existing page payload that a newly split note must fit beside. */\ninterface FootnotePackingContext {\n footnoteIds: readonly string[];\n continuation?: FootnoteContinuation | null;\n partialFootnotes?: readonly PartialFootnote[];\n}\n\ntype ParagraphSplitAttempt =\n | { kind: \"split\"; head: HTMLElement; tail: HTMLElement }\n | { kind: \"no-fit\" }\n | { kind: \"indivisible\" };\n\ninterface ParagraphFragmentEndpoint {\n node: Node;\n offset: number;\n /** UTF-16 offset in the paragraph's flattened text. */\n textOffset: number;\n /** Prefer a DOM boundary outside an atomic field over its last text-node boundary. */\n priority: number;\n}\n\n/**\n * A section's `w:pgNumType`, as stamped on its wrapper by the converter. Both fields are optional\n * because both attributes are: an absent `start` means the section continues the previous section's\n * numbering, and an absent `format` means Word's default `1, 2, 3`.\n */\ninterface SectionPageNumbering {\n start?: number;\n format?: string;\n}\n\n/**\n * The top and bottom margins a block occupies in its parent's flow, in CSS px, AFTER CSS margin\n * collapsing through its first and last in-flow children (CSS 2.1 \u00A78.3.1). getBoundingClientRect()\n * excludes such a collapsed-through margin, and getComputedStyle() reports only the element's own:\n * the converter wraps a table in an unstyled `div`, so the table's own top margin collapses\n * through the wrapper and occupies page height that neither of those reads accounted for. The\n * paginator's budget then fell a few pixels to a line short of the laid-out page, and the export\n * refused the clipped page (issue #848).\n *\n * A margin collapses with a parent's while the parent is an ordinary block box (display block or\n * list-item, overflow visible, not floated or absolutely positioned \u2014 anything else establishes\n * its own formatting context) with no border or padding on that side, the child is the parent's\n * first (last) in-flow block-level child, and no line content precedes (follows) it. For the\n * bottom edge the parent must also have an automatic height. Positive margins combine by maximum\n * and negative ones by minimum, as CSS collapses them.\n */\nexport function collapsedBlockMarginsPx(view: Window, element: HTMLElement): { topPx: number; bottomPx: number } {\n return {\n topPx: collapseMarginChain(view, element, \"top\"),\n bottomPx: collapseMarginChain(view, element, \"bottom\"),\n };\n}\n\nfunction collapseMarginChain(view: Window, element: HTMLElement, edge: \"top\" | \"bottom\"): number {\n const margins: number[] = [];\n let current: HTMLElement | null = element;\n while (current) {\n const style = view.getComputedStyle(current);\n margins.push(parseFloat(edge === \"top\" ? style.marginTop : style.marginBottom) || 0);\n current = collapsesThroughTo(view, current, style, edge);\n }\n const positive = Math.max(0, ...margins);\n const negative = Math.min(0, ...margins);\n return positive + negative;\n}\n\n/** The child whose `edge` margin collapses through `parent`'s, or null when none does. */\nfunction collapsesThroughTo(\n view: Window,\n parent: HTMLElement,\n style: CSSStyleDeclaration,\n edge: \"top\" | \"bottom\",\n): HTMLElement | null {\n const ordinaryBlock = (style.display === \"block\" || style.display === \"list-item\")\n && style.overflowX === \"visible\" && style.overflowY === \"visible\"\n && style.float === \"none\" && style.position !== \"absolute\" && style.position !== \"fixed\";\n if (!ordinaryBlock) return null;\n // Column boxes establish a formatting context: child margins stay inside the multicol\n // box and are already included in its measured height (CSS Multi-column Layout \u00A72).\n if (style.columnCount !== \"auto\" || style.columnWidth !== \"auto\") return null;\n const border = parseFloat(edge === \"top\" ? style.borderTopWidth : style.borderBottomWidth) || 0;\n const padding = parseFloat(edge === \"top\" ? style.paddingTop : style.paddingBottom) || 0;\n if (border !== 0 || padding !== 0) return null;\n if (edge === \"bottom\" && parent.style.height !== \"\") return null;\n\n const nodes = Array.from(parent.childNodes);\n if (edge === \"bottom\") nodes.reverse();\n for (const node of nodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n if ((node.textContent ?? \"\").trim() !== \"\") return null; // line content comes first\n continue;\n }\n if (node.nodeType !== Node.ELEMENT_NODE) continue;\n const child = node as HTMLElement;\n const childStyle = view.getComputedStyle(child);\n if (childStyle.display === \"none\") continue;\n if (childStyle.position === \"absolute\" || childStyle.position === \"fixed\" || childStyle.float !== \"none\") continue;\n const blockLevel = childStyle.display === \"block\" || childStyle.display === \"list-item\"\n || childStyle.display === \"table\" || childStyle.display === \"flow-root\"\n || childStyle.display === \"flex\" || childStyle.display === \"grid\";\n return blockLevel ? child : null; // an inline-level child starts a line box\n }\n return null;\n}\n\n/** A page-space box in client coordinates: left/top inclusive, right/bottom exclusive. */\nexport interface VisibleBox {\n left: number;\n top: number;\n right: number;\n bottom: number;\n}\n\n/**\n * Set by the paginator on a floating drawing it promotes out of its paragraph into the page box;\n * the value is the `data-source-anchor-id` of the element that hosted it. It survives into the\n * standalone export, whose offline re-verification measures through the same function.\n */\nexport const DRAWING_HOST_ATTRIBUTE = \"data-docx-anchor-host\";\n\n/**\n * Set on a source-anchored element a floating drawing was promoted out of, so\n * {@link measureRenderedSource} looks up promoted drawings only for elements that have them.\n */\nexport const HOSTS_PROMOTED_DRAWING_ATTRIBUTE = \"data-docx-hosts-promoted-drawing\";\n\n/** True when `element` shows no text (beyond white space) and no image, SVG or canvas. */\nfunction rendersOnlyItsLine(element: HTMLElement): boolean {\n return (element.textContent ?? '').replace(/[\\s\\u00a0]/g, '') === ''\n && element.querySelector('img, svg, canvas, [data-docx-drawing-anchor]') === null;\n}\n\n/** Self-contained closure for trusted host evaluation in the script-disabled print context. */\nfunction createRenderedSourceMeasurer(\n clipInset: typeof insetClipBounds,\n drawingHostAttribute: string,\n hostsPromotedDrawingAttribute: string,\n) {\n /**\n * Intersect a box with the page and with every ancestor that establishes an overflow clip before\n * the page root. getBoundingClientRect() reports layout outside those clips, which is not rendered\n * and therefore must not satisfy PageMap completeness or inflate portable geometry.\n */\n function visibleWithinPage(\n view: Window,\n element: HTMLElement,\n page: HTMLElement,\n pageRect: DOMRect,\n rect: DOMRect,\n ): VisibleBox {\n let left = Math.max(rect.left, pageRect.left);\n let top = Math.max(rect.top, pageRect.top);\n let right = Math.min(rect.right, pageRect.right);\n let bottom = Math.min(rect.bottom, pageRect.bottom);\n const clips = (value: string) =>\n value === \"hidden\" || value === \"clip\" || value === \"scroll\" || value === \"auto\";\n\n for (let ancestor = element.parentElement;\n ancestor && ancestor !== page;\n ancestor = ancestor.parentElement) {\n const style = view.getComputedStyle(ancestor);\n const clipsX = clips(style.overflowX);\n const clipsY = clips(style.overflowY);\n if (!clipsX && !clipsY && !style.clipPath.startsWith(\"inset(\")) continue;\n const ancestorRect = ancestor.getBoundingClientRect();\n const scale = ancestorRect.width / ancestor.offsetWidth || 1;\n const inset = clipInset(style.clipPath, ancestorRect, scale);\n if (inset) {\n left = Math.max(left, inset.left);\n top = Math.max(top, inset.top);\n right = Math.min(right, inset.right);\n bottom = Math.min(bottom, inset.bottom);\n }\n if (clipsX) {\n left = Math.max(left, ancestorRect.left);\n right = Math.min(right, ancestorRect.right);\n }\n if (clipsY) {\n top = Math.max(top, ancestorRect.top);\n bottom = Math.min(bottom, ancestorRect.bottom);\n }\n }\n return { left, top, right, bottom };\n }\n\n return function measureRenderedSource(\n view: Window,\n element: HTMLElement,\n page: HTMLElement,\n pageRect: DOMRect = page.getBoundingClientRect(),\n ): { rect: DOMRect; visible: VisibleBox } {\n const own = element.getBoundingClientRect();\n const ownResult = () => ({ rect: own, visible: visibleWithinPage(view, element, page, pageRect, own) });\n const ownMeasurable = own.width > 0 && own.height > 0;\n const hostsPromotedDrawing = element.hasAttribute(hostsPromotedDrawingAttribute);\n if (ownMeasurable && !hostsPromotedDrawing) return ownResult();\n\n const hostAnchorId = element.dataset.sourceAnchorId;\n const promoted = hostAnchorId\n ? Array.from(page.querySelectorAll<HTMLElement>(`[${drawingHostAttribute}]`))\n .filter((drawing) => drawing.getAttribute(drawingHostAttribute) === hostAnchorId)\n : [];\n if (ownMeasurable && promoted.length === 0) return ownResult();\n const rendered = [\n ...(ownMeasurable ? [element] : Array.from(element.querySelectorAll<HTMLElement>(\"*\"))),\n ...promoted.flatMap((drawing) => [drawing, ...Array.from(drawing.querySelectorAll<HTMLElement>(\"*\"))]),\n ];\n\n let left = Infinity;\n let top = Infinity;\n let right = -Infinity;\n let bottom = -Infinity;\n for (const child of rendered) {\n const style = view.getComputedStyle(child);\n if (style.display === \"none\" || style.visibility === \"hidden\") continue;\n const childRect = child.getBoundingClientRect();\n if (childRect.width <= 0 || childRect.height <= 0) continue;\n const visible = visibleWithinPage(view, child, page, pageRect, childRect);\n if (visible.right <= visible.left || visible.bottom <= visible.top) continue;\n left = Math.min(left, visible.left);\n top = Math.min(top, visible.top);\n right = Math.max(right, visible.right);\n bottom = Math.max(bottom, visible.bottom);\n }\n if (!(left < right && top < bottom)) return ownResult();\n return { rect: new DOMRect(left, top, right - left, bottom - top), visible: { left, top, right, bottom } };\n };\n}\n\n/**\n * Where a source-anchored element renders on `page`: `rect` is its layout box and `visible` the\n * part of it the page shows. Normally that is the element's own border box. An element the\n * paginator promoted floating drawings out of measures as the union of what it renders \u2014 its own\n * box (or, when that is empty, its descendants) and the drawings promoted out of it (linked by\n * {@link DRAWING_HOST_ATTRIBUTE}) \u2014 each clipped along its OWN ancestor chain, since a promoted\n * drawing sits outside the text column that clips its host (issue #849). Such a paragraph keeps a\n * line of its own when the drawing was its only content (issue #880), and its fragment still\n * encloses the drawing. Returns the element's own degenerate box when none of that renders.\n *\n * Fragment-identity normalization, PageMap materialization and the standalone export's offline\n * re-verification all measure through this one function, so they agree on which elements are\n * measurable and where.\n */\nexport const measureRenderedSource = createRenderedSourceMeasurer(\n insetClipBounds, DRAWING_HOST_ATTRIBUTE, HOSTS_PROMOTED_DRAWING_ATTRIBUTE,\n);\n\n/** @internal Owned runtime code only; never inserts a script or enables document JavaScript. */\nexport function renderedSourceMeasurerExpression(): string {\n return `(${createRenderedSourceMeasurer.toString()})(${insetClipBounds.toString()},\n ${JSON.stringify(DRAWING_HOST_ATTRIBUTE)}, ${JSON.stringify(HOSTS_PROMOTED_DRAWING_ATTRIBUTE)})`;\n}\n\nexport class PaginationEngine {\n private stagingElement: HTMLElement;\n private containerElement: HTMLElement;\n private document: Document;\n private view: Window & typeof globalThis;\n private scale: number;\n private cssPrefix: string;\n private showPageNumbers: boolean;\n private pageGap: number;\n private fragmentParagraphs: boolean;\n private deferFragmentIdentities: boolean;\n private bodyBudgetReductionsPt: Readonly<Record<number, number>>;\n private cancellationCheckpoint?: () => void;\n private pageCountCheckpoint?: (prospectivePageCount: number) => void;\n private createdPageCount = 0;\n private layoutToken?: { documentVersion: number; rendererFingerprint: string };\n private hfRegistry: HeaderFooterRegistry;\n private footnoteRegistry: FootnoteRegistry;\n private footnoteSeparator: HTMLElement | null = null;\n private footnoteContinuationSeparator: HTMLElement | null = null;\n private commentMarginRegistry: Map<string, HTMLElement>;\n private footnoteLayoutLikeWord8 = false;\n private pendingFootnoteContinuation: FootnoteContinuation | null = null;\n /** Per-section `w:pgNumType` (start / format), read off the section wrappers. */\n private pageNumbering: Map<number, SectionPageNumbering> = new Map();\n private lastPages: PageInfo[] = [];\n private expectedPageMapAnchorIds: Set<string> = new Set();\n private state: \"ready\" | \"running\" | \"complete\" | \"failed\" = \"ready\";\n\n /**\n * Creates a new pagination engine.\n *\n * @param staging - The staging element or its ID containing the content to paginate\n * @param container - The container element or its ID where pages will be rendered\n * @param options - Pagination options\n */\n constructor(\n staging: HTMLElement | string,\n container: HTMLElement | string,\n options: PaginationOptions = {}\n ) {\n const ownerDocument =\n typeof staging !== \"string\"\n ? staging.ownerDocument\n : typeof container !== \"string\"\n ? container.ownerDocument\n : globalThis.document;\n this.stagingElement =\n typeof staging === \"string\"\n ? (ownerDocument.getElementById(staging) as HTMLElement)\n : staging;\n this.containerElement =\n typeof container === \"string\"\n ? (ownerDocument.getElementById(container) as HTMLElement)\n : container;\n\n if (!this.stagingElement) {\n throw new Error(\"Staging element not found\");\n }\n if (!this.containerElement) {\n throw new Error(\"Container element not found\");\n }\n if (this.stagingElement.ownerDocument !== this.containerElement.ownerDocument) {\n throw new Error(\"Staging and container elements must belong to the same document\");\n }\n const view = ownerDocument.defaultView;\n if (!view) {\n throw new Error(\"Pagination requires an attached document with a defaultView\");\n }\n this.document = ownerDocument;\n this.view = view as Window & typeof globalThis;\n\n this.scale = options.scale ?? 1;\n this.cssPrefix = options.cssPrefix ?? \"page-\";\n this.showPageNumbers = options.showPageNumbers ?? true;\n this.pageGap = options.pageGap ?? 20;\n this.fragmentParagraphs = options.fragmentParagraphs ?? false;\n this.deferFragmentIdentities = options.deferFragmentIdentities ?? false;\n this.bodyBudgetReductionsPt = options.bodyBudgetReductionsPt ?? {};\n this.cancellationCheckpoint = options.checkCancellation;\n this.pageCountCheckpoint = options.checkPageCount;\n this.layoutToken = options.layoutToken;\n this.hfRegistry = new Map();\n this.footnoteRegistry = new Map();\n this.commentMarginRegistry = new Map();\n }\n\n /**\n * Runs the pagination process.\n *\n * @returns PaginationResult with page information\n */\n paginate(): PaginationResult {\n this.checkpoint();\n if (this.state !== \"ready\") {\n throw new Error(`PaginationEngine is one-shot and is already ${this.state}`);\n }\n if (!this.stagingElement.isConnected || !this.containerElement.isConnected) {\n throw new Error(\"Pagination requires staging and container elements attached to their document\");\n }\n if (this.document.documentElement.getBoundingClientRect().width <= 0) {\n throw new Error(\"Pagination requires a browsing context with non-zero layout\");\n }\n this.state = \"running\";\n\n try {\n const pages: PageInfo[] = [];\n let pageNumber = 1;\n\n // Parse the header/footer registry if present\n this.hfRegistry = this.parseHeaderFooterRegistry();\n\n // Parse the footnote registry if present\n this.footnoteRegistry = this.parseFootnoteRegistry();\n ({\n normal: this.footnoteSeparator,\n continuation: this.footnoteContinuationSeparator,\n } = this.parseFootnoteSeparators());\n\n // Parse the margin-comment registry if present. Its entries are cloned into\n // the side substrate of pages that contain the corresponding range marker.\n this.commentMarginRegistry = this.parseCommentMarginRegistry();\n this.footnoteLayoutLikeWord8 =\n this.stagingElement.dataset.footnoteLayoutLikeWord8 === \"true\";\n\n // Find all section containers\n const sections = this.stagingElement.querySelectorAll<HTMLElement>(\n \"[data-section-index]\"\n );\n\n this.pageNumbering = this.parsePageNumbering(sections);\n\n // If no sections found, treat the entire staging content as one section\n const sectionsToProcess =\n sections.length > 0 ? Array.from(sections) : [this.stagingElement];\n\n // Snapshot the addressable SOURCE inventory before flow moves nodes out of staging. PageMap\n // completeness cannot be inferred from whatever survives into page boxes: that would let a\n // dropped block silently disappear from both the DOM and the supposedly authoritative map.\n // Running-story variants and cited notes are inventoried from their source registries.\n this.expectedPageMapAnchorIds = new Set();\n const referencedFootnoteIds = new Set<string>();\n const referencedCommentIds = new Set<string>();\n for (const section of sectionsToProcess) {\n this.checkpoint();\n this.collectExpectedSourceAnchors(section, this.expectedPageMapAnchorIds, true);\n for (const reference of Array.from(section.querySelectorAll<HTMLElement>(\"[data-footnote-id]\"))) {\n this.checkpoint();\n if (reference.closest(\"#pagination-footnote-registry, #pagination-hf-registry\")) continue;\n const id = reference.dataset.footnoteId;\n if (id) referencedFootnoteIds.add(id);\n }\n for (const reference of Array.from(section.querySelectorAll<HTMLElement>(\"[data-comment-id]\"))) {\n this.checkpoint();\n if (reference.closest(\n \"#pagination-comment-margin-registry, #pagination-footnote-registry, #pagination-hf-registry\",\n )) continue;\n const id = reference.dataset.commentId;\n if (id) referencedCommentIds.add(id);\n }\n }\n for (const id of referencedFootnoteIds) {\n this.checkpoint();\n const source = this.footnoteRegistry.get(id);\n if (!source) continue;\n this.collectExpectedSourceAnchors(source, this.expectedPageMapAnchorIds);\n // Margin comments are presentation stories selected by markers. Markers\n // inside a cited footnote are just as visible/addressable as body markers.\n for (const reference of Array.from(\n source.querySelectorAll<HTMLElement>(\"[data-comment-id]\"),\n )) {\n this.checkpoint();\n const commentId = reference.dataset.commentId;\n if (commentId) referencedCommentIds.add(commentId);\n }\n }\n for (const id of referencedCommentIds) {\n this.checkpoint();\n const source = this.commentMarginRegistry.get(id);\n if (source) this.collectExpectedSourceAnchors(source, this.expectedPageMapAnchorIds);\n }\n\n // Group adjacent sections into page runs. A `w:type=\"continuous\"` section keeps\n // filling the page its predecessor started rather than opening a fresh one, so it\n // joins the previous run \u2014 provided the page box (size and margins) is unchanged,\n // which is also Word's own condition for honoring a continuous break. Pages of a\n // merged run begins under the leading section's running stories. Each measured block retains\n // its own section, though: once a continuous section spills to a later physical page, that\n // page must switch to the new section's headers, footers, and page-numbering state.\n interface PageRun {\n sections: HTMLElement[];\n sectionIndex: number;\n sectionType: string;\n dims: PageDimensions;\n sectionDimensions: Map<number, PageDimensions>;\n }\n const runs: PageRun[] = [];\n for (const section of sectionsToProcess) {\n this.checkpoint();\n const dims = parseSectionDimensions(section);\n const previous = runs[runs.length - 1];\n if (\n previous &&\n section.dataset.sectionType === \"continuous\" &&\n samePageBox(previous.dims, dims)\n ) {\n previous.sections.push(section);\n previous.sectionDimensions.set(\n parseInt(section.dataset.sectionIndex || \"0\", 10),\n dims,\n );\n } else {\n const sectionIndex = parseInt(section.dataset.sectionIndex || \"0\", 10);\n runs.push({\n sections: [section],\n sectionIndex,\n sectionType: section.dataset.sectionType ?? \"nextPage\",\n dims,\n sectionDimensions: new Map([[sectionIndex, dims]]),\n });\n }\n }\n\n for (const run of runs) {\n this.checkpoint();\n // Odd/even section breaks begin the new section on the requested physical side. When the\n // following page has the opposite parity, Word inserts one intentionally blank filler page.\n // It belongs to the preceding section, advances physical/logical numbering, retains that\n // section's paper geometry, and carries no running story.\n const needsParityFiller = pages.length > 0\n && ((run.sectionType === \"oddPage\" && pageNumber % 2 === 0)\n || (run.sectionType === \"evenPage\" && pageNumber % 2 === 1));\n if (needsParityFiller) {\n const precedingPage = pages[pages.length - 1];\n const precedingPageInSection = parseInt(\n precedingPage.element.dataset.pageInSection ?? \"1\",\n 10,\n );\n const precedingDisplayedPageNumber = parseInt(\n precedingPage.element.dataset.displayedPageNumber ?? String(precedingPage.pageNumber),\n 10,\n );\n const filler = this.createPage(\n precedingPage.dimensions,\n pageNumber,\n precedingPage.sectionIndex,\n precedingDisplayedPageNumber + 1,\n [],\n precedingPageInSection + 1,\n [],\n 0,\n null,\n undefined,\n true,\n );\n pages.push(filler);\n pageNumber++;\n }\n // Make staging visible for measurement\n this.stagingElement.style.visibility = \"hidden\";\n this.stagingElement.style.position = \"absolute\";\n this.stagingElement.style.left = \"-9999px\";\n this.stagingElement.style.display = \"block\";\n\n const blocks: MeasuredBlock[] = [];\n for (const section of run.sections) {\n this.checkpoint();\n const sectionIndex = parseInt(section.dataset.sectionIndex || \"0\", 10);\n const sectionDims = run.sectionDimensions.get(sectionIndex) ?? run.dims;\n // Set width for accurate line wrapping\n section.style.width = `${sectionDims.contentWidth}pt`;\n\n const columnCount = parseInt(section.dataset.cols || \"1\", 10);\n if (columnCount > 1) {\n const gap = parseFloat(section.dataset.colGap || \"\");\n blocks.push(...this.buildColumnBlocks(\n section,\n sectionDims,\n sectionIndex,\n columnCount,\n Number.isFinite(gap) ? gap : 36,\n section.dataset.sectionType === \"continuous\"\n && section === sectionsToProcess[sectionsToProcess.length - 1],\n ));\n } else {\n blocks.push(...this.measureBlocks(section, sectionDims, sectionIndex));\n }\n }\n\n // Flow blocks into pages\n const sectionPages = this.flowToPages(\n blocks,\n run.dims,\n pageNumber,\n run.sectionIndex,\n run.sectionDimensions,\n );\n this.checkpoint();\n pages.push(...sectionPages);\n pageNumber += sectionPages.length;\n }\n\n // Hide staging after measurement\n this.stagingElement.style.display = \"none\";\n\n // Every page box exists now, so NUMPAGES has an answer and each PAGE marker knows its page.\n this.substitutePageNumberFields(pages.length);\n\n // Only running-story variants selected by a real page are expected to materialize. Read IDs\n // from registry sources, not presentation clones, so a failed clone remains detectable.\n for (const page of pages) {\n this.checkpoint();\n if (page.element.dataset.sectionFiller === \"true\") continue;\n const pageInSection = parseInt(page.element.dataset.pageInSection || \"1\", 10);\n const displayedPageNumber = parseInt(\n page.element.dataset.displayedPageNumber || String(page.pageNumber),\n 10,\n );\n const header = this.selectHeader(page.sectionIndex, pageInSection, displayedPageNumber);\n const footer = this.selectFooter(page.sectionIndex, pageInSection, displayedPageNumber);\n if (header) this.collectExpectedSourceAnchors(header, this.expectedPageMapAnchorIds);\n if (footer) this.collectExpectedSourceAnchors(footer, this.expectedPageMapAnchorIds);\n }\n\n // Establish one active editor anchor and page-qualify every presentation fragment.\n // Full canonical source identities remain on all clones, including table cells.\n this.qualifyPageFragments(pages);\n this.transferVisibleFragmentTargets();\n if (!this.deferFragmentIdentities) this.normalizeVisiblePageFragments(pages);\n this.lastPages = pages;\n\n const result = {\n totalPages: pages.length,\n pages,\n pageMap: this.layoutToken\n ? this.materializePageMap(\n this.layoutToken.documentVersion,\n this.layoutToken.rendererFingerprint,\n )\n : undefined,\n };\n this.state = \"complete\";\n return result;\n } catch (error) {\n this.state = \"failed\";\n throw error;\n }\n }\n\n private checkpoint(): void {\n this.cancellationCheckpoint?.();\n }\n\n /**\n * Normalize visible fragment identities after a caller applies final standalone styles. This\n * deliberately runs before the stability barrier; materializePageMap is read-only so PageMap\n * measurement cannot mutate a tree after it was declared stable.\n */\n normalizePageMapFragmentIdentities(): void {\n if (this.lastPages.length === 0) {\n throw new Error(\"paginate() must complete before fragment identities can be normalized\");\n }\n this.normalizeVisiblePageFragments(this.lastPages);\n }\n\n /**\n * Materialize the last completed browser layout as portable page-relative point geometry.\n * The caller supplies both invalidation tokens; this engine never guesses a document version\n * or renderer fingerprint.\n */\n materializePageMap(documentVersion: number, rendererFingerprint: string): PageMap {\n if (!Number.isSafeInteger(documentVersion) || documentVersion < 0) {\n throw new Error(\"documentVersion must be a non-negative safe integer\");\n }\n if (!rendererFingerprint) throw new Error(\"rendererFingerprint must be non-empty\");\n if (this.lastPages.length === 0) throw new Error(\"paginate() must complete before materializePageMap()\");\n\n const pages: PageMapPage[] = this.lastPages.map((page) => ({\n pageNumber: page.pageNumber,\n pageInSection: parseInt(page.element.dataset.pageInSection || \"1\", 10),\n width: page.dimensions.pageWidth,\n height: page.dimensions.pageHeight,\n sectionIndex: page.sectionIndex,\n pageName: `docxodus-section-${page.sectionIndex}`,\n }));\n\n const fragments: PageMapFragment[] = [];\n const requiredAnchorIds = new Set(this.expectedPageMapAnchorIds);\n if (requiredAnchorIds.size === 0) {\n throw new Error(\"cannot publish an available PageMap without canonical source inventory\");\n }\n const measuredAnchorIds = new Set<string>();\n const emittedFragmentCounts = new Map<string, number>();\n for (const page of this.lastPages) {\n this.checkpoint();\n const pageRect = page.element.getBoundingClientRect();\n if (pageRect.width <= 0 || pageRect.height <= 0) {\n throw new Error(`page ${page.pageNumber} has no measurable geometry`);\n }\n // Ratio-to-known-page-size removes CSS px, zoom, and transform from the contract.\n const pointPerRenderedX = page.dimensions.pageWidth / pageRect.width;\n const pointPerRenderedY = page.dimensions.pageHeight / pageRect.height;\n const nodes = page.element.querySelectorAll<HTMLElement>(\"[data-source-anchor-id]\");\n for (const element of Array.from(nodes)) {\n this.checkpoint();\n // Preserve the source-side exclusion contract on presentation clones as well. This\n // covers the node itself and any excluded/hidden/aria-hidden ancestor within the page.\n if (this.isDeliberatelyUnrenderedSource(element, page.element)) continue;\n const anchorId = element.dataset.sourceAnchorId;\n if (!anchorId || !element.dataset.pageFragmentId\n || !Number.isInteger(parseInt(element.dataset.fragmentIndex || \"\", 10))) {\n throw new Error(`page ${page.pageNumber} contains an unqualified source anchor`);\n }\n\n const style = this.view.getComputedStyle(element);\n const deliberatelyHidden = style.display === \"none\" || style.visibility === \"hidden\";\n if (deliberatelyHidden) continue;\n const { rect, visible: visibleRect } = measureRenderedSource(this.view, element, page.element, pageRect);\n requiredAnchorIds.add(anchorId);\n const left = visibleRect.left;\n const top = visibleRect.top;\n const right = visibleRect.right;\n const bottom = visibleRect.bottom;\n if (rect.width <= 0 || rect.height <= 0 || right <= left || bottom <= top) {\n // A continued note/story clone can contain children clipped off this page which become\n // measurable on its next clone. Enforce completeness once every page has been inspected.\n continue;\n }\n\n measuredAnchorIds.add(anchorId);\n // Clipped descendants in repeated note/story clones are deliberately omitted from the\n // portable map. Re-number only the visible fragments so the emitted contract remains\n // contiguous even when an earlier DOM clone carried no visible geometry on its page.\n const fragmentIndex = emittedFragmentCounts.get(anchorId) ?? 0;\n emittedFragmentCounts.set(anchorId, fragmentIndex + 1);\n const fragmentId = `p${page.pageNumber}-f${fragmentIndex}-${anchorId}`;\n if (element.dataset.fragmentIndex !== String(fragmentIndex)\n || element.dataset.pageFragmentId !== fragmentId\n || element.dataset.pageNumber !== String(page.pageNumber)) {\n throw new Error(\n `page ${page.pageNumber} fragment identity changed after final-tree normalization`,\n );\n }\n fragments.push({\n fragmentId,\n anchorId,\n fragmentIndex,\n pageNumber: page.pageNumber,\n geometry: {\n x: (left - pageRect.left) * pointPerRenderedX,\n y: (top - pageRect.top) * pointPerRenderedY,\n width: (right - left) * pointPerRenderedX,\n height: (bottom - top) * pointPerRenderedY,\n },\n story: this.storyForCanonicalAnchor(anchorId),\n inTableCell: element.matches(\"td,th\") || element.closest(\"td,th\") !== null,\n });\n }\n }\n\n const missingAnchor = Array.from(requiredAnchorIds).find((id) => !measuredAnchorIds.has(id));\n if (missingAnchor) {\n throw new Error(`source anchor ${missingAnchor} has no measurable fragment in the paginated layout`);\n }\n\n return {\n schemaVersion: 1,\n mode: \"paginated\",\n availability: \"available\",\n documentVersion,\n rendererFingerprint,\n pages,\n fragments,\n };\n }\n\n private normalizeVisiblePageFragments(pages: PageInfo[]): void {\n const emittedFragmentCounts = new Map<string, number>();\n for (const page of pages) {\n this.checkpoint();\n const pageRect = page.element.getBoundingClientRect();\n for (const element of Array.from(\n page.element.querySelectorAll<HTMLElement>(\"[data-source-anchor-id]\"),\n )) {\n this.checkpoint();\n if (this.isDeliberatelyUnrenderedSource(element, page.element)) continue;\n const anchorId = element.dataset.sourceAnchorId;\n if (!anchorId) continue;\n const style = this.view.getComputedStyle(element);\n if (style.display === \"none\" || style.visibility === \"hidden\") continue;\n const { rect, visible } = measureRenderedSource(this.view, element, page.element, pageRect);\n if (rect.width <= 0 || rect.height <= 0\n || visible.right <= visible.left || visible.bottom <= visible.top) continue;\n const fragmentIndex = emittedFragmentCounts.get(anchorId) ?? 0;\n emittedFragmentCounts.set(anchorId, fragmentIndex + 1);\n element.dataset.pageNumber = String(page.pageNumber);\n element.dataset.fragmentIndex = String(fragmentIndex);\n element.dataset.pageFragmentId = `p${page.pageNumber}-f${fragmentIndex}-${anchorId}`;\n }\n }\n }\n\n private storyForCanonicalAnchor(anchorId: string): PageMapStory {\n const first = anchorId.indexOf(\":\");\n const second = first < 0 ? -1 : anchorId.indexOf(\":\", first + 1);\n const scope = first >= 0 && second > first ? anchorId.slice(first + 1, second) : \"body\";\n if (scope.startsWith(\"hdr\")) return \"header\";\n if (scope.startsWith(\"ftr\")) return \"footer\";\n if (scope === \"fn\") return \"footnote\";\n if (scope === \"en\") return \"endnote\";\n if (scope === \"cmt\") return \"comment\";\n return \"body\";\n }\n\n /**\n * Add canonical IDs from an addressable source subtree to the pre-pagination inventory.\n * Registry wrappers are excluded when scanning staging because selectable registry contents are\n * inventoried separately. Producers may explicitly mark content that has no visual substrate\n * with `data-page-map-exclude=\"true\"`; native hidden semantics carry the same signal.\n */\n private collectExpectedSourceAnchors(\n source: HTMLElement,\n destination: Set<string>,\n excludeRegistries = false,\n ): void {\n const candidates: HTMLElement[] = source.matches(\"[data-source-anchor-id]\") ? [source] : [];\n candidates.push(...Array.from(source.querySelectorAll<HTMLElement>(\"[data-source-anchor-id]\")));\n for (const element of candidates) {\n if (excludeRegistries && element.closest(\n \"#pagination-hf-registry, #pagination-footnote-registry, #pagination-comment-margin-registry\",\n )) {\n continue;\n }\n if (this.isZeroHeightExplicitBreakCarrier(element)) {\n // Flow consumes the following break marker and clones this otherwise-empty paragraph.\n // Persist the exclusion so that the clone cannot reintroduce the anchor during PageMap\n // measurement after the marker itself has disappeared.\n element.dataset.pageMapExclude = \"true\";\n }\n if (this.isDeliberatelyUnrenderedSource(element, source)) continue;\n const anchorId = element.dataset.sourceAnchorId;\n if (anchorId) destination.add(anchorId);\n }\n }\n\n private isZeroHeightExplicitBreakCarrier(element: HTMLElement): boolean {\n const next = element.nextElementSibling as HTMLElement | null;\n const bounds = element.getBoundingClientRect();\n return element.hasAttribute(\"data-source-anchor-id\")\n && (element.textContent ?? \"\").replace(/\\u00a0/g, \"\").trim() === \"\"\n // Exclude only the converter's zero-height carrier. A blank paragraph with height from\n // padding, borders, a background, or authored sizing still has a visible page substrate and\n // must remain addressable under the authoritative PageMap contract.\n && bounds.height <= 0.01\n && !element.querySelector(\"[data-source-anchor-id]\")\n && !element.querySelector(\"img,svg,canvas,table,hr,input,textarea,select\")\n && (next?.dataset.pageBreak === \"true\"\n || next?.classList.contains(`${this.cssPrefix}break`) === true);\n }\n\n private isDeliberatelyUnrenderedSource(element: HTMLElement, sourceRoot: HTMLElement): boolean {\n for (let current: HTMLElement | null = element; current; current = current.parentElement) {\n const zeroHeightExplicitBreakCarrier = current === element\n && this.isZeroHeightExplicitBreakCarrier(current);\n if (\n current.dataset.pageMapExclude === \"true\"\n // An explicit page-break marker controls flow but has no painted substrate. The converter\n // intentionally emits it as an empty div, so requiring point geometry for its source\n // identity would make every otherwise-valid document with w:br[type=page] fail closed.\n || current.dataset.pageBreak === \"true\"\n || current.classList.contains(`${this.cssPrefix}break`)\n || zeroHeightExplicitBreakCarrier\n || current.hidden\n || current.getAttribute(\"aria-hidden\") === \"true\"\n || current.style.display === \"none\"\n || current.style.visibility === \"hidden\"\n ) {\n return true;\n }\n if (current === sourceRoot) break;\n }\n return false;\n }\n\n /**\n * Keep exactly one active bare-Unid editor anchor per source block. Presentation clones use\n * canonical source identity plus page/fragment qualification instead.\n */\n private qualifyPageFragments(pages: PageInfo[]): void {\n const fragmentCounts = new Map<string, number>();\n const activeCanonicalIds = new Set<string>();\n const activeBareAnchorIds = new Set<string>();\n\n const makeInactive = (element: HTMLElement): void => {\n element.removeAttribute(\"data-anchor\");\n element.removeAttribute(\"data-committed-text\");\n if (element.hasAttribute(\"contenteditable\")) element.setAttribute(\"contenteditable\", \"false\");\n };\n\n for (const page of pages) {\n const nodes = page.element.querySelectorAll<HTMLElement>(\"[data-source-anchor-id]\");\n for (const element of Array.from(nodes)) {\n const anchorId = element.dataset.sourceAnchorId;\n if (!anchorId) continue;\n const fragmentIndex = fragmentCounts.get(anchorId) ?? 0;\n fragmentCounts.set(anchorId, fragmentIndex + 1);\n element.dataset.pageNumber = String(page.pageNumber);\n element.dataset.fragmentIndex = String(fragmentIndex);\n element.dataset.pageFragmentId = `p${page.pageNumber}-f${fragmentIndex}-${anchorId}`;\n\n const story = this.storyForCanonicalAnchor(anchorId);\n const mayOwnActiveEditorAnchor =\n story === \"body\" || story === \"comment\" || story === \"footnote\" || story === \"endnote\";\n if (element.hasAttribute(\"data-anchor\")) {\n const bareAnchorId = element.dataset.anchor!;\n if (mayOwnActiveEditorAnchor\n && !activeCanonicalIds.has(anchorId)\n && !activeBareAnchorIds.has(bareAnchorId)) {\n activeCanonicalIds.add(anchorId);\n activeBareAnchorIds.add(bareAnchorId);\n } else {\n makeInactive(element);\n }\n }\n }\n }\n\n // Body/comment page nodes are the editable copies. A repeated header/footer registry entry can\n // also render the same source story once per section/variant, so retain at most one active\n // staging node per canonical source and make every presentation duplicate inert.\n const activeStagingCanonicalIds = new Set<string>();\n for (const element of Array.from(\n this.stagingElement.querySelectorAll<HTMLElement>(\"[data-source-anchor-id][data-anchor]\"),\n )) {\n const anchorId = element.dataset.sourceAnchorId;\n if (!anchorId) continue;\n const bareAnchorId = element.dataset.anchor!;\n if (activeCanonicalIds.has(anchorId)\n || activeStagingCanonicalIds.has(anchorId)\n || activeBareAnchorIds.has(bareAnchorId)) {\n makeInactive(element);\n } else {\n activeStagingCanonicalIds.add(anchorId);\n activeBareAnchorIds.add(bareAnchorId);\n }\n }\n }\n\n /**\n * Page flow clones source blocks while the hidden staging tree stays in the document. Any HTML\n * fragment target copied into a visible page would therefore resolve to its earlier hidden\n * source. Transfer target ownership to the page presentation after flow is complete; registry\n * and wrapper IDs that have no visible counterpart remain available to pagination internals.\n */\n private transferVisibleFragmentTargets(): void {\n const visibleIds = new Set(Array.from(\n this.containerElement.querySelectorAll<HTMLElement>(\"[id]\"),\n ).map((element) => element.id).filter(Boolean));\n if (visibleIds.size === 0) return;\n for (const source of Array.from(\n this.stagingElement.querySelectorAll<HTMLElement>(\"[id]\"),\n )) {\n if (visibleIds.has(source.id)) source.removeAttribute(\"id\");\n }\n }\n\n /** Read each section's `w:pgNumType` off its wrapper (see {@link SectionPageNumbering}). */\n private parsePageNumbering(sections: ArrayLike<HTMLElement>): Map<number, SectionPageNumbering> {\n const map = new Map<number, SectionPageNumbering>();\n for (const section of Array.from(sections)) {\n const index = parseInt(section.dataset.sectionIndex || \"0\", 10);\n const rawStart = section.dataset.pageNumStart;\n const start = rawStart === undefined ? undefined : parseInt(rawStart, 10);\n map.set(index, {\n start: start !== undefined && Number.isFinite(start) ? start : undefined,\n format: section.dataset.pageNumFmt,\n });\n }\n return map;\n }\n\n /**\n * Fill in the page-number fields inside every page's cloned header/footer.\n *\n * A header/footer is authored once and cloned onto each page, so a PAGE field's single cached\n * result would otherwise show the same number on every page \u2014 the whole reason the converter\n * marks these. `data-field-format` (the field's own `\\*` switch) wins over the section's format\n * when present, which is exactly how Word resolves the two.\n *\n * Runs after layout because NUMPAGES cannot be known before the last page exists. The\n * substituted text can therefore be marginally wider than the cached result the header was\n * measured with; the header band clips, so the failure mode is a hair of overflow rather than\n * a layout that disagrees with itself.\n *\n * Scoped to the CLONED header/footer regions on purpose. A page-number field in body text is\n * ordinary run content that the editor may make editable, and committing an edited block writes\n * back whatever text the DOM holds \u2014 rewriting it here would mean a body field commits a number\n * the document never contained. Body content is also not cloned, so it does not have the problem\n * this method exists to solve.\n */\n private substitutePageNumberFields(totalPages: number): void {\n const boxes = this.containerElement.querySelectorAll<HTMLElement>(`.${this.cssPrefix}box`);\n for (const box of Array.from(boxes)) {\n const markers = box.querySelectorAll<HTMLElement>(\n `.${this.cssPrefix}header [data-field], .${this.cssPrefix}footer [data-field]`,\n );\n if (markers.length === 0) continue;\n\n const sectionIndex = parseInt(box.dataset.sectionIndex || \"0\", 10);\n const pageNumber = parseInt(box.dataset.pageNumber || \"1\", 10);\n const numbering = this.pageNumbering.get(sectionIndex) ?? {};\n const displayed = parseInt(box.dataset.displayedPageNumber || String(pageNumber), 10);\n\n for (const marker of Array.from(markers)) {\n const kind = marker.dataset.field;\n if (kind !== \"PAGE\" && kind !== \"NUMPAGES\") continue;\n const format = marker.dataset.fieldFormat ?? numbering.format;\n marker.textContent = formatPageNumber(kind === \"PAGE\" ? displayed : totalPages, format);\n }\n }\n }\n\n /**\n * Measures all content blocks in a section.\n */\n private measureBlocks(\n section: HTMLElement,\n dims: PageDimensions,\n sectionIndex: number,\n ): MeasuredBlock[] {\n const blocks: MeasuredBlock[] = [];\n\n // Get direct children (paragraphs, tables, divs, etc.)\n const children = Array.from(section.children) as HTMLElement[];\n\n for (const child of children) {\n this.checkpoint();\n // Skip section dividers that are just wrappers\n if (child.dataset.sectionIndex !== undefined) {\n // Recursively get blocks from nested sections\n const nestedSectionIndex = parseInt(child.dataset.sectionIndex || String(sectionIndex), 10);\n const nestedBlocks = this.measureBlocks(child, dims, nestedSectionIndex);\n blocks.push(...nestedBlocks);\n continue;\n }\n\n // Converter-shaped endnotes are a safe nested block structure whose outer\n // section/list wrappers must not make the complete endnote collection one\n // indivisible page block. Flatten only the exact shape we understand; any\n // richer author HTML retains the conservative whole-block fallback below.\n if (child.matches(\"section.endnotes\")) {\n const endnoteBlocks = this.measureSafeEndnoteBlocks(child, dims, sectionIndex);\n if (endnoteBlocks) {\n blocks.push(...endnoteBlocks);\n continue;\n }\n }\n\n // Measure height and margins separately for proper margin collapsing calculation\n // getBoundingClientRect() returns content+padding+border, not margins\n const rect = child.getBoundingClientRect();\n const { topPx: marginTopPx, bottomPx: marginBottomPx } = collapsedBlockMarginsPx(this.view, child);\n const heightPt = pxToPt(rect.height);\n const marginTopPt = pxToPt(marginTopPx);\n const marginBottomPt = pxToPt(marginBottomPx);\n\n const isPageBreak =\n child.dataset.pageBreak === \"true\" ||\n child.classList.contains(`${this.cssPrefix}break`);\n\n blocks.push({\n element: child,\n sectionIndex,\n heightPt,\n marginTopPt,\n marginBottomPt,\n keepWithNext: child.dataset.keepWithNext === \"true\",\n keepLines: child.dataset.keepLines === \"true\",\n pageBreakBefore: child.dataset.pageBreakBefore === \"true\",\n isPageBreak,\n isWordParagraph: this.isWordParagraphElement(child),\n });\n }\n\n return blocks;\n }\n\n /**\n * Flatten the converter's `section.endnotes > ol > li > p` presentation into\n * ordinary paragraph blocks. This preserves paragraph formatting and canonical\n * p:en/en:en identities while allowing the existing paragraph fragmenter to\n * split a long endnote across page boundaries.\n */\n private measureSafeEndnoteBlocks(\n section: HTMLElement,\n dims: PageDimensions,\n sectionIndex: number,\n ): MeasuredBlock[] | null {\n const sectionChildren = Array.from(section.children) as HTMLElement[];\n const list = sectionChildren.find((child) => child.tagName === \"OL\");\n if (\n !list\n || sectionChildren.some((child) => child.tagName !== \"HR\" && child !== list)\n || Array.from(list.children).some((child) => child.tagName !== \"LI\")\n ) {\n return null;\n }\n\n const items = Array.from(list.children) as HTMLElement[];\n if (items.length === 0 || items.some((item) =>\n item.children.length === 0\n || Array.from(item.children).some((child) => child.tagName !== \"P\")\n )) {\n return null;\n }\n\n const blocks: MeasuredBlock[] = [];\n const sectionStyle = this.view.getComputedStyle(section);\n for (const rule of sectionChildren.filter((child) => child.tagName === \"HR\")) {\n this.checkpoint();\n const clonedRule = rule.cloneNode(true) as HTMLElement;\n // The rule leaves its section when flattened, so preserve the section-scoped\n // print styling before measuring and painting the detached clone.\n const ruleStyle = this.view.getComputedStyle(rule);\n for (const property of [\"height\", \"width\", \"max-width\", \"border\", \"background-color\", \"color\",\n \"margin-top\", \"margin-right\", \"margin-bottom\", \"margin-left\"]) {\n clonedRule.style.setProperty(property, ruleStyle.getPropertyValue(property));\n }\n if (blocks.length === 0) {\n clonedRule.style.marginTop = `calc(${sectionStyle.marginTop} + ${ruleStyle.marginTop})`;\n }\n blocks.push(this.measureElement(clonedRule, dims, sectionIndex));\n }\n\n const listStyle = this.view.getComputedStyle(list);\n for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {\n this.checkpoint();\n const item = items[itemIndex];\n const ownerAnchorId = item.dataset.sourceAnchorId;\n const paragraphs = Array.from(item.children) as HTMLElement[];\n for (let paragraphIndex = 0; paragraphIndex < paragraphs.length; paragraphIndex++) {\n this.checkpoint();\n const paragraph = paragraphs[paragraphIndex];\n // The flattened clone no longer has the section/ol/li ancestors that supplied the\n // source's computed layout. Validate while the real paragraph is still attached; the\n // marker below records that completed check for canFragmentParagraph(), whose detached\n // clone cannot obtain meaningful computed styles. A richer custom endnote falls back to\n // the established indivisible section path instead of being range-split incorrectly.\n if (!this.hasRangeFragmentSafeLayout(paragraph)) {\n return null;\n }\n\n const clone = paragraph.cloneNode(true) as HTMLElement;\n clone.dataset.paginationSafeEndnote = \"true\";\n clone.style.fontSize ||= sectionStyle.fontSize;\n clone.style.lineHeight ||= sectionStyle.lineHeight;\n clone.style.paddingLeft ||= listStyle.paddingLeft;\n\n // Older/custom producers may put the endnote identity only on the li.\n // Mirror it into the visible paragraph without displacing the paragraph's\n // own identity, matching current converter output.\n if (ownerAnchorId && !Array.from(\n clone.querySelectorAll<HTMLElement>(\"[data-source-anchor-id]\"),\n ).some((node) => node.dataset.sourceAnchorId === ownerAnchorId)) {\n const owner = this.document.createElement(\"span\");\n owner.dataset.sourceAnchorId = ownerAnchorId;\n while (clone.firstChild) owner.appendChild(clone.firstChild);\n clone.appendChild(owner);\n }\n\n if (paragraphIndex === 0) {\n // Flattening must preserve both ends of the converter's endnote link and the list's\n // numbering format. The outer id survives only on the leading range fragment; normal\n // continuation cleanup removes it from every later fragment.\n const itemId = item.id;\n if (itemId) {\n if (clone.id && clone.id !== itemId) return null;\n clone.id = itemId;\n }\n if (!clone.querySelector('[data-endnote-number]')) {\n const value = parseInt(item.getAttribute(\"value\") || String(itemIndex + 1), 10);\n const marker = this.formatOrderedListMarker(\n Number.isFinite(value) ? value : itemIndex + 1,\n listStyle.listStyleType,\n );\n clone.insertBefore(this.document.createTextNode(`${marker}. `), clone.firstChild);\n }\n }\n blocks.push(this.measureElement(clone, dims, sectionIndex));\n }\n }\n\n return blocks;\n }\n\n /** Render the CSS ordered-list formats emitted by the converter after an endnote is flattened. */\n private formatOrderedListMarker(value: number, listStyleType: string): string {\n const format = (() => {\n switch (listStyleType) {\n case \"lower-roman\": return \"lowerRoman\";\n case \"upper-roman\": return \"upperRoman\";\n case \"lower-alpha\":\n case \"lower-latin\": return \"lowerLetter\";\n case \"upper-alpha\":\n case \"upper-latin\": return \"upperLetter\";\n default: return \"decimal\";\n }\n })();\n return formatPageNumber(value, format);\n }\n\n /**\n * Flows a multi-column (`w:cols`) section's children into CSS-multicol container\n * blocks. Word lays such a section out as N columns inside the same body extent;\n * a `column-count` container reproduces that geometry, and the paginator\n * then places each container as one ordinary measured block. A container grows\n * greedily until it would exceed the smallest page body available to the section.\n * Final continuous sections fill that height sequentially; other sections retain\n * balancing. A long columned section still splits across pages at block\n * boundaries. Each child lands in exactly one container, so anchors never\n * duplicate. An explicit page break child passes through as its own block, which\n * ends the current container and lets the normal flow logic turn the page.\n */\n private buildColumnBlocks(\n section: HTMLElement,\n dims: PageDimensions,\n sectionIndex: number,\n columnCount: number,\n columnGapPt: number,\n sequential = false,\n ): MeasuredBlock[] {\n const children = Array.from(section.children) as HTMLElement[];\n const blocks: MeasuredBlock[] = [];\n const maxFragmentHeight = this.smallestEffectiveContentHeight(dims, sectionIndex);\n\n const isBreak = (child: HTMLElement) =>\n child.dataset.pageBreak === \"true\" ||\n child.classList.contains(`${this.cssPrefix}break`);\n\n const makeContainer = (slice: HTMLElement[]): HTMLElement => {\n const container = this.document.createElement(\"div\");\n container.style.columnCount = String(columnCount);\n container.style.columnGap = `${columnGapPt}pt`;\n if (sequential) {\n container.dataset.paginationSequentialColumns = \"true\";\n container.style.columnFill = \"auto\";\n container.style.maxHeight = `${maxFragmentHeight}pt`;\n }\n for (const child of slice) {\n container.appendChild(child.cloneNode(true));\n }\n if (sequential) this.liftColumnSpaceBefore(container, dims);\n return container;\n };\n\n let start = 0;\n while (start < children.length) {\n this.checkpoint();\n if (isBreak(children[start])) {\n blocks.push(this.measureElement(children[start], dims, sectionIndex));\n start++;\n continue;\n }\n\n // Grow the container one child at a time. Even a single oversized child is\n // emitted alone, preserving the established oversized-block fallback.\n let end = start + 1;\n let container = makeContainer(children.slice(start, end));\n if (sequential && this.columnContainerOverflows(container, dims)) {\n // An indivisible child that exceeds all available columns keeps the established\n // oversized-block path; a constrained box must not hide it in an extra column.\n delete container.dataset.paginationSequentialColumns;\n container.style.columnFill = \"balance\";\n container.style.maxHeight = \"\";\n }\n let measured = this.measureElement(container, dims, sectionIndex);\n while (end < children.length && !isBreak(children[end])) {\n this.checkpoint();\n const candidate = makeContainer(children.slice(start, end + 1));\n const candidateMeasured = this.measureElement(candidate, dims, sectionIndex);\n if (candidateMeasured.heightPt > maxFragmentHeight\n || (sequential && this.columnContainerOverflows(candidate, dims))) break;\n container = candidate;\n measured = candidateMeasured;\n end++;\n }\n\n blocks.push({\n element: container,\n sectionIndex,\n heightPt: measured.heightPt,\n marginTopPt: measured.marginTopPt,\n marginBottomPt: measured.marginBottomPt,\n keepWithNext: false,\n keepLines: false,\n pageBreakBefore: false,\n isPageBreak: false,\n isWordParagraph: false,\n });\n start = end;\n }\n\n return blocks;\n }\n\n /** Keep Word's paragraph space-before in the ordinary inter-block spacing budget. */\n private liftColumnSpaceBefore(container: HTMLElement, dims: PageDimensions): void {\n container.style.marginTop = \"\";\n const first = container.firstElementChild as HTMLElement | null;\n if (!first || !this.isWordParagraphElement(first)) return;\n const host = this.document.createElement(\"div\");\n host.style.width = `${dims.contentWidth}pt`;\n host.appendChild(container);\n this.stagingElement.appendChild(host);\n try {\n const spaceBefore = first.dataset.paginationColumnSpaceBefore\n ?? this.view.getComputedStyle(first).marginTop;\n first.dataset.paginationColumnSpaceBefore = spaceBefore;\n first.style.marginTop = \"0\";\n container.style.marginTop = spaceBefore;\n } finally {\n container.remove();\n host.remove();\n }\n }\n\n /** A height-constrained multicol box overflows horizontally when it needs another column. */\n private columnContainerOverflows(element: HTMLElement, dims: PageDimensions): boolean {\n const host = this.document.createElement(\"div\");\n host.style.width = `${dims.contentWidth}pt`;\n const clone = element.cloneNode(true) as HTMLElement;\n host.appendChild(clone);\n this.stagingElement.appendChild(host);\n try {\n if (clone.scrollWidth > clone.clientWidth + 1) return true;\n // Keep-lines paragraphs must fit as a whole. A constrained column container\n // can report only its first partial box, even when scrollWidth still fits.\n // Move that source paragraph to the next page before print clips its text.\n return Array.from(clone.querySelectorAll<HTMLElement>('[data-keep-lines=\"true\"]'))\n .some(paragraph => paragraph.getClientRects().length > 1);\n } finally {\n host.remove();\n }\n }\n\n /**\n * Reflow a final continuous column section against the actual remaining body band.\n * A preceding title, running story or note reservation can make it shorter than the\n * fresh-page band used while collecting source blocks. Split at source-child boundaries\n * when the narrower band would create an extra horizontal column; the tail is reconsidered\n * normally on the following page. No source child is duplicated or discarded.\n */\n private reflowSequentialColumns(\n block: MeasuredBlock,\n dims: PageDimensions,\n availableHeightPt: number,\n ): MeasuredBlock[] | null {\n if (block.element.dataset.paginationSequentialColumns !== \"true\"\n || availableHeightPt <= 0) return null;\n const maximumHeight = this.smallestEffectiveContentHeight(dims, block.sectionIndex);\n const height = Math.min(availableHeightPt, maximumHeight);\n if (Math.abs(parseFloat(block.element.style.maxHeight) - height) < 0.01) return null;\n const children = Array.from(block.element.children) as HTMLElement[];\n const make = (slice: HTMLElement[], limit: number): HTMLElement => {\n const container = block.element.cloneNode(false) as HTMLElement;\n container.style.maxHeight = `${limit}pt`;\n for (const child of slice) container.appendChild(child.cloneNode(true));\n this.liftColumnSpaceBefore(container, dims);\n return container;\n };\n const whole = make(children, height);\n if (!this.columnContainerOverflows(whole, dims)) {\n return [this.measureElement(whole, dims, block.sectionIndex)];\n }\n let end = 0;\n for (let count = 1; count < children.length; count++) {\n this.checkpoint();\n const candidate = make(children.slice(0, count), height);\n if (this.columnContainerOverflows(candidate, dims)) break;\n if (children[count - 1].dataset.keepWithNext !== \"true\") end = count;\n }\n if (end === 0) return null;\n return [\n this.measureElement(make(children.slice(0, end), height), dims, block.sectionIndex),\n this.measureElement(make(children.slice(end), maximumHeight), dims, block.sectionIndex),\n ];\n }\n\n /**\n * Measures one element in the same hidden staging context used for the source blocks.\n * This is intentionally DOM-based: table row heights cannot be inferred from individual\n * rows because wrapping and collapsed borders change the height of a fragment.\n */\n private measureElement(\n element: HTMLElement,\n dims: PageDimensions,\n sectionIndex: number,\n ): MeasuredBlock {\n const measurementHost = this.document.createElement(\"div\");\n measurementHost.style.position = \"absolute\";\n measurementHost.style.visibility = \"hidden\";\n measurementHost.style.left = \"-9999px\";\n measurementHost.style.width = `${dims.contentWidth}pt`;\n\n const measuredElement = element.cloneNode(true) as HTMLElement;\n measurementHost.appendChild(measuredElement);\n this.stagingElement.appendChild(measurementHost);\n\n const rect = measuredElement.getBoundingClientRect();\n const margins = collapsedBlockMarginsPx(this.view, measuredElement);\n const measured: MeasuredBlock = {\n element,\n sectionIndex,\n heightPt: pxToPt(rect.height),\n marginTopPt: pxToPt(margins.topPx),\n marginBottomPt: pxToPt(margins.bottomPx),\n keepWithNext: element.dataset.keepWithNext === \"true\",\n keepLines: element.dataset.keepLines === \"true\",\n pageBreakBefore: element.dataset.pageBreakBefore === \"true\",\n isPageBreak:\n element.dataset.pageBreak === \"true\" ||\n element.classList.contains(`${this.cssPrefix}break`),\n isWordParagraph: this.isWordParagraphElement(element),\n };\n\n this.stagingElement.removeChild(measurementHost);\n return measured;\n }\n\n /**\n * Returns the contiguous keep-with-next chain beginning at a block.\n *\n * A hard page break or a page-break-before directive is stronger than a\n * keep-with-next directive, so it terminates the chain. The caller only\n * keeps a chain together when the whole chain can fit on a fresh page.\n */\n private getKeepWithNextChain(blocks: MeasuredBlock[], startIndex: number): MeasuredBlock[] {\n const firstBlock = blocks[startIndex];\n if (!firstBlock) return [];\n\n const chain = [firstBlock];\n let lastIndex = startIndex;\n\n while (blocks[lastIndex].keepWithNext) {\n const nextBlock = blocks[lastIndex + 1];\n if (!nextBlock || nextBlock.isPageBreak || nextBlock.pageBreakBefore) {\n break;\n }\n\n chain.push(nextBlock);\n lastIndex++;\n }\n\n return chain;\n }\n\n /**\n * Measures the visible body height of a keep-with-next chain using the same\n * collapsed-margin rules as normal block placement. The trailing margin is\n * intentionally excluded, matching the individual block fit check.\n */\n private measureKeepWithNextChainBodyHeight(\n chain: MeasuredBlock[],\n previousMarginBottomPt: number,\n isFirstOnPage: boolean,\n pageInSection: number\n ): number {\n const firstBlock = chain[0];\n if (!firstBlock) return 0;\n\n const firstMarginTop = this.effectiveBlockMarginTop(\n firstBlock,\n previousMarginBottomPt,\n isFirstOnPage,\n pageInSection\n );\n let bodyHeight = firstMarginTop + firstBlock.heightPt;\n\n for (let index = 1; index < chain.length; index++) {\n const previousBlock = chain[index - 1];\n const block = chain[index];\n bodyHeight += Math.max(previousBlock.marginBottomPt, block.marginTopPt) + block.heightPt;\n }\n\n return bodyHeight;\n }\n\n /** Word paragraphs render as `p`, or as `h1`\u2013`h6` when their style has an outline level. */\n private isWordParagraphElement(element: HTMLElement): boolean {\n return element.tagName === \"P\" || /^H[1-6]$/.test(element.tagName);\n }\n\n private shouldSuppressPageTopSpacing(\n block: MeasuredBlock,\n isFirstOnPage: boolean,\n pageInSection: number\n ): boolean {\n return isFirstOnPage && pageInSection > 1 && block.isWordParagraph === true;\n }\n\n /**\n * Resolves the part of a block's top margin that consumes the current page.\n *\n * In Word's native DOCX layout, paragraph space-before is suppressed when a paragraph is the\n * first body block on a later page of the SAME section. The first page of a document/section is\n * the exception and keeps its spacing. Tables and other block margins are not paragraph spacing,\n * so they continue to use the ordinary CSS collapsing rule.\n */\n private effectiveBlockMarginTop(\n block: MeasuredBlock,\n previousMarginBottomPt: number,\n isFirstOnPage: boolean,\n pageInSection: number\n ): number {\n if (this.shouldSuppressPageTopSpacing(block, isFirstOnPage, pageInSection)) {\n return 0;\n }\n return isFirstOnPage\n ? block.marginTopPt\n : Math.max(block.marginTopPt, previousMarginBottomPt) - previousMarginBottomPt;\n }\n\n /** Clone a source block with the same page-top spacing decision used by the height budget. */\n private cloneBlockForPage(\n block: MeasuredBlock,\n isFirstOnPage: boolean,\n pageInSection: number\n ): HTMLElement {\n const clone = block.element.cloneNode(true) as HTMLElement;\n if (this.shouldSuppressPageTopSpacing(block, isFirstOnPage, pageInSection)) {\n clone.style.setProperty(\"margin-top\", \"0\", \"important\");\n }\n return clone;\n }\n\n /**\n * Finds footnote references introduced by a sequence of blocks, preserving\n * document order and excluding references already assigned to the page.\n */\n private collectNewFootnoteIds(\n blocks: MeasuredBlock[],\n existingFootnoteIds: string[]\n ): string[] {\n const knownIds = new Set(existingFootnoteIds);\n const newIds: string[] = [];\n\n for (const block of blocks) {\n this.checkpoint();\n for (const id of this.extractFootnoteRefs(block.element)) {\n if (!knownIds.has(id)) {\n knownIds.add(id);\n newIds.push(id);\n }\n }\n }\n\n return newIds;\n }\n\n /**\n * The shortest body available to a section's first, default, or even page.\n * A row fragment must fit every variant, otherwise a later header/footer could\n * send it through the oversized-block fallback again.\n */\n private smallestEffectiveContentHeight(dims: PageDimensions, sectionIndex: number): number {\n return Math.min(\n this.getPageBands(dims, sectionIndex, 1, 1).bodyHeight,\n this.getPageBands(dims, sectionIndex, 2, 2).bodyHeight,\n this.getPageBands(dims, sectionIndex, 3, 3).bodyHeight\n );\n }\n\n /**\n * Builds a clone of a simple table wrapper containing a contiguous run of rows.\n * Complex table features are deliberately rejected by the caller: a split across\n * vertically merged cells (rowspan), nested tables, or footnotes cannot be made\n * correct by cloning rows. Horizontal merges (colspan) need no rejection: a colspan\n * is confined to its own row, and rows are only ever cloned whole.\n */\n private createSimpleTableFragment(\n wrapper: HTMLElement,\n table: HTMLTableElement,\n body: HTMLTableSectionElement,\n rows: HTMLTableRowElement[],\n retainAnchor: boolean\n ): HTMLElement {\n const wrapperClone = wrapper.cloneNode(false) as HTMLElement;\n const tableClone = table.cloneNode(false) as HTMLTableElement;\n\n // The eligibility gate permits only colgroups alongside the body. Keep each\n // colgroup so fixed and proportional column widths remain stable per fragment.\n for (const child of Array.from(table.children)) {\n if (child !== body) {\n tableClone.appendChild(child.cloneNode(true));\n }\n }\n\n const bodyClone = body.cloneNode(false) as HTMLTableSectionElement;\n for (const row of rows) {\n bodyClone.appendChild(row.cloneNode(true));\n }\n tableClone.appendChild(bodyClone);\n\n if (!retainAnchor) {\n wrapperClone.removeAttribute(\"data-anchor\");\n tableClone.removeAttribute(\"data-anchor\");\n }\n\n wrapperClone.appendChild(tableClone);\n return wrapperClone;\n }\n\n /**\n * Splits an oversized, ordinary table at row boundaries. This only participates\n * in the existing oversized-block fallback; unsupported tables keep the previous\n * overflow behavior rather than risking broken table semantics.\n */\n private trySplitSimpleOversizedTable(\n block: MeasuredBlock,\n dims: PageDimensions,\n sectionIndex: number\n ): MeasuredBlock[] | null {\n const wrapper = block.element;\n if (\n wrapper.tagName !== \"DIV\" ||\n wrapper.children.length !== 1 ||\n block.keepWithNext ||\n block.keepLines ||\n block.pageBreakBefore ||\n block.isPageBreak\n ) {\n return null;\n }\n\n const tableElement = wrapper.firstElementChild;\n if (!tableElement || tableElement.localName !== \"table\") {\n return null;\n }\n const table = tableElement as HTMLTableElement;\n\n const body = table.tBodies.length === 1 ? table.tBodies[0] : null;\n if (\n !body ||\n table.tHead ||\n table.tFoot ||\n body.rows.length < 2 ||\n Array.from(table.children).some(child => child !== body && child.tagName !== \"COLGROUP\") ||\n table.querySelector(\"table, [rowspan], [data-footnote-id]\") ||\n wrapper.querySelector(\"[data-footnote-id]\")\n ) {\n return null;\n }\n\n const rows = Array.from(body.rows);\n const minimumContentHeight = this.smallestEffectiveContentHeight(dims, sectionIndex);\n // Use the source's full vertical margins while forming groups. Continuation\n // fragments later clear their joining margins, so this conservative bound\n // cannot create a fragment that overflows a header/footer variant.\n const maximumFragmentHeight = minimumContentHeight - block.marginTopPt - block.marginBottomPt;\n if (maximumFragmentHeight <= 0) {\n return null;\n }\n\n const groups: HTMLTableRowElement[][] = [];\n let start = 0;\n while (start < rows.length) {\n this.checkpoint();\n let end = start;\n while (end < rows.length) {\n this.checkpoint();\n const candidate = this.createSimpleTableFragment(\n wrapper,\n table,\n body,\n rows.slice(start, end + 1),\n start === 0\n );\n const measured = this.measureElement(candidate, dims, block.sectionIndex);\n if (measured.heightPt > maximumFragmentHeight) {\n break;\n }\n end++;\n }\n\n // Even a one-row fragment cannot fit. Preserve the established overflow\n // fallback rather than looping or clipping a partially split row.\n if (end === start) {\n return null;\n }\n\n groups.push(rows.slice(start, end));\n start = end;\n }\n\n if (groups.length < 2) {\n return null;\n }\n\n const fragments: MeasuredBlock[] = [];\n for (let index = 0; index < groups.length; index++) {\n const isFirst = index === 0;\n const isLast = index === groups.length - 1;\n const fragment = this.createSimpleTableFragment(\n wrapper,\n table,\n body,\n groups[index],\n isFirst\n );\n\n // Keep the source's outer spacing only at the table's real boundaries.\n // Continuation margins would otherwise add blank space at the top/bottom\n // of every paginated fragment.\n if (!isFirst) {\n fragment.style.setProperty(\"margin-top\", \"0\", \"important\");\n }\n if (!isLast) {\n fragment.style.setProperty(\"margin-bottom\", \"0\", \"important\");\n }\n\n const measured = this.measureElement(fragment, dims, block.sectionIndex);\n if (\n measured.heightPt + measured.marginTopPt + measured.marginBottomPt >\n minimumContentHeight\n ) {\n return null;\n }\n\n fragments.push({\n ...measured,\n keepWithNext: false,\n keepLines: false,\n pageBreakBefore: false,\n isPageBreak: false,\n });\n }\n\n return fragments;\n }\n\n /**\n * DOM endpoints that can finish a paragraph fragment. The flattened UTF-16\n * offsets are checked against the browser's Unicode grapheme segmenter, so a\n * formatting-run boundary can never bisect a surrogate pair, combining\n * sequence, or joined emoji. NBSP/word-joiner boundaries remain indivisible.\n * PAGE/NUMPAGES field results are atomic because splitting their marker would\n * make later substitution duplicate or replace only half of the field.\n */\n private paragraphFragmentEndpoints(\n paragraph: HTMLElement,\n emergencyGraphemeBreaks = false,\n ): ParagraphFragmentEndpoint[] {\n const textNodes: Text[] = [];\n const textStarts = new Map<Text, number>();\n const lastTextByField = new Map<HTMLElement, Text>();\n const walker = this.document.createTreeWalker(paragraph, this.view.NodeFilter.SHOW_TEXT);\n const flattenedChunks: string[] = [];\n let flattenedLength = 0;\n let textNode: Text | null;\n while ((textNode = walker.nextNode() as Text | null)) {\n this.checkpoint();\n textStarts.set(textNode, flattenedLength);\n textNodes.push(textNode);\n flattenedChunks.push(textNode.data);\n flattenedLength += textNode.data.length;\n let field = textNode.parentElement?.closest<HTMLElement>(\"[data-field]\") ?? null;\n while (field?.parentElement?.closest<HTMLElement>(\"[data-field]\")) {\n field = field.parentElement.closest<HTMLElement>(\"[data-field]\");\n }\n if (field && paragraph.contains(field)) lastTextByField.set(field, textNode);\n }\n const flattenedText = flattenedChunks.join(\"\");\n if (!this.hasVisibleText(flattenedText)) return [];\n\n const invisible = /[\\s\\u200B-\\u200F\\uFEFF]/;\n let firstVisibleOffset = -1;\n let lastVisibleOffset = -1;\n for (let index = 0; index < flattenedText.length; index++) {\n if (index % 4096 === 0) this.checkpoint();\n if (invisible.test(flattenedText[index])) continue;\n if (firstVisibleOffset < 0) firstVisibleOffset = index;\n lastVisibleOffset = index;\n }\n\n const graphemeBoundaries = this.graphemeBoundaryOffsets(flattenedText);\n const candidates: ParagraphFragmentEndpoint[] = [];\n const addCandidate = (candidate: ParagraphFragmentEndpoint): void => {\n const { textOffset } = candidate;\n if (textOffset <= 0 || textOffset >= flattenedText.length) return;\n if (textOffset <= firstVisibleOffset || textOffset > lastVisibleOffset) return;\n if (this.isNonBreakingTextBoundary(flattenedText, textOffset)) return;\n if (!this.isLegalParagraphLineBoundary(paragraph, flattenedText, textOffset)) return;\n if (graphemeBoundaries) {\n if (!graphemeBoundaries.has(textOffset)) return;\n } else if (!this.isConservativeFallbackTextBoundary(flattenedText, textOffset)) {\n return;\n }\n candidates.push(candidate);\n };\n\n for (const node of textNodes) {\n this.checkpoint();\n const start = textStarts.get(node)!;\n // Field results and converter list markers are semantic atoms. A field\n // receives one boundary outside its wrapper below; a list marker stays\n // with the first real text fragment and is never emitted by itself.\n const atomic = node.parentElement?.closest<HTMLElement>(\n \"[data-field], [data-list-marker], a[data-comment-id]\",\n );\n if (atomic && paragraph.contains(atomic)) continue;\n\n // Only CSS-collapsible ASCII whitespace is a wrapping opportunity. JS's\n // broader `\\s` class includes NBSP and other explicitly non-breaking text.\n const whitespace = /[\\u0009-\\u000D\\u0020]+/g;\n let match: RegExpExecArray | null;\n let matchesSinceCheckpoint = 0;\n while ((match = whitespace.exec(node.data)) !== null) {\n if (++matchesSinceCheckpoint % 256 === 0) this.checkpoint();\n const offset = match.index + match[0].length;\n addCandidate({ node, offset, textOffset: start + offset, priority: 0 });\n }\n addCandidate({\n node,\n offset: node.data.length,\n textOffset: start + node.data.length,\n priority: 0,\n });\n if (emergencyGraphemeBreaks) {\n for (let offset = 1; offset < node.data.length; offset++) {\n if (offset % 256 === 0) this.checkpoint();\n addCandidate({\n node,\n offset,\n textOffset: start + offset,\n priority: -1,\n });\n }\n }\n }\n\n // A field is splittable only immediately after its complete outer wrapper.\n // Starting the tail at the parent's child boundary prevents Range from\n // cloning an empty `[data-field]` shell that substitution could repopulate.\n for (const field of Array.from(paragraph.querySelectorAll<HTMLElement>(\"[data-field]\"))) {\n this.checkpoint();\n if (field.parentElement?.closest(\"[data-field]\")) continue;\n const last = lastTextByField.get(field);\n const parent = field.parentNode;\n if (!last || !parent) continue;\n const childIndex = Array.prototype.indexOf.call(parent.childNodes, field);\n if (childIndex < 0) continue;\n addCandidate({\n node: parent,\n offset: childIndex + 1,\n textOffset: textStarts.get(last)! + last.data.length,\n priority: 1,\n });\n }\n\n // Several DOM boundaries can represent the same flattened offset. Prefer\n // the outer atomic boundary, then keep one stable document-order candidate.\n candidates.sort((left, right) =>\n left.textOffset - right.textOffset || right.priority - left.priority);\n const endpoints: ParagraphFragmentEndpoint[] = [];\n for (const candidate of candidates) {\n if (endpoints[endpoints.length - 1]?.textOffset !== candidate.textOffset) {\n endpoints.push(candidate);\n }\n }\n return endpoints;\n }\n\n /** Browser-native UAX #29 boundaries; null keeps older runtimes conservative. */\n private graphemeBoundaryOffsets(text: string): Set<number> | null {\n type Segment = { segment: string; index: number };\n type Segmenter = new (\n locale?: string,\n options?: { granularity: \"grapheme\" },\n ) => { segment(value: string): Iterable<Segment> };\n const SegmenterConstructor = (this.view.Intl as typeof Intl & {\n Segmenter?: Segmenter;\n }).Segmenter;\n if (!SegmenterConstructor) return null;\n\n const boundaries = new Set<number>([0, text.length]);\n let segmentCount = 0;\n for (const part of new SegmenterConstructor(\"en\", { granularity: \"grapheme\" }).segment(text)) {\n if (++segmentCount % 256 === 0) this.checkpoint();\n boundaries.add(part.index);\n boundaries.add(part.index + part.segment.length);\n }\n return boundaries;\n }\n\n /**\n * Conservative UAX #14/CSS wrapping opportunities used for synthetic page\n * boundaries. In particular, a formatting-run boundary is not itself a word\n * boundary, and Japanese opening/closing punctuation stays with its pair.\n * Arbitrary grapheme breaks are admitted only when the paragraph's CSS asks\n * the browser to wrap anywhere.\n */\n private isLegalParagraphLineBoundary(\n paragraph: HTMLElement,\n text: string,\n offset: number,\n ): boolean {\n const lastCodeUnit = text.charCodeAt(offset - 1);\n const beforeOffset = lastCodeUnit >= 0xDC00 && lastCodeUnit <= 0xDFFF\n ? Math.max(0, offset - 2)\n : offset - 1;\n const beforeCodePoint = text.codePointAt(beforeOffset);\n const afterCodePoint = text.codePointAt(offset);\n const before = beforeCodePoint === undefined ? \"\" : String.fromCodePoint(beforeCodePoint);\n const after = afterCodePoint === undefined ? \"\" : String.fromCodePoint(afterCodePoint);\n if (/^[\\u0009-\\u000D\\u0020]$/.test(before)\n || /^[\\u0009-\\u000D\\u0020]$/.test(after)) return true;\n if (/[-\\u00AD\\u2010]$/u.test(before)) return true;\n\n const style = this.view.getComputedStyle(paragraph);\n if (style.wordBreak === \"break-all\"\n || style.overflowWrap === \"anywhere\"\n || style.overflowWrap === \"break-word\") return true;\n\n const eastAsian = /[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}]/u;\n if (!eastAsian.test(before) && !eastAsian.test(after)) return false;\n const opening = \"([{<\\u2018\\u201C\\u3008\\u300A\\u300C\\u300E\\u3010\\u3014\\u3016\\u3018\\u301A\\uFF08\\uFF3B\\uFF5B\";\n const closing = \")]}>\\u2019\\u201D\\u3001\\u3002\\u3009\\u300B\\u300D\\u300F\\u3011\\u3015\\u3017\\u3019\\u301B\\uFF01\\uFF05\\uFF09\\uFF0C\\uFF0E\\uFF1A\\uFF1B\\uFF1F\\uFF3D\\uFF5D\";\n return !opening.includes(before) && !closing.includes(after);\n }\n\n /** Never fragment across characters whose line-break meaning is explicitly non-breaking. */\n private isNonBreakingTextBoundary(text: string, offset: number): boolean {\n const codePointBefore = (index: number): number | undefined => {\n if (index <= 0) return undefined;\n const last = text.charCodeAt(index - 1);\n const start = last >= 0xDC00 && last <= 0xDFFF ? index - 2 : index - 1;\n return text.codePointAt(Math.max(0, start));\n };\n const nonBreaking = new Set([\n 0x00A0, 0x200E, 0x200F, 0x2011, 0x202A, 0x202B, 0x202C,\n 0x202D, 0x202E, 0x202F, 0x2060, 0x2066, 0x2067, 0x2068,\n 0x2069, 0xFEFF,\n ]);\n return nonBreaking.has(codePointBefore(offset) ?? -1)\n || nonBreaking.has(text.codePointAt(offset) ?? -1);\n }\n\n /**\n * Without Intl.Segmenter, admit only an all-ASCII boundary. This still\n * fragments ordinary prose while refusing to guess about Unicode clusters.\n */\n private isConservativeFallbackTextBoundary(text: string, offset: number): boolean {\n return text.charCodeAt(offset - 1) <= 0x7F && text.charCodeAt(offset) <= 0x7F;\n }\n\n /**\n * Whether a range contains visible text after ignoring bidi/zero-width marks.\n * Paragraph fragmentation deliberately excludes non-textual descendants, so\n * this is enough to reject empty head or tail fragments.\n */\n private hasVisibleFragmentText(fragment: DocumentFragment): boolean {\n return this.hasVisibleText(fragment.textContent || \"\");\n }\n\n private hasVisibleText(text: string): boolean {\n return text\n .replace(/[\\u200B-\\u200F\\uFEFF]/g, \"\")\n .trim()\n .length > 0;\n }\n\n /**\n * Phase one only handles text-like paragraph descendants. Objects, explicit\n * line breaks, list markers, notes, and out-of-flow/inline-block content all\n * require their own line-layout rules and retain the established whole-block\n * fallback instead of risking broken content or duplicate anchors.\n */\n private canFragmentParagraph(block: MeasuredBlock): boolean {\n if (!this.fragmentParagraphs) {\n return false;\n }\n\n const paragraph = block.element;\n if (\n block.keepWithNext ||\n block.keepLines ||\n block.pageBreakBefore ||\n block.isPageBreak ||\n paragraph.dataset.widowControl === \"true\" ||\n paragraph.hasAttribute(\"contenteditable\")\n ) {\n return false;\n }\n\n return this.canRangeFragmentParagraph(paragraph);\n }\n\n /**\n * Shared structural gate for body and note paragraph fragmentation. Footnote\n * first paragraphs are inline beside their marker, so that one known layout\n * context may opt into an inline root while retaining every descendant and\n * break-safety restriction used for body text.\n */\n private canRangeFragmentParagraph(\n paragraph: HTMLElement,\n allowInlineRoot: boolean = false,\n ): boolean {\n if (\n paragraph.tagName !== \"P\" ||\n paragraph.dataset.keepWithNext === \"true\" ||\n paragraph.dataset.keepLines === \"true\" ||\n paragraph.dataset.pageBreakBefore === \"true\" ||\n paragraph.dataset.widowControl === \"true\" ||\n paragraph.hasAttribute(\"contenteditable\")\n ) {\n return false;\n }\n\n // Non-textual/out-of-flow descendants still need dedicated fragmenters.\n // Inline ids/editor anchors are reconciled after Range cloning, and list\n // markers are kept atomically with the leading text fragment.\n const unsupportedDescendants = [\n \"br\",\n \"img\",\n \"picture\",\n \"svg\",\n \"math\",\n \"canvas\",\n \"video\",\n \"audio\",\n \"iframe\",\n \"object\",\n \"embed\",\n \"input\",\n \"button\",\n \"select\",\n \"textarea\",\n \"table\",\n \"ol\",\n \"ul\",\n \"li\",\n \"dl\",\n \"div\",\n \"p\",\n \"section\",\n \"article\",\n \"aside\",\n \"figure\",\n \"fieldset\",\n \"details\",\n \"[data-footnote-id]\",\n \"[contenteditable]\",\n ].join(\", \");\n if (paragraph.querySelector(unsupportedDescendants)) {\n return false;\n }\n\n const isValidatedEndnote = paragraph.dataset.paginationSafeEndnote === \"true\";\n return isValidatedEndnote || this.hasRangeFragmentSafeLayout(paragraph, allowInlineRoot);\n }\n\n /**\n * A range clone preserves nested inline formatting exactly. Anything that establishes its own\n * box/layout context is deferred until a future fragmenter can model it accurately. Callers\n * must invoke this while the paragraph is attached to the styled document.\n */\n private hasRangeFragmentSafeLayout(\n paragraph: HTMLElement,\n allowInlineRoot: boolean = false,\n ): boolean {\n const paragraphStyle = this.view.getComputedStyle(paragraph);\n if (\n (paragraphStyle.display !== \"block\" &&\n !(allowInlineRoot && paragraphStyle.display === \"inline\")) ||\n paragraphStyle.position !== \"static\" ||\n paragraphStyle.float !== \"none\" ||\n (paragraphStyle.whiteSpace !== \"normal\" && paragraphStyle.whiteSpace !== \"pre-wrap\") ||\n paragraphStyle.breakBefore !== \"auto\" ||\n paragraphStyle.breakAfter !== \"auto\" ||\n paragraphStyle.breakInside === \"avoid\" ||\n paragraphStyle.pageBreakBefore !== \"auto\" ||\n paragraphStyle.pageBreakAfter !== \"auto\" ||\n paragraphStyle.pageBreakInside === \"avoid\"\n ) {\n return false;\n }\n\n for (const descendant of Array.from(paragraph.querySelectorAll<HTMLElement>(\"*\"))) {\n const style = this.view.getComputedStyle(descendant);\n if (\n style.display !== \"inline\" ||\n style.position !== \"static\" ||\n style.float !== \"none\" ||\n (style.whiteSpace !== \"normal\" && style.whiteSpace !== \"pre-wrap\")\n ) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Builds one range-cloned paragraph fragment. Only the leading fragment keeps\n * the source paragraph's addressability; continuations must not duplicate an\n * id/data-anchor in the rendered document.\n */\n private createParagraphFragment(\n paragraph: HTMLElement,\n range: Range,\n retainSourceIdentity: boolean,\n isFinalFragment: boolean\n ): HTMLElement {\n const fragment = paragraph.cloneNode(false) as HTMLElement;\n const contents = range.cloneContents();\n fragment.appendChild(contents);\n\n if (!retainSourceIdentity) {\n fragment.removeAttribute(\"id\");\n fragment.removeAttribute(\"data-anchor\");\n // A continuation starts with a normal line rather than repeating a first-\n // line/hanging indent. Keep the side margin so paragraph alignment remains.\n fragment.style.setProperty(\"margin-top\", \"0\", \"important\");\n fragment.style.setProperty(\"text-indent\", \"0\", \"important\");\n }\n if (!isFinalFragment) {\n // The original bottom spacing belongs after the complete paragraph, not\n // between synthetic page fragments.\n fragment.style.setProperty(\"margin-bottom\", \"0\", \"important\");\n }\n\n return fragment;\n }\n\n /**\n * Range clones repeat an inline ancestor when the split lands inside it. Keep\n * semantic wrappers (links, comments, formatting) on both sides, but retain a\n * duplicated HTML/editor identity only on the leading fragment. Targets that\n * occur wholly after the split are absent from `head` and remain on `tail`.\n */\n private reconcileParagraphFragmentIdentities(\n head: HTMLElement,\n tail: HTMLElement,\n ): void {\n const elements = (root: HTMLElement, selector: string): HTMLElement[] => [\n ...(root.matches(selector) ? [root] : []),\n ...Array.from(root.querySelectorAll<HTMLElement>(selector)),\n ];\n\n const headIds = new Set(elements(head, \"[id]\").map((element) => element.id));\n for (const element of elements(tail, \"[id]\")) {\n if (headIds.has(element.id)) element.removeAttribute(\"id\");\n }\n\n const headAnchors = new Set(elements(head, \"[data-anchor]\")\n .map((element) => element.dataset.anchor)\n .filter((anchor): anchor is string => Boolean(anchor)));\n for (const element of elements(tail, \"[data-anchor]\")) {\n if (!element.dataset.anchor || !headAnchors.has(element.dataset.anchor)) continue;\n element.removeAttribute(\"data-anchor\");\n element.removeAttribute(\"data-committed-text\");\n }\n }\n\n /**\n * Range-clone the largest safe prefix accepted by `fits`. The measurement\n * policy stays with the caller, allowing body blocks and note bands to share\n * one DOM fragmenter while measuring in their respective layout contexts.\n */\n private splitParagraphAtLargestFit(\n paragraph: HTMLElement,\n fits: (head: HTMLElement) => boolean,\n options: {\n emergencyGraphemeBreaks?: boolean;\n forceFirstOnNoFit?: boolean;\n } = {},\n ): ParagraphSplitAttempt {\n const largestFit = (endpoints: ParagraphFragmentEndpoint[]) => {\n // Prefix height is usually monotone, but selector-sensitive inline CSS\n // (`:last-child`, `:only-child`) can make a longer Range clone shorter.\n // Probe the largest legal endpoint first so the common non-monotone case\n // cannot be discarded by the binary search below.\n const lastEndpoint = endpoints[endpoints.length - 1];\n if (lastEndpoint) {\n const lastRange = this.document.createRange();\n lastRange.setStart(paragraph, 0);\n lastRange.setEnd(lastEndpoint.node, lastEndpoint.offset);\n const lastContents = lastRange.cloneContents();\n if (this.hasVisibleFragmentText(lastContents)) {\n const lastHead = this.createParagraphFragment(paragraph, lastRange, true, false);\n if (fits(lastHead)) return { endpoint: lastEndpoint, head: lastHead };\n }\n }\n\n let low = 0;\n let high = endpoints.length - 2;\n let best: { endpoint: ParagraphFragmentEndpoint; head: HTMLElement } | null = null;\n while (low <= high) {\n this.checkpoint();\n const middle = Math.floor((low + high) / 2);\n const endpoint = endpoints[middle];\n const headRange = this.document.createRange();\n headRange.setStart(paragraph, 0);\n headRange.setEnd(endpoint.node, endpoint.offset);\n const headContents = headRange.cloneContents();\n if (!this.hasVisibleFragmentText(headContents)) {\n low = middle + 1;\n continue;\n }\n\n const head = this.createParagraphFragment(paragraph, headRange, true, false);\n if (fits(head)) {\n best = { endpoint, head };\n low = middle + 1;\n } else {\n high = middle - 1;\n }\n }\n return best;\n };\n\n let endpoints = this.paragraphFragmentEndpoints(paragraph);\n let best = largestFit(endpoints);\n if (!best && options.emergencyGraphemeBreaks) {\n endpoints = this.paragraphFragmentEndpoints(paragraph, true);\n best = largestFit(endpoints);\n }\n if (!best && options.forceFirstOnNoFit && endpoints.length > 0) {\n const endpoint = endpoints[0];\n const headRange = this.document.createRange();\n headRange.setStart(paragraph, 0);\n headRange.setEnd(endpoint.node, endpoint.offset);\n best = {\n endpoint,\n head: this.createParagraphFragment(paragraph, headRange, true, false),\n };\n }\n if (!best) {\n return endpoints.length > 0 ? { kind: \"no-fit\" } : { kind: \"indivisible\" };\n }\n\n const tailRange = this.document.createRange();\n tailRange.setStart(best.endpoint.node, best.endpoint.offset);\n tailRange.setEnd(paragraph, paragraph.childNodes.length);\n const tailContents = tailRange.cloneContents();\n if (!this.hasVisibleFragmentText(tailContents)) return { kind: \"indivisible\" };\n\n const tail = this.createParagraphFragment(paragraph, tailRange, false, true);\n this.reconcileParagraphFragmentIdentities(best.head, tail);\n\n return {\n kind: \"split\",\n head: best.head,\n tail,\n };\n }\n\n /**\n * Splits a simple paragraph at the largest DOM Range endpoint that fits the\n * currently available body space. The caller then processes the tail normally,\n * allowing it to fragment again on later pages when necessary.\n */\n private tryFragmentParagraph(\n block: MeasuredBlock,\n dims: PageDimensions,\n availableHeightPt: number,\n effectiveMarginTopPt: number\n ): MeasuredBlock[] | null {\n if (!this.canFragmentParagraph(block) || availableHeightPt <= effectiveMarginTopPt) {\n return null;\n }\n\n const split = this.splitParagraphAtLargestFit(block.element, (head) => {\n const measured = this.measureElement(head, dims, block.sectionIndex);\n return effectiveMarginTopPt + measured.heightPt <= availableHeightPt;\n });\n if (split.kind !== \"split\") return null;\n\n const headMeasured = this.measureElement(split.head, dims, block.sectionIndex);\n const tailMeasured = this.measureElement(split.tail, dims, block.sectionIndex);\n\n return [\n {\n ...headMeasured,\n element: split.head,\n keepWithNext: false,\n keepLines: false,\n pageBreakBefore: false,\n isPageBreak: false,\n },\n {\n ...tailMeasured,\n element: split.tail,\n keepWithNext: false,\n keepLines: false,\n pageBreakBefore: false,\n isPageBreak: false,\n },\n ];\n }\n\n /**\n * Parses the header/footer registry from the staging element.\n * Also measures heights during parsing for lazy-loading compatibility.\n */\n private parseHeaderFooterRegistry(): HeaderFooterRegistry {\n const registry: HeaderFooterRegistry = new Map();\n const registryEl = this.stagingElement.querySelector(\"#pagination-hf-registry\");\n\n if (!registryEl) return registry;\n\n // Build a map of section index -> content width for measurement\n const sectionWidths = new Map<number, number>();\n const sections = Array.from(this.stagingElement.querySelectorAll<HTMLElement>(\"[data-section-index]\"));\n for (const section of sections) {\n const idx = parseInt(section.dataset.sectionIndex || \"0\", 10);\n const contentWidth = parseFloat(section.dataset.contentWidth || \"\") || DEFAULT_PAGE_WIDTH - 2 * DEFAULT_MARGIN;\n sectionWidths.set(idx, contentWidth);\n }\n // Fallback content width if no sections found\n const defaultContentWidth = sectionWidths.get(0) || DEFAULT_PAGE_WIDTH - 2 * DEFAULT_MARGIN;\n\n const entries = Array.from(registryEl.querySelectorAll<HTMLElement>(\"[data-section][data-hf-type]\"));\n\n for (const entry of entries) {\n const sectionIndex = parseInt(entry.dataset.section || \"0\", 10);\n const hfType = entry.dataset.hfType as string;\n\n if (!registry.has(sectionIndex)) {\n registry.set(sectionIndex, {});\n }\n\n const section = registry.get(sectionIndex)!;\n // Clone the first child element (the actual header/footer content)\n const content = entry.cloneNode(true) as HTMLElement;\n\n // Get content width for this section (for accurate measurement)\n const contentWidth = sectionWidths.get(sectionIndex) || defaultContentWidth;\n\n // Measure height during parsing (one-time cost, enables lazy loading)\n const measuredHeight = this.measureHeaderFooterHeight(content, contentWidth);\n\n switch (hfType) {\n case \"header-default\":\n section.headerDefault = content;\n section.headerDefaultHeight = measuredHeight;\n break;\n case \"header-first\":\n section.headerFirst = content;\n section.headerFirstHeight = measuredHeight;\n break;\n case \"header-even\":\n section.headerEven = content;\n section.headerEvenHeight = measuredHeight;\n break;\n case \"footer-default\":\n section.footerDefault = content;\n section.footerDefaultHeight = measuredHeight;\n break;\n case \"footer-first\":\n section.footerFirst = content;\n section.footerFirstHeight = measuredHeight;\n break;\n case \"footer-even\":\n section.footerEven = content;\n section.footerEvenHeight = measuredHeight;\n break;\n }\n }\n\n return registry;\n }\n\n /**\n * Parses the footnote registry from the staging element.\n */\n private parseFootnoteRegistry(): FootnoteRegistry {\n const registry: FootnoteRegistry = new Map();\n const registryEl = this.stagingElement.querySelector(\"#pagination-footnote-registry\");\n\n if (!registryEl) return registry;\n\n // Only direct registry entries are definitions. Custom separator stories may\n // legitimately contain arbitrary converted markup, including stale semantic\n // attributes that must never be mistaken for another note definition.\n const entries = Array.from(registryEl.children)\n .filter((entry): entry is HTMLElement =>\n entry instanceof this.view.HTMLElement && entry.hasAttribute(\"data-footnote-id\"));\n\n for (const entry of entries) {\n const footnoteId = entry.dataset.footnoteId;\n if (footnoteId) {\n // Clone the footnote element for later use\n registry.set(footnoteId, entry.cloneNode(true) as HTMLElement);\n }\n }\n\n return registry;\n }\n\n /** Read Word's optional normal and continuation separator stories. */\n private parseFootnoteSeparators(): {\n normal: HTMLElement | null;\n continuation: HTMLElement | null;\n } {\n const registry = this.stagingElement.querySelector(\"#pagination-footnote-registry\");\n const clone = (kind: \"normal\" | \"continuation\") => {\n const source = Array.from(registry?.children ?? []).find((entry) =>\n entry instanceof this.view.HTMLElement\n && entry.getAttribute(\"data-footnote-separator\") === kind,\n );\n return source?.cloneNode(true) as HTMLElement | undefined;\n };\n return {\n normal: clone(\"normal\") ?? null,\n continuation: clone(\"continuation\") ?? null,\n };\n }\n\n /** Append the exact separator story selected for this initial/continued note band. */\n private appendFootnoteSeparator(container: HTMLElement, continuation: boolean): void {\n const kind = continuation ? \"continuation\" : \"normal\";\n const source = continuation ? this.footnoteContinuationSeparator : this.footnoteSeparator;\n if (!source) {\n const fallback = this.document.createElement(\"hr\");\n fallback.dataset.footnoteSeparator = kind;\n container.appendChild(fallback);\n return;\n }\n\n const clone = source.cloneNode(true) as HTMLElement;\n for (const element of [clone, ...Array.from(clone.querySelectorAll<HTMLElement>(\"*\"))]) {\n element.removeAttribute(\"id\");\n element.removeAttribute(\"data-anchor\");\n element.removeAttribute(\"data-committed-text\");\n element.removeAttribute(\"data-source-anchor-id\");\n element.removeAttribute(\"data-page-fragment-id\");\n element.removeAttribute(\"data-fragment-index\");\n element.removeAttribute(\"data-footnote-id\");\n element.removeAttribute(\"data-comment-id\");\n element.removeAttribute(\"name\");\n if (element instanceof this.view.HTMLAnchorElement\n && element.getAttribute(\"href\")?.startsWith(\"#\")) {\n element.removeAttribute(\"href\");\n }\n element.setAttribute(\"contenteditable\", \"false\");\n }\n container.appendChild(clone);\n }\n\n /** Parses the hidden source notes used to render paginated margin comments. */\n private parseCommentMarginRegistry(): Map<string, HTMLElement> {\n const registry = new Map<string, HTMLElement>();\n const registryEl = this.stagingElement.querySelector(\n \"#pagination-comment-margin-registry\",\n );\n if (!registryEl) return registry;\n\n for (const entry of Array.from(\n registryEl.querySelectorAll<HTMLElement>(\"[data-comment-id]\"),\n )) {\n const commentId = entry.dataset.commentId;\n if (!commentId) continue;\n // A reply's note nests inside its thread root (issue #540), so every id in a thread\n // maps to the root's clone \u2014 a reply marker selects the whole thread, and the\n // placement loop dedupes by the clone's own id so the thread lands once per page.\n let root = entry;\n for (\n let parent = root.parentElement?.closest<HTMLElement>(\"[data-comment-id]\");\n parent && registryEl.contains(parent);\n parent = root.parentElement?.closest<HTMLElement>(\"[data-comment-id]\")\n ) {\n root = parent;\n }\n registry.set(commentId, root.cloneNode(true) as HTMLElement);\n }\n return registry;\n }\n\n /**\n * Extracts footnote reference IDs from an element.\n */\n private extractFootnoteRefs(element: HTMLElement): string[] {\n const refs = element.querySelectorAll<HTMLElement>(\"[data-footnote-id]\");\n const ids: string[] = [];\n for (const ref of Array.from(refs)) {\n const id = ref.dataset.footnoteId;\n if (id && !ids.includes(id)) {\n ids.push(id);\n }\n }\n return ids;\n }\n\n /** Clone a note child for the continuation queue with its original selector position. */\n private cloneFootnoteElementForContinuation(\n element: HTMLElement,\n sourceIndex: number,\n ): HTMLElement {\n const clone = element.cloneNode(true) as HTMLElement;\n clone.setAttribute(\n FOOTNOTE_SOURCE_POSITION_ATTR,\n sourceIndex === 0 ? \"first\" : \"later\",\n );\n return clone;\n }\n\n /** Remove identities that belong only to the initial registry presentation shell. */\n private makeContinuationShellInert(element: HTMLElement): void {\n element.removeAttribute(\"id\");\n element.removeAttribute(\"data-anchor\");\n element.removeAttribute(\"data-committed-text\");\n }\n\n /**\n * Build the exact continuation shape shared by measurement and paint.\n *\n * Keep the source `.footnote-item > .footnote-content` ancestry: document\n * CSS, inherited direction/language, and custom classes frequently target\n * those shells. Only the number and initial HTML/editor identities are\n * omitted. A hidden sentinel preserves `p:not(:first-of-type)` for a page\n * whose first carried element was a later source paragraph.\n */\n private createFootnoteContinuationWrapper(\n continuation: FootnoteContinuation,\n elements: readonly HTMLElement[] = continuation.remainingElements,\n ): HTMLElement {\n const source = this.footnoteRegistry.get(continuation.footnoteId);\n const wrapper = source\n ? source.cloneNode(false) as HTMLElement\n : this.document.createElement(\"div\");\n this.makeContinuationShellInert(wrapper);\n wrapper.classList.add(\"footnote-continuation\");\n wrapper.dataset.footnoteId = continuation.footnoteId;\n if (continuation.sourceAnchorId) {\n wrapper.dataset.sourceAnchorId = continuation.sourceAnchorId;\n }\n\n const sourceContent = source?.querySelector<HTMLElement>(\".footnote-content\");\n const content = sourceContent\n ? sourceContent.cloneNode(false) as HTMLElement\n : this.document.createElement(\"span\");\n this.makeContinuationShellInert(content);\n if (!sourceContent) content.className = \"footnote-content\";\n\n const first = elements[0];\n if (\n first?.tagName === \"P\"\n && first.getAttribute(FOOTNOTE_SOURCE_POSITION_ATTR) === \"later\"\n ) {\n const sentinel = this.document.createElement(\"p\");\n sentinel.className = \"footnote-continuation-position-sentinel\";\n sentinel.setAttribute(\"aria-hidden\", \"true\");\n sentinel.style.setProperty(\"display\", \"none\", \"important\");\n content.appendChild(sentinel);\n }\n for (let index = 0; index < elements.length; index++) {\n this.checkpoint();\n const element = elements[index];\n const clone = element.cloneNode(true) as HTMLElement;\n clone.removeAttribute(FOOTNOTE_SOURCE_POSITION_ATTR);\n if (index === 0 && clone.tagName === \"P\") {\n // Without the initial number, a carried paragraph always starts a new\n // line even when source CSS made the note's first paragraph inline.\n clone.style.setProperty(\"display\", \"block\", \"important\");\n }\n content.appendChild(clone);\n }\n wrapper.appendChild(content);\n return wrapper;\n }\n\n /** Build the exact partial-note item shape shared by measurement and paint. */\n private createPartialFootnoteItem(\n footnote: HTMLElement,\n fittingElements: readonly HTMLElement[],\n ): HTMLElement {\n const item = footnote.cloneNode(false) as HTMLElement;\n const number = footnote.querySelector(\".footnote-number\");\n if (number) item.appendChild(number.cloneNode(true));\n\n const sourceContent = footnote.querySelector<HTMLElement>(\".footnote-content\");\n const content = sourceContent\n ? sourceContent.cloneNode(false) as HTMLElement\n : this.document.createElement(\"span\");\n if (!sourceContent) content.className = \"footnote-content\";\n for (const element of fittingElements) {\n this.checkpoint();\n content.appendChild(element.cloneNode(true));\n }\n item.appendChild(content);\n return item;\n }\n\n /**\n * Where a note measurement tree is attached.\n *\n * A note band is reserved from a measurement and then painted; if the two\n * happen under different inherited typography the painted notes overflow the\n * reserve, which is the invisible clipping this engine exists to avoid. The\n * registry lives in the staging tree but a band paints inside the output\n * container, so measure there. The host is never a page box, so a page's\n * `zoom` cannot scale a reserve that is accounted for in unscaled points.\n */\n private noteMeasurementHost(): HTMLElement {\n return this.containerElement.isConnected\n ? this.containerElement\n : this.stagingElement;\n }\n\n /**\n * Measures the height of footnotes for given IDs (in points).\n * Creates a temporary container to measure the footnotes.\n * @param footnoteIds - IDs of footnotes to measure\n * @param contentWidth - Width for measurement\n * @param continuation - Optional continuation content to include first\n */\n private measureFootnotesHeight(\n footnoteIds: string[],\n contentWidth: number,\n continuation?: FootnoteContinuation | null,\n partialFootnotes?: readonly PartialFootnote[],\n ): number {\n const hasContinuation = continuation && continuation.remainingElements.length > 0;\n if (footnoteIds.length === 0 && !hasContinuation) {\n return 0;\n }\n // Mirror addPageFootnotes: with no registry and nothing carried, no band is\n // painted, so reserving the separator's height would shrink every page's\n // body for a document whose note references resolve to nothing.\n if (this.footnoteRegistry.size === 0 && !hasContinuation) {\n return 0;\n }\n\n // Measure in the SAME styling context the notes render in: `.page-footnotes` carries\n // its own font-size and line-height, so measuring without the class sizes the note\n // block against body type and the reserve can never match what is drawn.\n // Create a temporary measurement container\n const measureContainer = this.document.createElement(\"div\");\n measureContainer.style.position = \"absolute\";\n measureContainer.style.visibility = \"hidden\";\n measureContainer.style.width = `${contentWidth}pt`;\n measureContainer.style.left = \"-9999px\";\n measureContainer.className = this.cssPrefix + \"footnotes\";\n\n // Add the same normal/continuation separator story that will be painted.\n this.appendFootnoteSeparator(measureContainer, Boolean(hasContinuation));\n\n // Add continuation content first (if any)\n if (hasContinuation) {\n measureContainer.appendChild(this.createFootnoteContinuationWrapper(continuation!));\n }\n\n // Add footnotes\n const partialById = new Map(\n partialFootnotes?.map((partial) => [partial.footnoteId, partial] as const) ?? [],\n );\n for (const id of footnoteIds) {\n this.checkpoint();\n const footnote = this.footnoteRegistry.get(id);\n if (footnote) {\n const partial = partialById.get(id);\n measureContainer.appendChild(partial\n ? this.createPartialFootnoteItem(footnote, partial.fittingElements)\n : footnote.cloneNode(true));\n }\n }\n\n // Append to staging for measurement\n this.noteMeasurementHost().appendChild(measureContainer);\n try {\n return pxToPt(measureContainer.getBoundingClientRect().height);\n } finally {\n measureContainer.remove();\n }\n }\n\n /**\n * Partition a continuation for one page's note band, preferring complete children\n * and range-fragmenting an eligible paragraph when necessary. Always advances by\n * at least one element so an indivisible oversized paragraph follows the established\n * clipped fallback without trapping pagination in a loop.\n */\n private splitContinuationForPage(\n continuation: FootnoteContinuation,\n availableHeightPt: number,\n contentWidth: number,\n ): { current: FootnoteContinuation; overflow: FootnoteContinuation | null } {\n const fitting: HTMLElement[] = [];\n let remaining: HTMLElement[] = [];\n\n // Keep one live measurement tree and append each candidate exactly once.\n // Rebuilding `[...fitting, candidate]` for every child cloned 1+2+...+N\n // descendants before a page/resource cap could run, which is quadratic for\n // producer-authored notes containing thousands of tiny paragraphs/runs.\n const measureContainer = this.document.createElement(\"div\");\n measureContainer.style.position = \"absolute\";\n measureContainer.style.visibility = \"hidden\";\n measureContainer.style.width = `${contentWidth}pt`;\n measureContainer.style.left = \"-9999px\";\n measureContainer.className = this.cssPrefix + \"footnotes\";\n this.appendFootnoteSeparator(measureContainer, true);\n const wrapper = this.createFootnoteContinuationWrapper(continuation, []);\n const content = wrapper.querySelector<HTMLElement>(\":scope > .footnote-content\");\n if (!content) {\n throw new Error(\"Footnote continuation is missing its content shell\");\n }\n measureContainer.appendChild(wrapper);\n this.noteMeasurementHost().appendChild(measureContainer);\n\n try {\n for (let index = 0; index < continuation.remainingElements.length; index++) {\n this.checkpoint();\n const element = continuation.remainingElements[index];\n const sourcePosition = element.getAttribute(FOOTNOTE_SOURCE_POSITION_ATTR);\n if (\n fitting.length === 0\n && element.tagName === \"P\"\n && element.getAttribute(FOOTNOTE_SOURCE_POSITION_ATTR) === \"later\"\n ) {\n const sentinel = this.document.createElement(\"p\");\n sentinel.className = \"footnote-continuation-position-sentinel\";\n sentinel.setAttribute(\"aria-hidden\", \"true\");\n sentinel.style.setProperty(\"display\", \"none\", \"important\");\n content.appendChild(sentinel);\n }\n\n const candidate = element.cloneNode(true) as HTMLElement;\n candidate.removeAttribute(FOOTNOTE_SOURCE_POSITION_ATTR);\n if (fitting.length === 0 && candidate.tagName === \"P\") {\n candidate.style.setProperty(\"display\", \"block\", \"important\");\n }\n content.appendChild(candidate);\n const candidateHeight = pxToPt(measureContainer.getBoundingClientRect().height);\n if (candidateHeight <= availableHeightPt) {\n fitting.push(element);\n continue;\n }\n\n const canSplitCandidate = candidate.tagName === \"P\"\n && this.canRangeFragmentParagraph(candidate);\n candidate.remove();\n let split: ParagraphSplitAttempt | null = null;\n if (canSplitCandidate) {\n split = this.splitParagraphAtLargestFit(candidate, (head) => {\n content.appendChild(head);\n try {\n return pxToPt(measureContainer.getBoundingClientRect().height) <= availableHeightPt;\n } finally {\n head.remove();\n }\n }, {\n // Both fallbacks below cut where ordinary line breaking would not,\n // so they are only ever right for an element that owns the whole\n // band: if this page already carries earlier content, a paragraph\n // that will not start here belongs intact in the next note band.\n emergencyGraphemeBreaks: fitting.length === 0,\n // A continuation page owns the full note band. If even one legal\n // grapheme is taller than it, clip only that unit and keep draining.\n forceFirstOnNoFit: fitting.length === 0,\n });\n }\n if (split?.kind === \"split\") {\n if (sourcePosition) {\n split.head.setAttribute(FOOTNOTE_SOURCE_POSITION_ATTR, sourcePosition);\n split.tail.setAttribute(FOOTNOTE_SOURCE_POSITION_ATTR, sourcePosition);\n }\n fitting.push(split.head);\n remaining = [split.tail, ...continuation.remainingElements.slice(index + 1)];\n } else if (fitting.length === 0) {\n // A genuinely indivisible first element retains the established visible\n // clipped fallback, but only for itself. Its siblings continue later.\n fitting.push(element);\n remaining = continuation.remainingElements.slice(index + 1);\n } else {\n remaining = continuation.remainingElements.slice(index);\n }\n break;\n }\n } finally {\n measureContainer.remove();\n }\n\n return {\n current: {\n footnoteId: continuation.footnoteId,\n sourceAnchorId: continuation.sourceAnchorId,\n remainingElements: fitting,\n },\n overflow: remaining.length > 0 ? {\n footnoteId: continuation.footnoteId,\n sourceAnchorId: continuation.sourceAnchorId,\n remainingElements: remaining,\n } : null,\n };\n }\n\n /**\n * Splits a footnote element into parts that fit within the available height.\n * Returns the elements that fit and the elements that need to continue.\n */\n private splitFootnoteToFit(\n footnoteElement: HTMLElement,\n availableHeightPt: number,\n contentWidth: number,\n forceProgress = false,\n existingPayload?: FootnotePackingContext,\n ): { fits: HTMLElement[]; overflow: HTMLElement[] } {\n // Registry entries are detached clones, so getComputedStyle() cannot validate\n // their real paragraph layout. Attach an exact clone in the rendered note\n // context for the duration of the conservative range-fragmentation check.\n const layoutContext = this.document.createElement(\"div\");\n layoutContext.style.position = \"absolute\";\n layoutContext.style.visibility = \"hidden\";\n layoutContext.style.width = `${contentWidth}pt`;\n layoutContext.style.left = \"-9999px\";\n layoutContext.className = this.cssPrefix + \"footnotes\";\n this.appendFootnoteSeparator(layoutContext, false);\n const attachedFootnote = footnoteElement.cloneNode(true) as HTMLElement;\n layoutContext.appendChild(attachedFootnote);\n this.noteMeasurementHost().appendChild(layoutContext);\n\n // A second live tree represents the exact already-packed page payload plus\n // an initially empty partial item. Candidates are appended once and layout\n // is read in place, avoiding cumulative prefix re-cloning.\n const measureContainer = this.document.createElement(\"div\");\n measureContainer.style.position = \"absolute\";\n measureContainer.style.visibility = \"hidden\";\n measureContainer.style.width = `${contentWidth}pt`;\n measureContainer.style.left = \"-9999px\";\n measureContainer.className = this.cssPrefix + \"footnotes\";\n const hasContinuation = Boolean(existingPayload?.continuation?.remainingElements.length);\n this.appendFootnoteSeparator(measureContainer, hasContinuation);\n if (hasContinuation) {\n measureContainer.appendChild(this.createFootnoteContinuationWrapper(\n existingPayload!.continuation!,\n ));\n }\n const partialById = new Map(\n existingPayload?.partialFootnotes?.map((partial) =>\n [partial.footnoteId, partial] as const) ?? [],\n );\n for (const id of existingPayload?.footnoteIds ?? []) {\n this.checkpoint();\n const source = this.footnoteRegistry.get(id);\n if (!source) continue;\n const partial = partialById.get(id);\n measureContainer.appendChild(partial\n ? this.createPartialFootnoteItem(source, partial.fittingElements)\n : source.cloneNode(true));\n }\n const measuredPartial = this.createPartialFootnoteItem(attachedFootnote, []);\n const measuredContent = measuredPartial.querySelector<HTMLElement>(\":scope > .footnote-content\");\n if (!measuredContent) {\n layoutContext.remove();\n throw new Error(\"Footnote is missing its content shell\");\n }\n measureContainer.appendChild(measuredPartial);\n this.noteMeasurementHost().appendChild(measureContainer);\n\n // Get child elements (paragraphs) of the footnote content.\n //\n // `fits` is spliced into a freshly built `.footnote-item` > `.footnote-content` wrapper by\n // addPageFootnotes, so it must contain the note's CONTENT, never the note element itself.\n // Returning the whole `.footnote-item` here nested a complete item (number span and all)\n // inside another item's content span; the inner block-level div then broke the line, so the\n // note's number rendered alone above its text \u2014 the same visible symptom as the escaped-CSS\n // bug, from an unrelated cause, on the notes that happened to take a can't-split path.\n try {\n const footnoteContent = attachedFootnote.querySelector(\".footnote-content\");\n if (!footnoteContent) {\n // No content structure to split \u2014 hand back the element's own children.\n return {\n fits: Array.from(attachedFootnote.children).map((el) =>\n el.cloneNode(true) as HTMLElement),\n overflow: [],\n };\n }\n\n const children = Array.from(footnoteContent.children) as HTMLElement[];\n const fits: HTMLElement[] = [];\n let overflow: HTMLElement[] = [];\n\n for (let i = 0; i < children.length; i++) {\n this.checkpoint();\n const child = children[i];\n const measuredCandidate = child.cloneNode(true) as HTMLElement;\n measuredContent.appendChild(measuredCandidate);\n const candidateFits = pxToPt(measureContainer.getBoundingClientRect().height)\n <= availableHeightPt;\n if (candidateFits) {\n fits.push(child.cloneNode(true) as HTMLElement);\n continue;\n }\n\n measuredCandidate.remove();\n\n const split = this.canRangeFragmentParagraph(child, true)\n ? this.splitParagraphAtLargestFit(child, (head) => {\n measuredContent.appendChild(head);\n try {\n return pxToPt(measureContainer.getBoundingClientRect().height)\n <= availableHeightPt;\n } finally {\n head.remove();\n }\n }, {\n // Both fallbacks cut where ordinary line breaking would not, so they\n // are only ever right for an element that owns the whole band: with\n // earlier siblings already packed here, a paragraph that will not\n // start belongs intact in the next note band.\n emergencyGraphemeBreaks: fits.length === 0 && forceProgress,\n forceFirstOnNoFit: fits.length === 0 && forceProgress,\n })\n : null;\n if (split?.kind === \"split\") {\n fits.push(split.head);\n split.tail.setAttribute(\n FOOTNOTE_SOURCE_POSITION_ATTR,\n i === 0 ? \"first\" : \"later\",\n );\n overflow = [split.tail, ...children.slice(i + 1).map((element, offset) =>\n this.cloneFootnoteElementForContinuation(element, i + 1 + offset))];\n } else if (split?.kind === \"no-fit\") {\n // The paragraph is splittable, but this citation page has less than\n // one line left. Defer it whole so a fresh note band can try again.\n overflow = children.slice(i).map((element, offset) =>\n this.cloneFootnoteElementForContinuation(element, i + offset));\n } else if (fits.length === 0 && forceProgress) {\n // Preserve the one-element clipping fallback for content that cannot be\n // range-fragmented only on a dedicated full note band, while allowing\n // every later sibling to continue. A residual citation-page band must\n // defer the whole element: it may fit untouched on the next page.\n fits.push(child.cloneNode(true) as HTMLElement);\n overflow = children.slice(i + 1).map((element, offset) =>\n this.cloneFootnoteElementForContinuation(element, i + 1 + offset));\n } else {\n overflow = children.slice(i).map((element, offset) =>\n this.cloneFootnoteElementForContinuation(element, i + offset));\n }\n break;\n }\n\n return { fits, overflow };\n } finally {\n measureContainer.remove();\n layoutContext.remove();\n }\n }\n\n /**\n * Adds footnotes to a page container, including continuation content.\n */\n private addPageFootnotes(\n pageBox: HTMLElement,\n footnoteIds: string[],\n dims: PageDimensions,\n bands: PageBands,\n footnoteHeight: number,\n continuation?: FootnoteContinuation | null,\n partialFootnotes?: PartialFootnote[]\n ): void {\n const hasContinuation = continuation && continuation.remainingElements.length > 0;\n if (footnoteIds.length === 0 && !hasContinuation) {\n return;\n }\n if (this.footnoteRegistry.size === 0 && !hasContinuation) {\n return;\n }\n\n // Calculate max height for footnotes area (content height minus margin for body content)\n const maxFootnoteHeight = Math.min(\n footnoteHeight,\n bands.bodyHeight * MAX_FOOTNOTE_AREA_RATIO\n );\n\n const footnotesDiv = this.document.createElement(\"div\");\n footnotesDiv.className = `${this.cssPrefix}footnotes`;\n footnotesDiv.style.position = \"absolute\";\n // Notes sit at the FOOT OF THE BODY BAND, not at the bottom margin: a footer taller than\n // its margin raises that edge, and anchoring to the raw margin would draw notes over it.\n footnotesDiv.style.bottom = `${dims.pageHeight - (bands.bodyTop + bands.bodyHeight)}pt`;\n footnotesDiv.style.left = `${dims.marginLeft}pt`;\n footnotesDiv.style.width = `${dims.contentWidth}pt`;\n footnotesDiv.style.boxSizing = \"border-box\";\n // Constrain height and clip overflow to prevent footnotes covering body content\n footnotesDiv.style.maxHeight = `${maxFootnoteHeight}pt`;\n footnotesDiv.style.overflow = \"hidden\";\n\n this.appendFootnoteSeparator(footnotesDiv, Boolean(hasContinuation));\n\n // Add continuation content first (if any)\n if (hasContinuation) {\n footnotesDiv.appendChild(this.createFootnoteContinuationWrapper(continuation!));\n }\n\n // Clone footnotes in order of appearance\n for (const id of footnoteIds) {\n // Check if this is a partial footnote\n const partial = partialFootnotes?.find(p => p.footnoteId === id);\n if (partial) {\n // Render partial footnote (only the fitting elements)\n const footnote = this.footnoteRegistry.get(id);\n if (footnote) {\n footnotesDiv.appendChild(\n this.createPartialFootnoteItem(footnote, partial.fittingElements),\n );\n }\n } else {\n // Render full footnote from registry\n const footnote = this.footnoteRegistry.get(id);\n if (footnote) {\n footnotesDiv.appendChild(footnote.cloneNode(true));\n }\n }\n }\n\n pageBox.appendChild(footnotesDiv);\n }\n\n /** Select the section's first/odd/even header from its one-based page position. */\n private selectHeader(\n sectionIndex: number,\n pageInSection: number,\n displayedPageNumber: number,\n ): HTMLElement | undefined {\n const sectionHf = this.hfRegistry.get(sectionIndex);\n if (!sectionHf) return undefined;\n\n // First page of section uses first header if available\n if (pageInSection === 1 && sectionHf.headerFirst) {\n return sectionHf.headerFirst;\n }\n\n // ECMA-376 \u00A717.10.5 hangs the even story on \"even numbered pages\": the PAGE NUMBER,\n // which keeps counting across a section boundary unless w:pgNumType restarts it (and a\n // restart moves the parity with it). Word and LibreOffice both render DB001-Sections\n // this way; selecting by position-in-section flips every story of a section that\n // begins on an even page (issue #536).\n if (displayedPageNumber % 2 === 0 && sectionHf.headerEven) {\n return sectionHf.headerEven;\n }\n\n // Default (odd) pages\n return sectionHf.headerDefault;\n }\n\n /**\n * The story KIND (`\"first\"` / `\"even\"` / `\"default\"`) a page position selects \u2014 the same\n * decision {@link selectHeader} / {@link selectFooter} make, named rather than resolved to\n * an element, so a page can advertise which OOXML story it is showing.\n */\n private storyKindFor(\n which: \"header\" | \"footer\",\n sectionIndex: number,\n pageInSection: number,\n displayedPageNumber: number,\n ): \"first\" | \"even\" | \"default\" {\n const sectionHf = this.hfRegistry.get(sectionIndex);\n const first = which === \"header\" ? sectionHf?.headerFirst : sectionHf?.footerFirst;\n const even = which === \"header\" ? sectionHf?.headerEven : sectionHf?.footerEven;\n if (pageInSection === 1 && first) return \"first\";\n if (displayedPageNumber % 2 === 0 && even) return \"even\";\n return \"default\";\n }\n\n /** Select the section's first/odd/even footer from its one-based page position. */\n private selectFooter(\n sectionIndex: number,\n pageInSection: number,\n displayedPageNumber: number,\n ): HTMLElement | undefined {\n const sectionHf = this.hfRegistry.get(sectionIndex);\n if (!sectionHf) return undefined;\n\n // First page of section uses first footer if available\n if (pageInSection === 1 && sectionHf.footerFirst) {\n return sectionHf.footerFirst;\n }\n\n if (displayedPageNumber % 2 === 0 && sectionHf.footerEven) {\n return sectionHf.footerEven;\n }\n\n // Default (odd) pages\n return sectionHf.footerDefault;\n }\n\n /**\n * The header, body, and footer bands for one page position.\n *\n * The single owner of \"where does anything sit vertically on this page\" \u2014 placement in\n * {@link createPage}, the body budget the flow loop spends, and the note area's anchor all\n * read it, so those three cannot disagree about where the body ends.\n *\n * Deterministic: it depends only on the section's page setup and the registry's pre-measured\n * story heights, never on the page's content, which is what keeps it lazy-loading compatible.\n */\n /** The body height a physical page may fill: its body band less any caller-requested reduction. */\n private bodyBudgetPt(bodyHeightPt: number, physicalPageNumber: number): number {\n return Math.max(0, bodyHeightPt - (this.bodyBudgetReductionsPt[physicalPageNumber] ?? 0));\n }\n\n private getPageBands(\n dims: PageDimensions,\n sectionIndex: number,\n pageInSection: number,\n displayedPageNumber: number,\n ): PageBands {\n const sectionHf = this.hfRegistry.get(sectionIndex);\n return resolvePageBands(\n dims,\n this.selectStoryHeight(\n sectionHf?.headerFirstHeight,\n sectionHf?.headerEvenHeight,\n sectionHf?.headerDefaultHeight,\n pageInSection,\n displayedPageNumber\n ),\n this.selectStoryHeight(\n sectionHf?.footerFirstHeight,\n sectionHf?.footerEvenHeight,\n sectionHf?.footerDefaultHeight,\n pageInSection,\n displayedPageNumber\n )\n );\n }\n\n /**\n * The measured height of the running story this page position selects, mirroring\n * {@link selectHeader}/{@link selectFooter}. Zero when the page has no such story.\n */\n private selectStoryHeight(\n first: number | undefined,\n even: number | undefined,\n fallback: number | undefined,\n pageInSection: number,\n displayedPageNumber: number,\n ): number {\n if (pageInSection === 1 && first != null) return first;\n if (displayedPageNumber % 2 === 0 && even != null) return even;\n return fallback ?? 0;\n }\n\n /**\n * Measures the content height of a header or footer element.\n *\n * This is what tells {@link resolvePageBands} whether the story stays inside its margin or\n * pushes the body, so it must measure the story ALONE \u2014 any padding added here would have to\n * be added to the rendered band too, and the two drifting apart is exactly how a header\n * silently starts overlapping body text.\n */\n private measureHeaderFooterHeight(\n source: HTMLElement,\n contentWidth: number\n ): number {\n // Create a temporary measurement container\n const measureContainer = this.document.createElement(\"div\");\n measureContainer.style.position = \"absolute\";\n measureContainer.style.visibility = \"hidden\";\n measureContainer.style.width = `${contentWidth}pt`;\n measureContainer.style.left = \"-9999px\";\n\n // Clone and add the header/footer content\n for (const child of Array.from(source.childNodes)) {\n measureContainer.appendChild(child.cloneNode(true));\n }\n\n // Append to staging for measurement\n this.stagingElement.appendChild(measureContainer);\n\n // Measure\n const rect = measureContainer.getBoundingClientRect();\n const heightPt = pxToPt(rect.height);\n\n // Clean up\n this.stagingElement.removeChild(measureContainer);\n\n return heightPt;\n }\n\n /**\n * Flows measured blocks into page containers.\n * Implements a single-pass, forward-only algorithm that is compatible with future lazy loading.\n * Supports footnote continuation - long footnotes can split across pages.\n */\n private flowToPages(\n blocks: MeasuredBlock[],\n dims: PageDimensions,\n startPageNumber: number,\n sectionIndex: number,\n sectionDimensions: ReadonlyMap<number, PageDimensions>,\n ): PageInfo[] {\n const pages: PageInfo[] = [];\n let currentContent: HTMLElement[] = [];\n let pageNumber = startPageNumber;\n let pageSectionIndex = sectionIndex;\n // A continuous section can begin on a page owned by its predecessor. That shared physical\n // page is still page 1 of the later section, so its first independently owned page is page 2.\n const sectionStartPages = new Map<number, number>([[sectionIndex, startPageNumber]]);\n const pageInSection = (owner = pageSectionIndex, physicalPage = pageNumber) =>\n physicalPage - (sectionStartPages.get(owner) ?? physicalPage) + 1;\n const dimensionsFor = (owner = pageSectionIndex) =>\n sectionDimensions.get(owner) ?? dims;\n const markSectionPlaced = (owner: number) => {\n if (!sectionStartPages.has(owner)) sectionStartPages.set(owner, pageNumber);\n };\n const previousBox = this.containerElement.querySelector<HTMLElement>(\n `.${this.cssPrefix}box:last-of-type`,\n );\n let precedingDisplayedPageNumber = parseInt(\n previousBox?.dataset.displayedPageNumber ?? \"0\",\n 10,\n );\n const displayedPageNumber = (\n owner = pageSectionIndex,\n ownerPageInSection = pageInSection(owner),\n physicalPage = pageNumber,\n ) => {\n const numbering = this.pageNumbering.get(owner) ?? {};\n if (numbering.start !== undefined) {\n return numbering.start + ownerPageInSection - 1;\n }\n const ownerNumbering = this.pageNumbering.get(pageSectionIndex) ?? {};\n const currentPhysicalNumber = ownerNumbering.start !== undefined\n ? ownerNumbering.start + pageInSection(pageSectionIndex) - 1\n : precedingDisplayedPageNumber + 1;\n return currentPhysicalNumber + physicalPage - pageNumber;\n };\n\n // Get effective content height for first page (accounts for header/footer sizes)\n let effectiveContentHeight = this.bodyBudgetPt(this.getPageBands(\n dimensionsFor(), pageSectionIndex, pageInSection(), displayedPageNumber()\n ).bodyHeight, pageNumber);\n let remainingHeight = effectiveContentHeight;\n\n // Track the previous block's bottom margin for margin collapsing\n let prevMarginBottomPt = 0;\n // Track footnote IDs for the current page\n let currentFootnoteIds: string[] = [];\n let currentPageHasFootnoteReference = false;\n // Track height consumed by footnotes on current page\n let currentFootnoteHeight = 0;\n // Track footnote continuation for current page (from previous page)\n let currentContinuation: FootnoteContinuation | null = this.pendingFootnoteContinuation;\n // Track any new continuation that will carry to next page\n let nextPageContinuation: FootnoteContinuation | null = null;\n let currentContinuationPartitioned = false;\n let currentPageAdmitted = false;\n /**\n * Whole notes that could not be started on this page and must render on the next one.\n *\n * `nextPageContinuation` is a single slot, but the code that fills it runs once per note in a\n * page's citation list \u2014 so when two notes on the same page both failed to fit, the second\n * overwrote the first and that note was never rendered anywhere. On a 94-footnote document\n * four notes disappeared from the output entirely. A deferral queue keeps the single-slot\n * continuation for its real meaning (the tail of a note that was SPLIT) and carries\n * never-started notes forward as ordinary footnote ids, which the next page already knows how\n * to lay out.\n */\n let deferredFootnoteIds: string[] = [];\n // Track partial footnotes for current page (footnotes that were split)\n let currentPartialFootnotes: PartialFootnote[] = [];\n\n const adoptEmptyPageOwner = (owner: number) => {\n pageSectionIndex = owner;\n const bands = this.getPageBands(\n dimensionsFor(owner),\n owner,\n pageInSection(owner),\n displayedPageNumber(owner),\n );\n effectiveContentHeight = this.bodyBudgetPt(bands.bodyHeight, pageNumber);\n remainingHeight = effectiveContentHeight;\n };\n\n const admitCurrentPage = () => {\n if (currentPageAdmitted) return;\n this.admitPageAllocation();\n currentPageAdmitted = true;\n };\n\n const prepareCurrentContinuation = () => {\n if (currentContinuationPartitioned\n || (currentContinuation?.remainingElements.length ?? 0) === 0) return;\n // A continuation guarantees that this physical page will exist. Admit it\n // before touching the carried DOM, then partition once and retain that\n // exact head while body placement is decided.\n admitCurrentPage();\n const ownedDimensions = dimensionsFor();\n const pageBands = this.getPageBands(\n ownedDimensions,\n pageSectionIndex,\n pageInSection(),\n displayedPageNumber(),\n );\n const partition = this.splitContinuationForPage(\n currentContinuation!,\n pageBands.bodyHeight * MAX_FOOTNOTE_AREA_RATIO,\n ownedDimensions.contentWidth,\n );\n currentContinuation = partition.current;\n if (partition.overflow) nextPageContinuation = partition.overflow;\n currentContinuationPartitioned = true;\n currentFootnoteHeight = this.measureFootnotesHeight(\n currentFootnoteIds,\n ownedDimensions.contentWidth,\n currentContinuation,\n currentPartialFootnotes,\n );\n };\n\n const finishPage = (\n nextPageSectionIndex = pageSectionIndex,\n forceEmptyPage = false,\n ) => {\n const hasCurrentContinuation =\n (currentContinuation?.remainingElements.length ?? 0) > 0;\n if (!forceEmptyPage && currentContent.length === 0 && currentFootnoteIds.length === 0\n && !hasCurrentContinuation) {\n adoptEmptyPageOwner(nextPageSectionIndex);\n return;\n }\n\n prepareCurrentContinuation();\n // Pages without a carried continuation are charged here. Continuation\n // pages were charged before their page-owned partition above.\n admitCurrentPage();\n\n let pageContinuation = currentContinuation;\n const ownedPageInSection = pageInSection();\n const ownedDimensions = dimensionsFor();\n const ownedDisplayedPageNumber = displayedPageNumber(\n pageSectionIndex,\n ownedPageInSection,\n );\n const pageBands = this.getPageBands(\n ownedDimensions,\n pageSectionIndex,\n ownedPageInSection,\n ownedDisplayedPageNumber,\n );\n const maxFootnoteHeight = pageBands.bodyHeight * MAX_FOOTNOTE_AREA_RATIO;\n // `prepareCurrentContinuation` has already packed the exact head for this\n // page. Keeping that partition stable lets body fit decisions share the\n // remaining band without rescanning the entire tail.\n pageContinuation = currentContinuation;\n\n // Recompute the entire painted payload after continuation partitioning.\n // Measuring only the carried head here discarded the reserve for a newer\n // whole/partial note and let the clipped note band silently consume it.\n currentFootnoteHeight = this.measureFootnotesHeight(\n currentFootnoteIds,\n ownedDimensions.contentWidth,\n pageContinuation,\n currentPartialFootnotes,\n );\n\n // A final body page can seed the next page with several whole notes. Partition that queue\n // before materializing a note-only page: addPageFootnotes deliberately clips its band, so\n // placing the entire queue in one page would keep the DOM nodes while making later notes\n // invisible (and therefore absent from a geometry-clipped PageMap).\n if (currentContent.length === 0 && currentFootnoteIds.length > 0\n && currentPartialFootnotes.length === 0) {\n const fittingIds: string[] = [];\n for (let index = 0; index < currentFootnoteIds.length; index++) {\n const footnoteId = currentFootnoteIds[index];\n const candidateIds = [...fittingIds, footnoteId];\n const candidateHeight = this.measureFootnotesHeight(\n candidateIds, ownedDimensions.contentWidth, pageContinuation);\n const guardedCandidateHeight = candidateHeight + FOOTNOTE_MEASUREMENT_GUARD_PT;\n if (guardedCandidateHeight <= maxFootnoteHeight) {\n fittingIds.push(footnoteId);\n currentFootnoteHeight = guardedCandidateHeight;\n continue;\n }\n\n const hasPageContinuation =\n (pageContinuation?.remainingElements.length ?? 0) > 0;\n if (fittingIds.length === 0 && !hasPageContinuation) {\n // One note alone is taller than the note band. Split at the same safe paragraph\n // boundaries used during body flow; if it is indivisible, preserve the established\n // visible clipped fallback while still advancing the queue.\n const source = this.footnoteRegistry.get(footnoteId);\n const split = source\n ? this.splitFootnoteToFit(\n source,\n maxFootnoteHeight - FOOTNOTE_MEASUREMENT_GUARD_PT,\n ownedDimensions.contentWidth,\n true,\n )\n : null;\n fittingIds.push(footnoteId);\n if (source && split && split.fits.length > 0 && split.overflow.length > 0) {\n currentPartialFootnotes.push({ footnoteId, fittingElements: split.fits });\n nextPageContinuation = {\n footnoteId,\n sourceAnchorId: source.dataset.sourceAnchorId,\n remainingElements: split.overflow,\n };\n currentFootnoteHeight = maxFootnoteHeight;\n } else {\n currentFootnoteHeight = guardedCandidateHeight;\n }\n deferredFootnoteIds.push(...currentFootnoteIds.slice(index + 1));\n } else {\n deferredFootnoteIds.push(...currentFootnoteIds.slice(index));\n }\n break;\n }\n currentFootnoteIds = fittingIds;\n }\n\n const page = this.createPage(\n ownedDimensions,\n pageNumber,\n pageSectionIndex,\n ownedDisplayedPageNumber,\n currentContent,\n ownedPageInSection,\n currentFootnoteIds,\n currentFootnoteHeight,\n pageContinuation,\n currentPartialFootnotes.length > 0 ? currentPartialFootnotes : undefined,\n false,\n currentPageAdmitted,\n );\n pages.push(page);\n precedingDisplayedPageNumber = ownedDisplayedPageNumber;\n\n pageNumber++;\n currentContent = [];\n\n pageSectionIndex = nextPageSectionIndex;\n if (!sectionStartPages.has(pageSectionIndex)) {\n // A carried note can own pages before the first body block of a new\n // section lands. Count those physical pages in that section so first /\n // odd / even stories and restarted displayed numbering advance once.\n sectionStartPages.set(pageSectionIndex, pageNumber);\n }\n\n // Get effective content height for new page position\n const newBands = this.getPageBands(\n dimensionsFor(),\n pageSectionIndex,\n pageInSection(),\n displayedPageNumber(),\n );\n effectiveContentHeight = this.bodyBudgetPt(newBands.bodyHeight, pageNumber);\n remainingHeight = effectiveContentHeight;\n\n prevMarginBottomPt = 0; // Reset margin tracking for new page\n currentFootnoteIds = []; // Reset footnotes for new page\n currentPageHasFootnoteReference = false;\n currentPartialFootnotes = []; // Reset partial footnotes for new page\n\n // Carry over continuation to next page\n currentContinuation = nextPageContinuation;\n nextPageContinuation = null;\n currentContinuationPartitioned = false;\n currentPageAdmitted = false;\n\n // Notes that never got started land at the top of the new page's note area. They are\n // ordinary footnotes from here on, so the normal fitting path handles them \u2014 and because\n // this page is fresh, the space they were denied now exists.\n if (deferredFootnoteIds.length > 0) {\n currentFootnoteIds = [...deferredFootnoteIds];\n deferredFootnoteIds = [];\n }\n\n // Whole deferred notes have no carried DOM and can be measured directly.\n // A continuation is partitioned lazily after the prospective page has\n // passed its resource admission check, so never clone its entire tail here.\n const nextDimensions = dimensionsFor();\n currentFootnoteHeight = currentContinuation\n ? 0\n : this.measureFootnotesHeight(currentFootnoteIds, nextDimensions.contentWidth);\n };\n\n const pageHasPayload = () => currentContent.length > 0\n || currentFootnoteIds.length > 0\n || (currentContinuation?.remainingElements.length ?? 0) > 0;\n\n for (let i = 0; i < blocks.length; i++) {\n this.checkpoint();\n const block = blocks[i];\n const allBlockFootnoteIds = this.extractFootnoteRefs(block.element);\n\n // Word normally lets a same-box continuous section begin on its predecessor's page. By\n // default, a footnote reference before that boundary promotes it to a page break. The\n // footnoteLayoutLikeWW8 compatibility switch permits post-break paragraphs without their own\n // references to remain on the shared page; keep checking until the page turns so a later\n // referenced paragraph still begins on a fresh page.\n if (block.sectionIndex !== pageSectionIndex && currentPageHasFootnoteReference\n && (!this.footnoteLayoutLikeWord8 || allBlockFootnoteIds.length > 0)) {\n finishPage(block.sectionIndex);\n }\n\n const pageIsEmpty = currentContent.length === 0\n && currentFootnoteIds.length === 0\n && (currentContinuation?.remainingElements.length ?? 0) === 0;\n if (pageIsEmpty && block.sectionIndex !== pageSectionIndex) {\n adoptEmptyPageOwner(block.sectionIndex);\n }\n\n prepareCurrentContinuation();\n\n if (currentFootnoteHeight > 0) {\n const ownerDimensions = dimensionsFor();\n const ownerBands = this.getPageBands(\n ownerDimensions,\n pageSectionIndex,\n pageInSection(),\n displayedPageNumber(),\n );\n const ownerMaxFootnoteArea = ownerBands.bodyHeight * MAX_FOOTNOTE_AREA_RATIO;\n if (currentFootnoteHeight > ownerMaxFootnoteArea) {\n // A queue of whole notes larger than the band does not entitle it to\n // the whole page: the band is capped and the rest of the page still\n // belongs to body text. Keep the notes that fit here, defer the rest,\n // and only fall back to a note-owned page when not even one note fits\n // \u2014 that case needs the splitting finishPage performs.\n const fittingIds: string[] = [];\n let fittingHeight = 0;\n if ((currentContinuation?.remainingElements.length ?? 0) === 0\n && currentPartialFootnotes.length === 0) {\n for (const footnoteId of currentFootnoteIds) {\n this.checkpoint();\n const candidateHeight = this.measureFootnotesHeight(\n [...fittingIds, footnoteId],\n ownerDimensions.contentWidth,\n );\n if (candidateHeight + FOOTNOTE_MEASUREMENT_GUARD_PT > ownerMaxFootnoteArea) break;\n fittingIds.push(footnoteId);\n fittingHeight = candidateHeight;\n }\n }\n if (fittingIds.length > 0) {\n deferredFootnoteIds = [\n ...currentFootnoteIds.slice(fittingIds.length),\n ...deferredFootnoteIds,\n ];\n currentFootnoteIds = fittingIds;\n currentFootnoteHeight = fittingHeight;\n } else {\n finishPage(block.sectionIndex);\n i--;\n continue;\n }\n }\n }\n const blockDimensions = dimensionsFor(block.sectionIndex);\n const nextBlockPageInSection = pageInSection(block.sectionIndex, pageNumber + 1);\n const freshBlockPageBodyHeight = this.getPageBands(\n blockDimensions,\n block.sectionIndex,\n nextBlockPageInSection,\n displayedPageNumber(block.sectionIndex, nextBlockPageInSection, pageNumber + 1),\n ).bodyHeight;\n\n // Handle explicit page breaks\n if (block.isPageBreak) {\n finishPage(block.sectionIndex);\n continue;\n }\n\n // Handle page break before\n if (block.pageBreakBefore && currentContent.length > 0) {\n finishPage(block.sectionIndex);\n }\n\n // A series of keep-with-next blocks is one indivisible placement unit\n // when it can fit a new page. The former one-block lookahead was never\n // applied to the placement decision, and it could not preserve a chain of\n // headings/paragraphs. Do not force an oversized chain to a fresh page:\n // its members retain the established greedy/overflow behavior instead.\n const previousBlock = blocks[i - 1];\n const startsKeepChain =\n !previousBlock ||\n !previousBlock.keepWithNext ||\n previousBlock.isPageBreak ||\n block.pageBreakBefore;\n // A footnote continuation also occupies this page even when its body has\n // no blocks yet. In that case a feasible chain may need to move past the\n // continuation as a unit.\n const pageHasOccupiedSpace = currentContent.length > 0 || currentFootnoteHeight > 0;\n if (pageHasOccupiedSpace && block.keepWithNext && startsKeepChain) {\n const keepChain = this.getKeepWithNextChain(blocks, i);\n if (keepChain.length > 1) {\n const newChainFootnoteIds = this.collectNewFootnoteIds(\n keepChain,\n currentFootnoteIds\n );\n let additionalChainFootnoteHeight = 0;\n if (newChainFootnoteIds.length > 0 && this.footnoteRegistry.size > 0) {\n const totalChainFootnoteHeight = this.measureFootnotesHeight(\n [...currentFootnoteIds, ...newChainFootnoteIds],\n blockDimensions.contentWidth,\n currentContinuation\n );\n additionalChainFootnoteHeight = Math.max(\n 0,\n totalChainFootnoteHeight - currentFootnoteHeight\n );\n }\n\n const currentChainHeight =\n this.measureKeepWithNextChainBodyHeight(\n keepChain,\n prevMarginBottomPt,\n currentContent.length === 0,\n pageInSection(block.sectionIndex)\n ) +\n additionalChainFootnoteHeight;\n const currentAvailableHeight = remainingHeight - currentFootnoteHeight;\n\n if (currentChainHeight > currentAvailableHeight) {\n const nextPageBands = this.getPageBands(\n dimensionsFor(block.sectionIndex),\n block.sectionIndex,\n pageInSection(block.sectionIndex, pageNumber + 1),\n displayedPageNumber(\n block.sectionIndex,\n pageInSection(block.sectionIndex, pageNumber + 1),\n pageNumber + 1,\n ),\n );\n const freshChainBodyHeight = this.measureKeepWithNextChainBodyHeight(\n keepChain,\n 0,\n true,\n pageInSection(block.sectionIndex, pageNumber + 1)\n );\n // finishPage transfers this continuation to the new page's\n // currentContinuation state, so include it in the destination\n // page's footnote reservation before deciding to move the chain.\n const freshChainFootnoteHeight = this.measureFootnotesHeight(\n newChainFootnoteIds,\n blockDimensions.contentWidth,\n nextPageContinuation\n );\n\n if (\n freshChainBodyHeight + freshChainFootnoteHeight <=\n nextPageBands.bodyHeight\n ) {\n finishPage(block.sectionIndex);\n }\n }\n }\n }\n\n // Extract footnote references from this block\n // Only count new footnotes (not already on this page)\n const newFootnoteIds = this.collectNewFootnoteIds([block], currentFootnoteIds);\n\n // Calculate additional footnote height if this block is added\n let combinedFootnoteHeight = currentFootnoteHeight;\n let additionalFootnoteHeight = 0;\n if (newFootnoteIds.length > 0 && this.footnoteRegistry.size > 0) {\n // Measure the combined height of all footnotes that would be on this page\n // (including any continuation)\n const combinedFootnoteIds = [...currentFootnoteIds, ...newFootnoteIds];\n combinedFootnoteHeight = this.measureFootnotesHeight(\n combinedFootnoteIds,\n blockDimensions.contentWidth,\n currentContinuation,\n currentPartialFootnotes,\n );\n additionalFootnoteHeight = Math.max(\n 0,\n combinedFootnoteHeight - currentFootnoteHeight,\n );\n }\n\n // Calculate the effective height this block will consume\n // Account for margin collapsing: the gap between blocks is max(prevBottom, currTop), not sum\n const isFirstOnPage = currentContent.length === 0;\n const effectiveMarginTop = this.effectiveBlockMarginTop(\n block,\n prevMarginBottomPt,\n isFirstOnPage,\n pageInSection(block.sectionIndex)\n );\n const columnFragments = this.reflowSequentialColumns(\n block,\n blockDimensions,\n remainingHeight - currentFootnoteHeight - additionalFootnoteHeight - effectiveMarginTop,\n );\n if (columnFragments) {\n blocks.splice(i, 1, ...columnFragments);\n i--;\n continue;\n }\n // Visible height = top margin gap + content + footnote space\n // Note: bottom margin is NOT included in the fit check because the last block's\n // bottom margin extends beyond the content area and is clipped by overflow:hidden.\n // It is still tracked in remainingHeight for correct margin collapsing with the next block.\n const blockSpace = effectiveMarginTop + block.heightPt + additionalFootnoteHeight;\n\n // Effective remaining height (content area minus footnotes already on page)\n const effectiveRemainingHeight = remainingHeight - currentFootnoteHeight;\n\n // Calculate maximum footnote area for this page (can expand into body content space)\n const bodyContentUsed = effectiveContentHeight - remainingHeight;\n const maxFootnoteArea = effectiveContentHeight * MAX_FOOTNOTE_AREA_RATIO;\n\n // A paragraph that cannot fit as a whole may still have a simple text-only\n // prefix that fits this page. Fragment before the ordinary next-page or\n // oversized fallback so the cloned head participates in the same margin\n // and footnote accounting as every other block.\n if (blockSpace > effectiveRemainingHeight) {\n const paragraphFragments = this.tryFragmentParagraph(\n block,\n blockDimensions,\n effectiveRemainingHeight,\n effectiveMarginTop\n );\n if (paragraphFragments) {\n blocks.splice(i, 1, ...paragraphFragments);\n i--;\n continue;\n }\n }\n\n // Check if block fits on current page (including its footnotes)\n if (\n blockSpace <= effectiveRemainingHeight\n && (combinedFootnoteHeight === 0\n || combinedFootnoteHeight + FOOTNOTE_MEASUREMENT_GUARD_PT <= maxFootnoteArea)\n ) {\n // Block fits with current footnote allocation\n markSectionPlaced(block.sectionIndex);\n currentContent.push(this.cloneBlockForPage(\n block,\n isFirstOnPage,\n pageInSection(block.sectionIndex),\n ));\n remainingHeight -= (effectiveMarginTop + block.heightPt + block.marginBottomPt);\n prevMarginBottomPt = block.marginBottomPt;\n // Add new footnotes to current page\n if (newFootnoteIds.length > 0) {\n currentFootnoteIds.push(...newFootnoteIds);\n currentFootnoteHeight = combinedFootnoteHeight;\n }\n currentPageHasFootnoteReference ||= allBlockFootnoteIds.length > 0;\n } else if (\n block.heightPt + this.effectiveBlockMarginTop(\n block,\n 0,\n true,\n pageInSection(block.sectionIndex, pageNumber + 1),\n ) <= freshBlockPageBodyHeight\n ) {\n // Block doesn't fit with current allocation - try expanding footnote area\n const blockSpaceWithoutFootnotes = effectiveMarginTop + block.heightPt;\n\n if (newFootnoteIds.length > 0 && blockSpaceWithoutFootnotes <= effectiveRemainingHeight) {\n // Block itself fits, but footnotes don't - expand footnote area\n markSectionPlaced(block.sectionIndex);\n currentContent.push(this.cloneBlockForPage(\n block,\n isFirstOnPage,\n pageInSection(block.sectionIndex),\n ));\n remainingHeight -= (effectiveMarginTop + block.heightPt + block.marginBottomPt);\n prevMarginBottomPt = block.marginBottomPt;\n\n // Calculate EXPANDED space available for footnotes\n // Footnotes can take up to maxFootnoteArea or all remaining space, whichever is less\n const availableForFootnotes = Math.min(\n maxFootnoteArea,\n effectiveContentHeight - bodyContentUsed - blockSpaceWithoutFootnotes\n );\n // Deferring a note costs a page turn, and it only buys anything if the\n // next page's band is larger than what this page can already offer.\n // When this page already offers the maximum band, a note that cannot\n // start here cannot start there either: keep the established clipped\n // fallback on the citing page rather than evacuating it.\n const nextPageMaxFootnoteArea =\n freshBlockPageBodyHeight * MAX_FOOTNOTE_AREA_RATIO;\n const deferralCannotHelp = availableForFootnotes >= nextPageMaxFootnoteArea;\n\n // Try to fit as much of each new footnote as possible in expanded area\n for (let noteIndex = 0; noteIndex < newFootnoteIds.length; noteIndex++) {\n this.checkpoint();\n const footnoteId = newFootnoteIds[noteIndex];\n const footnote = this.footnoteRegistry.get(footnoteId);\n if (!footnote) continue;\n\n // One page can carry only one split tail. Once that slot is used,\n // keep every later note in source order on the deferral queue.\n if (nextPageContinuation) {\n deferredFootnoteIds.push(...newFootnoteIds.slice(noteIndex));\n break;\n }\n\n const candidateIds = [...currentFootnoteIds, footnoteId];\n const candidateHeight = this.measureFootnotesHeight(\n candidateIds,\n blockDimensions.contentWidth,\n currentContinuation,\n currentPartialFootnotes,\n );\n const spaceLeftForFootnotes = availableForFootnotes - currentFootnoteHeight;\n\n if (candidateHeight + FOOTNOTE_MEASUREMENT_GUARD_PT <= availableForFootnotes) {\n // Whole footnote fits in expanded area\n currentFootnoteIds.push(footnoteId);\n currentFootnoteHeight = candidateHeight;\n } else {\n // Footnote needs to be split - use all available expanded space\n if (spaceLeftForFootnotes > 20) { // Minimum space to start a footnote\n const { fits, overflow } = this.splitFootnoteToFit(\n footnote,\n availableForFootnotes,\n blockDimensions.contentWidth,\n deferralCannotHelp,\n {\n footnoteIds: currentFootnoteIds,\n continuation: currentContinuation,\n partialFootnotes: currentPartialFootnotes,\n },\n );\n\n if (fits.length > 0) {\n // Add partial footnote to current page\n currentFootnoteIds.push(footnoteId);\n currentPartialFootnotes.push({\n footnoteId,\n fittingElements: fits\n });\n if (overflow.length > 0) {\n nextPageContinuation = {\n footnoteId,\n sourceAnchorId: footnote.dataset.sourceAnchorId,\n remainingElements: overflow\n };\n }\n currentFootnoteHeight = this.measureFootnotesHeight(\n currentFootnoteIds,\n blockDimensions.contentWidth,\n currentContinuation,\n currentPartialFootnotes,\n );\n if (overflow.length > 0) {\n deferredFootnoteIds.push(...newFootnoteIds.slice(noteIndex + 1));\n break;\n }\n } else {\n // Nothing of this note fits: defer the WHOLE note rather than assigning the\n // single continuation slot, which a later note on this page would overwrite.\n deferredFootnoteIds.push(...newFootnoteIds.slice(noteIndex));\n break;\n }\n } else {\n // Not enough space to even start the note \u2014 same deferral.\n deferredFootnoteIds.push(...newFootnoteIds.slice(noteIndex));\n break;\n }\n }\n }\n currentPageHasFootnoteReference ||= allBlockFootnoteIds.length > 0;\n } else {\n // Block itself doesn't fit. Retry after the page turn so carried\n // continuations and deferred notes participate in the normal fit and\n // split decisions instead of being overwritten by forced placement.\n finishPage(block.sectionIndex, !pageHasPayload());\n i--;\n continue;\n }\n } else {\n // Block is taller than a page. Ordinary tables can be split at complete\n // row boundaries; every other block retains the established overflow path.\n const tableFragments = this.trySplitSimpleOversizedTable(\n block,\n dimensionsFor(block.sectionIndex),\n block.sectionIndex,\n );\n if (tableFragments) {\n if (currentContent.length > 0 || currentContinuation) {\n finishPage(block.sectionIndex);\n }\n blocks.splice(i, 1, ...tableFragments);\n i--;\n continue;\n }\n\n // Unsupported oversized blocks are intentionally left intact. Splitting\n // arbitrary HTML, merged tables, or footnote-bearing tables would be less\n // correct than the prior clipped fallback.\n if (pageHasPayload()) {\n finishPage(block.sectionIndex);\n i--;\n continue;\n }\n markSectionPlaced(block.sectionIndex);\n currentContent.push(this.cloneBlockForPage(\n block,\n true,\n pageInSection(block.sectionIndex),\n ));\n // An unsupported body block already occupies/clips its whole body band.\n // Preserve its notes losslessly on following note-only pages rather\n // than drawing them underneath that clipped fallback.\n deferredFootnoteIds.push(...newFootnoteIds);\n currentPageHasFootnoteReference ||= allBlockFootnoteIds.length > 0;\n finishPage(block.sectionIndex);\n }\n }\n\n // Finish last page\n finishPage();\n\n // A split created while finishing the final body page still needs a page substrate.\n // Drain all remaining note paragraphs into footnote-only continuation pages.\n while (\n currentFootnoteIds.length > 0\n || deferredFootnoteIds.length > 0\n || (currentContinuation?.remainingElements.length ?? 0) > 0\n ) {\n finishPage();\n }\n\n // Store any remaining continuation for next section\n this.pendingFootnoteContinuation = nextPageContinuation;\n\n return pages;\n }\n\n\n /**\n * Strip block addressing from a header/footer node cloned into a page box.\n *\n * A running story is authored ONCE and cloned onto every page, so the clones all carry the same\n * `data-anchor` \u2014 on this document, 42 page boxes claiming one footer paragraph. Left editable,\n * committing any one of them writes back through that single shared anchor, and the per-page\n * page-number substitution makes it worse: each clone shows a DIFFERENT number, so a commit\n * writes that page's number into the story as literal text and destroys the PAGE field.\n *\n * Page-box header/footer content is presentation. The docked editing bands\n * (`editor-headerfooter.ts`) are the addressable affordance, and they exist precisely because a\n * cloned node cannot be uniquely addressed.\n */\n private makeClonedStoryInert(root: HTMLElement): void {\n const nodes = [root, ...Array.from(root.querySelectorAll<HTMLElement>(\"*\"))];\n for (const el of nodes) {\n el.removeAttribute(\"data-anchor\");\n el.removeAttribute(\"data-committed-text\");\n if (el.getAttribute(\"contenteditable\") !== null) el.setAttribute(\"contenteditable\", \"false\");\n }\n }\n\n /** A repeated margin note is presentation, not a second bookmark/link target. */\n private makeClonedMarginCommentInert(root: HTMLElement): void {\n this.makeClonedStoryInert(root);\n const nodes = [root, ...Array.from(root.querySelectorAll<HTMLElement>(\"*\"))];\n for (const element of nodes) {\n element.removeAttribute(\"id\");\n if (element.localName === \"a\" && element.getAttribute(\"href\")?.startsWith(\"#\")) {\n element.removeAttribute(\"href\");\n element.setAttribute(\"aria-disabled\", \"true\");\n element.tabIndex = -1;\n }\n }\n }\n\n /**\n * Resolves floating DrawingML objects after their anchor paragraphs have landed on a page.\n *\n * The converter deliberately carries the OOXML bases and offsets as data instead of flattening\n * them into CSS: page/margin/column bases belong to the page, while paragraph/line/character\n * bases belong to the laid-out anchor. Once both coordinate systems exist, promote the object\n * from the clipped text column into the page box and position it in one shared point space.\n */\n private positionDrawingAnchors(\n pageBox: HTMLElement,\n contentArea: HTMLElement,\n dims: PageDimensions,\n pageNumber: number,\n ): void {\n const anchors = Array.from(\n contentArea.querySelectorAll<HTMLElement>('[data-docx-drawing-anchor=\"true\"]'),\n );\n if (anchors.length === 0) return;\n\n const pageRect = pageBox.getBoundingClientRect();\n const pixelsPerPoint = pageRect.width / dims.pageWidth;\n if (!(pixelsPerPoint > 0)) return;\n\n for (const anchor of anchors) {\n const staticRect = anchor.getBoundingClientRect();\n const paragraph = anchor.closest<HTMLElement>('p, h1, h2, h3, h4, h5, h6');\n const paragraphRect = paragraph?.getBoundingClientRect() ?? staticRect;\n const toPageX = (x: number) => (x - pageRect.left) / pixelsPerPoint;\n const toPageY = (y: number) => (y - pageRect.top) / pixelsPerPoint;\n\n const context = {\n staticLeft: toPageX(staticRect.left),\n staticTop: toPageY(staticRect.top),\n lineHeight: paragraph\n ? (parseFloat(this.view.getComputedStyle(paragraph).lineHeight) || staticRect.height) / pixelsPerPoint\n : staticRect.height / pixelsPerPoint,\n paragraphLeft: toPageX(paragraphRect.left),\n paragraphTop: toPageY(paragraphRect.top),\n paragraphWidth: paragraphRect.width / pixelsPerPoint,\n paragraphHeight: paragraphRect.height / pixelsPerPoint,\n };\n\n const widthReference = this.horizontalAnchorReference(\n anchor.getAttribute('data-docx-anchor-width-relative') ?? 'margin',\n dims,\n pageNumber,\n context,\n );\n const widthPercent = this.anchorNumber(anchor, 'width-percent');\n // Word supports strictly positive relative dimensions (MS-ODRAWXML 2.18.3.1/2).\n // Zero is schema-valid but must not collapse a visible object with a stored extent.\n if (widthPercent !== undefined && widthPercent > 0) {\n anchor.style.width = `${widthReference.size * widthPercent / 100}pt`;\n }\n\n const heightReference = this.verticalAnchorReference(\n anchor.getAttribute('data-docx-anchor-height-relative') ?? 'margin',\n dims,\n pageNumber,\n context,\n );\n const heightPercent = this.anchorNumber(anchor, 'height-percent');\n if (heightPercent !== undefined && heightPercent > 0 && anchor.dataset.docxAnchorAutofit !== 'true') {\n anchor.style.height = `${heightReference.size * heightPercent / 100}pt`;\n }\n\n // Read the final border-box size after relative sizing and before reparenting. The stored\n // wp:extent remains the fallback; wps:bodyPr insets stay inside it through border-box sizing.\n const sizedRect = anchor.getBoundingClientRect();\n const width = sizedRect.width / pixelsPerPoint;\n const height = sizedRect.height / pixelsPerPoint;\n const horizontal = this.horizontalAnchorReference(\n anchor.getAttribute('data-docx-anchor-h-relative') ?? 'column',\n dims,\n pageNumber,\n context,\n );\n const vertical = this.verticalAnchorReference(\n anchor.getAttribute('data-docx-anchor-v-relative') ?? 'paragraph',\n dims,\n pageNumber,\n context,\n );\n const left = this.resolveAnchorAxis(\n horizontal,\n width,\n anchor.getAttribute('data-docx-anchor-h-align'),\n this.anchorNumber(anchor, 'h-offset'),\n pageNumber,\n );\n const top = this.resolveAnchorAxis(\n vertical,\n height,\n anchor.getAttribute('data-docx-anchor-v-align'),\n this.anchorNumber(anchor, 'v-offset'),\n pageNumber,\n );\n\n // Leaving the paragraph must not orphan it: a paragraph whose only content was this drawing\n // renders as the drawing, and measureRenderedSource finds it through this link (issue #849).\n const hostElement = anchor.parentElement?.closest<HTMLElement>('[data-source-anchor-id]');\n const hostAnchorId = hostElement?.dataset.sourceAnchorId;\n if (hostAnchorId) anchor.setAttribute(DRAWING_HOST_ATTRIBUTE, hostAnchorId);\n pageBox.appendChild(anchor);\n // A host left with nothing but its paragraph-mark line (issue #880) renders as that line plus\n // the drawing; one with text of its own keeps measuring as its own box.\n if (hostElement && rendersOnlyItsLine(hostElement))\n hostElement.setAttribute(HOSTS_PROMOTED_DRAWING_ATTRIBUTE, 'true');\n anchor.style.position = 'absolute';\n anchor.style.left = `${left}pt`;\n anchor.style.top = `${top}pt`;\n anchor.style.margin = '0';\n }\n }\n\n private anchorNumber(anchor: HTMLElement, suffix: string): number | undefined {\n const raw = anchor.getAttribute(`data-docx-anchor-${suffix}`);\n if (raw === null) return undefined;\n const value = Number(raw);\n return Number.isFinite(value) ? value : undefined;\n }\n\n private horizontalAnchorReference(\n relativeFrom: string,\n dims: PageDimensions,\n pageNumber: number,\n context: {\n staticLeft: number;\n paragraphLeft: number;\n paragraphWidth: number;\n },\n ): { start: number; size: number } {\n const leftMargin = { start: 0, size: dims.marginLeft };\n const rightMargin = {\n start: dims.marginLeft + dims.contentWidth,\n size: dims.marginRight,\n };\n switch (relativeFrom) {\n case 'page':\n return { start: 0, size: dims.pageWidth };\n case 'character':\n return { start: context.staticLeft, size: 0 };\n case 'leftMargin':\n return leftMargin;\n case 'rightMargin':\n return rightMargin;\n case 'insideMargin':\n return pageNumber % 2 === 1 ? leftMargin : rightMargin;\n case 'outsideMargin':\n return pageNumber % 2 === 1 ? rightMargin : leftMargin;\n case 'paragraph':\n // Not part of ST_RelFromH, but accepting it gives malformed/legacy producers the\n // intuitive base without conflating it with the whole text column.\n return { start: context.paragraphLeft, size: context.paragraphWidth };\n case 'column':\n case 'margin':\n default:\n // The paginator currently lays out one text column per section, so the column and page\n // margin boxes coincide. Keeping the names distinct here leaves multi-column geometry\n // localized to this resolver when that layout support is added.\n return { start: dims.marginLeft, size: dims.contentWidth };\n }\n }\n\n private verticalAnchorReference(\n relativeFrom: string,\n dims: PageDimensions,\n pageNumber: number,\n context: {\n staticTop: number;\n lineHeight: number;\n paragraphTop: number;\n paragraphHeight: number;\n },\n ): { start: number; size: number } {\n const topMargin = { start: 0, size: dims.marginTop };\n const bottomMargin = {\n start: dims.marginTop + dims.contentHeight,\n size: dims.marginBottom,\n };\n switch (relativeFrom) {\n case 'page':\n return { start: 0, size: dims.pageHeight };\n case 'paragraph':\n return { start: context.paragraphTop, size: context.paragraphHeight };\n case 'line':\n return { start: context.staticTop, size: context.lineHeight };\n case 'topMargin':\n return topMargin;\n case 'bottomMargin':\n return bottomMargin;\n case 'insideMargin':\n return pageNumber % 2 === 1 ? topMargin : bottomMargin;\n case 'outsideMargin':\n return pageNumber % 2 === 1 ? bottomMargin : topMargin;\n case 'margin':\n default:\n return { start: dims.marginTop, size: dims.contentHeight };\n }\n }\n\n private resolveAnchorAxis(\n reference: { start: number; size: number },\n objectSize: number,\n alignment: string | null,\n offset: number | undefined,\n pageNumber: number,\n ): number {\n if (offset !== undefined) return reference.start + offset;\n\n let fraction = 0;\n if (alignment === 'center') fraction = 0.5;\n else if (alignment === 'right' || alignment === 'bottom') fraction = 1;\n else if (alignment === 'inside') fraction = pageNumber % 2 === 1 ? 0 : 1;\n else if (alignment === 'outside') fraction = pageNumber % 2 === 1 ? 1 : 0;\n return reference.start + (reference.size - objectSize) * fraction;\n }\n\n /** Charge a physical page before any page-owned partitioning or DOM allocation. */\n private admitPageAllocation(): void {\n const prospectivePageCount = this.createdPageCount + 1;\n this.pageCountCheckpoint?.(prospectivePageCount);\n this.createdPageCount = prospectivePageCount;\n }\n\n /**\n * Creates a page container element.\n */\n private createPage(\n dims: PageDimensions,\n pageNumber: number,\n sectionIndex: number,\n displayedPageNumber: number,\n content: HTMLElement[],\n pageInSection: number,\n footnoteIds: string[] = [],\n footnoteHeight: number = 0,\n continuation?: FootnoteContinuation | null,\n partialFootnotes?: PartialFootnote[],\n isSectionFiller = false,\n pageAlreadyAdmitted = false,\n ): PageInfo {\n if (!pageAlreadyAdmitted) this.admitPageAllocation();\n // Create page box at full size, then scale the entire box\n // This ensures proper clipping and consistent scaling of all elements\n const pageBox = this.document.createElement(\"div\");\n pageBox.className = `${this.cssPrefix}box`;\n pageBox.style.width = `${dims.pageWidth}pt`;\n pageBox.style.height = `${dims.pageHeight}pt`;\n pageBox.style.overflow = \"hidden\";\n pageBox.style.position = \"relative\";\n // Use CSS zoom for better text rendering when supported, fall back to transform\n // Zoom affects layout (no negative margin hack needed) and renders text more crisply\n // Note: zoom is non-standard but supported in all major browsers\n if (this.scale !== 1) {\n if (this.view.CSS?.supports(\"zoom\", \"1\")) {\n pageBox.style.zoom = String(this.scale);\n } else {\n pageBox.style.transform = `scale(${this.scale})`;\n pageBox.style.transformOrigin = \"top left\";\n // Transform does not affect layout, so compensate for the natural box dimensions.\n const heightReductionPt = dims.pageHeight * (1 - this.scale);\n const widthReductionPt = dims.pageWidth * (1 - this.scale);\n const heightReductionPx = ptToPx(heightReductionPt);\n const widthReductionPx = ptToPx(widthReductionPt);\n pageBox.style.marginRight = `-${widthReductionPx}px`;\n pageBox.style.marginBottom = `${this.pageGap - heightReductionPx}px`;\n }\n }\n // Hint browser for GPU compositing and layout isolation\n pageBox.style.willChange = \"transform\";\n pageBox.style.contain = \"layout paint\";\n pageBox.dataset.pageNumber = String(pageNumber);\n pageBox.dataset.sectionIndex = String(sectionIndex);\n pageBox.dataset.displayedPageNumber = String(displayedPageNumber);\n if (isSectionFiller) pageBox.dataset.sectionFiller = \"true\";\n // Needed by substitutePageNumberFields: a section that restarts numbering counts from its own\n // first page, not from the document's.\n pageBox.dataset.pageInSection = String(pageInSection);\n\n // Where the three bands sit on this page (no re-measurement needed)\n const bands = this.getPageBands(dims, sectionIndex, pageInSection, displayedPageNumber);\n\n // Add header if available for this section/page\n const headerSource = isSectionFiller\n ? undefined\n : this.selectHeader(sectionIndex, pageInSection, displayedPageNumber);\n\n if (headerSource) {\n const headerDiv = this.document.createElement(\"div\");\n headerDiv.className = `${this.cssPrefix}header`;\n // Which story this page shows, so an editor can map the page back to the OOXML part it\n // edits in place (a first-page header is a different part from the default one).\n headerDiv.dataset.hfType = this.storyKindFor(\n \"header\", sectionIndex, pageInSection, displayedPageNumber,\n );\n headerDiv.style.position = \"absolute\";\n // `w:header` is the distance to the TOP of the story, and the story grows downward from\n // there; `flex-start` therefore pins the edge the OOXML actually declares, and content\n // taller than the measurement clips at the bottom rather than sliding up the page.\n headerDiv.style.top = `${bands.headerTop}pt`;\n headerDiv.style.bottom = \"auto\";\n headerDiv.style.left = `${dims.marginLeft}pt`;\n headerDiv.style.width = `${dims.contentWidth}pt`;\n headerDiv.style.height = `${bands.headerHeight}pt`;\n headerDiv.style.overflow = \"hidden\";\n headerDiv.style.boxSizing = \"border-box\";\n headerDiv.style.display = \"flex\";\n headerDiv.style.flexDirection = \"column\";\n headerDiv.style.justifyContent = \"flex-start\";\n // Clone the header content (skip the wrapper div's data attributes)\n for (const child of Array.from(headerSource.childNodes)) {\n const clonedheaderDiv = child.cloneNode(true) as HTMLElement;\n if (clonedheaderDiv.nodeType === 1) this.makeClonedStoryInert(clonedheaderDiv);\n headerDiv.appendChild(clonedheaderDiv);\n }\n pageBox.appendChild(headerDiv);\n }\n\n // Create content area using pre-computed effective heights\n const contentAreaTop = bands.bodyTop;\n const contentAreaHeight = bands.bodyHeight;\n\n const contentArea = this.document.createElement(\"div\");\n contentArea.className = `${this.cssPrefix}content`;\n contentArea.style.position = \"absolute\";\n contentArea.style.top = `${contentAreaTop}pt`;\n contentArea.style.left = `${dims.marginLeft}pt`;\n contentArea.style.width = `${dims.contentWidth}pt`;\n contentArea.style.height = `${contentAreaHeight}pt`;\n // Clip only vertically: Word lets over-wide content (e.g. a table pulled left by a negative\n // w:tblInd, issue #827) run into the side margins, clipping it only at the paper edge.\n // `clip` rather than `hidden`, because `hidden` would force the x axis to `auto`.\n contentArea.style.overflowX = \"visible\";\n contentArea.style.overflowY = \"clip\";\n\n // Add content\n for (const el of content) {\n contentArea.appendChild(el);\n }\n\n pageBox.appendChild(contentArea);\n\n // Add footnotes if any references appear on this page (or continuation from previous)\n const hasContinuation = continuation && continuation.remainingElements.length > 0;\n if (!isSectionFiller && (footnoteIds.length > 0 || hasContinuation)) {\n this.addPageFootnotes(pageBox, footnoteIds, dims, bands, footnoteHeight, continuation, partialFootnotes);\n\n }\n\n // Materialize margin comments after footnotes exist so markers inside a\n // note participate in the same page-owned comment story as body markers.\n const pageCommentIds: string[] = [];\n for (const marker of Array.from(\n pageBox.querySelectorAll<HTMLElement>(\"[data-comment-id]\"),\n )) {\n if (marker.closest(`.${this.cssPrefix}comment-margin`)) continue;\n const id = marker.dataset.commentId;\n if (id && this.commentMarginRegistry.has(id) && !pageCommentIds.includes(id)) {\n pageCommentIds.push(id);\n }\n }\n if (pageCommentIds.length > 0) {\n const marginColumn = this.document.createElement(\"aside\");\n marginColumn.className = `${this.cssPrefix}comment-margin`;\n marginColumn.style.position = \"absolute\";\n marginColumn.style.top = `${contentAreaTop}pt`;\n marginColumn.style.left = `${dims.marginLeft + dims.contentWidth + 3}pt`;\n marginColumn.style.width = `${Math.max(12, dims.marginRight - 6)}pt`;\n marginColumn.style.maxHeight = `${contentAreaHeight}pt`;\n marginColumn.style.overflow = \"hidden\";\n marginColumn.style.boxSizing = \"border-box\";\n const placedThreadRoots = new Set<string>();\n for (const id of pageCommentIds) {\n const source = this.commentMarginRegistry.get(id);\n if (source) {\n // Every id in a nested thread maps to the same root note; place it once even\n // when the root's and a reply's markers share the page.\n const rootId = source.dataset.commentId ?? id;\n if (placedThreadRoots.has(rootId)) continue;\n placedThreadRoots.add(rootId);\n const clone = source.cloneNode(true) as HTMLElement;\n this.makeClonedMarginCommentInert(clone);\n marginColumn.appendChild(clone);\n }\n }\n pageBox.appendChild(marginColumn);\n }\n\n // Add footer if available for this section/page\n const footerSource = isSectionFiller\n ? undefined\n : this.selectFooter(sectionIndex, pageInSection, displayedPageNumber);\n if (footerSource) {\n const footerDiv = this.document.createElement(\"div\");\n footerDiv.className = `${this.cssPrefix}footer`;\n footerDiv.dataset.hfType = this.storyKindFor(\n \"footer\", sectionIndex, pageInSection, displayedPageNumber,\n );\n footerDiv.style.position = \"absolute\";\n // `w:footer` is the distance to the BOTTOM of the story, and the story grows upward from\n // there \u2014 the mirror of the header, so `flex-end` and a bottom anchor.\n footerDiv.style.top = \"auto\";\n footerDiv.style.bottom = `${dims.footerDistance}pt`;\n footerDiv.style.left = `${dims.marginLeft}pt`;\n footerDiv.style.width = `${dims.contentWidth}pt`;\n footerDiv.style.height = `${bands.footerHeight}pt`;\n footerDiv.style.overflow = \"hidden\";\n footerDiv.style.boxSizing = \"border-box\";\n footerDiv.style.display = \"flex\";\n footerDiv.style.flexDirection = \"column\";\n footerDiv.style.justifyContent = \"flex-end\";\n // Clone the footer content (skip the wrapper div's data attributes)\n for (const child of Array.from(footerSource.childNodes)) {\n const clonedfooterDiv = child.cloneNode(true) as HTMLElement;\n if (clonedfooterDiv.nodeType === 1) this.makeClonedStoryInert(clonedfooterDiv);\n footerDiv.appendChild(clonedfooterDiv);\n }\n pageBox.appendChild(footerDiv);\n }\n\n // Add page number (will be hidden by CSS if document has footer)\n if (this.showPageNumbers && !isSectionFiller) {\n const pageNum = this.document.createElement(\"div\");\n pageNum.className = `${this.cssPrefix}number`;\n pageNum.textContent = String(pageNumber);\n pageBox.appendChild(pageNum);\n }\n\n // Add to container\n this.containerElement.appendChild(pageBox);\n\n // Floating objects need the final page and anchor-paragraph boxes. Resolve them only after\n // append, when getBoundingClientRect() is meaningful, and lift them out of content clipping.\n this.positionDrawingAnchors(pageBox, contentArea, dims, pageNumber);\n\n // Body and notes must occupy DISJOINT bands. The note block is absolutely positioned against\n // the page bottom and grows upward, while the content area spans the whole text height \u2014 so\n // nothing but the layout loop's arithmetic keeps them apart, and any disagreement between the\n // height the loop reserved and the height the notes actually render at draws body text and note\n // text on top of each other (observed on a 94-footnote document: ~134pt of superimposed,\n // illegible glyphs). Shrinking the content area to the space the notes actually left removes\n // the failure mode by construction \u2014 the worst case becomes a clean clip by the content area's\n // vertical overflow clip, which is obvious and recoverable rather than silent corruption.\n //\n // This runs AFTER the append on purpose: `getBoundingClientRect()` on a detached node is all\n // zeroes, so measuring while building the page silently did nothing.\n const notesEl = pageBox.querySelector<HTMLElement>(`.${this.cssPrefix}footnotes`);\n if (notesEl) {\n const notesHeightPt = pxToPt(notesEl.getBoundingClientRect().height);\n if (notesHeightPt > 0) {\n contentArea.style.height = `${Math.max(0, contentAreaHeight - notesHeightPt)}pt`;\n }\n }\n\n // Paint offsets must follow range fragmentation: positioned runs are deliberately excluded\n // from that structural algorithm, even though these offsets leave every line box unchanged.\n alignExactLineBaselines(contentArea);\n const paper = pageBox.getBoundingClientRect();\n const header = pageBox.querySelector<HTMLElement>(`.${this.cssPrefix}header`);\n const footer = pageBox.querySelector<HTMLElement>(`.${this.cssPrefix}footer`);\n preserveExactLineInk(contentArea,\n Math.max(paper.top, header?.getBoundingClientRect().bottom ?? paper.top),\n Math.min(paper.bottom, footer?.getBoundingClientRect().top ?? paper.bottom,\n notesEl?.getBoundingClientRect().top ?? paper.bottom), paper);\n\n return {\n pageNumber,\n sectionIndex,\n dimensions: dims,\n element: pageBox,\n };\n }\n}\n\n/**\n * Convenience function to paginate HTML content.\n *\n * @param html - HTML string with pagination metadata\n * @param container - Container element or ID where pages will be rendered\n * @param options - Pagination options\n * @returns PaginationResult\n *\n * @example\n * ```typescript\n * const html = await convertDocxToHtml(docx, { paginationMode: PaginationMode.Paginated });\n *\n * // Create a container for the paginated view\n * const container = document.getElementById('viewer');\n *\n * // Parse and paginate\n * container.innerHTML = html;\n * const staging = document.getElementById('pagination-staging');\n * const pageContainer = document.getElementById('pagination-container');\n *\n * const engine = new PaginationEngine(staging, pageContainer, { scale: 0.8 });\n * const result = engine.paginate();\n *\n * console.log(`Document has ${result.totalPages} pages`);\n * ```\n */\nexport function paginateHtml(\n html: string,\n container: HTMLElement | string,\n options: PaginationOptions = {}\n): PaginationResult {\n const ownerDocument =\n typeof container === \"string\" ? globalThis.document : container.ownerDocument;\n const containerEl =\n typeof container === \"string\"\n ? (ownerDocument.getElementById(container) as HTMLElement)\n : container;\n\n if (!containerEl) {\n throw new Error(\"Container element not found\");\n }\n\n // Insert HTML into container\n containerEl.innerHTML = html;\n\n // Find staging and page container\n const cssPrefix = options.cssPrefix ?? \"page-\";\n const staging = containerEl.querySelector<HTMLElement>(\"#pagination-staging\") ||\n containerEl.querySelector<HTMLElement>(`.${cssPrefix}staging`);\n const pageContainer = containerEl.querySelector<HTMLElement>(\"#pagination-container\") ||\n containerEl.querySelector<HTMLElement>(`.${cssPrefix}container`);\n\n if (!staging) {\n throw new Error(\n \"Pagination staging element not found. Make sure the HTML was generated with PaginationMode.Paginated\"\n );\n }\n\n if (!pageContainer) {\n throw new Error(\"Pagination container element not found\");\n }\n\n // This convenience function is the read-only HTML viewer path. Keep the\n // lower-level engine conservative by default, while enabling paragraph\n // fragmentation here unless a caller deliberately opts out.\n const engine = new PaginationEngine(staging, pageContainer, {\n ...options,\n fragmentParagraphs: options.fragmentParagraphs ?? true,\n });\n return engine.paginate();\n}\n", "/**\n * The document viewport \u2014 what a word processor calls the page view's zoom.\n *\n * The editor's continuous view used to have no page geometry at all: it injected the\n * converter's body into whatever box the host gave it, so the text column was the DEVICE's\n * width. Three things follow from that, and all three are wrong:\n *\n * - Line breaking differs on every screen, and matches neither Word nor the editor's own\n * paginated view of the same document.\n * - A table authored at, say, 496pt cannot fit a 354pt phone column. A table box never\n * shrinks below its content's minimum, so it overflows the sheet and is clipped by the\n * window \u2014 the document visibly runs off the paper.\n * - Enlarging a run's font size makes that minimum grow, so the overflow gets worse exactly\n * when the user is editing.\n *\n * Word and LibreOffice hold the column at the section's authored width and ZOOM the page to\n * fit the window. This class does the same: it stamps each section wrapper with its own\n * `w:sectPr` geometry (content width + margins, so the section IS the sheet), then observes\n * the host and applies a fit-to-width zoom. Narrow screens get a smaller \u2014 never a reflowed \u2014\n * page, so what the user sees is what the document says.\n */\n\nimport {\n applyZoom,\n fitScale,\n parseSectionDimensions,\n ptToPx,\n pxToPt,\n sectionWrappers,\n} from \"./page-geometry.js\";\n\n/**\n * How the continuous view sizes its text column.\n *\n * - `\"section\"` (default): the section's own content width, as Word lays it out. Fidelity.\n * - `\"fluid\"`: the host's width, the pre-geometry behavior. For embeds that want the document\n * to reflow as ordinary web text and accept that line breaking will not match Word.\n */\nexport type ColumnWidth = \"section\" | \"fluid\";\n\nexport interface DocumentViewportOptions {\n /** Text-column sizing for the continuous view. Default `\"section\"`. */\n columnWidth?: ColumnWidth;\n /**\n * Scale the page down when it is wider than the host, the way a word processor's\n * fit-to-width zoom does. Default true. With it off, an oversized page simply overflows\n * (the host may scroll).\n */\n fitToWidth?: boolean;\n /** Author-pinned zoom, applied on top of fit-to-width (which never magnifies past it). Default 1. */\n scale?: number;\n}\n\nexport class DocumentViewport {\n private host: HTMLElement;\n private readonly options: Required<DocumentViewportOptions>;\n private root: HTMLElement | null = null;\n /** Natural page size in points \u2014 the widest section's PAGE box, which is what must fit. */\n private natural = { width: 0, height: 0 };\n private observer: ResizeObserver | null = null;\n\n constructor(host: HTMLElement, options: DocumentViewportOptions = {}) {\n this.host = host;\n this.options = {\n columnWidth: options.columnWidth ?? \"section\",\n fitToWidth: options.fitToWidth ?? true,\n scale: options.scale ?? 1,\n };\n }\n\n /** Retarget the mounted document to an equivalent host after its DOM is adopted. */\n adoptHost(host: HTMLElement): void {\n if (host === this.host) return;\n this.observer?.disconnect();\n this.observer = null;\n this.host.style.removeProperty(\"--docx-sheet-width\");\n this.host = host;\n this.refresh();\n if (this.root && typeof ResizeObserver !== \"undefined\") {\n this.observer = new ResizeObserver(() => this.refresh());\n this.observer.observe(this.host);\n }\n }\n\n /**\n * Adopt a freshly mounted document root (a continuous flow, or the paginated page stack).\n * Safe to call on every remount; the previous root is released first.\n *\n * `applySectionGeometry` is false for the paginated view, which already builds real page\n * boxes at the section's dimensions \u2014 there the viewport contributes only the fit zoom.\n */\n attach(root: HTMLElement, applySectionGeometry: boolean): void {\n this.release();\n this.root = root;\n this.natural = applySectionGeometry ? this.stampSections(root) : this.measurePages(root);\n this.refresh();\n if (typeof ResizeObserver !== \"undefined\") {\n this.observer = new ResizeObserver(() => this.refresh());\n this.observer.observe(this.host);\n }\n }\n\n /** Recompute the fit zoom against the host's current width. */\n refresh(): void {\n if (!this.root) return;\n const scale = this.scale;\n applyZoom(this.root, scale, this.natural);\n // Publish the page's on-screen width so chrome docked OUTSIDE the zoomed sheet \u2014 the\n // header/footer bands \u2014 can line up with it at whatever zoom is in force.\n this.host.style.setProperty(\n \"--docx-sheet-width\",\n this.natural.width > 0 ? `${ptToPx(this.natural.width) * scale}px` : \"100%\",\n );\n }\n\n /**\n * Change the author-pinned zoom and re-apply it. Fit-to-width still caps it: a page wider\n * than the host never magnifies past what fits, so \"100%\" on a phone is the fit zoom.\n */\n setScale(scale: number): void {\n this.options.scale = Math.max(0.1, Math.min(4, scale));\n this.refresh();\n }\n\n /** The author-pinned zoom (the value a zoom control shows), before fit-to-width caps it. */\n get requestedScale(): number {\n return this.options.scale;\n }\n\n /** The zoom currently applied (1 = 100%). Reported by the ribbon's anchor rail. */\n get scale(): number {\n if (!this.root) return this.options.scale;\n return this.options.fitToWidth\n ? fitScale(this.availableWidthPx(), this.natural.width, this.options.scale)\n : this.options.scale;\n }\n\n dispose(): void {\n this.release();\n this.root = null;\n }\n\n private release(): void {\n this.observer?.disconnect();\n this.observer = null;\n if (this.root) applyZoom(this.root, 1);\n this.host.style.removeProperty(\"--docx-sheet-width\");\n }\n\n /** The host's content box, which is the space a page has to fit into. */\n private availableWidthPx(): number {\n const style = typeof getComputedStyle === \"function\" ? getComputedStyle(this.host) : null;\n const padding = style\n ? (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0)\n : 0;\n return Math.max(0, this.host.clientWidth - padding);\n }\n\n /**\n * Give each section wrapper its `w:sectPr` geometry: the authored text column, guttered by\n * the authored margins. The wrapper then measures exactly one page wide, which is what the\n * sheet chrome paints and what the fit zoom scales.\n */\n private stampSections(root: HTMLElement): { width: number; height: number } {\n const sections = sectionWrappers(root);\n if (this.options.columnWidth === \"fluid\") {\n // The pre-geometry behavior: the host's width is the column. Nothing to fit.\n root.style.removeProperty(\"width\");\n for (const section of sections) {\n section.style.removeProperty(\"width\");\n section.style.removeProperty(\"padding-left\");\n section.style.removeProperty(\"padding-right\");\n }\n return { width: 0, height: 0 };\n }\n\n let widest = 0;\n for (const section of sections) {\n const dims = parseSectionDimensions(section);\n section.style.width = `${dims.contentWidth}pt`;\n section.style.paddingLeft = `${dims.marginLeft}pt`;\n section.style.paddingRight = `${dims.marginRight}pt`;\n section.style.boxSizing = \"content-box\";\n section.style.marginLeft = \"auto\";\n section.style.marginRight = \"auto\";\n widest = Math.max(widest, dims.pageWidth);\n }\n // The sheet is exactly as wide as the widest page it holds, so the chrome that paints it\n // paints a page rather than a full-bleed panel \u2014 and centering it is the host's business.\n if (widest > 0 && sections[0] !== root) root.style.width = `${widest}pt`;\n return { width: widest, height: 0 };\n }\n\n /**\n * The paginated view's page boxes are already page-sized \u2014 `pagination.ts` writes each\n * box's `width` in points \u2014 so the widest of those is the natural width. Reading the\n * inline width rather than the laid-out box keeps this independent of the per-box zoom\n * pagination may itself have applied.\n */\n private measurePages(root: HTMLElement): { width: number; height: number } {\n let widest = 0;\n for (const box of Array.from(root.children) as HTMLElement[]) {\n const declared = /^([\\d.]+)pt$/.exec(box.style.width || \"\");\n widest = Math.max(widest, declared ? parseFloat(declared[1]) : pxToPt(box.offsetWidth));\n }\n return { width: widest, height: 0 };\n }\n}\n", "/** Engine API: safe to import in plain Node ESM without loading the browser editor. */\nimport type {\n ConversionOptions,\n CompareOptions,\n RevisionListEntry,\n RevisionListFilter,\n CommentListEntry,\n RevisionRepairKind,\n RevisionRepairProposal,\n RevisionRepairRequest,\n RevisionCarrierIdentity,\n RevisionRepairOutcome,\n RevisionRepairResult,\n VersionInfo,\n ErrorResponse,\n CompareResult,\n PackageManifest,\n DeliverableVerificationResult,\n DeliverableVerificationRequest,\n DeliverableVerificationPolicyOptions,\n DeliverablePackageChangeExpectation,\n DeliverableCompanionArtifactInput,\n DeliverableRenderDiagnostic,\n DeliverableRenderDiagnosticKind,\n DeliveryReceiptVerificationResult,\n RedlineReversibilityProof,\n DocxodusWasmExports,\n FormatChangeDetails,\n // DocxDiff (IR diff engine)\n DocxDiffSettings,\n DocxDiffRevision,\n DocxDiffBatchCandidate,\n DocxDiffBatchResult,\n DocxDiffProduct,\n DocxDiffProducts,\n SemanticChange,\n SemanticChangeFamily,\n SemanticChangeOperation,\n SemanticChangeSet,\n SemanticValue,\n // DocxDiff consolidate (composite N-way)\n DocxDiffReviewer,\n DocxDiffConsolidateSettings,\n DocxDiffConflict,\n DocxDiffConflictCompetitor,\n DocxDiffConsolidatedRevision,\n Annotation,\n AddAnnotationRequest,\n AddAnnotationResponse,\n RemoveAnnotationResponse,\n AnnotationOptions,\n DocumentStructure,\n DocumentElement,\n TableColumnInfo,\n AnnotationTarget,\n AddAnnotationWithTargetRequest,\n DocumentMetadata,\n SectionMetadata,\n // OpenContracts export types\n OpenContractDocExport,\n PawlsPage,\n PawlsPageBoundary,\n PawlsToken,\n OpenContractsAnnotation,\n OpenContractsSinglePageAnnotation,\n BoundingBox,\n TokenId,\n TextSpan,\n OpenContractsRelationship,\n // External annotation types\n AnnotationLabel,\n ExternalAnnotationSet,\n ExternalAnnotationValidationResult,\n ExternalAnnotationValidationIssue,\n ExternalAnnotationProjectionSettings,\n // Comparison log types\n // Markdown projection types\n MarkdownProjectionSettings,\n MarkdownAnchorTarget,\n MarkdownProjection,\n MutationTransaction,\n MutationTransactionIdentity,\n ContentControlNestedPolicy,\n ContentControlOperationSupport,\n MutationPreviewRetention,\n DeliveryEvidenceStatus,\n DeliveryReceiptPrivacyProfile,\n DeliveryReceiptBuildOptions,\n DeliveryBundleArtifact,\n DeliveryBundleResult,\n // DocxSession mutation API\n DocxSessionSettings,\n} from \"./types.js\";\n\nimport { DocxSession, openDocxSession as openDocxSessionImpl } from \"./session.js\";\nimport { serializeVerificationRequest } from \"./verification-request.js\";\nimport { needsCompleteConversion } from \"./conversion-options.js\";\nimport {\n readExternalAnnotationSet,\n readExternalAnnotationValidation,\n readOpenContractExport,\n readProjectedHtml,\n} from \"./external-annotation-wire.js\";\nimport { DocxHistoryArchive, DocxHistoryClient, installHistoryStorageImports } from './history.js';\nimport type { HistoryStorage } from './history.js';\nexport * from './history.js';\nexport * from './history-checkpoints.js';\nexport * from './history-indexeddb.js';\nexport * from './history-controls.js';\n\n/** Open history over host-owned storage after initialize(). No network layer is installed. */\nexport function openDocxHistory(storage: HistoryStorage): DocxHistoryClient {\n const bridge = ensureInitialized().HistoryBridge;\n if (!bridge) throw new Error('This WASM build does not include history bindings.');\n return new DocxHistoryClient(bridge, storage);\n}\n\n/** Open a self-contained readonly .docxhistory file after initialize(); no storage adapter needed. */\nexport function openDocxHistoryArchive(bytes: Uint8Array): Promise<DocxHistoryArchive> {\n const bridge = ensureInitialized().HistoryBridge;\n if (!bridge) throw new Error('This WASM build does not include history bindings.');\n return DocxHistoryArchive.open(bridge, bytes);\n}\n\nexport { DocxSession } from \"./session.js\";\nexport type {\n AnchorInfo,\n AnchorRef,\n AnchorTargetRef,\n BlockMetadata,\n BookmarkInfo,\n BookmarkRangeSegment,\n CharSpan,\n CommentListEntry,\n NoteListEntry,\n ContentControlBindingInfo,\n ContentControlBindingPolicy,\n ContentControlFillOptions,\n ContentControlInfo,\n ContentControlPlacement,\n ContentControlType,\n DocumentAnnotation,\n DocumentRange,\n DocxSessionProjection,\n DocxSessionSettings,\n EditError,\n EditErrorCode,\n EditResult,\n FindOptions,\n EditorRenderOptions,\n FormatOp,\n HyperlinkInfo,\n HyperlinkKind,\n ImageBinaryFormat,\n ImageCapabilities,\n ImageDimensions,\n ImageFormatCapability,\n ImageHorizontalAlignment,\n ImageHorizontalReference,\n ImageInsertOptions,\n ImageMarkupCapability,\n ImageMarkupKind,\n ImageOccurrence,\n ImageOperationSupport,\n ImagePlacement,\n ImageVerticalAlignment,\n ImageVerticalReference,\n ImageWrapMode,\n ImageWrapPoint,\n ImageWrapPolygon,\n ImageWrapSide,\n FloatingImageLayout,\n LineSpacingRule,\n ListMembership,\n FormattingInspection,\n InlineSpan,\n ParagraphFormatting,\n RunFormattingInfo,\n StyleInfo,\n TableStyleFormatting,\n MarkdownPatch,\n MarkdownPatchBlock,\n NumberFormat,\n PageCitation,\n PageCitationFragment,\n PageCitationPage,\n PageCitationRequest,\n PageCitationUnavailableReason,\n PageMapRegistrationResult,\n PageMapStatus,\n PageNumberField,\n PageNumberingOp,\n PageSetupOp,\n ParagraphBorderEdge,\n ParagraphFormatOp,\n RevisionDiagnostic,\n RevisionFamily,\n RevisionResolutionStatus,\n SectionInfo,\n SessionRevisionType,\n TableOfAuthoritiesOptions,\n TableOfContentsOptions,\n TableOfFiguresOptions,\n TableBorderScope,\n TableBorderSpec,\n TableInsertOptions,\n TableMergeContent,\n TableShadingScope,\n PackageManifest,\n PackageManifestInspectionLimits,\n PackageManifestEntry,\n PackageManifestFacts,\n PackageRelationship,\n PackageContentTypeDeclaration,\n PackageRevisionCounts,\n PackageAnnotationCounts,\n DeliverableVerificationResult,\n DeliverableVerificationRequest,\n DeliverableVerificationPolicyOptions,\n DeliverablePackageChangeExpectation,\n DeliverableCompanionArtifactInput,\n DeliverableRenderDiagnostic,\n DeliverableRenderDiagnosticKind,\n DeliveryArtifactVerification,\n DeliveryArtifactVerificationStatus,\n DeliveryReceiptVerificationResult,\n DeliverableVerificationMode,\n DeliverableVerificationDecision,\n DeliverableFindingDisposition,\n DeliverableFindingCategory,\n DeliverableCheckStatus,\n DeliverablePackageChangeKind,\n DeliverableArtifactRole,\n DeliverableArtifactAvailability,\n DeliverableSemanticChangeFamily,\n DeliverablePackageIdentity,\n DeliverableCheckResult,\n DeliverableFinding,\n DeliverablePackageChange,\n DeliverableSemanticChange,\n DeliverableSemanticDelta,\n DeliverableArtifactMetadata,\n VerificationDigest,\n VerificationFinding,\n VerificationFindingSeverity,\n ChangeLocation,\n RedlineReversibilityProof,\n RedlineProofPathResult,\n RedlineProofPackageIdentity,\n RedlineProofFinding,\n RedlineProofDirection,\n RedlineRevisionClassification,\n RedlineRevisionDisposition,\n RedlineRevisionIdentity,\n RedlineRevisionFamily,\n RedlineRevisionResolutionStatus,\n RedlineRevisionDiagnostic,\n RedlineModeledSemanticComparison,\n RedlinePackageDivergence,\n RedlinePackageDivergenceKind,\n} from \"./types.js\";\nexport type { FillOptions, BulkEditResult } from \"./types.js\";\nexport { PlaceholderKinds, ContextBoundary } from \"./types.js\";\nexport { DiffFormat } from \"./types.js\";\nexport type { EditSummary, DiffEntry } from \"./types.js\";\n\n/**\n * Open a {@link DocxSession} for surgical mutation of a DOCX. Requires\n * {@link initialize} to have been called and awaited.\n *\n * The returned session keeps the document in WASM memory; call\n * {@link DocxSession.close} when done.\n */\nexport function openDocxSession(\n bytes: Uint8Array,\n settings?: DocxSessionSettings,\n): DocxSession {\n const wasm = ensureInitialized();\n return openDocxSessionImpl(bytes, wasm, settings);\n}\n\n/**\n * Mint a complete, blank single-paragraph DOCX (Normal style, US-Letter section) as bytes \u2014\n * a \"New document\" seed for editors that draft from scratch. Requires {@link initialize}.\n */\nexport function createBlankDocx(): Uint8Array {\n return ensureInitialized().DocxSessionBridge.CreateBlankDocx();\n}\n\nimport {\n CommentRenderMode,\n PaginationMode,\n AnnotationLabelMode,\n RevisionPresentation,\n RevisionType,\n DocxDiffRevisionGranularity,\n DocxDiffFormatComparison,\n ConflictResolution,\n ProjectionScopes,\n AnchorRenderMode,\n TableRenderMode,\n TrackedChangeMode,\n EmptyParagraphMode,\n AnchorIdRendering,\n ProjectionDepth,\n DocumentElementType,\n ComparisonLogLevel,\n ComparisonLogCodes,\n isInsertion,\n isDeletion,\n isMove,\n isFormatChange,\n findElementById,\n findElementsByType,\n getParagraphs,\n getTables,\n getTableColumns,\n targetElement,\n targetParagraph,\n targetParagraphRange,\n targetRun,\n targetTable,\n targetTableRow,\n targetTableCell,\n targetTableColumn,\n targetSearch,\n targetSearchInElement,\n} from \"./types.js\";\n\n// Re-export pagination types and engine\nexport type {\n PageDimensions,\n MeasuredBlock,\n PageInfo,\n PaginationResult,\n PaginationOptions,\n PageMap,\n PageMapPage,\n PageMapFragment,\n PageMapRect,\n PageMapMode,\n PageMapAvailability,\n PageMapStory,\n PageCitationNavigation,\n} from \"./pagination.js\";\n\nexport {\n PaginationEngine,\n clearPageCitationHighlight,\n createUnavailablePageMap,\n navigateToPageCitation,\n paginateHtml,\n} from \"./pagination.js\";\n\nexport type {\n CommentProfile,\n CompleteRenderReport,\n DocxodusExportErrorCode,\n ExportPhase,\n ExportResourceLimits,\n FailedRenderReport,\n FontConfigurationIdentity,\n FontResolution,\n FontResolver,\n PaginatedHtmlOptions,\n PaginatedHtmlResult,\n PaginatedRenderMetadata,\n ReadinessOutcome,\n RenderReport,\n RenderReportBase,\n RenderWarning,\n ResourceOutcome,\n ReviewProfile,\n UnsupportedContentOutcome,\n UnsupportedContentPolicy,\n} from \"./export-browser.js\";\n\n// Page geometry is the document's own page setup (w:sectPr), read off the section wrappers\n// the converter stamps in every render mode, plus the fit-to-width zoom a view applies to it.\nexport {\n DEFAULT_MARGIN,\n DEFAULT_PAGE_HEIGHT,\n DEFAULT_PAGE_WIDTH,\n fitScale,\n parseSectionDimensions,\n ptToPx,\n pxToPt,\n} from \"./page-geometry.js\";\n\nexport { DocumentViewport } from \"./viewport.js\";\nexport type { ColumnWidth, DocumentViewportOptions } from \"./viewport.js\";\n\nexport type {\n ConversionOptions,\n CompareOptions,\n RevisionListEntry,\n RevisionListFilter,\n RevisionRepairKind,\n RevisionRepairProposal,\n RevisionRepairRequest,\n RevisionCarrierIdentity,\n RevisionRepairOutcome,\n RevisionRepairResult,\n VersionInfo,\n ErrorResponse,\n CompareResult,\n FormatChangeDetails,\n Annotation,\n AddAnnotationRequest,\n AddAnnotationResponse,\n RemoveAnnotationResponse,\n AnnotationOptions,\n DocumentStructure,\n DocumentElement,\n TableColumnInfo,\n AnnotationTarget,\n AddAnnotationWithTargetRequest,\n // Document metadata (useful for info)\n DocumentMetadata,\n SectionMetadata,\n // OpenContracts export types\n OpenContractDocExport,\n PawlsPage,\n PawlsPageBoundary,\n PawlsToken,\n OpenContractsAnnotation,\n OpenContractsSinglePageAnnotation,\n BoundingBox,\n TokenId,\n TextSpan,\n OpenContractsRelationship,\n // External annotation types\n AnnotationLabel,\n ExternalAnnotationSet,\n ExternalAnnotationValidationResult,\n ExternalAnnotationValidationIssue,\n ExternalAnnotationProjectionSettings,\n // Comparison log types\n // Markdown projection types\n MarkdownProjectionSettings,\n MarkdownAnchorTarget,\n MarkdownProjection,\n // DocxDiff (IR diff engine)\n DocxDiffSettings,\n DocxDiffRevision,\n DocxDiffBatchCandidate,\n DocxDiffBatchResult,\n DocxDiffProduct,\n DocxDiffProducts,\n SemanticChange,\n SemanticChangeFamily,\n SemanticChangeOperation,\n SemanticChangeSet,\n SemanticValue,\n // DocxDiff consolidate (composite N-way)\n DocxDiffReviewer,\n DocxDiffConsolidateSettings,\n DocxDiffConflict,\n DocxDiffConflictCompetitor,\n DocxDiffConsolidatedRevision,\n};\n\nexport {\n CommentRenderMode,\n PaginationMode,\n AnnotationLabelMode,\n RevisionPresentation,\n RevisionType,\n DocxDiffRevisionGranularity,\n DocxDiffFormatComparison,\n ConflictResolution,\n ProjectionScopes,\n AnchorRenderMode,\n TableRenderMode,\n TrackedChangeMode,\n EmptyParagraphMode,\n AnchorIdRendering,\n ProjectionDepth,\n DocumentElementType,\n ComparisonLogLevel,\n ComparisonLogCodes,\n isInsertion,\n isDeletion,\n isMove,\n isFormatChange,\n // Document structure helpers\n findElementById,\n findElementsByType,\n getParagraphs,\n getTables,\n getTableColumns,\n // Annotation target factory functions\n targetElement,\n targetParagraph,\n targetParagraphRange,\n targetRun,\n targetTable,\n targetTableRow,\n targetTableCell,\n targetTableColumn,\n targetSearch,\n targetSearchInElement,\n};\n\nlet wasmExports: DocxodusWasmExports | null = null;\nlet initPromise: Promise<void> | null = null;\n\n/**\n * Yields to the browser's main thread, allowing pending UI updates to render.\n *\n * This is critical for WASM operations: since WASM runs synchronously on the\n * main thread, React state updates (like loading spinners) won't paint unless\n * we yield before the blocking work begins.\n *\n * Uses requestAnimationFrame which fires just before the next paint, ensuring\n * any queued state updates are committed to the DOM.\n *\n * @internal\n */\nasync function yieldToMain(): Promise<void> {\n // In non-browser environments (SSR, tests), skip yielding\n if (typeof requestAnimationFrame === \"undefined\") {\n return;\n }\n\n // Double-rAF ensures the browser has fully painted before we continue\n // First rAF: scheduled for next frame\n // Second rAF: ensures first frame actually painted\n await new Promise<void>((resolve) => {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => resolve());\n });\n });\n}\n\n/**\n * Derive the WASM base path from this module's URL.\n * Works whether loaded from node_modules, CDN, or bundled.\n */\nfunction getDefaultWasmBasePath(): string {\n try {\n // import.meta.url gives us the URL of this module\n // e.g., \"https://cdn.jsdelivr.net/npm/docxodus@12.6.5/dist/core.js\"\n // or \"file:///path/to/node_modules/docxodus/dist/core.js\"\n const moduleUrl = import.meta.url;\n\n // Remove the filename to get the directory\n const baseDir = moduleUrl.substring(0, moduleUrl.lastIndexOf('/') + 1);\n\n // WASM files are in ./wasm/ relative to dist/\n return baseDir + \"wasm/\";\n } catch {\n // Fallback if import.meta.url is not available\n return \"\";\n }\n}\n\n/**\n * Current base path for WASM files.\n * Empty string means auto-detect from module URL.\n */\nexport let wasmBasePath = \"\";\n\n/**\n * Set custom base path for WASM files.\n * Pass empty string or don't call this to auto-detect from module location.\n *\n * @param path - Custom path to WASM files, or empty string for auto-detection\n */\nexport function setWasmBasePath(path: string): void {\n wasmBasePath = path && !path.endsWith(\"/\") ? path + \"/\" : path;\n}\n\n/**\n * Initialize the Docxodus WASM runtime.\n * Must be called before using any conversion/comparison functions.\n * Safe to call multiple times - will only initialize once.\n *\n * By default, WASM files are auto-detected from the module's location\n * (works with CDN, npm, or local hosting).\n * Pass a basePath to load from a custom location instead.\n *\n * @param basePath - Optional custom path to WASM files. Leave empty for auto-detection.\n */\nexport async function initialize(basePath?: string): Promise<void> {\n if (wasmExports) return;\n\n if (initPromise) {\n return initPromise;\n }\n\n if (basePath !== undefined) {\n setWasmBasePath(basePath);\n }\n\n // Clear the cached promise on failure so a caller can retry with a\n // different base path (a rejected initialize() used to be permanent).\n initPromise = loadWasm().catch((e) => {\n initPromise = null;\n throw e;\n });\n return initPromise;\n}\n\n/**\n * Try to load WASM from a specific base path\n */\nasync function tryLoadFromPath(basePath: string): Promise<boolean> {\n try {\n const dotnetPath = basePath + \"_framework/dotnet.js\";\n const { dotnet } = await import(/* webpackIgnore: true */ /* @vite-ignore */ dotnetPath);\n\n const { getAssemblyExports, getConfig, setModuleImports } = await dotnet\n .withDiagnosticTracing(false)\n .create();\n\n installHistoryStorageImports(setModuleImports);\n const config = getConfig();\n const exports = await getAssemblyExports(config.mainAssemblyName);\n\n wasmExports = {\n DocumentConverter: exports.DocxodusWasm.DocumentConverter,\n DocumentComparer: exports.DocxodusWasm.DocumentComparer,\n DocxDiffBridge: exports.DocxodusWasm.DocxDiffBridge,\n DocxSessionBridge: exports.DocxodusWasm.DocxSessionBridge,\n HistoryBridge: exports.DocxodusWasm.HistoryBridge,\n };\n return true;\n } catch {\n return false;\n }\n}\n\nasync function loadWasm(): Promise<void> {\n // If a custom path is set, use it directly\n if (wasmBasePath) {\n const success = await tryLoadFromPath(wasmBasePath);\n if (success) return;\n throw new Error(\n `Failed to load WASM from custom path: ${wasmBasePath}. ` +\n `Ensure the WASM files are served at this location.`\n );\n }\n\n // Try to auto-detect from module URL (works for CDN and local imports)\n const autoDetectedPath = getDefaultWasmBasePath();\n if (autoDetectedPath) {\n const success = await tryLoadFromPath(autoDetectedPath);\n if (success) {\n wasmBasePath = autoDetectedPath;\n return;\n }\n }\n\n // Auto-detection failed\n throw new Error(\n `Failed to load WASM files. ` +\n `Auto-detected path: ${autoDetectedPath || \"(none)\"}. ` +\n `You can specify a custom path by calling initialize(\"/path/to/wasm/\").`\n );\n}\n\nfunction ensureInitialized(): DocxodusWasmExports {\n if (!wasmExports) {\n throw new Error(\n \"Docxodus not initialized. Call initialize() first and await it.\"\n );\n }\n return wasmExports;\n}\n\nfunction isErrorResponse(result: string): result is string {\n try {\n const parsed = JSON.parse(result);\n return typeof parsed === \"object\" && \"Error\" in parsed;\n } catch {\n return false;\n }\n}\n\nfunction parseError(result: string): ErrorResponse {\n const parsed = JSON.parse(result);\n return {\n error: parsed.Error || parsed.error,\n type: parsed.Type || parsed.type,\n };\n}\n\n/**\n * Convert a File or Uint8Array to Uint8Array\n */\nasync function toBytes(input: File | Uint8Array): Promise<Uint8Array> {\n if (input instanceof Uint8Array) {\n return input;\n }\n const buffer = await input.arrayBuffer();\n return new Uint8Array(buffer);\n}\n\n/**\n * Generate a deterministic, non-mutating verification manifest from DOCX bytes.\n * Invalid, malformed, and encrypted packages are represented by structured findings.\n */\nexport async function generatePackageManifest(\n document: File | Uint8Array,\n): Promise<PackageManifest> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n await yieldToMain();\n return JSON.parse(\n exports.DocumentConverter.GeneratePackageManifest(bytes),\n ) as PackageManifest;\n}\n\n/**\n * Run the default bounded deliverable-verification policy on exact DOCX bytes.\n * Invalid, malformed, encrypted, and safety-limited packages are returned as\n * structured report findings rather than editable-session errors. When supplied,\n * the exact baseline bytes are used to classify pre-existing, new, and resolved findings.\n */\nexport async function verifyDeliverable(\n document: File | Uint8Array,\n baseline?: File | Uint8Array,\n request?: DeliverableVerificationRequest,\n): Promise<DeliverableVerificationResult> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n const baselineBytes = baseline === undefined ? undefined : await toBytes(baseline);\n await yieldToMain();\n if (request !== undefined) {\n // The full request (issue #747): the same wire shape every transport parses.\n const requestJson = serializeVerificationRequest(request);\n const converter = exports.DocumentConverter;\n if (!converter.VerifyDeliverableWithRequest || !converter.VerifyDeliverableWithBaselineAndRequest) {\n throw new Error(\"This WASM bundle predates full verification requests; rebuild docxodus.\");\n }\n return JSON.parse(\n baselineBytes === undefined\n ? converter.VerifyDeliverableWithRequest(bytes, requestJson)\n : converter.VerifyDeliverableWithBaselineAndRequest(baselineBytes, bytes, requestJson),\n ) as DeliverableVerificationResult;\n }\n return JSON.parse(\n baselineBytes === undefined\n ? exports.DocumentConverter.VerifyDeliverable(bytes)\n : exports.DocumentConverter.VerifyDeliverableWithBaseline(\n baselineBytes,\n bytes,\n ),\n ) as DeliverableVerificationResult;\n}\n\n/**\n * Verify a portable JSON delivery change receipt against supplied artifact bytes.\n *\n * The receipt travels as its JSON envelope string; `artifacts` maps each artifact id\n * the receipt records to the exact bytes to independently re-hash against it. Omitted\n * artifacts report `\"missing\"`. Malformed input yields a structured invalid verdict\n * whose findings carry the reason \u2014 never a thrown error.\n */\nexport async function verifyDeliveryReceipt(\n receiptJson: string,\n artifacts?: Record<string, Uint8Array>,\n): Promise<DeliveryReceiptVerificationResult> {\n const exports = ensureInitialized();\n const artifactsJson =\n artifacts === undefined\n ? \"\"\n : JSON.stringify(\n Object.fromEntries(\n Object.entries(artifacts).map(([artifactId, bytes]) => [\n artifactId,\n bytesToBase64(bytes),\n ]),\n ),\n );\n await yieldToMain();\n return JSON.parse(\n exports.DocumentConverter.VerifyDeliveryReceipt(receiptJson, artifactsJson),\n ) as DeliveryReceiptVerificationResult;\n}\n\n/**\n * Prove that a redline's generated revisions accept to the intended final and reject to the\n * selected baseline without consuming pre-existing review state.\n *\n * Three packages are inspected and two rebuilt, so on a UI thread prefer the worker proxy's\n * `proveRedlineReversibility`. Malformed, encrypted, and safety-limited packages are reported as\n * structured proof findings rather than thrown errors. The rebuilt packages are not returned:\n * the proof carries their digests and the divergences between them and each expected document.\n *\n * @param baseline - The document the redline was generated against\n * @param intendedFinal - The document accepting the generated revisions must reproduce\n * @param redline - The generated redline under proof\n */\nexport async function proveRedlineReversibility(\n baseline: File | Uint8Array,\n intendedFinal: File | Uint8Array,\n redline: File | Uint8Array,\n): Promise<RedlineReversibilityProof> {\n const exports = ensureInitialized();\n const baselineBytes = await toBytes(baseline);\n const intendedFinalBytes = await toBytes(intendedFinal);\n const redlineBytes = await toBytes(redline);\n await yieldToMain();\n return JSON.parse(\n exports.DocumentConverter.ProveRedlineReversibility(\n baselineBytes,\n intendedFinalBytes,\n redlineBytes,\n ),\n ) as RedlineReversibilityProof;\n}\n\n/**\n * Convert a DOCX document to HTML.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @param options - Conversion options\n * @returns HTML string\n * @throws Error if conversion fails\n *\n * @example\n * ```typescript\n * // Basic conversion\n * const html = await convertDocxToHtml(docxFile);\n *\n * // With pagination (PDF.js-style page view)\n * const html = await convertDocxToHtml(docxFile, {\n * paginationMode: PaginationMode.Paginated,\n * paginationScale: 0.8\n * });\n *\n * // With annotations rendered\n * const html = await convertDocxToHtml(docxFile, {\n * renderAnnotations: true,\n * annotationLabelMode: AnnotationLabelMode.Above\n * });\n *\n * // With footnotes and endnotes\n * const html = await convertDocxToHtml(docxFile, {\n * renderFootnotesAndEndnotes: true\n * });\n *\n * // With headers and footers\n * const html = await convertDocxToHtml(docxFile, {\n * renderHeadersAndFooters: true\n * });\n *\n * // With tracked changes (redlines visible)\n * const html = await convertDocxToHtml(docxFile, {\n * renderTrackedChanges: true,\n * showDeletedContent: true,\n * renderMoveOperations: true\n * });\n * ```\n */\n/**\n * Render a single document block to faithful HTML, addressed by its anchor.\n *\n * The anchor is the `data-anchor` value stamped on a block during a full\n * conversion (a bare 32-hex Unid), or a full `kind:scope:unid` anchor \u2014 either\n * form works. Powers the editor's incremental per-block re-render: apply an edit\n * to a DocxSession, then re-render only the changed block instead of the whole\n * document. Returns the block's HTML element (no `<html>`/`<head>` wrapper).\n */\nexport async function renderBlockHtml(\n document: File | Uint8Array,\n anchorId: string,\n options?: { cssPrefix?: string; fabricateClasses?: boolean }\n): Promise<string> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n await yieldToMain();\n\n const result = exports.DocumentConverter.RenderBlockHtml(\n bytes,\n anchorId,\n options?.cssPrefix ?? \"docx-\",\n options?.fabricateClasses ?? false\n );\n\n if (isErrorResponse(result)) {\n throw new Error(`Block rendering failed: ${parseError(result).error}`);\n }\n return result;\n}\n\nexport async function convertDocxToHtml(\n document: File | Uint8Array,\n options?: ConversionOptions\n): Promise<string> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n // Yield to browser before heavy WASM work - allows loading states to render\n await yieldToMain();\n\n let result: string;\n\n // Use complete method when any complete-only option is specified (most comprehensive)\n if (needsCompleteConversion(options)) {\n result = exports.DocumentConverter.ConvertDocxToHtmlComplete(\n bytes,\n options?.pageTitle ?? \"Document\",\n options?.cssPrefix ?? \"docx-\",\n options?.fabricateClasses ?? true,\n options?.additionalCss ?? \"\",\n options?.commentRenderMode ?? CommentRenderMode.Disabled,\n options?.commentCssClassPrefix ?? \"comment-\",\n options?.paginationMode ?? PaginationMode.None,\n options?.paginationScale ?? 1.0,\n options?.paginationCssClassPrefix ?? \"page-\",\n options?.renderAnnotations ?? false,\n options?.annotationLabelMode ?? AnnotationLabelMode.Above,\n options?.annotationCssClassPrefix ?? \"annot-\",\n options?.renderFootnotesAndEndnotes ?? false,\n options?.renderHeadersAndFooters ?? false,\n options?.renderTrackedChanges ?? false,\n options?.showDeletedContent ?? true,\n options?.renderMoveOperations ?? true,\n options?.renderUnsupportedContentPlaceholders ?? false,\n options?.documentLanguage ?? null,\n options?.stampAnchors ?? false,\n options?.revisionPresentation ?? RevisionPresentation.Docxodus,\n options?.semanticLists ?? false\n );\n }\n // Use pagination-aware method when pagination is requested\n else if (options?.paginationMode !== undefined && options.paginationMode !== PaginationMode.None) {\n result = exports.DocumentConverter.ConvertDocxToHtmlWithPagination(\n bytes,\n options.pageTitle ?? \"Document\",\n options.cssPrefix ?? \"docx-\",\n options.fabricateClasses ?? true,\n options.additionalCss ?? \"\",\n options.commentRenderMode ?? CommentRenderMode.Disabled,\n options.commentCssClassPrefix ?? \"comment-\",\n options.paginationMode,\n options.paginationScale ?? 1.0,\n options.paginationCssClassPrefix ?? \"page-\"\n );\n } else if (options) {\n result = exports.DocumentConverter.ConvertDocxToHtmlWithOptions(\n bytes,\n options.pageTitle ?? \"Document\",\n options.cssPrefix ?? \"docx-\",\n options.fabricateClasses ?? true,\n options.additionalCss ?? \"\",\n options.commentRenderMode ?? CommentRenderMode.Disabled,\n options.commentCssClassPrefix ?? \"comment-\"\n );\n } else {\n result = exports.DocumentConverter.ConvertDocxToHtml(bytes);\n }\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Conversion failed: ${error.error}`);\n }\n\n return result;\n}\n\n/**\n * Compare two DOCX documents and return the redlined result as a DOCX.\n *\n * @param original - Original DOCX document\n * @param modified - Modified DOCX document\n * @param options - Comparison options\n * @returns Redlined DOCX as Uint8Array\n * @throws Error if comparison fails\n */\nexport async function compareDocuments(\n original: File | Uint8Array,\n modified: File | Uint8Array,\n options?: CompareOptions\n): Promise<Uint8Array> {\n const exports = ensureInitialized();\n const originalBytes = await toBytes(original);\n const modifiedBytes = await toBytes(modified);\n\n // Yield to browser before heavy WASM work - allows loading states to render\n await yieldToMain();\n\n let result: Uint8Array;\n\n if (options?.caseInsensitive) {\n result = exports.DocumentComparer.CompareDocumentsWithOptions(\n originalBytes,\n modifiedBytes,\n options?.authorName ?? null,\n options.caseInsensitive\n );\n } else {\n result = exports.DocumentComparer.CompareDocuments(\n originalBytes,\n modifiedBytes,\n options?.authorName ?? null\n );\n }\n\n if (result.length === 0) {\n throw new Error(\"Comparison failed - empty result\");\n }\n\n return result;\n}\n\n/**\n * Compare two DOCX documents and return the result as HTML.\n *\n * @param original - Original DOCX document\n * @param modified - Modified DOCX document\n * @param options - Comparison options\n * @returns HTML string with redlined content\n * @throws Error if comparison fails\n */\nexport async function compareDocumentsToHtml(\n original: File | Uint8Array,\n modified: File | Uint8Array,\n options?: CompareOptions\n): Promise<string> {\n const exports = ensureInitialized();\n const originalBytes = await toBytes(original);\n const modifiedBytes = await toBytes(modified);\n\n // Yield to browser before heavy WASM work - allows loading states to render\n await yieldToMain();\n\n const renderTrackedChanges = options?.renderTrackedChanges ?? true;\n\n let result: string;\n\n if (options?.caseInsensitive !== undefined) {\n result = exports.DocumentComparer.CompareDocumentsToHtmlFull(\n originalBytes,\n modifiedBytes,\n options?.authorName ?? null,\n options.caseInsensitive,\n renderTrackedChanges\n );\n } else {\n result = exports.DocumentComparer.CompareDocumentsToHtmlWithOptions(\n originalBytes,\n modifiedBytes,\n options?.authorName ?? null,\n renderTrackedChanges\n );\n }\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Comparison failed: ${error.error}`);\n }\n\n return result;\n}\n\n\n\n\n/**\n * Read the tracked revisions already present in a document without opening a session.\n * Same entries as `session.listRevisions()`; moves come from the document's own\n * `w:moveFrom`/`w:moveTo` markup, so there are no detection options.\n *\n * @param document - A document carrying tracked changes\n * @returns Array of revisions\n * @throws Error if operation fails\n */\nexport async function getRevisions(\n document: File | Uint8Array\n): Promise<RevisionListEntry[]> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n // Yield to browser before WASM work - allows loading states to render\n await yieldToMain();\n\n const result = exports.DocumentComparer.GetRevisionsJson(bytes);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to get revisions: ${error.error}`);\n }\n\n // The payload is the session's own revision wire shape, so it needs no remapping.\n return JSON.parse(result) as RevisionListEntry[];\n}\n\n/**\n * Read a document's native Word comments without opening a session \u2014 the comment\n * twin of {@link getRevisions}. Same entries as `session.listComments()`, in\n * comments-part order; empty when the document has no comments part.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @throws Error if operation fails\n */\nexport async function getComments(\n document: File | Uint8Array\n): Promise<CommentListEntry[]> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n await yieldToMain();\n\n const result = exports.DocumentComparer.GetCommentsJson(bytes);\n if (isErrorResponse(result)) {\n throw new Error(`Failed to get comments: ${parseError(result).error}`);\n }\n return JSON.parse(result) as CommentListEntry[];\n}\n\n// \u2500\u2500\u2500 DocxDiff (IR diff engine) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// The structure-aware default comparison engine. Its specialized APIs add\n// anchor-addressed revisions and the diff-as-data edit script. Settings flow as\n// a JSON object; an empty `{}` (or omitted options) uses the engine defaults.\n\n/** Serialize DocxDiffSettings to the wire JSON the bridge parses (empty string when undefined). */\nfunction docxDiffSettingsJson(settings?: DocxDiffSettings): string {\n return settings ? JSON.stringify(settings) : \"\";\n}\n\n/**\n * Compare two DOCX documents with the IR diff engine and return the redlined\n * result as a DOCX (native w:ins/w:del/w:moveFrom/w:moveTo/w:rPrChange markup).\n *\n * @param left - The earlier/original document.\n * @param right - The later/revised document.\n * @param settings - Optional {@link DocxDiffSettings}; omit for engine defaults.\n * @returns Redlined DOCX as Uint8Array.\n * @throws Error if comparison fails.\n */\nexport async function docxDiffCompare(\n left: File | Uint8Array,\n right: File | Uint8Array,\n settings?: DocxDiffSettings\n): Promise<Uint8Array> {\n const exports = ensureInitialized();\n const leftBytes = await toBytes(left);\n const rightBytes = await toBytes(right);\n\n await yieldToMain();\n\n const result = exports.DocxDiffBridge.Compare(\n leftBytes,\n rightBytes,\n docxDiffSettingsJson(settings)\n );\n\n if (result.length === 0) {\n throw new Error(\"DocxDiff comparison failed - empty result\");\n }\n\n return result;\n}\n\n/**\n * Compare two DOCX documents with the IR diff engine and return the\n * anchor-addressed revision list.\n *\n * @param left - The earlier/original document.\n * @param right - The later/revised document.\n * @param settings - Optional {@link DocxDiffSettings}; omit for engine defaults.\n * @returns Array of {@link DocxDiffRevision} (each carrying its left/right block anchors).\n * @throws Error if the operation fails.\n */\nexport async function docxDiffGetRevisions(\n left: File | Uint8Array,\n right: File | Uint8Array,\n settings?: DocxDiffSettings\n): Promise<DocxDiffRevision[]> {\n const exports = ensureInitialized();\n const leftBytes = await toBytes(left);\n const rightBytes = await toBytes(right);\n\n await yieldToMain();\n\n const result = exports.DocxDiffBridge.GetRevisionsJson(\n leftBytes,\n rightBytes,\n docxDiffSettingsJson(settings)\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to get DocxDiff revisions: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n return (parsed.revisions || parsed.Revisions || []).map(mapDocxDiffRevision);\n}\n\n/**\n * Compare two DOCX documents ONCE and return every requested data product from\n * that single memoized pass (issue #594). Where a review pipeline calling\n * {@link docxDiffCompare}, {@link docxDiffGetRevisions}, and\n * {@link docxDiffGetEditScript} separately pays for the alignment per call, this\n * runs it once \u2014 each product identical to its standalone counterpart (the edit\n * script is handed over parsed rather than as the serialized string).\n *\n * @param left - The earlier/original document.\n * @param right - The later/revised document.\n * @param settings - Optional {@link DocxDiffSettings}; omit for engine defaults.\n * @param products - Products to compute; omit for all four.\n * @throws Error if the operation fails.\n */\nexport async function docxDiffCompareProducts(\n left: File | Uint8Array,\n right: File | Uint8Array,\n settings?: DocxDiffSettings,\n products?: DocxDiffProduct[]\n): Promise<DocxDiffProducts> {\n const exports = ensureInitialized();\n const leftBytes = await toBytes(left);\n const rightBytes = await toBytes(right);\n\n await yieldToMain();\n\n const result = exports.DocxDiffBridge.CompareProductsJson(\n leftBytes,\n rightBytes,\n docxDiffSettingsJson(settings),\n products ? JSON.stringify(products) : \"\"\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to compare products: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n return {\n redline: typeof parsed.redlineB64 === \"string\"\n ? Uint8Array.from(atob(parsed.redlineB64), c => c.charCodeAt(0))\n : undefined,\n revisions: Array.isArray(parsed.revisions)\n ? parsed.revisions.map(mapDocxDiffRevision)\n : undefined,\n editScript: parsed.editScript !== undefined\n ? (parsed.editScript as Record<string, unknown>)\n : undefined,\n semanticChanges: parsed.semanticChanges !== undefined\n ? (parsed.semanticChanges as SemanticChangeSet)\n : undefined,\n };\n}\n\n/**\n * Compare ONE baseline against MANY candidates, reading the baseline once (issue #617).\n *\n * The read is the single largest stage of a comparison, and a fan-out \u2014 one negotiated\n * draft against every counterparty's markup \u2014 otherwise re-reads the baseline for each\n * one. This reads it once and compares every candidate against that snapshot; each\n * result is identical to what {@link docxDiffCompareProducts} returns for the same pair.\n *\n * A candidate that fails carries an `error` instead of products; the rest of the batch\n * still comes back, because one malformed markup should not cost the other ninety-nine.\n *\n * @param baseline - The shared left-hand document.\n * @param candidates - The documents to compare against it, in order.\n * @param settings - Optional {@link DocxDiffSettings}; omit for engine defaults.\n * @param products - Products to compute; omit for all four.\n * @throws Error if the batch itself fails (a bad baseline, malformed settings).\n */\nexport async function docxDiffCompareBatch(\n baseline: File | Uint8Array,\n candidates: readonly DocxDiffBatchCandidate[],\n settings?: DocxDiffSettings,\n products?: DocxDiffProduct[]\n): Promise<DocxDiffBatchResult[]> {\n const exports = ensureInitialized();\n const baselineBytes = await toBytes(baseline);\n const payload = [];\n for (let i = 0; i < candidates.length; i++) {\n const bytes = await toBytes(candidates[i].document);\n payload.push({\n name: candidates[i].name ?? String(i),\n docB64: bytesToBase64(bytes),\n });\n }\n\n await yieldToMain();\n\n const result = exports.DocxDiffBridge.CompareBatchJson(\n baselineBytes,\n JSON.stringify(payload),\n docxDiffSettingsJson(settings),\n products ? JSON.stringify(products) : \"\"\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to compare batch: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n return (parsed.results ?? []).map((entry: Record<string, unknown>) => ({\n name: String(entry.name ?? \"\"),\n error: typeof entry.error === \"string\" ? entry.error : undefined,\n redline: typeof entry.redlineB64 === \"string\"\n ? Uint8Array.from(atob(entry.redlineB64), c => c.charCodeAt(0))\n : undefined,\n revisions: Array.isArray(entry.revisions)\n ? entry.revisions.map(mapDocxDiffRevision)\n : undefined,\n editScript: entry.editScript !== undefined\n ? (entry.editScript as Record<string, unknown>)\n : undefined,\n semanticChanges: entry.semanticChanges !== undefined\n ? (entry.semanticChanges as SemanticChangeSet)\n : undefined,\n }));\n}\n\n/**\n * Compare two DOCX documents with the IR diff engine and return the edit script\n * as a JSON string \u2014 the diff-as-data differentiator. The script is the\n * anchor-addressed list of block operations the markup and revision renderers\n * both consume: stable and machine-readable for storage, transport, and audit.\n *\n * @param left - The earlier/original document.\n * @param right - The later/revised document.\n * @param settings - Optional {@link DocxDiffSettings}; omit for engine defaults.\n * @returns The edit script serialized as indented JSON.\n * @throws Error if the operation fails.\n */\nexport async function docxDiffGetEditScript(\n left: File | Uint8Array,\n right: File | Uint8Array,\n settings?: DocxDiffSettings\n): Promise<string> {\n const exports = ensureInitialized();\n const leftBytes = await toBytes(left);\n const rightBytes = await toBytes(right);\n\n await yieldToMain();\n\n const result = exports.DocxDiffBridge.GetEditScriptJson(\n leftBytes,\n rightBytes,\n docxDiffSettingsJson(settings)\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to get DocxDiff edit script: ${error.error}`);\n }\n\n return result;\n}\n\n/**\n * Compare two DOCX documents and return the stable, versioned semantic-change\n * schema. This is the audit/verification surface; it classifies document meaning\n * beyond the renderer's internal edit script and preserves unknown package changes.\n */\nexport async function docxDiffGetSemanticChanges(\n left: File | Uint8Array,\n right: File | Uint8Array,\n settings?: DocxDiffSettings\n): Promise<SemanticChangeSet> {\n const exports = ensureInitialized();\n const leftBytes = await toBytes(left);\n const rightBytes = await toBytes(right);\n\n await yieldToMain();\n\n const result = exports.DocxDiffBridge.GetSemanticChangesJson(\n leftBytes,\n rightBytes,\n docxDiffSettingsJson(settings)\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to get semantic changes: ${error.error}`);\n }\n\n return JSON.parse(result) as SemanticChangeSet;\n}\n\n/**\n * Accept every tracked revision in a redlined DOCX and return the resulting bytes\n * (materializes the \"right\"/revised side). The byte-in, byte-out counterpart of\n * {@link docxDiffCompare}: `docxDiffAcceptRevisions(await docxDiffCompare(left, right))`\n * equals `right` at the per-block text level \u2014 so callers can verify the round-trip\n * contract of a redline, not just inspect its shape.\n *\n * @param redline - A DOCX carrying tracked-changes markup (e.g. {@link docxDiffCompare} output).\n * @returns The DOCX bytes with all revisions accepted.\n * @throws Error if the operation fails.\n */\nexport async function docxDiffAcceptRevisions(\n redline: File | Uint8Array\n): Promise<Uint8Array> {\n const exports = ensureInitialized();\n const bytes = await toBytes(redline);\n await yieldToMain();\n const result = exports.DocxDiffBridge.AcceptRevisions(bytes);\n if (result.length === 0) {\n throw new Error(\"DocxDiff accept-revisions failed - empty result\");\n }\n return result;\n}\n\n/**\n * Reject every tracked revision in a redlined DOCX and return the resulting bytes\n * (materializes the \"left\"/original side): `docxDiffRejectRevisions(await\n * docxDiffCompare(left, right))` equals `left` at the per-block text level.\n *\n * @param redline - A DOCX carrying tracked-changes markup (e.g. {@link docxDiffCompare} output).\n * @returns The DOCX bytes with all revisions rejected.\n * @throws Error if the operation fails.\n */\nexport async function docxDiffRejectRevisions(\n redline: File | Uint8Array\n): Promise<Uint8Array> {\n const exports = ensureInitialized();\n const bytes = await toBytes(redline);\n await yieldToMain();\n const result = exports.DocxDiffBridge.RejectRevisions(bytes);\n if (result.length === 0) {\n throw new Error(\"DocxDiff reject-revisions failed - empty result\");\n }\n return result;\n}\n\n// \u2500\u2500\u2500 DocxDiff consolidate (composite N-way) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Merge several reviewers' edits against one shared base DOCX. Each reviewer is\n// base64-encoded into the `[{author,docB64}]` wire shape the host base64-DECODES\n// (standard base64, not url-safe). Settings flow as the diff-settings JSON object\n// extended with an optional integer `conflictResolution`.\n\n/**\n * Encode a Uint8Array to a standard (non-url-safe) base64 string. Uses a chunked\n * binary string so large documents don't blow the call-stack limit of\n * `String.fromCharCode(...bytes)`, and works in both browser (`btoa`) and Node\n * (`Buffer`) hosts.\n */\nfunction bytesToBase64(bytes: Uint8Array): string {\n if (typeof btoa === \"function\") {\n let binary = \"\";\n const chunkSize = 0x8000; // 32 KB per chunk keeps the spread small\n for (let i = 0; i < bytes.length; i += chunkSize) {\n const chunk = bytes.subarray(i, i + chunkSize);\n binary += String.fromCharCode.apply(null, chunk as unknown as number[]);\n }\n return btoa(binary);\n }\n // Node fallback (e.g. unit tests outside a browser).\n return Buffer.from(bytes).toString(\"base64\");\n}\n\n/** Serialize reviewers to the `[{author,docB64}]` wire JSON the host expects. */\nasync function reviewersJson(reviewers: DocxDiffReviewer[]): Promise<string> {\n const arr = await Promise.all(\n reviewers.map(async (r) => ({\n author: r.author,\n docB64: bytesToBase64(await toBytes(r.document)),\n }))\n );\n return JSON.stringify(arr);\n}\n\n/**\n * Serialize DocxDiffConsolidateSettings to the wire JSON the bridge parses. Same\n * shape as {@link docxDiffSettingsJson} plus the integer `conflictResolution`\n * when present (empty string when undefined).\n */\nfunction docxDiffConsolidateSettingsJson(\n settings?: DocxDiffConsolidateSettings\n): string {\n return settings ? JSON.stringify(settings) : \"\";\n}\n\n/** Map a single revision wire object (camelCase or PascalCase) to {@link DocxDiffRevision}. */\nfunction mapDocxDiffRevision(r: any): DocxDiffRevision {\n return {\n revisionType: r.revisionType ?? r.RevisionType,\n text: r.text ?? r.Text,\n author: r.author ?? r.Author,\n date: r.date ?? r.Date,\n moveGroupId: r.moveGroupId ?? r.MoveGroupId ?? undefined,\n isMoveSource: r.isMoveSource ?? r.IsMoveSource ?? undefined,\n formatChange: (r.formatChange || r.FormatChange) ? {\n oldProperties: r.formatChange?.oldProperties ?? r.FormatChange?.OldProperties,\n newProperties: r.formatChange?.newProperties ?? r.FormatChange?.NewProperties,\n changedPropertyNames: r.formatChange?.changedPropertyNames ?? r.FormatChange?.ChangedPropertyNames,\n } : undefined,\n leftAnchor: r.leftAnchor ?? r.LeftAnchor ?? undefined,\n rightAnchor: r.rightAnchor ?? r.RightAnchor ?? undefined,\n };\n}\n\n/**\n * Consolidate several reviewers' edits against a shared base DOCX and return the\n * merged redlined result as a DOCX (native multi-author tracked-changes markup).\n *\n * Compares the accepted view of the base and of every reviewer, as Word's Compare\n * does: tracked changes the inputs already carry (body, headers, footers, notes)\n * are accepted first, so they never reach the redline under their original\n * authors. `preserveInputRevisions` still turns that pre-accept off.\n *\n * @param base - The shared base document all reviewers edited from.\n * @param reviewers - The reviewers' edited copies + author names.\n * @param settings - Optional {@link DocxDiffConsolidateSettings}; omit for defaults.\n * @returns Consolidated redlined DOCX as Uint8Array.\n * @throws Error if consolidation fails.\n */\nexport async function docxDiffConsolidate(\n base: File | Uint8Array,\n reviewers: DocxDiffReviewer[],\n settings?: DocxDiffConsolidateSettings\n): Promise<Uint8Array> {\n const exports = ensureInitialized();\n const baseBytes = await toBytes(base);\n const reviewersJsonStr = await reviewersJson(reviewers);\n\n await yieldToMain();\n\n const result = exports.DocxDiffBridge.Consolidate(\n baseBytes,\n reviewersJsonStr,\n docxDiffConsolidateSettingsJson(settings)\n );\n\n if (result.length === 0) {\n throw new Error(\"DocxDiff consolidation failed - empty result\");\n }\n\n return result;\n}\n\n/**\n * Consolidate several reviewers' edits against a shared base DOCX and return the\n * per-token conflict report \u2014 every base span two or more reviewers edited\n * incompatibly, with each reviewer's competing variant.\n *\n * @param base - The shared base document all reviewers edited from.\n * @param reviewers - The reviewers' edited copies + author names.\n * @param settings - Optional {@link DocxDiffConsolidateSettings}; omit for defaults. The base and every\n * reviewer are always compared on their accepted view (see {@link docxDiffConsolidate}).\n * @returns Array of {@link DocxDiffConflict}.\n * @throws Error if the operation fails.\n */\nexport async function docxDiffGetConflicts(\n base: File | Uint8Array,\n reviewers: DocxDiffReviewer[],\n settings?: DocxDiffConsolidateSettings\n): Promise<DocxDiffConflict[]> {\n const exports = ensureInitialized();\n const baseBytes = await toBytes(base);\n const reviewersJsonStr = await reviewersJson(reviewers);\n\n await yieldToMain();\n\n const result = exports.DocxDiffBridge.GetConflictsJson(\n baseBytes,\n reviewersJsonStr,\n docxDiffConsolidateSettingsJson(settings)\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to get DocxDiff conflicts: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n return (parsed.conflicts || parsed.Conflicts || []).map((c: any) => ({\n id: c.id ?? c.Id,\n baseAnchor: c.baseAnchor ?? c.BaseAnchor,\n tokenStart: c.tokenStart ?? c.TokenStart,\n tokenEnd: c.tokenEnd ?? c.TokenEnd,\n policy: c.policy ?? c.Policy,\n competitors: (c.competitors || c.Competitors || []).map((comp: any) => ({\n author: comp.author ?? comp.Author,\n resultText: comp.resultText ?? comp.ResultText,\n })),\n }));\n}\n\n/**\n * Consolidate several reviewers' edits against a shared base DOCX and return the\n * merged revision list \u2014 each revision carrying its author, block anchors, and\n * (when contested) the {@link DocxDiffConsolidatedRevision.conflictId} linking it\n * to a {@link DocxDiffConflict}.\n *\n * @param base - The shared base document all reviewers edited from.\n * @param reviewers - The reviewers' edited copies + author names.\n * @param settings - Optional {@link DocxDiffConsolidateSettings}; omit for defaults. The base and every\n * reviewer are always compared on their accepted view (see {@link docxDiffConsolidate}).\n * @returns Array of {@link DocxDiffConsolidatedRevision}.\n * @throws Error if the operation fails.\n */\nexport async function docxDiffGetConsolidatedRevisions(\n base: File | Uint8Array,\n reviewers: DocxDiffReviewer[],\n settings?: DocxDiffConsolidateSettings\n): Promise<DocxDiffConsolidatedRevision[]> {\n const exports = ensureInitialized();\n const baseBytes = await toBytes(base);\n const reviewersJsonStr = await reviewersJson(reviewers);\n\n await yieldToMain();\n\n const result = exports.DocxDiffBridge.GetConsolidatedRevisionsJson(\n baseBytes,\n reviewersJsonStr,\n docxDiffConsolidateSettingsJson(settings)\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to get DocxDiff consolidated revisions: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n return (parsed.revisions || parsed.Revisions || []).map((r: any) => ({\n ...mapDocxDiffRevision(r),\n conflictId: r.conflictId ?? r.ConflictId ?? undefined,\n }));\n}\n\n/**\n * Consolidate several reviewers' edits against a shared base DOCX and return the\n * merged edit script as a JSON string \u2014 the diff-as-data view of the\n * consolidation (the anchor-addressed list of composite block operations).\n *\n * @param base - The shared base document all reviewers edited from.\n * @param reviewers - The reviewers' edited copies + author names.\n * @param settings - Optional {@link DocxDiffConsolidateSettings}; omit for defaults. The base and every\n * reviewer are always compared on their accepted view (see {@link docxDiffConsolidate}).\n * @returns The consolidated edit script serialized as indented JSON.\n * @throws Error if the operation fails.\n */\nexport async function docxDiffGetConsolidatedEditScript(\n base: File | Uint8Array,\n reviewers: DocxDiffReviewer[],\n settings?: DocxDiffConsolidateSettings\n): Promise<string> {\n const exports = ensureInitialized();\n const baseBytes = await toBytes(base);\n const reviewersJsonStr = await reviewersJson(reviewers);\n\n await yieldToMain();\n\n const result = exports.DocxDiffBridge.GetConsolidatedEditScriptJson(\n baseBytes,\n reviewersJsonStr,\n docxDiffConsolidateSettingsJson(settings)\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to get DocxDiff consolidated edit script: ${error.error}`);\n }\n\n return result;\n}\n\n/**\n * Get version information about the library.\n */\nexport function getVersion(): VersionInfo {\n const exports = ensureInitialized();\n const result = exports.DocumentConverter.GetVersion();\n const parsed = JSON.parse(result);\n return {\n library: parsed.Library || parsed.library,\n dotnetVersion: parsed.DotnetVersion || parsed.dotnetVersion,\n platform: parsed.Platform || parsed.platform,\n };\n}\n\n/**\n * Check if the WASM runtime is initialized.\n */\nexport function isInitialized(): boolean {\n return wasmExports !== null;\n}\n\n/**\n * The raw WASM bridge exports (DocumentConverter, DocxSessionBridge, ...).\n *\n * For consumers that drive a bridge class directly \u2014 most notably\n * `DocxEditor.open(container, bytes, exports)`, which needs the exports object\n * rather than the wrapped functions in this module. Requires `initialize()` to\n * have completed; throws otherwise.\n */\nexport function getWasmExports(): DocxodusWasmExports {\n return ensureInitialized();\n}\n\n/**\n * Get all annotations from a document.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @returns Array of annotations\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * const annotations = await getAnnotations(docxFile);\n * for (const annot of annotations) {\n * console.log(`${annot.label}: \"${annot.annotatedText}\"`);\n * }\n * ```\n */\nexport async function getAnnotations(\n document: File | Uint8Array\n): Promise<Annotation[]> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n const result = exports.DocumentConverter.GetAnnotations(bytes);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to get annotations: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n return (parsed.Annotations || parsed.annotations || []).map((a: any) => ({\n id: a.Id || a.id,\n labelId: a.LabelId || a.labelId,\n label: a.Label || a.label,\n color: a.Color || a.color,\n author: a.Author || a.author,\n created: a.Created || a.created,\n bookmarkName: a.BookmarkName || a.bookmarkName,\n startPage: a.StartPage ?? a.startPage,\n endPage: a.EndPage ?? a.endPage,\n annotatedText: a.AnnotatedText || a.annotatedText,\n metadata: a.Metadata || a.metadata,\n }));\n}\n\n/**\n * Add an annotation to a document.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @param request - Annotation details including search text or paragraph indices\n * @returns Response with modified document bytes and annotation info\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * // Annotate by searching for text\n * const result = await addAnnotation(docxFile, {\n * id: \"annot-1\",\n * labelId: \"CLAUSE_A\",\n * label: \"Important Clause\",\n * color: \"#FFEB3B\",\n * searchText: \"shall not be liable\",\n * occurrence: 1\n * });\n *\n * // Annotate by paragraph range\n * const result = await addAnnotation(docxFile, {\n * id: \"annot-2\",\n * labelId: \"SECTION_1\",\n * label: \"Introduction\",\n * color: \"#4CAF50\",\n * startParagraphIndex: 0,\n * endParagraphIndex: 2\n * });\n *\n * // Get modified document\n * const modifiedDocBytes = base64ToBytes(result.documentBytes);\n * ```\n */\nexport async function addAnnotation(\n document: File | Uint8Array,\n request: AddAnnotationRequest\n): Promise<AddAnnotationResponse> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n // Yield to browser before WASM work - allows loading states to render\n await yieldToMain();\n\n const requestJson = JSON.stringify({\n Id: request.id,\n LabelId: request.labelId,\n Label: request.label,\n Color: request.color ?? \"#FFEB3B\",\n Author: request.author,\n SearchText: request.searchText,\n Occurrence: request.occurrence ?? 1,\n StartParagraphIndex: request.startParagraphIndex,\n EndParagraphIndex: request.endParagraphIndex,\n Metadata: request.metadata,\n });\n\n const result = exports.DocumentConverter.AddAnnotation(bytes, requestJson);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to add annotation: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n const annotation = parsed.Annotation || parsed.annotation;\n\n return {\n success: parsed.Success ?? parsed.success ?? true,\n documentBytes: parsed.DocumentBytes || parsed.documentBytes,\n annotation: annotation ? {\n id: annotation.Id || annotation.id,\n labelId: annotation.LabelId || annotation.labelId,\n label: annotation.Label || annotation.label,\n color: annotation.Color || annotation.color,\n author: annotation.Author || annotation.author,\n created: annotation.Created || annotation.created,\n bookmarkName: annotation.BookmarkName || annotation.bookmarkName,\n annotatedText: annotation.AnnotatedText || annotation.annotatedText,\n } : undefined,\n };\n}\n\n/**\n * Remove an annotation from a document.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @param annotationId - The ID of the annotation to remove\n * @returns Response with modified document bytes\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * const result = await removeAnnotation(docxFile, \"annot-1\");\n * const modifiedDocBytes = base64ToBytes(result.documentBytes);\n * ```\n */\nexport async function removeAnnotation(\n document: File | Uint8Array,\n annotationId: string\n): Promise<RemoveAnnotationResponse> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n const result = exports.DocumentConverter.RemoveAnnotation(bytes, annotationId);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to remove annotation: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n return {\n success: parsed.Success ?? parsed.success ?? true,\n documentBytes: parsed.DocumentBytes || parsed.documentBytes,\n };\n}\n\n/**\n * Check if a document has any annotations.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @returns true if the document has annotations\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * if (await hasAnnotations(docxFile)) {\n * const annotations = await getAnnotations(docxFile);\n * console.log(`Document has ${annotations.length} annotations`);\n * }\n * ```\n */\nexport async function hasAnnotations(\n document: File | Uint8Array\n): Promise<boolean> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n const result = exports.DocumentConverter.HasAnnotations(bytes);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to check annotations: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n return parsed.HasAnnotations ?? parsed.hasAnnotations ?? false;\n}\n\n/**\n * Get the document structure for element-based annotation targeting.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @returns Document structure with element tree\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * const structure = await getDocumentStructure(docxFile);\n *\n * // Navigate the structure tree\n * console.log(`Document has ${structure.root.children.length} top-level elements`);\n *\n * // Find all paragraphs\n * const paragraphs = getParagraphs(structure);\n * console.log(`Found ${paragraphs.length} paragraphs`);\n *\n * // Find all tables\n * const tables = getTables(structure);\n * for (const table of tables) {\n * const columns = getTableColumns(structure, table.id);\n * console.log(`Table ${table.id} has ${columns.length} columns`);\n * }\n *\n * // Look up element by ID\n * const element = findElementById(structure, \"doc/p-0\");\n * if (element) {\n * console.log(`First paragraph: \"${element.textPreview}\"`);\n * }\n * ```\n */\nexport async function getDocumentStructure(\n document: File | Uint8Array\n): Promise<DocumentStructure> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n // Yield to browser before WASM work - allows loading states to render\n await yieldToMain();\n\n const result = exports.DocumentConverter.GetDocumentStructure(bytes);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to get document structure: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n\n // Convert from PascalCase to camelCase\n const convertElement = (el: any): DocumentElement => ({\n id: el.Id || el.id,\n anchorId: el.AnchorId || el.anchorId,\n type: el.Type || el.type,\n textPreview: el.TextPreview || el.textPreview,\n index: el.Index ?? el.index,\n rowIndex: el.RowIndex ?? el.rowIndex,\n columnIndex: el.ColumnIndex ?? el.columnIndex,\n rowSpan: el.RowSpan ?? el.rowSpan,\n columnSpan: el.ColumnSpan ?? el.columnSpan,\n children: (el.Children || el.children || []).map(convertElement),\n });\n\n const convertTableColumn = (col: any): TableColumnInfo => ({\n tableId: col.TableId || col.tableId,\n anchorId: col.AnchorId || col.anchorId,\n tableAnchorId: col.TableAnchorId || col.tableAnchorId,\n isVirtual: col.IsVirtual ?? col.isVirtual ?? false,\n columnIndex: col.ColumnIndex ?? col.columnIndex,\n cellIds: col.CellIds || col.cellIds || [],\n cellAnchorIds: col.CellAnchorIds || col.cellAnchorIds || [],\n rowCount: col.RowCount ?? col.rowCount,\n });\n\n const root = convertElement(parsed.Root || parsed.root);\n\n // Convert elementsById dictionary\n const elementsById: Record<string, DocumentElement> = {};\n const rawElementsById = parsed.ElementsById || parsed.elementsById || {};\n for (const [key, el] of Object.entries(rawElementsById)) {\n elementsById[key] = convertElement(el);\n }\n\n // Convert tableColumns dictionary\n const tableColumns: Record<string, TableColumnInfo> = {};\n const rawTableColumns = parsed.TableColumns || parsed.tableColumns || {};\n for (const [key, col] of Object.entries(rawTableColumns)) {\n tableColumns[key] = convertTableColumn(col);\n }\n\n return {\n root,\n elementsById,\n tableColumns,\n };\n}\n\n/**\n * Get document metadata for lazy loading pagination.\n * This is a fast operation that extracts structure information without full HTML rendering.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @returns Document metadata including sections, dimensions, and content counts\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * const metadata = await getDocumentMetadata(docxFile);\n *\n * // Check document overview\n * console.log(`Document has ${metadata.totalParagraphs} paragraphs`);\n * console.log(`Document has ${metadata.sections.length} sections`);\n * console.log(`Estimated ${metadata.estimatedPageCount} pages`);\n *\n * // Check section properties\n * for (const section of metadata.sections) {\n * console.log(`Section ${section.sectionIndex}: ${section.pageWidthPt}x${section.pageHeightPt}pt`);\n * console.log(` Paragraphs: ${section.paragraphCount}, Tables: ${section.tableCount}`);\n * console.log(` Has header: ${section.hasHeader}, Has footer: ${section.hasFooter}`);\n * }\n *\n * // Check document features\n * if (metadata.hasTrackedChanges) {\n * console.log(\"Document has tracked changes\");\n * }\n * if (metadata.hasFootnotes) {\n * console.log(\"Document has footnotes\");\n * }\n * ```\n */\nexport async function getDocumentMetadata(\n document: File | Uint8Array\n): Promise<DocumentMetadata> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n // Yield to browser before WASM work - allows loading states to render\n await yieldToMain();\n\n const result = exports.DocumentConverter.GetDocumentMetadata(bytes);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to get document metadata: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n\n // Convert from PascalCase to camelCase\n const convertSection = (s: any): SectionMetadata => ({\n sectionIndex: s.SectionIndex ?? s.sectionIndex,\n pageWidthPt: s.PageWidthPt ?? s.pageWidthPt,\n pageHeightPt: s.PageHeightPt ?? s.pageHeightPt,\n marginTopPt: s.MarginTopPt ?? s.marginTopPt,\n marginRightPt: s.MarginRightPt ?? s.marginRightPt,\n marginBottomPt: s.MarginBottomPt ?? s.marginBottomPt,\n marginLeftPt: s.MarginLeftPt ?? s.marginLeftPt,\n contentWidthPt: s.ContentWidthPt ?? s.contentWidthPt,\n contentHeightPt: s.ContentHeightPt ?? s.contentHeightPt,\n headerPt: s.HeaderPt ?? s.headerPt,\n footerPt: s.FooterPt ?? s.footerPt,\n paragraphCount: s.ParagraphCount ?? s.paragraphCount,\n tableCount: s.TableCount ?? s.tableCount,\n hasHeader: s.HasHeader ?? s.hasHeader,\n hasFooter: s.HasFooter ?? s.hasFooter,\n hasFirstPageHeader: s.HasFirstPageHeader ?? s.hasFirstPageHeader,\n hasFirstPageFooter: s.HasFirstPageFooter ?? s.hasFirstPageFooter,\n hasEvenPageHeader: s.HasEvenPageHeader ?? s.hasEvenPageHeader,\n hasEvenPageFooter: s.HasEvenPageFooter ?? s.hasEvenPageFooter,\n startParagraphIndex: s.StartParagraphIndex ?? s.startParagraphIndex,\n endParagraphIndex: s.EndParagraphIndex ?? s.endParagraphIndex,\n startTableIndex: s.StartTableIndex ?? s.startTableIndex,\n endTableIndex: s.EndTableIndex ?? s.endTableIndex,\n });\n\n return {\n sections: (parsed.Sections || parsed.sections || []).map(convertSection),\n totalParagraphs: parsed.TotalParagraphs ?? parsed.totalParagraphs,\n totalTables: parsed.TotalTables ?? parsed.totalTables,\n hasFootnotes: parsed.HasFootnotes ?? parsed.hasFootnotes,\n hasEndnotes: parsed.HasEndnotes ?? parsed.hasEndnotes,\n hasTrackedChanges: parsed.HasTrackedChanges ?? parsed.hasTrackedChanges,\n hasComments: parsed.HasComments ?? parsed.hasComments,\n estimatedPageCount: parsed.EstimatedPageCount ?? parsed.estimatedPageCount,\n estimatedPageCountSource: parsed.EstimatedPageCountSource ?? parsed.estimatedPageCountSource ?? \"heuristic\",\n };\n}\n\n/**\n * Export document to OpenContracts format.\n *\n * This provides complete document text, structure, and layout information\n * compatible with the OpenContracts ecosystem for document analysis.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @returns OpenContractDocExport with complete document data\n * @throws Error if export fails\n *\n * @example\n * ```typescript\n * const result = await exportToOpenContract(docxFile);\n *\n * // Access complete document text\n * console.log(`Content length: ${result.content.length} characters`);\n *\n * // Get document structure\n * console.log(`Pages: ${result.pageCount}`);\n * console.log(`Structural annotations: ${result.labelledText.filter(a => a.structural).length}`);\n *\n * // Access PAWLS layout data\n * for (const page of result.pawlsFileContent) {\n * console.log(`Page ${page.page.index}: ${page.tokens.length} tokens`);\n * }\n * ```\n */\nexport async function exportToOpenContract(\n document: File | Uint8Array\n): Promise<OpenContractDocExport> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n // Yield to browser before WASM work - allows loading states to render\n await yieldToMain();\n\n const result = exports.DocumentConverter.ExportToOpenContract(bytes);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to export to OpenContract format: ${error.error}`);\n }\n\n return readOpenContractExport(JSON.parse(result));\n}\n\n/**\n * Convert a DOCX file to an anchor-addressed Markdown projection.\n *\n * The projection is a deterministic, anchor-keyed Markdown rendering of the document,\n * suitable for LLM editing pipelines, structured search indexers, and diff/review UIs.\n * Every paragraph, heading, list item, table, table cell, footnote, endnote, and\n * comment is addressable by an `{#kind:scope:unid}` anchor that survives reformatting.\n *\n * See `docs/architecture/markdown_projection.md` for the projection spec.\n *\n * @param document - DOCX file as `File` or `Uint8Array`\n * @param settings - Optional projection settings (defaults: all scopes, anchor blocks, accept tracked changes)\n * @throws Error if conversion fails\n *\n * @example\n * ```typescript\n * const result = await convertWmlToMarkdown(docxFile);\n * console.log(result.markdown);\n * for (const [id, target] of Object.entries(result.anchorIndex)) {\n * console.log(id, target.partUri);\n * }\n * ```\n */\nexport async function convertWmlToMarkdown(\n document: File | Uint8Array,\n settings: MarkdownProjectionSettings = {}\n): Promise<MarkdownProjection> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n await yieldToMain();\n\n const settingsJson = JSON.stringify({\n Scopes: settings.scopes ?? ProjectionScopes.All,\n HeadingLevelOffset: settings.headingLevelOffset ?? 0,\n AnchorMode: settings.anchorMode ?? AnchorRenderMode.Block,\n TableMode: settings.tableMode ?? TableRenderMode.GfmWithOpaqueFallback,\n TableInlineCellMax: settings.tableInlineCellMax ?? 80,\n TrackedChanges: settings.trackedChanges ?? TrackedChangeMode.Accept,\n ResolveNumbering: settings.resolveNumbering ?? true,\n EmptyParagraphs: settings.emptyParagraphs ?? EmptyParagraphMode.AnchorOnly,\n });\n\n const result = exports.DocumentConverter.ConvertWmlToMarkdown(bytes, settingsJson);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to convert document to markdown: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n const rawIndex = parsed.AnchorIndex ?? parsed.anchorIndex ?? {};\n const anchorIndex: Record<string, MarkdownAnchorTarget> = {};\n for (const [key, value] of Object.entries(rawIndex)) {\n const v = value as any;\n anchorIndex[key] = {\n id: v.Id ?? v.id,\n kind: v.Kind ?? v.kind,\n scope: v.Scope ?? v.scope,\n unid: v.Unid ?? v.unid,\n partUri: v.PartUri ?? v.partUri,\n textPreview: v.TextPreview ?? v.textPreview ?? \"\",\n };\n }\n return {\n markdown: parsed.Markdown ?? parsed.markdown ?? \"\",\n anchorIndex,\n };\n}\n\n/**\n * Add an annotation using flexible targeting (element ID, indices, or text search).\n *\n * @param document - DOCX file as File object or Uint8Array\n * @param request - Annotation details with target specification\n * @returns Response with modified document bytes and annotation info\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * // First get the document structure to find target elements\n * const structure = await getDocumentStructure(docxFile);\n *\n * // Annotate a specific paragraph by element ID\n * const result1 = await addAnnotationWithTarget(docxFile, {\n * id: \"annot-1\",\n * labelId: \"INTRO\",\n * label: \"Introduction\",\n * color: \"#4CAF50\",\n * target: targetElement(\"doc/p-0\")\n * });\n *\n * // Annotate a table cell\n * const result2 = await addAnnotationWithTarget(docxFile, {\n * id: \"annot-2\",\n * labelId: \"CELL_HIGHLIGHT\",\n * label: \"Important Cell\",\n * color: \"#FFEB3B\",\n * target: targetTableCell(0, 1, 2) // Table 0, Row 1, Cell 2\n * });\n *\n * // Annotate a table column\n * const result3 = await addAnnotationWithTarget(docxFile, {\n * id: \"annot-3\",\n * labelId: \"COLUMN_DATA\",\n * label: \"Values Column\",\n * color: \"#2196F3\",\n * target: targetTableColumn(0, 1) // Table 0, Column 1\n * });\n *\n * // Search for text within a specific element\n * const result4 = await addAnnotationWithTarget(docxFile, {\n * id: \"annot-4\",\n * labelId: \"KEYWORD\",\n * label: \"Keyword\",\n * color: \"#FF5722\",\n * target: targetSearchInElement(\"doc/p-2\", \"important\", 1)\n * });\n * ```\n */\nexport async function addAnnotationWithTarget(\n document: File | Uint8Array,\n request: AddAnnotationWithTargetRequest\n): Promise<AddAnnotationResponse> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n // Yield to browser before WASM work - allows loading states to render\n await yieldToMain();\n\n const requestJson = JSON.stringify({\n Id: request.id,\n LabelId: request.labelId,\n Label: request.label,\n Color: request.color ?? \"#FFEB3B\",\n Author: request.author,\n Metadata: request.metadata,\n ElementId: request.target.elementId,\n ElementType: request.target.elementType,\n ParagraphIndex: request.target.paragraphIndex,\n RunIndex: request.target.runIndex,\n TableIndex: request.target.tableIndex,\n RowIndex: request.target.rowIndex,\n CellIndex: request.target.cellIndex,\n ColumnIndex: request.target.columnIndex,\n SearchText: request.target.searchText,\n Occurrence: request.target.occurrence ?? 1,\n RangeEndParagraphIndex: request.target.rangeEndParagraphIndex,\n });\n\n const result = exports.DocumentConverter.AddAnnotationWithTarget(bytes, requestJson);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to add annotation: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n const annotation = parsed.Annotation || parsed.annotation;\n\n return {\n success: parsed.Success ?? parsed.success ?? true,\n documentBytes: parsed.DocumentBytes || parsed.documentBytes,\n annotation: annotation ? {\n id: annotation.Id || annotation.id,\n labelId: annotation.LabelId || annotation.labelId,\n label: annotation.Label || annotation.label,\n color: annotation.Color || annotation.color,\n author: annotation.Author || annotation.author,\n created: annotation.Created || annotation.created,\n bookmarkName: annotation.BookmarkName || annotation.bookmarkName,\n annotatedText: annotation.AnnotatedText || annotation.annotatedText,\n metadata: annotation.Metadata || annotation.metadata,\n } : undefined,\n };\n}\n\n// ============================================================================\n// External Annotation Functions (Issue #57)\n// ============================================================================\n\n/**\n * Compute the SHA256 hash of a document for integrity validation.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @returns SHA256 hash as lowercase hex string\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * const hash = await computeDocumentHash(docxFile);\n * console.log(`Document hash: ${hash}`);\n *\n * // Later, verify the document hasn't changed\n * const currentHash = await computeDocumentHash(docxFile);\n * if (currentHash !== storedHash) {\n * console.log(\"Document has been modified\");\n * }\n * ```\n */\nexport async function computeDocumentHash(\n document: File | Uint8Array\n): Promise<string> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n const result = exports.DocumentConverter.ComputeDocumentHash(bytes);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to compute document hash: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n return parsed.Hash ?? parsed.hash;\n}\n\n/**\n * Create an ExternalAnnotationSet from a document.\n * This extracts the document structure and computes the hash for integrity validation.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @param documentId - Unique identifier for the document (filename, UUID, etc.)\n * @returns ExternalAnnotationSet ready for adding annotations\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * // Create an annotation set\n * const set = await createExternalAnnotationSet(docxFile, \"contract-v1.0\");\n *\n * // Access document text for searching\n * console.log(`Document length: ${set.content.length} chars`);\n *\n * // Add label definitions\n * set.textLabels[\"IMPORTANT\"] = {\n * id: \"IMPORTANT\",\n * text: \"Important\",\n * color: \"#FF0000\",\n * description: \"Important text\",\n * icon: \"\",\n * labelType: \"text\"\n * };\n *\n * // Create annotations using the content\n * const annotation = createAnnotationFromSearch(\n * \"ann-001\", \"IMPORTANT\", set.content, \"shall not be liable\"\n * );\n * if (annotation) {\n * set.labelledText.push(annotation);\n * }\n *\n * // Serialize for storage\n * const json = JSON.stringify(set);\n * ```\n */\nexport async function createExternalAnnotationSet(\n document: File | Uint8Array,\n documentId: string\n): Promise<ExternalAnnotationSet> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n // Yield to browser before WASM work - allows loading states to render\n await yieldToMain();\n\n const result = exports.DocumentConverter.CreateExternalAnnotationSet(bytes, documentId);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to create external annotation set: ${error.error}`);\n }\n\n return readExternalAnnotationSet(JSON.parse(result));\n}\n\n/**\n * Validate an external annotation set against a document.\n * Checks hash match and verifies each annotation's text still matches.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @param annotationSet - The annotation set to validate\n * @returns Validation result with any issues found\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * const result = await validateExternalAnnotations(docxFile, annotationSet);\n *\n * if (!result.isValid) {\n * if (result.hashMismatch) {\n * console.log(\"Document has been modified since annotations were created\");\n * }\n * for (const issue of result.issues) {\n * console.log(`${issue.issueType}: ${issue.description}`);\n * }\n * }\n * ```\n */\nexport async function validateExternalAnnotations(\n document: File | Uint8Array,\n annotationSet: ExternalAnnotationSet\n): Promise<ExternalAnnotationValidationResult> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n // Yield to browser before WASM work - allows loading states to render\n await yieldToMain();\n\n const annotationSetJson = JSON.stringify(annotationSet);\n const result = exports.DocumentConverter.ValidateExternalAnnotations(bytes, annotationSetJson);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to validate external annotations: ${error.error}`);\n }\n\n return readExternalAnnotationValidation(JSON.parse(result));\n}\n\n/**\n * Convert a DOCX document to HTML with external annotations projected.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @param annotationSet - The external annotation set to project\n * @param conversionOptions - HTML conversion options\n * @param projectionOptions - Annotation projection options\n * @returns HTML string with annotations projected\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * // Basic usage\n * const html = await convertDocxToHtmlWithExternalAnnotations(\n * docxFile,\n * annotationSet\n * );\n *\n * // With custom options\n * const html = await convertDocxToHtmlWithExternalAnnotations(\n * docxFile,\n * annotationSet,\n * { pageTitle: \"Annotated Document\" },\n * { labelMode: AnnotationLabelMode.Inline, cssClassPrefix: \"my-annot-\" }\n * );\n * ```\n */\nexport async function convertDocxToHtmlWithExternalAnnotations(\n document: File | Uint8Array,\n annotationSet: ExternalAnnotationSet,\n conversionOptions?: ConversionOptions,\n projectionOptions?: ExternalAnnotationProjectionSettings\n): Promise<string> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n // Yield to browser before WASM work - allows loading states to render\n await yieldToMain();\n\n const annotationSetJson = JSON.stringify(annotationSet);\n const result = exports.DocumentConverter.ConvertDocxToHtmlWithExternalAnnotations(\n bytes,\n annotationSetJson,\n conversionOptions?.pageTitle ?? \"Document\",\n conversionOptions?.cssPrefix ?? \"docx-\",\n conversionOptions?.fabricateClasses ?? true,\n conversionOptions?.additionalCss ?? \"\",\n projectionOptions?.cssClassPrefix ?? \"ext-annot-\",\n projectionOptions?.labelMode ?? AnnotationLabelMode.Above\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to convert with external annotations: ${error.error}`);\n }\n\n return readProjectedHtml(JSON.parse(result));\n}\n\n/**\n * Search for text in a document and return character offsets.\n * Useful for finding text locations to create annotations.\n *\n * @param document - DOCX file as File object or Uint8Array\n * @param searchText - Text to search for\n * @param maxResults - Maximum number of results (default: 100)\n * @returns Array of TextSpan objects with offsets\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * const occurrences = await searchTextOffsets(docxFile, \"liability\");\n * console.log(`Found ${occurrences.length} occurrences`);\n *\n * for (const span of occurrences) {\n * console.log(`\"${span.text}\" at offset ${span.start}-${span.end}`);\n * }\n * ```\n */\nexport async function searchTextOffsets(\n document: File | Uint8Array,\n searchText: string,\n maxResults: number = 100\n): Promise<TextSpan[]> {\n const exports = ensureInitialized();\n const bytes = await toBytes(document);\n\n // Yield to browser before WASM work - allows loading states to render\n await yieldToMain();\n\n const result = exports.DocumentConverter.SearchTextOffsets(bytes, searchText, maxResults);\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to search text: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n\n return (parsed.Results || parsed.results || []).map((r: any) => ({\n id: r.Id ?? r.id,\n start: r.Start ?? r.start,\n end: r.End ?? r.end,\n text: r.Text ?? r.text,\n }));\n}\n\n/**\n * Create an annotation from character offsets.\n * This is a client-side helper - no WASM call needed.\n *\n * @param id - Unique identifier for the annotation\n * @param labelId - Label/category ID for the annotation\n * @param documentText - Full document text (from annotationSet.content)\n * @param startOffset - Start character offset (0-indexed, inclusive)\n * @param endOffset - End character offset (exclusive)\n * @returns OpenContractsAnnotation ready to add to an annotation set\n * @throws Error if offsets are invalid\n *\n * @example\n * ```typescript\n * const set = await createExternalAnnotationSet(docxFile, \"doc-1\");\n * const annotation = createAnnotation(\"ann-001\", \"IMPORTANT\", set.content, 100, 150);\n * set.labelledText.push(annotation);\n * ```\n */\nexport function createAnnotation(\n id: string,\n labelId: string,\n documentText: string,\n startOffset: number,\n endOffset: number\n): OpenContractsAnnotation {\n if (startOffset < 0) {\n throw new Error(\"Start offset must be non-negative\");\n }\n if (endOffset < startOffset) {\n throw new Error(\"End offset must be >= start offset\");\n }\n if (endOffset > documentText.length) {\n throw new Error(\"End offset exceeds document length\");\n }\n\n const rawText = documentText.substring(startOffset, endOffset);\n\n return {\n id,\n annotationLabel: labelId,\n rawText,\n page: 0,\n annotationJson: {\n id,\n start: startOffset,\n end: endOffset,\n text: rawText,\n },\n annotationType: \"text\",\n structural: false,\n };\n}\n\n/**\n * Create an annotation by searching for text in the document.\n * This is a client-side helper - no WASM call needed.\n *\n * @param id - Unique identifier for the annotation\n * @param labelId - Label/category ID for the annotation\n * @param documentText - Full document text (from annotationSet.content)\n * @param searchText - Text to search for\n * @param occurrence - Which occurrence to use (1-based, default: 1)\n * @returns OpenContractsAnnotation, or null if text not found\n *\n * @example\n * ```typescript\n * const set = await createExternalAnnotationSet(docxFile, \"doc-1\");\n *\n * // Find first occurrence\n * const ann1 = createAnnotationFromSearch(\"ann-001\", \"LIABILITY\", set.content, \"shall not be liable\");\n * if (ann1) set.labelledText.push(ann1);\n *\n * // Find second occurrence\n * const ann2 = createAnnotationFromSearch(\"ann-002\", \"LIABILITY\", set.content, \"shall not be liable\", 2);\n * if (ann2) set.labelledText.push(ann2);\n * ```\n */\nexport function createAnnotationFromSearch(\n id: string,\n labelId: string,\n documentText: string,\n searchText: string,\n occurrence: number = 1\n): OpenContractsAnnotation | null {\n if (occurrence < 1) {\n throw new Error(\"Occurrence must be >= 1\");\n }\n\n const offsets = findTextOccurrences(documentText, searchText);\n\n if (occurrence > offsets.length) {\n return null;\n }\n\n const { start, end } = offsets[occurrence - 1];\n return createAnnotation(id, labelId, documentText, start, end);\n}\n\n/**\n * Find all occurrences of a text string in the document.\n * This is a client-side helper - no WASM call needed.\n *\n * @param documentText - Full document text\n * @param searchText - Text to search for\n * @param maxResults - Maximum number of results (default: 100)\n * @returns Array of { start, end } offsets\n *\n * @example\n * ```typescript\n * const occurrences = findTextOccurrences(set.content, \"the\");\n * console.log(`Found ${occurrences.length} occurrences of \"the\"`);\n * ```\n */\nexport function findTextOccurrences(\n documentText: string,\n searchText: string,\n maxResults: number = 100\n): Array<{ start: number; end: number }> {\n if (!searchText) return [];\n\n const results: Array<{ start: number; end: number }> = [];\n let index = 0;\n\n while (results.length < maxResults) {\n index = documentText.indexOf(searchText, index);\n if (index < 0) break;\n\n results.push({ start: index, end: index + searchText.length });\n index += 1; // Move past start to find overlapping matches\n }\n\n return results;\n}\n\n// Helper function to convert PascalCase response to camelCase ExternalAnnotationSet\n\n// ============================================================================\n// Incremental Annotation Overlay API (Issue #106)\n// ============================================================================\n\n/**\n * Project external annotations onto already-converted HTML.\n * This avoids full DOCX re-conversion when only annotations change.\n *\n * Workflow:\n * 1. Convert DOCX to HTML once using `convertDocxToHtml()`\n * 2. Use this function to overlay annotations on the cached HTML\n * 3. When annotations change, call this again with the same base HTML\n *\n * @param html - HTML string (previously converted via convertDocxToHtml)\n * @param annotationSet - The external annotation set to project\n * @param projectionOptions - Projection settings (CSS prefix, label mode, etc.)\n * @returns HTML string with annotations projected\n * @throws Error if projection fails\n *\n * @example\n * ```typescript\n * // Step 1: Convert once\n * const baseHtml = await convertDocxToHtml(docxFile);\n *\n * // Step 2: Project annotations (fast, no DOCX re-conversion)\n * const annotatedHtml = await projectAnnotationsOntoHtml(baseHtml, annotationSet);\n *\n * // Step 3: When annotations change, project again on the same base HTML\n * annotationSet.labelledText.push(newAnnotation);\n * const updatedHtml = await projectAnnotationsOntoHtml(baseHtml, annotationSet);\n * ```\n */\nexport async function projectAnnotationsOntoHtml(\n html: string,\n annotationSet: ExternalAnnotationSet,\n projectionOptions?: ExternalAnnotationProjectionSettings\n): Promise<string> {\n const exports = ensureInitialized();\n\n await yieldToMain();\n\n const annotationSetJson = JSON.stringify(annotationSet);\n const result = exports.DocumentConverter.ProjectAnnotationsOntoHtml(\n html,\n annotationSetJson,\n projectionOptions?.cssClassPrefix ?? \"ext-annot-\",\n projectionOptions?.labelMode ?? AnnotationLabelMode.Above\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to project annotations: ${error.error}`);\n }\n\n return readProjectedHtml(JSON.parse(result));\n}\n\n/**\n * Add a single annotation to existing HTML without re-converting the document.\n * This is the fastest way to add one annotation to already-rendered HTML.\n *\n * @param html - HTML string (with or without existing annotations)\n * @param annotation - The annotation to add\n * @param label - Label definition for the annotation (optional, for color/text)\n * @param projectionOptions - Projection settings\n * @returns HTML string with the annotation added\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * const annotation = createAnnotation(\"ann-new\", \"CLAUSE\", set.content, 100, 150);\n * const label = { id: \"CLAUSE\", text: \"Clause\", color: \"#FF5722\" };\n * const updatedHtml = await addAnnotationToHtml(currentHtml, annotation, label);\n * ```\n */\nexport async function addAnnotationToHtml(\n html: string,\n annotation: OpenContractsAnnotation,\n label?: AnnotationLabel,\n projectionOptions?: ExternalAnnotationProjectionSettings\n): Promise<string> {\n const exports = ensureInitialized();\n\n await yieldToMain();\n\n const annotationJson = JSON.stringify(annotation);\n const labelJson = label ? JSON.stringify(label) : \"\";\n const result = exports.DocumentConverter.AddAnnotationToHtml(\n html,\n annotationJson,\n labelJson,\n projectionOptions?.cssClassPrefix ?? \"ext-annot-\",\n projectionOptions?.labelMode ?? AnnotationLabelMode.Above\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to add annotation to HTML: ${error.error}`);\n }\n\n return readProjectedHtml(JSON.parse(result));\n}\n\n/**\n * Remove a single annotation from HTML by annotation ID.\n * Unwraps annotation spans back to plain text.\n *\n * @param html - HTML string with annotations\n * @param annotationId - ID of the annotation to remove\n * @param cssClassPrefix - CSS class prefix used for annotations (default: \"ext-annot-\")\n * @returns HTML string with the annotation removed\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * const updatedHtml = await removeAnnotationFromHtml(currentHtml, \"ann-001\");\n * ```\n */\nexport async function removeAnnotationFromHtml(\n html: string,\n annotationId: string,\n cssClassPrefix?: string\n): Promise<string> {\n const exports = ensureInitialized();\n\n await yieldToMain();\n\n const result = exports.DocumentConverter.RemoveAnnotationFromHtml(\n html,\n annotationId,\n cssClassPrefix ?? \"ext-annot-\"\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to remove annotation from HTML: ${error.error}`);\n }\n\n return readProjectedHtml(JSON.parse(result));\n}\n\n/**\n * Generate CSS to hide annotations with specific label IDs.\n * Enables CSS-based label filtering without re-rendering HTML.\n *\n * Apply the returned CSS to your document (e.g., via a `<style>` element)\n * to hide/show annotations by label. This is much faster than re-projecting\n * all annotations.\n *\n * @param hiddenLabelIds - Array of label IDs to hide\n * @param cssClassPrefix - CSS class prefix (default: \"ext-annot-\")\n * @returns CSS string that hides the specified labels\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * // Hide annotations with label \"DRAFT\" and \"INTERNAL\"\n * const css = await generateAnnotationVisibilityCss([\"DRAFT\", \"INTERNAL\"]);\n *\n * // Apply to a <style> element in the DOM\n * const styleEl = document.getElementById(\"visibility-overrides\");\n * styleEl.textContent = css;\n *\n * // To show all annotations again, clear the style:\n * styleEl.textContent = \"\";\n * ```\n */\nexport async function generateAnnotationVisibilityCss(\n hiddenLabelIds: string[],\n cssClassPrefix?: string\n): Promise<string> {\n const exports = ensureInitialized();\n\n await yieldToMain();\n\n const result = exports.DocumentConverter.GenerateAnnotationVisibilityCss(\n JSON.stringify(hiddenLabelIds),\n cssClassPrefix ?? \"ext-annot-\"\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to generate visibility CSS: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n return parsed.Css ?? parsed.css;\n}\n\n/**\n * Generate annotation CSS for a set of labels.\n * Useful when managing CSS separately from HTML content.\n *\n * @param labels - Label definitions (keyed by label ID)\n * @param projectionOptions - Projection settings\n * @returns CSS string for the annotation styles\n * @throws Error if operation fails\n *\n * @example\n * ```typescript\n * const labels = {\n * \"CLAUSE\": { id: \"CLAUSE\", text: \"Clause\", color: \"#FF5722\" },\n * \"TERM\": { id: \"TERM\", text: \"Term\", color: \"#2196F3\" },\n * };\n * const css = await generateAnnotationCss(labels);\n * ```\n */\nexport async function generateAnnotationCss(\n labels: Record<string, AnnotationLabel>,\n projectionOptions?: ExternalAnnotationProjectionSettings\n): Promise<string> {\n const exports = ensureInitialized();\n\n await yieldToMain();\n\n const result = exports.DocumentConverter.GenerateAnnotationCss(\n JSON.stringify(labels),\n projectionOptions?.cssClassPrefix ?? \"ext-annot-\",\n projectionOptions?.labelMode ?? AnnotationLabelMode.Above\n );\n\n if (isErrorResponse(result)) {\n const error = parseError(result);\n throw new Error(`Failed to generate annotation CSS: ${error.error}`);\n }\n\n const parsed = JSON.parse(result);\n return parsed.Css ?? parsed.css;\n}\n", "/**\n * HeaderFooterRegion \u2014 the DocxEditor's header/footer editing surface.\n *\n * Header and footer stories live in their own OOXML parts (HeaderPart/FooterPart) *outside*\n * the body, so they cannot be another block in the body flow. This module presents them two\n * ways, both composed PER STORY PARAGRAPH via the editor's block renderer, which resolves\n * `hdr`/`ftr` anchors natively:\n *\n * - **Continuous view** \u2014 two bands, one docked above the body and one below, drawn as the\n * top and bottom margin of the sheet (a dashed rule and a small \"Header\"/\"Footer\" tag, the\n * look Word has while a header is being edited).\n * - **Page view** \u2014 no bands. The paginator clones each story onto every page as inert\n * presentation; clicking a page's header or footer area swaps THAT page's clone for the\n * real, editable story paragraphs. A commit re-renders the paragraph and re-clones the story\n * onto every other page that shows it, so all pages update live, and page-number fields on\n * each clone are substituted per page just as the paginator does.\n *\n * Once rendered, a story paragraph is an ORDINARY editable block: DocxSession's anchor\n * resolution indexes every scope and routes by part, so ReplaceText/ApplyFormat/SetParagraphFormat\n * all accept a `p:hdr1:<unid>` anchor. The editor wires story blocks with the same `wireBlock` it\n * uses for the body, which is why the whole ribbon works inside a story with no new command code.\n *\n * \"Different first page\" and \"Different odd & even pages\" are Word's two checkboxes, backed by\n * `w:titlePg` (per section) and `w:evenAndOddHeaders` (document-global). Enabling one seeds BOTH\n * the header and the footer story of that kind, exactly as Word does \u2014 page 1 stops using the\n * default stories the moment `w:titlePg` is set, so seeding only one side would silently leave\n * page 1 with no footer.\n */\n\nimport { formatPageNumber } from \"./page-number-format.js\";\nimport type { HeaderFooterKind, NumberFormat } from \"./types.js\";\n\n/** Which of the two stories an operation targets. */\nexport type BandWhich = \"header\" | \"footer\";\n\n/** The bridge slice the region needs. Structurally satisfied by `DocxEditorExports.DocxSessionBridge`;\n * declared locally so this module and `editor.ts` don't import each other. */\nexport interface HeaderFooterBridge {\n Project: (handle: number) => string;\n ListAnchors?: (handle: number) => string;\n GetSectionInfo: (handle: number, anchorId: string) => string;\n SetHeaderText: (handle: number, anchor: string, kind: string, markdown: string) => string;\n SetFooterText: (handle: number, anchor: string, kind: string, markdown: string) => string;\n InsertPageNumberField: (handle: number, anchor: string, field: string, format: string) => string;\n EnsureHeaderFooterVisible: (handle: number, anchor: string, kind: string) => string;\n /** Turn `w:titlePg` / `w:evenAndOddHeaders` on or off (optional: older bundles can only enable). */\n SetHeaderFooterKindEnabled?: (handle: number, anchor: string, kind: string, enabled: boolean) => string;\n SetPageNumbering: (handle: number, anchor: string, opJson: string) => string;\n ClearPageNumbering: (handle: number, anchor: string) => string;\n}\n\nexport interface HeaderFooterRegionCallbacks {\n /** Wire a freshly rendered story paragraph as an editable block (DocxEditor.wireBlock). */\n wireBlock: (el: HTMLElement) => void;\n /** Render one story paragraph by full anchor id, with the editor's own render profile. */\n renderBlock: (anchorId: string) => HTMLElement | null;\n /** Rebuild the editor's unid \u2192 full-anchor map (a seed adds a part, changing the projection). */\n refreshAnchorMap: () => void;\n /** Full anchor id of a rendered BODY block's unid, or undefined. */\n bodyAnchorIdOf: (unid: string) => string | undefined;\n /** Re-render the whole document (page view: a story changed height, or a kind flag flipped). */\n remount: () => void;\n /** The story host that is active changed (null = the caret left every story). */\n onActiveChange?: (host: HTMLElement | null, which: BandWhich | null) => void;\n}\n\ninterface HeaderFooterRefLite {\n kind: HeaderFooterKind;\n partUri: string;\n inherited?: boolean;\n}\n\ninterface SectionInfoLite {\n sectionUnid: string;\n headerRefs?: HeaderFooterRefLite[];\n footerRefs?: HeaderFooterRefLite[];\n pageNumberStart?: number;\n pageNumberFormat?: NumberFormat;\n /** `w:titlePg` on the governing sectPr (older bundles omit it: absent = unknown). */\n titlePage?: boolean;\n /** `w:evenAndOddHeaders` in the settings part. */\n evenAndOddHeaders?: boolean;\n}\n\ninterface AnchorEntryLite {\n partUri: string;\n unid: string;\n kind: string;\n scope: string;\n}\n\n/** Kinds/scopes the markdown projection addresses as editable text blocks. */\nconst STORY_BLOCK_KINDS = new Set([\"p\", \"h\", \"li\"]);\n\nconst KIND_LABELS: Record<HeaderFooterKind, { header: string; footer: string }> = {\n default: { header: \"Header\", footer: \"Footer\" },\n first: { header: \"First Page Header\", footer: \"First Page Footer\" },\n even: { header: \"Even Page Header\", footer: \"Even Page Footer\" },\n};\n\n/** Attributes the editor stamps on live story blocks and that a page clone must not carry. */\nconst LIVE_BLOCK_ATTRS = [\n \"contenteditable\", \"data-anchor\", \"data-hf-anchor\", \"data-hf-adopted\", \"data-hf-focused\",\n \"data-committed-text\", \"data-render-sig\", \"tabindex\",\n];\n\nexport class HeaderFooterRegion {\n readonly headerBand: HTMLElement;\n readonly footerBand: HTMLElement;\n\n private readonly bridge: HeaderFooterBridge;\n private readonly handle: number;\n private readonly callbacks: HeaderFooterRegionCallbacks;\n\n /** The body anchor whose section the region currently describes (needed to seed a story). */\n private bodyAnchorId: string | null = null;\n private sectionInfo: SectionInfoLite | null = null;\n /** Memoized body anchor \u2192 governing sectionUnid, so repeat focus costs no bridge call. */\n private readonly sectionOfAnchor = new Map<string, string>();\n\n /** Which story kind each continuous band shows. */\n private readonly kinds: Record<BandWhich, HeaderFooterKind> = { header: \"default\", footer: \"default\" };\n\n /** Page view: the page stack being edited in place, and the hosts currently holding live blocks. */\n private pageRoot: HTMLElement | null = null;\n private readonly pageHosts = new Set<HTMLElement>();\n private activeHost: HTMLElement | null = null;\n private readonly pageListeners = new Map<HTMLElement, (event: Event) => void>();\n\n constructor(bridge: HeaderFooterBridge, handle: number, callbacks: HeaderFooterRegionCallbacks) {\n this.bridge = bridge;\n this.handle = handle;\n this.callbacks = callbacks;\n this.headerBand = this.buildBand(\"header\");\n this.footerBand = this.buildBand(\"footer\");\n }\n\n // \u2500\u2500\u2500 public surface \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Point the region at the section governing `bodyAnchorId` and repaint if it changed.\n * Cheap to call on every focus change: the anchor \u2192 section lookup is memoized, and an\n * unchanged `sectionUnid` returns without touching the DOM (so it never clobbers the\n * user's kind selection).\n */\n syncToBody(bodyAnchorId: string | null): void {\n if (!bodyAnchorId) return;\n const cached = this.sectionOfAnchor.get(bodyAnchorId);\n if (cached !== undefined && cached === this.sectionInfo?.sectionUnid) {\n this.bodyAnchorId = bodyAnchorId; // same section \u2014 keep it as the seed target\n return;\n }\n const info = this.readSectionInfo(bodyAnchorId);\n if (!info) return; // not a body anchor (or no sectPr) \u2014 leave things as they are\n this.sectionOfAnchor.set(bodyAnchorId, info.sectionUnid);\n const changed = info.sectionUnid !== this.sectionInfo?.sectionUnid;\n this.bodyAnchorId = bodyAnchorId;\n this.sectionInfo = info;\n if (changed && !this.pageRoot) {\n // A kind the new section cannot show falls back to its default story.\n for (const which of [\"header\", \"footer\"] as BandWhich[]) {\n if (!this.partUriFor(which, this.kinds[which])) this.kinds[which] = \"default\";\n }\n this.refreshAll();\n }\n }\n\n /** Re-read the section and repaint one story (band, or the active page host and its clones). */\n refresh(which: BandWhich): void {\n this.sectionInfo = this.bodyAnchorId ? this.readSectionInfo(this.bodyAnchorId) : null;\n if (this.pageRoot) this.repaintPageStory(which);\n else this.renderBand(which);\n }\n\n /** Repaint both stories from the live session (after a remount, undo/redo, or section change). */\n refreshAll(): void {\n if (this.pageRoot) {\n this.repaintPageStory(\"header\");\n this.repaintPageStory(\"footer\");\n return;\n }\n this.renderBand(\"header\");\n this.renderBand(\"footer\");\n }\n\n /** Select (and, if absent, create) the story kind a continuous band shows. */\n setKind(which: BandWhich, kind: HeaderFooterKind): void {\n this.kinds[which] = kind;\n if (!this.partUriFor(which, kind)) this.seedStory(which, kind);\n // Selecting first/even IS the user saying \"use a different first/even page\", so the\n // section's flag must be set even when the part already exists: Word leaves first/even parts\n // behind when those options are switched off, so a real document commonly has the reference\n // WITHOUT the flag; without this the typed story is saved but never rendered.\n if (this.bodyAnchorId && kind !== \"default\") {\n this.bridge.EnsureHeaderFooterVisible(this.handle, this.bodyAnchorId, kind);\n }\n this.refresh(which);\n }\n\n /** The kind a band (or the active page host) is currently editing. */\n kindOf(which: BandWhich): HeaderFooterKind {\n if (this.pageRoot && this.activeHost && this.whichOf(this.activeHost) === which) {\n return (this.activeHost.dataset.hfType as HeaderFooterKind) ?? \"default\";\n }\n return this.kinds[which];\n }\n\n /** Word's checkbox state: whether `w:titlePg` (first) / `w:evenAndOddHeaders` (even) is set. */\n kindEnabled(kind: \"first\" | \"even\"): boolean {\n const info = this.sectionInfo;\n if (!info) return false;\n if (kind === \"first\") return info.titlePage ?? this.refsFor(\"header\").some((r) => r.kind === \"first\" && !r.inherited);\n return info.evenAndOddHeaders ?? false;\n }\n\n /**\n * Word's \"Different first page\" / \"Different odd & even pages\". Enabling seeds BOTH stories of\n * that kind when absent (page 1 uses its own header AND footer once `w:titlePg` is set, so a\n * missing first-page footer would leave page 1 footer-less) and sets the flag; disabling clears\n * the flag and leaves the parts in place, as Word does. Returns false when the bundle predates\n * the disable op and `enabled` is false.\n */\n setKindEnabled(kind: \"first\" | \"even\", enabled: boolean): boolean {\n if (!this.bodyAnchorId) return false;\n if (enabled) {\n for (const which of [\"header\", \"footer\"] as BandWhich[]) {\n // The odd/all-pages story too: once the option is on, its pages need somewhere to\n // type as much as the first/even ones do (Word shows an empty area for both).\n if (!this.partUriFor(which, \"default\")) this.seedStory(which, \"default\");\n if (!this.partUriFor(which, kind)) this.seedStory(which, kind);\n }\n const res = parseResult(this.bridge.EnsureHeaderFooterVisible(this.handle, this.bodyAnchorId, kind));\n if (!res.success) return false;\n } else {\n if (!this.bridge.SetHeaderFooterKindEnabled) return false;\n const res = parseResult(this.bridge.SetHeaderFooterKindEnabled(this.handle, this.bodyAnchorId, kind, false));\n if (!res.success) return false;\n for (const which of [\"header\", \"footer\"] as BandWhich[]) {\n if (this.kinds[which] === kind) this.kinds[which] = \"default\";\n }\n }\n this.reloadSection();\n // Page view selects stories per page from the flags, so the pages themselves must rebuild.\n if (this.pageRoot) this.callbacks.remount();\n return true;\n }\n\n /** Human label for the story a band (or the active host) shows \u2014 \"First Page Header\". */\n storyLabel(which: BandWhich): string {\n return KIND_LABELS[this.kindOf(which)][which];\n }\n\n /** The kinds a band could show right now (those with a story or an enabled flag). */\n availableKinds(which: BandWhich): HeaderFooterKind[] {\n const kinds: HeaderFooterKind[] = [\"default\"];\n if (this.kindEnabled(\"first\") || this.partUriFor(which, \"first\")) kinds.push(\"first\");\n if (this.kindEnabled(\"even\") || this.partUriFor(which, \"even\")) kinds.push(\"even\");\n return kinds;\n }\n\n /** Append a PAGE / NUMPAGES field to the story paragraph addressed by `anchorId`.\n * Deliberately a PLAIN field (no `\\*` switch), exactly as Word inserts one, so it follows the\n * section's page-number format \u2014 see {@link setPageNumbering}. */\n insertPageNumber(which: BandWhich, anchorId: string, field: \"currentPage\" | \"totalPages\" | \"pageOfTotal\"): boolean {\n const res = parseResult(this.bridge.InsertPageNumberField(this.handle, anchorId, field, \"\"));\n if (!res.success) return false;\n this.refresh(which);\n return true;\n }\n\n /** Insert a page number into a story's own target paragraph (focused, else last). Seeds the\n * story first if the selected kind has none, so the command is never a silent no-op. */\n insertPageNumberInBand(which: BandWhich, field: \"currentPage\" | \"totalPages\" | \"pageOfTotal\"): boolean {\n // Page view: the field goes into a live story, so open the story on the current page\n // first (Word does the same \u2014 inserting a page number takes you into the footer).\n if (this.pageRoot && !(this.activeHost && this.whichOf(this.activeHost) === which)) {\n const near = this.activeHost ?? null;\n if (!this.focusStory(which, near)) return false;\n }\n const kind = this.kindOf(which);\n if (!this.partUriFor(which, kind)) {\n this.seedStory(which, kind);\n this.refresh(which);\n }\n const target = this.pageNumberTarget(which);\n return target ? this.insertPageNumber(which, target, field) : false;\n }\n\n /** Set this section's page numbering (`w:pgNumType`) \u2014 Word's *Format Page Numbers\u2026*. */\n setPageNumbering(op: { start?: number; format?: NumberFormat }): boolean {\n if (!this.bodyAnchorId) return false;\n const res = parseResult(this.bridge.SetPageNumbering(this.handle, this.bodyAnchorId, JSON.stringify(op)));\n if (!res.success) return false;\n this.reloadSection();\n return true;\n }\n\n /** This section's page numbering as the live document states it (fields absent, not defaulted). */\n pageNumbering(): { start?: number; format?: NumberFormat } {\n return { start: this.sectionInfo?.pageNumberStart, format: this.sectionInfo?.pageNumberFormat };\n }\n\n /** Remove this section's page-numbering start/format. */\n clearPageNumbering(): boolean {\n if (!this.bodyAnchorId) return false;\n const res = parseResult(this.bridge.ClearPageNumbering(this.handle, this.bodyAnchorId));\n if (!res.success) return false;\n this.reloadSection();\n return true;\n }\n\n /** The story host (continuous band or active page area) containing `node`, or null. */\n bandOf(node: Node | null): HTMLElement | null {\n const el = node && node.nodeType === 1 ? (node as HTMLElement) : node?.parentElement ?? null;\n const band = el?.closest<HTMLElement>(\"[data-hf-band]\") ?? null;\n if (!band) return null;\n return band === this.headerBand || band === this.footerBand || this.pageHosts.has(band) ? band : null;\n }\n\n /** The block-list root (a story's container) owning `node`, or null. */\n blockRootOf(node: Node | null): HTMLElement | null {\n const band = this.bandOf(node);\n return band ? band.querySelector<HTMLElement>(\"[data-hf-body]\") : null;\n }\n\n /** True when `node` is inside a story host (band or page area). */\n contains(node: Node | null): boolean {\n return this.bandOf(node) !== null;\n }\n\n /** `\"header\"` / `\"footer\"` for a story host produced by this region. */\n whichOf(band: HTMLElement): BandWhich {\n return band.getAttribute(\"data-hf-band\") === \"footer\" ? \"footer\" : \"header\";\n }\n\n /** The story host currently being edited (page view), or null. */\n get active(): HTMLElement | null {\n return this.activeHost;\n }\n\n /** True while the caret is in a story (either view) \u2014 drives the contextual ribbon tab. */\n isStoryActive(): boolean {\n return this.activeHost !== null;\n }\n\n /**\n * Track focus: the editor calls this whenever any block takes focus. A body block leaving a\n * page story deactivates it (and re-paginates if the story grew past its band); a story block\n * activates its host.\n */\n noteFocus(el: HTMLElement | null): void {\n const host = el ? this.bandOf(el) : null;\n if (host === this.activeHost) return;\n const previous = this.activeHost;\n this.activeHost = host;\n if (previous) this.deactivateHost(previous);\n if (host) {\n host.setAttribute(\"data-hf-active\", \"\");\n if (this.pageHosts.has(host)) host.style.overflow = \"visible\";\n }\n this.callbacks.onActiveChange?.(host, host ? this.whichOf(host) : null);\n }\n\n /** Leave story editing: the caret goes back to the body (Word's \"Close Header and Footer\"). */\n close(): void {\n const previous = this.activeHost;\n this.activeHost = null;\n if (previous) this.deactivateHost(previous);\n this.callbacks.onActiveChange?.(null, null);\n }\n\n /**\n * Move the caret into a story (Word's \"Go to Header / Go to Footer\"). Page view activates the\n * area on the page the caret is on (else the first page); continuous view focuses the band.\n */\n focusStory(which: BandWhich, near?: HTMLElement | null): boolean {\n if (this.pageRoot) {\n const pages = Array.from(this.pageRoot.querySelectorAll<HTMLElement>(\".page-box\"));\n let page = near?.closest<HTMLElement>(\".page-box\") ?? pages[0] ?? null;\n if (!page) return false;\n let area = page.querySelector<HTMLElement>(`.page-${which}`);\n if (!area) {\n // No story of this kind exists, so the paginator drew no area to click. Seed it and\n // re-paginate; the page then carries an (empty) area for the caret to land in.\n const pageIndex = pages.indexOf(page);\n const bodyAnchor = this.bodyAnchorForPage(page);\n if (!bodyAnchor) return false;\n this.syncToBody(bodyAnchor);\n const kind = (page.querySelector<HTMLElement>(`.page-${which === \"header\" ? \"footer\" : \"header\"}`)?.dataset.hfType as HeaderFooterKind | undefined) ?? \"default\";\n if (!this.partUriFor(which, kind)) this.seedStory(which, kind);\n this.callbacks.remount();\n if (!this.pageRoot) return false;\n page = this.pageRoot.querySelectorAll<HTMLElement>(\".page-box\")[Math.max(0, pageIndex)] ?? null;\n area = page?.querySelector<HTMLElement>(`.page-${which}`) ?? null;\n if (!area) return false;\n }\n this.editInPage(area, \"end\");\n return true;\n }\n const band = which === \"header\" ? this.headerBand : this.footerBand;\n const block = band.querySelector<HTMLElement>('[data-anchor][contenteditable=\"true\"]');\n if (!block) return false;\n placeCaretAtEnd(block);\n return true;\n }\n\n /** After the editor swapped/split/merged a story block in place: show this page's own numbers\n * in the fresh render, then mirror it to the page clones. */\n afterStoryEdit(el: HTMLElement): void {\n const host = this.bandOf(el);\n if (!host || !this.pageRoot) return;\n this.substituteFields(host);\n this.propagate(host);\n }\n\n // \u2500\u2500\u2500 page view: edit in place \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Adopt a page stack: every page's header/footer area becomes click-to-edit. The paginator's\n * clones stay as they are until a click swaps one for the live story.\n */\n attachPages(pageRoot: HTMLElement): void {\n this.detachPages();\n this.pageRoot = pageRoot;\n for (const area of Array.from(pageRoot.querySelectorAll<HTMLElement>(\".page-header, .page-footer\"))) {\n area.setAttribute(\"data-hf-page\", area.classList.contains(\"page-footer\") ? \"footer\" : \"header\");\n area.setAttribute(\"data-hf-inert\", \"\");\n area.title = `Click to edit the ${area.classList.contains(\"page-footer\") ? \"footer\" : \"header\"}`;\n const listener = (event: Event) => {\n if (this.pageHosts.has(area)) return; // already live \u2014 the click lands in a block\n event.preventDefault();\n this.editInPage(area, \"point\", event as MouseEvent);\n };\n area.addEventListener(\"mousedown\", listener);\n this.pageListeners.set(area, listener);\n }\n }\n\n /** Release a page stack (before a remount replaces it). */\n detachPages(): void {\n for (const [area, listener] of this.pageListeners) area.removeEventListener(\"mousedown\", listener);\n this.pageListeners.clear();\n this.pageHosts.clear();\n const hadActive = this.activeHost !== null;\n this.activeHost = null;\n this.pageRoot = null;\n // The pages are being thrown away, so there is no host to deactivate \u2014 but the caret WAS\n // in a story, and the ribbon's contextual tab and story label follow this callback. Without\n // it, the next body focus compared null to null and never published \"back in the body\".\n if (hadActive) this.callbacks.onActiveChange?.(null, null);\n }\n\n /** True when the region is presenting stories inside page boxes rather than as bands. */\n get inPageMode(): boolean {\n return this.pageRoot !== null;\n }\n\n /**\n * Swap a page's cloned story for the live, editable one and put the caret in it. The page\n * advertises which story it shows (`data-hf-type`, stamped by the paginator) and which\n * section it belongs to (`data-section-index`); the section's body anchor comes from the\n * first anchored block on the page (or an earlier page of the same section).\n */\n private editInPage(area: HTMLElement, caret: \"point\" | \"end\", event?: MouseEvent): void {\n if (!this.pageRoot) return;\n const which: BandWhich = area.getAttribute(\"data-hf-page\") === \"footer\" ? \"footer\" : \"header\";\n const kind = (area.dataset.hfType as HeaderFooterKind | undefined) ?? \"default\";\n const page = area.closest<HTMLElement>(\".page-box\");\n const bodyAnchor = page ? this.bodyAnchorForPage(page) : null;\n if (!bodyAnchor) return;\n this.syncToBody(bodyAnchor);\n this.kinds[which] = kind;\n\n if (!this.pageHosts.has(area)) {\n area.setAttribute(\"data-hf-band\", which);\n area.removeAttribute(\"data-hf-inert\");\n area.dataset.hfLabel = KIND_LABELS[kind][which];\n this.pageHosts.add(area);\n this.renderHostStory(area, which, kind);\n }\n const blocks = Array.from(area.querySelectorAll<HTMLElement>('[data-anchor][contenteditable=\"true\"]'));\n if (blocks.length === 0) return;\n let target: HTMLElement = blocks[blocks.length - 1];\n if (caret === \"point\" && event) {\n const hit = (event.target as HTMLElement | null)?.closest<HTMLElement>('[data-anchor][contenteditable=\"true\"]');\n if (hit && area.contains(hit)) target = hit;\n const doc = area.ownerDocument;\n const point = caretFromPoint(doc, event.clientX, event.clientY);\n if (point && target.contains(point.node)) {\n const sel = doc.getSelection();\n const range = doc.createRange();\n range.setStart(point.node, point.offset);\n range.collapse(true);\n sel?.removeAllRanges();\n sel?.addRange(range);\n target.focus({ preventScroll: true });\n return;\n }\n }\n placeCaretAtEnd(target);\n }\n\n /** The full body anchor of the first anchored block on `page`, walking back to earlier pages. */\n private bodyAnchorForPage(page: HTMLElement): string | null {\n let box: HTMLElement | null = page;\n while (box) {\n const block = box.querySelector<HTMLElement>(\".page-content [data-anchor]\");\n const unid = block?.getAttribute(\"data-anchor\");\n const id = unid ? this.callbacks.bodyAnchorIdOf(unid) : undefined;\n if (id) return id;\n box = box.previousElementSibling as HTMLElement | null;\n }\n return null;\n }\n\n /** Render the live story into a page host (replacing the paginator's clone). */\n private renderHostStory(host: HTMLElement, which: BandWhich, kind: HeaderFooterKind): void {\n let body = host.querySelector<HTMLElement>(\":scope > [data-hf-body]\");\n if (!body) {\n host.replaceChildren();\n body = host.ownerDocument.createElement(\"div\");\n body.className = \"docx-hf-body\";\n body.setAttribute(\"data-hf-body\", \"\");\n host.appendChild(body);\n }\n const partUri = this.partUriFor(which, kind);\n if (!partUri) {\n // The page shows nothing because the story does not exist; Word still lets you click into\n // the margin and type. Seed it and render the empty paragraph.\n this.seedStory(which, kind);\n }\n this.fillStoryBody(body, which, kind);\n this.substituteFields(host);\n }\n\n /** Repaint the page story `which` (active host first, then every clone of the same story). */\n private repaintPageStory(which: BandWhich): void {\n const host = this.activeHost && this.whichOf(this.activeHost) === which ? this.activeHost : null;\n if (host) {\n const body = host.querySelector<HTMLElement>(\":scope > [data-hf-body]\");\n if (body) this.fillStoryBody(body, which, this.kindOf(which));\n this.substituteFields(host);\n this.propagate(host);\n return;\n }\n // No live host for this story \u2014 page clones carry the paginator's render; nothing to do\n // until the next remount picks the change up.\n }\n\n /** Mirror a live host's story onto every other page area showing the same story. */\n private propagate(host: HTMLElement): void {\n if (!this.pageRoot) return;\n const which = this.whichOf(host);\n const kind = (host.dataset.hfType as HeaderFooterKind | undefined) ?? \"default\";\n const partUri = this.partUriFor(which, kind);\n const sourceBody = host.querySelector<HTMLElement>(\":scope > [data-hf-body]\");\n if (!sourceBody) return;\n const sectionParts = new Map<string, string | null>();\n for (const area of Array.from(this.pageRoot.querySelectorAll<HTMLElement>(`.page-${which}`))) {\n if (area === host) continue;\n if ((area.dataset.hfType ?? \"default\") !== kind) continue;\n const page = area.closest<HTMLElement>(\".page-box\");\n if (!page) continue;\n const sectionIndex = page.dataset.sectionIndex ?? \"0\";\n let part = sectionParts.get(sectionIndex);\n if (part === undefined) {\n const anchor = this.bodyAnchorForPage(page);\n const info = anchor ? this.readSectionInfo(anchor) : null;\n const refs = (which === \"header\" ? info?.headerRefs : info?.footerRefs) ?? [];\n part = refs.find((r) => r.kind === kind)?.partUri ?? null;\n sectionParts.set(sectionIndex, part);\n }\n if (!partUri || part !== partUri) continue;\n if (this.pageHosts.has(area)) {\n // Another page already holds a live copy of this story: re-render it from truth too.\n const body = area.querySelector<HTMLElement>(\":scope > [data-hf-body]\");\n if (body) this.fillStoryBody(body, which, kind);\n } else {\n area.replaceChildren();\n for (const child of Array.from(sourceBody.children)) area.appendChild(inertClone(child as HTMLElement));\n }\n this.substituteFields(area);\n }\n }\n\n /** Substitute PAGE / NUMPAGES markers in a page area from the page's own numbering. */\n private substituteFields(area: HTMLElement): void {\n const page = area.closest<HTMLElement>(\".page-box\");\n if (!page || !this.pageRoot) return;\n const total = this.pageRoot.querySelectorAll(\".page-box:not([data-section-filler])\").length;\n const displayed = parseInt(page.dataset.displayedPageNumber || page.dataset.pageNumber || \"1\", 10);\n const format = this.sectionInfo?.pageNumberFormat;\n for (const marker of Array.from(area.querySelectorAll<HTMLElement>(\"[data-field]\"))) {\n const kind = marker.dataset.field;\n if (kind !== \"PAGE\" && kind !== \"NUMPAGES\") continue;\n // Keep the session's cached result on the element: the editor's offset space counts THAT,\n // not the per-page number shown here, so a later edit diffs against the right text.\n if (marker.dataset.fieldCached === undefined) marker.dataset.fieldCached = marker.textContent ?? \"\";\n marker.textContent = formatPageNumber(kind === \"PAGE\" ? displayed : total, marker.dataset.fieldFormat ?? format);\n }\n }\n\n private deactivateHost(host: HTMLElement): void {\n host.removeAttribute(\"data-hf-active\");\n if (!this.pageHosts.has(host)) return;\n host.style.overflow = \"hidden\";\n // The story may have grown past the band the paginator reserved for it; re-flow the pages\n // rather than clip it (Word pushes the body down).\n const body = host.querySelector<HTMLElement>(\":scope > [data-hf-body]\");\n // A couple of pixels of slack: the paginator measured the story in a detached box, and\n // sub-pixel rounding between that and the live host must not read as growth.\n if (body && body.scrollHeight > host.clientHeight + 3) {\n this.callbacks.remount();\n }\n }\n\n // \u2500\u2500\u2500 section + anchor resolution \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private readSectionInfo(bodyAnchorId: string): SectionInfoLite | null {\n try {\n const parsed = JSON.parse(this.bridge.GetSectionInfo(this.handle, bodyAnchorId)) as SectionInfoLite | null;\n return parsed && typeof parsed.sectionUnid === \"string\" ? parsed : null;\n } catch {\n return null;\n }\n }\n\n private reloadSection(): void {\n this.sectionInfo = this.bodyAnchorId ? this.readSectionInfo(this.bodyAnchorId) : null;\n this.refreshAll();\n }\n\n private refsFor(which: BandWhich): HeaderFooterRefLite[] {\n const info = this.sectionInfo;\n if (!info) return [];\n return (which === \"header\" ? info.headerRefs : info.footerRefs) ?? [];\n }\n\n private refFor(which: BandWhich, kind: HeaderFooterKind): HeaderFooterRefLite | null {\n return this.refsFor(which).find((r) => r.kind === kind) ?? null;\n }\n\n private partUriFor(which: BandWhich, kind: HeaderFooterKind): string | null {\n return this.refFor(which, kind)?.partUri ?? null;\n }\n\n /** Full anchor ids of the story paragraphs held in `partUri`, in document order. */\n private storyAnchors(partUri: string): string[] {\n let index: Record<string, AnchorEntryLite>;\n try {\n const raw = this.bridge.ListAnchors ? this.bridge.ListAnchors(this.handle) : this.bridge.Project(this.handle);\n index = (JSON.parse(raw) as { anchorIndex: Record<string, AnchorEntryLite> }).anchorIndex;\n } catch {\n return [];\n }\n return Object.entries(index)\n .filter(([, t]) => t.partUri === partUri && STORY_BLOCK_KINDS.has(t.kind))\n .map(([id]) => id);\n }\n\n /** Create an empty story for `kind` so there is a paragraph to click into. */\n private seedStory(which: BandWhich, kind: HeaderFooterKind): void {\n if (!this.bodyAnchorId) return;\n const set = which === \"header\" ? this.bridge.SetHeaderText : this.bridge.SetFooterText;\n const res = parseResult(set(this.handle, this.bodyAnchorId, kind, \"\"));\n if (!res.success) return;\n this.callbacks.refreshAnchorMap();\n this.sectionInfo = this.readSectionInfo(this.bodyAnchorId);\n }\n\n // \u2500\u2500\u2500 continuous view: bands \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private buildBand(which: BandWhich): HTMLElement {\n const band = document.createElement(\"div\");\n band.className = \"docx-hf-band\";\n band.setAttribute(\"data-hf-band\", which);\n\n const tag = document.createElement(\"div\");\n tag.className = \"docx-hf-tag\";\n const label = document.createElement(\"span\");\n label.className = \"docx-hf-label\";\n label.setAttribute(\"data-hf-label\", \"\");\n label.textContent = KIND_LABELS.default[which];\n tag.appendChild(label);\n const kinds = document.createElement(\"span\");\n kinds.className = \"docx-hf-kinds\";\n kinds.setAttribute(\"data-hf-kinds\", \"\");\n kinds.hidden = true;\n tag.appendChild(kinds);\n const note = document.createElement(\"span\");\n note.className = \"docx-hf-inherited\";\n note.setAttribute(\"data-hf-inherited-note\", \"\");\n note.hidden = true;\n tag.appendChild(note);\n band.appendChild(tag);\n\n const body = document.createElement(\"div\");\n body.className = \"docx-hf-body\";\n body.setAttribute(\"data-hf-body\", \"\");\n band.appendChild(body);\n return band;\n }\n\n /** Which story paragraph a page-number insert targets: the focused one, else the last. */\n private pageNumberTarget(which: BandWhich): string | null {\n const host = this.pageRoot\n ? (this.activeHost && this.whichOf(this.activeHost) === which ? this.activeHost : null)\n : (which === \"header\" ? this.headerBand : this.footerBand);\n const body = host?.querySelector<HTMLElement>(\"[data-hf-body]\");\n if (!body) return null;\n const focused = body.querySelector<HTMLElement>('[data-hf-focused=\"true\"][data-hf-anchor]');\n const blocks = Array.from(body.querySelectorAll<HTMLElement>(\"[data-hf-anchor]\"));\n return (focused ?? blocks[blocks.length - 1])?.getAttribute(\"data-hf-anchor\") ?? null;\n }\n\n private renderBand(which: BandWhich): void {\n const band = which === \"header\" ? this.headerBand : this.footerBand;\n const body = band.querySelector<HTMLElement>(\"[data-hf-body]\");\n if (!body) return;\n const kind = this.kinds[which];\n\n const label = band.querySelector<HTMLElement>(\"[data-hf-label]\");\n if (label) label.textContent = KIND_LABELS[kind][which];\n\n // The story switcher shows only when there is more than one story to switch between.\n const kinds = band.querySelector<HTMLElement>(\"[data-hf-kinds]\");\n if (kinds) {\n const available = this.availableKinds(which);\n kinds.hidden = available.length < 2;\n kinds.replaceChildren();\n for (const k of available) {\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.setAttribute(\"data-hf-kind\", k);\n button.textContent =\n k === \"default\"\n ? (this.kindEnabled(\"even\") ? \"Odd pages\" : \"All pages\")\n : k === \"first\" ? \"First page\" : \"Even pages\";\n button.toggleAttribute(\"data-on\", k === kind);\n button.addEventListener(\"mousedown\", (e) => e.preventDefault());\n button.addEventListener(\"click\", () => this.setKind(which, k));\n kinds.appendChild(button);\n }\n }\n\n const inherited = this.refFor(which, kind)?.inherited === true;\n band.toggleAttribute(\"data-hf-inherited\", inherited);\n const note = band.querySelector<HTMLElement>(\"[data-hf-inherited-note]\");\n if (note) {\n note.hidden = !inherited;\n note.textContent = inherited ? \"Same as previous section\" : \"\";\n }\n\n this.fillStoryBody(body, which, kind);\n }\n\n /** Render the story's paragraphs into `body` (a placeholder when there is no story yet). */\n private fillStoryBody(body: HTMLElement, which: BandWhich, kind: HeaderFooterKind): void {\n // A repaint replaces the story's nodes; if the caret was in one of them, put it back at the\n // end of the story (where a page-number field just landed) instead of dropping it.\n const hadFocus = body.contains(body.ownerDocument.activeElement);\n body.innerHTML = \"\";\n const band = body.closest<HTMLElement>(\"[data-hf-band]\");\n const partUri = this.partUriFor(which, kind);\n const anchors = partUri ? this.storyAnchors(partUri) : [];\n if (anchors.length === 0) {\n body.appendChild(this.placeholder(which, kind));\n band?.setAttribute(\"data-hf-empty\", \"true\");\n return;\n }\n band?.removeAttribute(\"data-hf-empty\");\n let last: HTMLElement | null = null;\n for (const anchorId of anchors) {\n const el = this.callbacks.renderBlock(anchorId);\n if (!el) continue;\n body.appendChild(el);\n // Adopt BEFORE wiring: the editor resolves a block's anchor from `data-hf-anchor` first,\n // because a story paragraph's content-addressed unid can collide with another part's.\n this.adoptBlock(el, anchorId);\n this.callbacks.wireBlock(el);\n last = el;\n }\n if (hadFocus && last) placeCaretAtEnd(last);\n }\n\n /**\n * Mark a story paragraph as belonging to this region. The full anchor id is stamped alongside\n * `data-anchor` (which carries only the bare unid) so chrome can address the block without\n * going through the editor's unid map. Called on first render AND after an incremental swap.\n */\n adoptBlock(el: HTMLElement, anchorId: string): void {\n const body = this.blockRootOf(el);\n if (!body) return;\n el.setAttribute(\"data-hf-anchor\", anchorId);\n if (el.dataset.hfAdopted === \"true\") return;\n el.dataset.hfAdopted = \"true\";\n el.addEventListener(\"focus\", () => {\n body.querySelectorAll(\"[data-hf-focused]\").forEach((sib) => sib.removeAttribute(\"data-hf-focused\"));\n el.setAttribute(\"data-hf-focused\", \"true\");\n });\n }\n\n private placeholder(which: BandWhich, kind: HeaderFooterKind): HTMLElement {\n const el = document.createElement(\"div\");\n el.className = \"docx-hf-placeholder\";\n el.setAttribute(\"data-hf-placeholder\", \"\");\n el.textContent = `No ${KIND_LABELS[kind][which].toLowerCase()} yet \u2014 click here to add one.`;\n el.addEventListener(\"mousedown\", (event) => {\n event.preventDefault();\n if (!this.bodyAnchorId) return;\n this.seedStory(which, kind);\n this.refresh(which);\n const block = el.parentElement?.querySelector<HTMLElement>('[data-anchor][contenteditable=\"true\"]');\n if (block) placeCaretAtEnd(block);\n });\n return el;\n }\n}\n\n/** A presentation-only copy of a live story block for another page. */\nfunction inertClone(el: HTMLElement): HTMLElement {\n const clone = el.cloneNode(true) as HTMLElement;\n for (const node of [clone, ...Array.from(clone.querySelectorAll<HTMLElement>(\"*\"))]) {\n for (const attr of LIVE_BLOCK_ATTRS) node.removeAttribute(attr);\n }\n return clone;\n}\n\nfunction placeCaretAtEnd(el: HTMLElement): void {\n const doc = el.ownerDocument;\n el.focus({ preventScroll: true });\n const sel = doc.getSelection();\n if (!sel) return;\n const range = doc.createRange();\n range.selectNodeContents(el);\n range.collapse(false);\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\nfunction caretFromPoint(doc: Document, x: number, y: number): { node: Node; offset: number } | null {\n const d = doc as Document & {\n caretPositionFromPoint?: (x: number, y: number) => { offsetNode: Node; offset: number } | null;\n caretRangeFromPoint?: (x: number, y: number) => Range | null;\n };\n const position = d.caretPositionFromPoint?.(x, y);\n if (position) return { node: position.offsetNode, offset: position.offset };\n const range = d.caretRangeFromPoint?.(x, y);\n return range ? { node: range.startContainer, offset: range.startOffset } : null;\n}\n\nfunction parseResult(json: string): { success: boolean } {\n try {\n return JSON.parse(json) as { success: boolean };\n } catch {\n return { success: false };\n }\n}\n", "/**\n * CommentGutter \u2014 Word-style comment bubbles beside the page.\n *\n * The converter renders a commented range inline (`span.comment-highlight[data-comment-id]`\n * around the runs, `a.comment-marker` at the reference), and `DocxSession.ListComments` is the\n * truth about the threads themselves. This module joins the two: for every thread root it finds\n * the highlight in the live DOM, places a bubble in a column beside the sheet at the highlight's\n * vertical position (stacking bubbles downward when they would overlap, the way Word's markup\n * area does), and draws a leader line from the highlight to the bubble.\n *\n * Nothing here is a second source of state. The bubbles are re-derived from `listComments()`\n * plus the DOM on every layout pass, and every action (reply, resolve, edit, delete, post a new\n * comment) goes through the editor's session commands, then re-lays out.\n *\n * The gutter lives INSIDE the editor's scrolling container so bubbles scroll with the page; the\n * host is responsible for reserving horizontal room for it (the ribbon pads the surface).\n */\n\nimport type { CommentListEntry } from \"./types.js\";\n\n/** What the gutter needs from its editor \u2014 the comment commands plus the DOM it overlays. */\nexport interface CommentGutterHost {\n /** The element the document renders into; the gutter is appended to it. */\n readonly container: HTMLElement;\n /** Author for comments and replies posted from the gutter. */\n readonly commentAuthor: string;\n listComments(): CommentListEntry[];\n /** Post a comment on `target` (captured at draft time \u2014 the live selection is long gone once\n * the user has typed into the bubble). Returns the created thread root, or null. */\n addComment(\n markdown: string,\n author: string,\n target?: CommentTarget,\n ): CommentListEntry | null;\n addCommentReply(parentAnchorId: string, markdown: string, author: string): boolean;\n updateComment(anchorId: string, markdown: string): boolean;\n removeComment(anchorId: string): boolean;\n setCommentResolved(anchorId: string, resolved: boolean): boolean;\n /** The block that would receive a new comment, and the selection span inside it. */\n commentTarget(): CommentTarget | null;\n}\n\nexport interface CommentGutterOptions {\n /** Column width in px. Default 248. */\n width?: number;\n /** Vertical gap between stacked bubbles. Default 8. */\n gap?: number;\n /** Called after every layout with the number of visible (unresolved) threads. */\n onChange?: (info: { threads: number; open: number; active: string | null }) => void;\n}\n\ninterface ThreadView {\n root: CommentListEntry;\n replies: CommentListEntry[];\n anchor: HTMLElement | null;\n bubble: HTMLElement;\n desiredTop: number;\n /** Horizontal position of the anchor, so threads on one line keep reading order. */\n desiredLeft: number;\n}\n\nconst HIGHLIGHT_SELECTOR = \"span.comment-highlight[data-comment-id]\";\nconst MARKER_SELECTOR = \"a.comment-marker[data-comment-id]\";\n\n/** Whether a `data-comment-id` value (possibly \"3,5\" for overlapping ranges) names `id`. */\nfunction idsOf(el: Element): string[] {\n return (el.getAttribute(\"data-comment-id\") ?? \"\").split(\",\").map((s) => s.trim()).filter(Boolean);\n}\n\nfunction formatDate(iso: string | undefined): string {\n if (!iso) return \"\";\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return iso;\n try {\n return new Intl.DateTimeFormat(undefined, {\n month: \"short\", day: \"numeric\", year: \"numeric\", hour: \"numeric\", minute: \"2-digit\",\n }).format(d);\n } catch {\n return d.toLocaleString();\n }\n}\n\nfunction initialsOf(author: string, initials?: string): string {\n if (initials && initials.trim()) return initials.trim().slice(0, 3).toUpperCase();\n const parts = author.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return \"?\";\n return parts.slice(0, 2).map((p) => p[0]!.toUpperCase()).join(\"\");\n}\n\n/** A stable per-author hue so every bubble and highlight of one reviewer share a colour. */\nfunction authorHue(author: string): number {\n let h = 0;\n for (let i = 0; i < author.length; i++) h = (h * 31 + author.charCodeAt(i)) >>> 0;\n return h % 360;\n}\n\n/**\n * What a comment is about to be attached to: a block and the selection span in it (null = the\n * whole paragraph). `anchor` and `text` record which paragraph, with what content, the target\n * was captured on, so a post that comes after the block was re-rendered or edited can find the\n * live node and tell whether the span still means the same characters.\n */\nexport interface CommentTarget {\n block: HTMLElement;\n span: { start: number; length: number } | null;\n anchor?: string;\n text?: string;\n}\n\n/**\n * Every comment hanging off `rootAnchorId`, transitively \u2014 replies to replies included \u2014 deepest\n * first, so removing them in order never leaves an orphan behind. The root itself is not listed.\n */\nexport function threadMembers(comments: readonly CommentListEntry[], rootAnchorId: string): string[] {\n const children = new Map<string, string[]>();\n for (const c of comments) {\n if (!c.parentAnchorId) continue;\n const list = children.get(c.parentAnchorId) ?? [];\n list.push(c.anchorId);\n children.set(c.parentAnchorId, list);\n }\n const out: string[] = [];\n const seen = new Set<string>([rootAnchorId]);\n const walk = (id: string) => {\n for (const child of children.get(id) ?? []) {\n if (seen.has(child)) continue;\n seen.add(child);\n walk(child);\n out.push(child);\n }\n };\n walk(rootAnchorId);\n return out;\n}\n\nexport class CommentGutter {\n readonly element: HTMLElement;\n\n private readonly host: CommentGutterHost;\n private readonly options: Required<Omit<CommentGutterOptions, \"onChange\">> &\n Pick<CommentGutterOptions, \"onChange\">;\n private readonly leaders: SVGSVGElement;\n private frame: number | null = null;\n private mutations: MutationObserver | null = null;\n private resize: ResizeObserver | null = null;\n private activeId: string | null = null;\n private draft: HTMLElement | null = null;\n private draftTarget: CommentTarget | null = null;\n private draftAnchorTop = 0;\n private editing: string | null = null;\n private replying: string | null = null;\n private expanded = new Set<string>();\n private visible = true;\n private disposed = false;\n private readonly onContainerClick: (event: MouseEvent) => void;\n\n constructor(host: CommentGutterHost, options: CommentGutterOptions = {}) {\n this.host = host;\n this.options = {\n width: options.width ?? 248,\n gap: options.gap ?? 8,\n onChange: options.onChange,\n };\n const doc = host.container.ownerDocument;\n this.element = doc.createElement(\"aside\");\n this.element.className = \"docx-comment-gutter\";\n this.element.setAttribute(\"data-docx-comments\", \"\");\n this.element.style.width = `${this.options.width}px`;\n this.leaders = doc.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n this.leaders.setAttribute(\"class\", \"docx-comment-leaders\");\n this.leaders.setAttribute(\"aria-hidden\", \"true\");\n if (getComputedStyle(host.container).position === \"static\") {\n host.container.style.position = \"relative\";\n }\n host.container.appendChild(this.leaders);\n host.container.appendChild(this.element);\n\n this.onContainerClick = (event) => {\n const target = event.target as HTMLElement | null;\n if (!target || this.element.contains(target)) return;\n const hit = target.closest<HTMLElement>(`${HIGHLIGHT_SELECTOR}, ${MARKER_SELECTOR}`);\n if (!hit) return;\n const id = idsOf(hit)[0];\n if (id) this.setActive(id, { scrollBubble: true });\n };\n host.container.addEventListener(\"click\", this.onContainerClick);\n\n if (typeof MutationObserver !== \"undefined\") {\n this.mutations = new MutationObserver((records) => {\n for (const record of records) {\n const node = record.target as Node;\n if (this.element.contains(node) || this.leaders.contains(node)) continue;\n this.schedule();\n return;\n }\n });\n this.mutations.observe(host.container, {\n childList: true, subtree: true, characterData: true, attributes: true,\n attributeFilter: [\"style\", \"class\", \"data-anchor\"],\n });\n }\n if (typeof ResizeObserver !== \"undefined\") {\n this.resize = new ResizeObserver(() => this.schedule());\n this.resize.observe(host.container);\n }\n this.schedule();\n }\n\n // \u2500\u2500 public surface \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Re-derive and re-position every bubble on the next animation frame. */\n schedule(): void {\n if (this.disposed || this.frame != null) return;\n const view = this.host.container.ownerDocument.defaultView;\n if (!view) return;\n this.frame = view.requestAnimationFrame(() => {\n this.frame = null;\n this.layout();\n });\n }\n\n /** Synchronous layout (tests, and callers that need the DOM settled now). */\n layout(): void {\n if (this.disposed) return;\n const doc = this.host.container.ownerDocument;\n const comments = this.host.listComments();\n const byId = new Map<string, CommentListEntry>();\n for (const entry of comments) byId.set(entry.anchorId, entry);\n const roots = comments.filter((c) => !c.parentAnchorId || !byId.has(c.parentAnchorId));\n const repliesOf = new Map<string, CommentListEntry[]>();\n for (const entry of comments) {\n if (!entry.parentAnchorId || !byId.has(entry.parentAnchorId)) continue;\n let root = byId.get(entry.parentAnchorId)!;\n // Reply-to-reply chains hang off the thread root, as Word draws them.\n const seen = new Set<string>();\n while (root.parentAnchorId && byId.has(root.parentAnchorId) && !seen.has(root.anchorId)) {\n seen.add(root.anchorId);\n root = byId.get(root.parentAnchorId)!;\n }\n const list = repliesOf.get(root.anchorId) ?? [];\n list.push(entry);\n repliesOf.set(root.anchorId, list);\n }\n\n // Reuse bubble nodes across layouts so an open textarea keeps its focus and text.\n const existing = new Map<string, HTMLElement>();\n for (const el of Array.from(this.element.querySelectorAll<HTMLElement>(\"[data-thread]\"))) {\n existing.set(el.dataset.thread!, el);\n }\n\n // Measure with the gutter shown: an empty gutter is display:none, whose rect is all zeros,\n // and every bubble top below is relative to it. The toggle at the end hides it again when\n // nothing is left to show.\n this.element.toggleAttribute(\"data-empty\", roots.length === 0 && !this.draft);\n const containerRect = this.host.container.getBoundingClientRect();\n const gutterRect = this.element.getBoundingClientRect();\n const views: ThreadView[] = [];\n for (const root of roots) {\n const anchor = this.anchorFor(root);\n const replies = repliesOf.get(root.anchorId) ?? [];\n let bubble = existing.get(root.anchorId);\n existing.delete(root.anchorId);\n const key = this.bubbleKey(root, replies);\n if (!bubble || bubble.dataset.key !== key) {\n const fresh = this.buildBubble(root, replies, doc);\n fresh.dataset.key = key;\n if (bubble) bubble.replaceWith(fresh);\n else this.element.appendChild(fresh);\n bubble = fresh;\n }\n const rect = anchor?.getBoundingClientRect();\n const desiredTop = rect ? rect.top - gutterRect.top : Number.POSITIVE_INFINITY;\n const desiredLeft = rect ? rect.left : Number.POSITIVE_INFINITY;\n views.push({ root, replies, anchor, bubble, desiredTop, desiredLeft });\n this.markHighlights(root, replies, anchor);\n }\n for (const stale of existing.values()) stale.remove();\n\n // Word orders the markup area by document position, not by comment id.\n views.sort(\n (a, b) =>\n a.desiredTop - b.desiredTop ||\n a.desiredLeft - b.desiredLeft ||\n a.root.anchorId.localeCompare(b.root.anchorId),\n );\n\n const gap = this.options.gap;\n let cursor = 0;\n const placed: Array<{ view: ThreadView | null; top: number; el: HTMLElement }> = [];\n let draftPlaced = false;\n const placeDraft = () => {\n if (!this.draft || draftPlaced) return;\n const top = Math.max(this.draftAnchorTop, cursor);\n this.draft.style.top = `${top}px`;\n cursor = top + this.draft.offsetHeight + gap;\n placed.push({ view: null, top, el: this.draft });\n draftPlaced = true;\n };\n for (const view of views) {\n if (this.draft && !draftPlaced && this.draftAnchorTop <= view.desiredTop) placeDraft();\n const orphan = !Number.isFinite(view.desiredTop);\n view.bubble.toggleAttribute(\"data-orphan\", orphan);\n const wanted = orphan ? cursor : Math.max(0, view.desiredTop);\n const top = Math.max(wanted, cursor);\n view.bubble.style.top = `${top}px`;\n cursor = top + view.bubble.offsetHeight + gap;\n placed.push({ view, top, el: view.bubble });\n }\n placeDraft();\n\n // Leader lines: from the highlight's right edge to the bubble's top-left, in the\n // container's coordinate space (the SVG covers the whole scrollable content).\n const scrollW = this.host.container.scrollWidth;\n const scrollH = this.host.container.scrollHeight;\n this.leaders.setAttribute(\"width\", String(scrollW));\n this.leaders.setAttribute(\"height\", String(scrollH));\n this.leaders.style.width = `${scrollW}px`;\n this.leaders.style.height = `${scrollH}px`;\n const paths: string[] = [];\n const offX = this.host.container.scrollLeft - containerRect.left;\n const offY = this.host.container.scrollTop - containerRect.top;\n const gutterX = gutterRect.left + offX;\n for (const { view, top } of placed) {\n const rect = view?.anchor?.getBoundingClientRect();\n const active = view ? view.root.anchorId === this.activeId : true;\n const source = rect ?? (view === null && this.draftTarget\n ? this.draftTarget.block.getBoundingClientRect()\n : null);\n if (!source) continue;\n // Leave the highlight along its baseline, the way Word's connector does: a line at the\n // underline position reads as an extension of the highlight rather than a strike through\n // the rest of the line.\n const x1 = source.right + offX;\n const y1 = source.bottom + offY - 1;\n const y2 = gutterRect.top + offY + top + 14;\n const x2 = gutterX;\n const xm = x2 - 14;\n paths.push(\n `<path d=\"M${x1.toFixed(1)} ${y1.toFixed(1)} H${xm.toFixed(1)} L${x2.toFixed(1)} ${y2.toFixed(1)}\"` +\n ` class=\"docx-comment-leader${active ? \" docx-comment-leader-active\" : \"\"}\"/>`,\n );\n }\n this.leaders.innerHTML = paths.join(\"\");\n this.element.toggleAttribute(\"data-empty\", views.length === 0 && !this.draft);\n this.element.hidden = !this.visible;\n this.leaders.style.display = this.visible ? \"\" : \"none\";\n this.options.onChange?.({\n threads: views.length,\n open: views.filter((v) => !v.root.resolved).length,\n active: this.activeId,\n });\n }\n\n /** Re-append the gutter's elements after the container was emptied by a mount. */\n reattach(): void {\n if (this.disposed) return;\n this.host.container.appendChild(this.leaders);\n this.host.container.appendChild(this.element);\n this.schedule();\n }\n\n /** Show or hide the markup area (Word's \"Show Comments\"). */\n setVisible(visible: boolean): void {\n const wasVisible = this.visible;\n this.visible = visible;\n this.element.hidden = !visible;\n this.leaders.style.display = visible ? \"\" : \"none\";\n this.host.container.toggleAttribute(\"data-comments-hidden\", !visible);\n // Layouts that ran while hidden measured a zero-height gutter and zero-height bubbles;\n // place everything again now that it can be measured.\n if (visible && !wasVisible) this.schedule();\n }\n\n get isVisible(): boolean {\n return this.visible;\n }\n\n /** The active thread root's anchor id, if any. */\n get active(): string | null {\n return this.activeId;\n }\n\n /** Activate a thread: its bubble lifts, its highlight darkens, and (optionally) it scrolls\n * into view. Pass null to clear. */\n setActive(id: string | null, opts: { scrollBubble?: boolean; scrollAnchor?: boolean } = {}): void {\n const comments = this.host.listComments();\n // A numeric id (from a highlight) or a cmt anchor id both resolve to the thread root.\n let root: CommentListEntry | undefined;\n if (id != null) {\n const byId = new Map(comments.map((c) => [c.anchorId, c] as const));\n root = comments.find((c) => c.anchorId === id || String(c.id) === id);\n const seen = new Set<string>();\n while (root?.parentAnchorId && byId.has(root.parentAnchorId) && !seen.has(root.anchorId)) {\n seen.add(root.anchorId);\n root = byId.get(root.parentAnchorId);\n }\n }\n this.activeId = root?.anchorId ?? null;\n for (const el of Array.from(this.element.querySelectorAll<HTMLElement>(\"[data-thread]\"))) {\n el.toggleAttribute(\"data-active\", el.dataset.thread === this.activeId);\n }\n for (const el of Array.from(this.host.container.querySelectorAll<HTMLElement>(HIGHLIGHT_SELECTOR))) {\n el.classList.toggle(\"docx-comment-active\", !!root && idsOf(el).includes(String(root.id)));\n }\n if (root && opts.scrollBubble) {\n this.element.querySelector<HTMLElement>(`[data-thread=\"${CSS.escape(root.anchorId)}\"]`)\n ?.scrollIntoView({ block: \"nearest\", behavior: \"smooth\" });\n }\n if (root && opts.scrollAnchor) {\n this.anchorFor(root)?.scrollIntoView({ block: \"center\", behavior: \"smooth\" });\n }\n this.schedule();\n }\n\n /** Thread roots in document order \u2014 what Previous/Next step through. */\n threadsInOrder(): CommentListEntry[] {\n const comments = this.host.listComments();\n const byId = new Set(comments.map((c) => c.anchorId));\n const roots = comments.filter((c) => !c.parentAnchorId || !byId.has(c.parentAnchorId));\n return roots\n .map((root) => {\n const rect = this.anchorFor(root)?.getBoundingClientRect();\n return { root, top: rect?.top ?? Number.POSITIVE_INFINITY, left: rect?.left ?? Number.POSITIVE_INFINITY };\n })\n .sort((a, b) => a.top - b.top || a.left - b.left || a.root.anchorId.localeCompare(b.root.anchorId))\n .map((x) => x.root);\n }\n\n /** Activate the thread after (or before) the active one, wrapping around. */\n step(direction: 1 | -1): CommentListEntry | null {\n const order = this.threadsInOrder();\n if (order.length === 0) return null;\n const index = order.findIndex((c) => c.anchorId === this.activeId);\n const next = index < 0\n ? (direction > 0 ? order[0] : order[order.length - 1])\n : order[(index + direction + order.length) % order.length];\n this.setActive(next.anchorId, { scrollBubble: true, scrollAnchor: true });\n return next;\n }\n\n /**\n * Start a new comment on the current selection: a draft bubble appears beside it with a\n * focused textarea. Posting goes through the editor; cancelling removes the draft. Returns\n * false when nothing is selected/focused to comment on.\n */\n beginDraft(): boolean {\n const target = this.host.commentTarget();\n if (!target) return false;\n this.cancelDraft();\n this.draftTarget = target;\n const doc = this.host.container.ownerDocument;\n // The first comment in a document drafts against a gutter that is still display:none\n // (no threads); its rect is zeros until shown, and the draft's top is relative to it.\n this.element.removeAttribute(\"data-empty\");\n const gutterRect = this.element.getBoundingClientRect();\n const sel = doc.defaultView?.getSelection();\n let rect: DOMRect | null = null;\n if (sel && sel.rangeCount > 0 && !sel.isCollapsed) {\n const r = sel.getRangeAt(0).getBoundingClientRect();\n if (r.height > 0) rect = r;\n }\n rect ??= target.block.getBoundingClientRect();\n this.draftAnchorTop = Math.max(0, rect.top - gutterRect.top);\n\n const bubble = doc.createElement(\"div\");\n bubble.className = \"docx-comment-bubble\";\n bubble.setAttribute(\"data-draft\", \"\");\n bubble.setAttribute(\"data-active\", \"\");\n bubble.style.setProperty(\"--docx-comment-hue\", String(authorHue(this.host.commentAuthor)));\n bubble.innerHTML =\n `<div class=\"docx-comment-head\"><span class=\"docx-comment-avatar\">${initialsOf(this.host.commentAuthor)}</span>` +\n `<span class=\"docx-comment-author\"></span></div>` +\n `<textarea class=\"docx-comment-input\" rows=\"3\" placeholder=\"Type a comment\u2026\" data-comment-draft-text></textarea>` +\n `<div class=\"docx-comment-actions\">` +\n `<button type=\"button\" class=\"docx-comment-primary\" data-comment-action=\"post\">Post</button>` +\n `<button type=\"button\" data-comment-action=\"cancel\">Cancel</button></div>`;\n bubble.querySelector(\".docx-comment-author\")!.textContent = this.host.commentAuthor;\n const input = bubble.querySelector<HTMLTextAreaElement>(\"textarea\")!;\n const post = () => {\n const text = input.value.trim();\n if (!text) { input.focus(); return; }\n const created = this.host.addComment(text, this.host.commentAuthor, target);\n this.cancelDraft();\n if (created) this.setActive(created.anchorId, { scrollBubble: true });\n else this.schedule();\n };\n bubble.querySelector('[data-comment-action=\"post\"]')!.addEventListener(\"click\", post);\n bubble.querySelector('[data-comment-action=\"cancel\"]')!.addEventListener(\"click\", () => this.cancelDraft());\n input.addEventListener(\"keydown\", (event) => {\n const key = event as KeyboardEvent;\n if (key.key === \"Escape\") { key.preventDefault(); this.cancelDraft(); }\n if (key.key === \"Enter\" && (key.ctrlKey || key.metaKey)) { key.preventDefault(); post(); }\n });\n // Mousedown on the draft must not collapse the document selection until the target is\n // captured \u2014 it already is, so let the textarea take focus normally.\n this.draft = bubble;\n this.element.appendChild(bubble);\n this.activeId = null;\n this.layout();\n input.focus();\n return true;\n }\n\n /** Remove the draft bubble, if any. */\n cancelDraft(): void {\n if (!this.draft) return;\n this.draft.remove();\n this.draft = null;\n this.draftTarget = null;\n this.schedule();\n }\n\n get hasDraft(): boolean {\n return this.draft !== null;\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n const view = this.host.container.ownerDocument.defaultView;\n if (this.frame != null) view?.cancelAnimationFrame(this.frame);\n this.frame = null;\n this.mutations?.disconnect();\n this.resize?.disconnect();\n this.host.container.removeEventListener(\"click\", this.onContainerClick);\n this.element.remove();\n this.leaders.remove();\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** The first highlight (else marker) carrying the thread's numeric id, in the live DOM. */\n private anchorFor(root: CommentListEntry): HTMLElement | null {\n const id = String(root.id);\n const candidates = this.host.container.querySelectorAll<HTMLElement>(\n `${HIGHLIGHT_SELECTOR}, ${MARKER_SELECTOR}`,\n );\n let marker: HTMLElement | null = null;\n for (const el of Array.from(candidates)) {\n if (this.element.contains(el)) continue;\n if (!idsOf(el).includes(id)) continue;\n // Hidden staging/registry copies must never win over the visible page.\n if (el.closest(\"#pagination-staging, [id^='pagination-'][style*='display:none'], [data-hf-inert]\")) continue;\n if (el.matches(HIGHLIGHT_SELECTOR)) return el;\n marker ??= el;\n }\n return marker;\n }\n\n private markHighlights(root: CommentListEntry, replies: CommentListEntry[], anchor: HTMLElement | null): void {\n const ids = new Set([String(root.id), ...replies.map((r) => String(r.id))]);\n const hue = String(authorHue(root.author || \"\"));\n for (const el of Array.from(this.host.container.querySelectorAll<HTMLElement>(HIGHLIGHT_SELECTOR))) {\n if (this.element.contains(el)) continue;\n if (!idsOf(el).some((x) => ids.has(x))) continue;\n // Only write what changed: the document's MutationObserver schedules a layout on every\n // style/class mutation, so an unconditional write here would lay out forever.\n if (el.style.getPropertyValue(\"--docx-comment-hue\") !== hue) el.style.setProperty(\"--docx-comment-hue\", hue);\n el.toggleAttribute(\"data-comment-resolved\", !!root.resolved);\n el.classList.toggle(\"docx-comment-active\", root.anchorId === this.activeId);\n }\n void anchor;\n }\n\n private bubbleKey(root: CommentListEntry, replies: CommentListEntry[]): string {\n const parts = [root.anchorId, root.author, root.date ?? \"\", root.text, root.resolved ? \"r\" : \"o\"];\n for (const r of replies) parts.push(r.anchorId, r.author, r.date ?? \"\", r.text);\n parts.push(this.editing === root.anchorId ? \"edit\" : \"\", this.replying === root.anchorId ? \"reply\" : \"\");\n parts.push(this.expanded.has(root.anchorId) ? \"x\" : \"\");\n for (const r of replies) if (this.editing === r.anchorId) parts.push(`edit:${r.anchorId}`);\n return parts.join(\"\u0001\");\n }\n\n private buildBubble(root: CommentListEntry, replies: CommentListEntry[], doc: Document): HTMLElement {\n const bubble = doc.createElement(\"div\");\n bubble.className = \"docx-comment-bubble\";\n bubble.dataset.thread = root.anchorId;\n bubble.dataset.commentId = String(root.id);\n bubble.style.setProperty(\"--docx-comment-hue\", String(authorHue(root.author || \"\")));\n if (root.resolved) bubble.setAttribute(\"data-resolved\", \"\");\n if (root.anchorId === this.activeId) bubble.setAttribute(\"data-active\", \"\");\n const collapsed = !!root.resolved && !this.expanded.has(root.anchorId);\n if (collapsed) bubble.setAttribute(\"data-collapsed\", \"\");\n\n bubble.appendChild(this.buildEntry(root, doc, true));\n for (const reply of replies) bubble.appendChild(this.buildEntry(reply, doc, false));\n\n if (!collapsed) {\n if (this.replying === root.anchorId) {\n const input = doc.createElement(\"textarea\");\n input.className = \"docx-comment-input\";\n input.rows = 2;\n input.placeholder = \"Reply\u2026\";\n input.setAttribute(\"data-comment-reply-text\", \"\");\n const actions = doc.createElement(\"div\");\n actions.className = \"docx-comment-actions\";\n const post = doc.createElement(\"button\");\n post.type = \"button\";\n post.className = \"docx-comment-primary\";\n post.textContent = \"Reply\";\n post.setAttribute(\"data-comment-action\", \"post-reply\");\n const cancel = doc.createElement(\"button\");\n cancel.type = \"button\";\n cancel.textContent = \"Cancel\";\n cancel.setAttribute(\"data-comment-action\", \"cancel-reply\");\n const submit = () => {\n const text = input.value.trim();\n if (!text) { input.focus(); return; }\n this.replying = null;\n this.host.addCommentReply(root.anchorId, text, this.host.commentAuthor);\n this.setActive(root.anchorId);\n };\n post.addEventListener(\"click\", submit);\n cancel.addEventListener(\"click\", () => { this.replying = null; this.schedule(); });\n input.addEventListener(\"keydown\", (event) => {\n const key = event as KeyboardEvent;\n if (key.key === \"Escape\") { key.preventDefault(); this.replying = null; this.schedule(); }\n if (key.key === \"Enter\" && (key.ctrlKey || key.metaKey)) { key.preventDefault(); submit(); }\n });\n actions.append(post, cancel);\n bubble.append(input, actions);\n queueMicrotask(() => input.focus());\n } else {\n const bar = doc.createElement(\"div\");\n bar.className = \"docx-comment-bar\";\n const reply = doc.createElement(\"button\");\n reply.type = \"button\";\n reply.textContent = \"Reply\";\n reply.setAttribute(\"data-comment-action\", \"reply\");\n reply.addEventListener(\"click\", () => {\n this.replying = root.anchorId;\n this.editing = null;\n this.setActive(root.anchorId);\n // Build the reply box now, not on the next frame: the click handler returns before a\n // scheduled layout would run, and a keystroke that lands in between goes to the page\n // instead of the textarea \u2014 the first letter of a quickly typed reply vanished.\n this.layout();\n });\n const resolve = doc.createElement(\"button\");\n resolve.type = \"button\";\n resolve.textContent = root.resolved ? \"Reopen\" : \"Resolve\";\n resolve.setAttribute(\"data-comment-action\", root.resolved ? \"reopen\" : \"resolve\");\n resolve.addEventListener(\"click\", () => {\n this.host.setCommentResolved(root.anchorId, !root.resolved);\n if (!root.resolved) this.expanded.delete(root.anchorId);\n this.setActive(root.anchorId);\n });\n bar.append(reply, resolve);\n bubble.appendChild(bar);\n }\n }\n\n bubble.addEventListener(\"mousedown\", (event) => {\n // Buttons and inputs must keep working; a click on the bubble body just activates it.\n const t = event.target as HTMLElement;\n if (t.closest(\"button, textarea, input, a\")) return;\n if (collapsed) { this.expanded.add(root.anchorId); }\n this.setActive(root.anchorId, { scrollAnchor: true });\n });\n return bubble;\n }\n\n private buildEntry(entry: CommentListEntry, doc: Document, isRoot: boolean): HTMLElement {\n const el = doc.createElement(\"div\");\n el.className = isRoot ? \"docx-comment-entry docx-comment-root\" : \"docx-comment-entry docx-comment-reply\";\n el.dataset.comment = entry.anchorId;\n const head = doc.createElement(\"div\");\n head.className = \"docx-comment-head\";\n const avatar = doc.createElement(\"span\");\n avatar.className = \"docx-comment-avatar\";\n avatar.textContent = initialsOf(entry.author || \"\", entry.initials);\n avatar.style.setProperty(\"--docx-comment-hue\", String(authorHue(entry.author || \"\")));\n const author = doc.createElement(\"span\");\n author.className = \"docx-comment-author\";\n author.textContent = entry.author || \"Unknown\";\n const date = doc.createElement(\"span\");\n date.className = \"docx-comment-date\";\n date.textContent = formatDate(entry.date);\n head.append(avatar, author, date);\n if (isRoot && entry.resolved) {\n const badge = doc.createElement(\"span\");\n badge.className = \"docx-comment-badge\";\n badge.textContent = \"Resolved\";\n head.appendChild(badge);\n }\n const menu = doc.createElement(\"span\");\n menu.className = \"docx-comment-menu\";\n const edit = doc.createElement(\"button\");\n edit.type = \"button\";\n edit.title = \"Edit\";\n edit.setAttribute(\"aria-label\", \"Edit comment\");\n edit.setAttribute(\"data-comment-action\", \"edit\");\n edit.innerHTML = \"✎\";\n edit.addEventListener(\"click\", () => { this.editing = entry.anchorId; this.replying = null; this.layout(); });\n const del = doc.createElement(\"button\");\n del.type = \"button\";\n del.title = isRoot ? \"Delete thread\" : \"Delete reply\";\n del.setAttribute(\"aria-label\", del.title);\n del.setAttribute(\"data-comment-action\", \"delete\");\n del.innerHTML = \"🗑\";\n del.addEventListener(\"click\", () => {\n if (isRoot) {\n // A deleted root would orphan its replies into top-level comments; take the thread\n // down, replies to replies included.\n for (const id of threadMembers(this.host.listComments(), entry.anchorId)) this.host.removeComment(id);\n }\n this.host.removeComment(entry.anchorId);\n if (this.activeId === entry.anchorId) this.activeId = null;\n this.schedule();\n });\n menu.append(edit, del);\n head.appendChild(menu);\n el.appendChild(head);\n\n if (this.editing === entry.anchorId) {\n const input = doc.createElement(\"textarea\");\n input.className = \"docx-comment-input\";\n input.rows = 3;\n input.value = entry.text;\n input.setAttribute(\"data-comment-edit-text\", \"\");\n const actions = doc.createElement(\"div\");\n actions.className = \"docx-comment-actions\";\n const save = doc.createElement(\"button\");\n save.type = \"button\";\n save.className = \"docx-comment-primary\";\n save.textContent = \"Save\";\n save.setAttribute(\"data-comment-action\", \"save\");\n const cancel = doc.createElement(\"button\");\n cancel.type = \"button\";\n cancel.textContent = \"Cancel\";\n cancel.setAttribute(\"data-comment-action\", \"cancel-edit\");\n const submit = () => {\n const text = input.value.trim();\n this.editing = null;\n if (text && text !== entry.text) this.host.updateComment(entry.anchorId, text);\n this.schedule();\n };\n save.addEventListener(\"click\", submit);\n cancel.addEventListener(\"click\", () => { this.editing = null; this.schedule(); });\n input.addEventListener(\"keydown\", (event) => {\n const key = event as KeyboardEvent;\n if (key.key === \"Escape\") { key.preventDefault(); this.editing = null; this.schedule(); }\n if (key.key === \"Enter\" && (key.ctrlKey || key.metaKey)) { key.preventDefault(); submit(); }\n });\n actions.append(save, cancel);\n el.append(input, actions);\n queueMicrotask(() => { input.focus(); input.setSelectionRange(input.value.length, input.value.length); });\n } else {\n const body = doc.createElement(\"div\");\n body.className = \"docx-comment-text\";\n body.textContent = entry.text;\n el.appendChild(body);\n }\n return el;\n }\n}\n\n/** The gutter's stylesheet \u2014 injected once per document by the editor. Scoped to the classes\n * this module emits, so it is safe on a host page. Colours derive from a per-author hue so a\n * reviewer's highlight and bubble read as one. */\nexport const COMMENT_GUTTER_CSS = `\n.docx-comment-gutter {\n position: absolute; top: 0; right: 0; bottom: 0; z-index: 4;\n pointer-events: none; font: 12.5px/1.4 \"Inter\", system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n}\n.docx-comment-gutter[data-empty] { display: none; }\n.docx-comment-leaders { position: absolute; top: 0; left: 0; z-index: 3; pointer-events: none; overflow: visible; }\n.docx-comment-leader { fill: none; stroke: hsl(var(--docx-comment-hue, 200) 45% 62%); stroke-width: 1; stroke-dasharray: 3 3; opacity: .55; }\n.docx-comment-leader-active { stroke-dasharray: none; opacity: .95; stroke-width: 1.5; }\n.docx-comment-bubble {\n position: absolute; left: 12px; right: 8px; pointer-events: auto;\n padding: 9px 10px 8px; border: 1px solid hsl(var(--docx-comment-hue, 200) 40% 78%);\n border-left: 3px solid hsl(var(--docx-comment-hue, 200) 55% 55%);\n border-radius: 8px; background: #fff; color: #1e293b;\n box-shadow: 0 1px 2px rgba(15, 23, 42, .06), 0 3px 8px rgba(15, 23, 42, .05);\n transition: top .18s cubic-bezier(.4,0,.2,1), box-shadow .15s ease, transform .15s ease;\n}\n.docx-comment-bubble[data-active] {\n border-color: hsl(var(--docx-comment-hue, 200) 55% 55%);\n box-shadow: 0 2px 6px rgba(15, 23, 42, .08), 0 10px 22px rgba(15, 23, 42, .1);\n transform: translateX(-4px); z-index: 2;\n}\n.docx-comment-bubble[data-resolved] { opacity: .72; background: #f8fafc; }\n.docx-comment-bubble[data-collapsed] .docx-comment-text { display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; color: #64748b; }\n.docx-comment-bubble[data-collapsed] .docx-comment-reply, .docx-comment-bubble[data-collapsed] .docx-comment-bar { display: none; }\n.docx-comment-bubble[data-orphan] { border-style: dashed; }\n.docx-comment-bubble[data-draft] { border-style: solid; }\n.docx-comment-entry + .docx-comment-entry { margin-top: 8px; padding-top: 8px; border-top: 1px solid #f1f5f9; }\n.docx-comment-reply { margin-left: 10px; }\n.docx-comment-head { display: flex; align-items: center; gap: 6px; min-height: 20px; }\n.docx-comment-avatar {\n display: inline-grid; place-items: center; flex: 0 0 auto; width: 20px; height: 20px; border-radius: 50%;\n background: hsl(var(--docx-comment-hue, 200) 55% 45%); color: #fff; font-size: 9px; font-weight: 700; letter-spacing: .02em;\n}\n.docx-comment-author { font-weight: 600; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.docx-comment-date { color: #94a3b8; font-size: 10.5px; white-space: nowrap; margin-left: auto; }\n.docx-comment-badge { padding: 1px 6px; border-radius: 999px; background: #dcfce7; color: #166534; font-size: 9.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; }\n.docx-comment-menu { display: none; gap: 2px; margin-left: 4px; }\n.docx-comment-bubble:hover .docx-comment-menu, .docx-comment-bubble[data-active] .docx-comment-menu { display: inline-flex; }\n.docx-comment-menu button {\n padding: 0 4px; min-height: 18px; border: 0; border-radius: 4px; background: none; color: #94a3b8; font-size: 12px; line-height: 1; cursor: pointer;\n}\n.docx-comment-menu button:hover { background: #f1f5f9; color: #1e293b; }\n.docx-comment-text { margin: 5px 0 0; white-space: pre-wrap; word-wrap: break-word; color: #334155; }\n.docx-comment-bar { display: flex; gap: 6px; margin-top: 8px; }\n.docx-comment-bar button, .docx-comment-actions button {\n min-height: 24px; padding: 2px 9px; border: 1px solid #e2e8f0; border-radius: 6px; background: #fff; color: #1e293b;\n font: inherit; font-size: 11.5px; font-weight: 500; cursor: pointer;\n}\n.docx-comment-bar button:hover, .docx-comment-actions button:hover { background: #f1f5f9; }\n.docx-comment-actions { display: flex; gap: 6px; margin-top: 6px; }\n.docx-comment-actions .docx-comment-primary { background: #0f766e; border-color: #0f766e; color: #fff; }\n.docx-comment-actions .docx-comment-primary:hover { background: #0d9488; }\n.docx-comment-input {\n display: block; width: 100%; margin-top: 6px; padding: 6px 8px; border: 1px solid #cbd5e1; border-radius: 6px;\n background: #fff; color: #1e293b; font: inherit; font-size: 12.5px; line-height: 1.4; resize: vertical; box-sizing: border-box;\n}\n.docx-comment-input:focus { outline: 2px solid #0f766e; outline-offset: 1px; border-color: #0f766e; }\n/* The commented range itself. The converter's stylesheet paints a flat yellow; the editor\n tints by author and lifts the active thread the way Word does. */\nspan.comment-highlight[data-comment-id] {\n background: hsl(var(--docx-comment-hue, 45) 90% 88%);\n border-bottom: 2px solid hsl(var(--docx-comment-hue, 45) 70% 55%);\n cursor: pointer;\n}\nspan.comment-highlight[data-comment-id][data-comment-resolved] { background: transparent; border-bottom-color: #cbd5e1; }\nspan.comment-highlight.docx-comment-active { background: hsl(var(--docx-comment-hue, 45) 90% 78%); }\n/* The [n] reference marker is engine chrome, not document text: hide it, keep the anchor.\n (Qualified by the editor's roots to outrank the converter's own a.comment-marker rule,\n which is injected later in the document.) */\n.docx-body-flow a.comment-marker, [data-hf-band] a.comment-marker, .page-box a.comment-marker { display: none; }\n[data-comments-hidden] span.comment-highlight[data-comment-id] { background: transparent; border-bottom-color: transparent; }\n`;\n", "function _arrayWithHoles(r) {\n if (Array.isArray(r)) return r;\n}\nexport { _arrayWithHoles as default };", "function _iterableToArrayLimit(r, l) {\n var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"];\n if (null != t) {\n var e,\n n,\n i,\n u,\n a = [],\n f = !0,\n o = !1;\n try {\n if (i = (t = t.call(r)).next, 0 === l) {\n if (Object(t) !== t) return;\n f = !1;\n } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);\n } catch (r) {\n o = !0, n = r;\n } finally {\n try {\n if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return;\n } finally {\n if (o) throw n;\n }\n }\n return a;\n }\n}\nexport { _iterableToArrayLimit as default };", "function _arrayLikeToArray(r, a) {\n (null == a || a > r.length) && (a = r.length);\n for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];\n return n;\n}\nexport { _arrayLikeToArray as default };", "import arrayLikeToArray from \"./arrayLikeToArray.js\";\nfunction _unsupportedIterableToArray(r, a) {\n if (r) {\n if (\"string\" == typeof r) return arrayLikeToArray(r, a);\n var t = {}.toString.call(r).slice(8, -1);\n return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? arrayLikeToArray(r, a) : void 0;\n }\n}\nexport { _unsupportedIterableToArray as default };", "function _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\nexport { _nonIterableRest as default };", "import arrayWithHoles from \"./arrayWithHoles.js\";\nimport iterableToArrayLimit from \"./iterableToArrayLimit.js\";\nimport unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nimport nonIterableRest from \"./nonIterableRest.js\";\nfunction _slicedToArray(r, e) {\n return arrayWithHoles(r) || iterableToArrayLimit(r, e) || unsupportedIterableToArray(r, e) || nonIterableRest();\n}\nexport { _slicedToArray as default };", "import _slicedToArray from \"@babel/runtime/helpers/slicedToArray\";\nimport { bind } from 'bind-event-listener';\nimport { getElementFromPointWithoutHoneypot } from '../honey-pot-fix/get-element-from-point-without-honey-pot';\nimport { makeHoneyPotFix } from '../honey-pot-fix/make-honey-pot-fix';\nimport { makeAdapter } from '../make-adapter/make-adapter';\nimport { combine } from '../public-utils/combine';\nimport { once } from '../public-utils/once';\nimport { addAttribute } from '../util/add-attribute';\nimport { androidFallbackText, isAndroid } from '../util/android';\nimport { getInput } from '../util/get-input';\nimport { textMediaType } from '../util/media-types/text-media-type';\nimport { URLMediaType } from '../util/media-types/url-media-type';\nimport { elementAdapterNativeDataKey } from './element-adapter-native-data-key';\nvar draggableRegistry = new WeakMap();\nfunction addToRegistry(args) {\n draggableRegistry.set(args.element, args);\n return function cleanup() {\n draggableRegistry.delete(args.element);\n };\n}\nvar honeyPotFix = makeHoneyPotFix();\nvar adapter = makeAdapter({\n typeKey: 'element',\n defaultDropEffect: 'move',\n mount: function mount(api) {\n /** Binding event listeners the `document` rather than `window` so that\n * this adapter always gets preference over the text adapter.\n * `document` is the first `EventTarget` under `window`\n * https://twitter.com/alexandereardon/status/1604658588311465985\n */\n return combine(honeyPotFix.bindEvents(), bind(document, {\n type: 'dragstart',\n listener: function listener(event) {\n var _entry$dragHandle, _entry$getInitialData, _entry$getInitialData2, _entry$dragHandle2, _entry$getInitialData3, _entry$getInitialData4;\n if (!api.canStart(event)) {\n return;\n }\n\n // If the \"dragstart\" event is cancelled, then a drag won't start\n // There will be no further drag operation events (eg no \"dragend\" event)\n if (event.defaultPrevented) {\n return;\n }\n\n // Technically `dataTransfer` can be `null` according to the types\n // But that behaviour does not seem to appear in the spec.\n // If there is not `dataTransfer`, we can assume something is wrong and not\n // start a drag\n if (!event.dataTransfer) {\n // Including this code on \"test\" and \"development\" environments:\n // - Browser tests commonly run against \"development\" builds\n // - Unit tests commonly run in \"test\"\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(\"\\n It appears as though you have are not testing DragEvents correctly.\\n\\n - If you are unit testing, ensure you have polyfilled DragEvent.\\n - If you are browser testing, ensure you are dispatching drag events correctly.\\n\\n Please see our testing guides for more information:\\n https://atlassian.design/components/pragmatic-drag-and-drop/core-package/testing\\n \".replace(/ {2}/g, ''));\n }\n return;\n }\n\n // the closest parent that is a draggable element will be marked as\n // the `event.target` for the event\n var target = event.target;\n\n // this source is only for elements\n // Note: only HTMLElements can have the \"draggable\" attribute\n if (!(target instanceof HTMLElement)) {\n return;\n }\n\n // see if the thing being dragged is owned by us\n var entry = draggableRegistry.get(target);\n\n // no matching element found\n // \u2192 dragging an element with `draggable=\"true\"` that is not controlled by us\n if (!entry) {\n return;\n }\n\n /**\n * A text selection drag _can_ have the `draggable` element be\n * the `event.target` if the user is dragging the text selection\n * from the `draggable`.\n *\n * To know if the `draggable` is being dragged, we look at whether any\n * `\"text/plain\"` data is being dragged. If it is, then a text selection\n * drag is occurring.\n *\n * This behaviour has been validated on:\n *\n * - Chrome@128 on Android@14\n * - Chrome@128 on iOS@17.6.1\n * - Chrome@128 on Windows@11\n * - Chrome@128 on MacOS@14.6.1\n * - Firefox@129 on Windows@11 (not possible for user to select text in a draggable)\n * - Firefox@129 on MacOS@14.6.1 (not possible for user to select text in a draggable)\n *\n * Note: Could usually just use: `event.dataTransfer.types.includes(textMediaType)`\n * but unfortunately ProseMirror is always setting `\"\"` as the dragged text\n *\n * Note: Unfortunately editor is (heavily) leaning on the current functionality today\n * and unwinding it will be a decent amount of effort. So for now, a text selection\n * where the `event.target` is a `draggable` element will still trigger the\n * element adapter.\n *\n * // Future state:\n * if(event.dataTransfer.getData(textMediaType)) {\n * \treturn;\n * }\n *\n */\n\n var input = getInput(event);\n var feedback = {\n element: entry.element,\n dragHandle: (_entry$dragHandle = entry.dragHandle) !== null && _entry$dragHandle !== void 0 ? _entry$dragHandle : null,\n input: input\n };\n\n // Check: does the draggable want to allow dragging?\n if (entry.canDrag && !entry.canDrag(feedback)) {\n // cancel drag operation if we cannot drag\n event.preventDefault();\n return;\n }\n\n // Check: is there a drag handle and is the user using it?\n if (entry.dragHandle) {\n // technically don't need this util, but just being\n // consistent with how we look up what is under the users\n // cursor.\n var over = getElementFromPointWithoutHoneypot({\n x: input.clientX,\n y: input.clientY\n });\n\n // if we are not dragging from the drag handle (or something inside the drag handle)\n // then we will cancel the active drag\n if (!entry.dragHandle.contains(over)) {\n event.preventDefault();\n return;\n }\n }\n\n /**\n * **Goal**\n * Pass information to other applications\n *\n * **Approach**\n * Put data into the native data store\n *\n * **What about the native adapter?**\n * When the element adapter puts native data into the native data store\n * the native adapter is not triggered in the current window,\n * but a native adapter in an external window _can_ be triggered\n *\n * **Why bake this into core?**\n * This functionality could be pulled out and exposed inside of\n * `onGenerateDragPreview`. But decided to make it a part of the\n * base API as it felt like a common enough use case and ended\n * up being a similar amount of code to include this function as\n * it was to expose the hook for it\n */\n var nativeData = (_entry$getInitialData = (_entry$getInitialData2 = entry.getInitialDataForExternal) === null || _entry$getInitialData2 === void 0 ? void 0 : _entry$getInitialData2.call(entry, feedback)) !== null && _entry$getInitialData !== void 0 ? _entry$getInitialData : null;\n if (nativeData) {\n for (var _i = 0, _Object$entries = Object.entries(nativeData); _i < _Object$entries.length; _i++) {\n var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),\n key = _Object$entries$_i[0],\n data = _Object$entries$_i[1];\n event.dataTransfer.setData(key, data !== null && data !== void 0 ? data : '');\n }\n }\n\n /**\n * \uD83D\uDCF1 For Android devices, a drag operation will not start unless\n * \"text/plain\" or \"text/uri-list\" data exists in the native data store\n * https://twitter.com/alexandereardon/status/1732189803754713424\n *\n * Tested on:\n * Device: Google Pixel 5\n * Android version: 14 (November 5, 2023)\n * Chrome version: 120.0\n */\n if (isAndroid() && !event.dataTransfer.types.includes(textMediaType) && !event.dataTransfer.types.includes(URLMediaType)) {\n event.dataTransfer.setData(textMediaType, androidFallbackText);\n }\n\n /**\n * 1. Must set any media type for `iOS15` to work\n * 2. We are also doing adding data so that the native adapter\n * can know that the element adapter has handled this drag\n *\n * We used to wrap this `setData()` in a `try/catch` for Firefox,\n * but it looks like that was not needed.\n *\n * Tested using: https://codesandbox.io/s/checking-firefox-throw-behaviour-on-dragstart-qt8h4f\n *\n * - \u2705 Firefox@70.0 (Oct 2019) on macOS Sonoma\n * - \u2705 Firefox@70.0 (Oct 2019) on macOS Big Sur\n * - \u2705 Firefox@70.0 (Oct 2019) on Windows 10\n *\n * // just checking a few more combinations to be super safe\n *\n * - \u2705 Chrome@78 (Oct 2019) on macOS Big Sur\n * - \u2705 Chrome@78 (Oct 2019) on Windows 10\n * - \u2705 Safari@14.1 on macOS Big Sur\n */\n event.dataTransfer.setData(elementAdapterNativeDataKey, '');\n var payload = {\n element: entry.element,\n dragHandle: (_entry$dragHandle2 = entry.dragHandle) !== null && _entry$dragHandle2 !== void 0 ? _entry$dragHandle2 : null,\n data: (_entry$getInitialData3 = (_entry$getInitialData4 = entry.getInitialData) === null || _entry$getInitialData4 === void 0 ? void 0 : _entry$getInitialData4.call(entry, feedback)) !== null && _entry$getInitialData3 !== void 0 ? _entry$getInitialData3 : {}\n };\n var dragType = {\n type: 'element',\n payload: payload,\n startedFrom: 'internal'\n };\n api.start({\n event: event,\n dragType: dragType\n });\n }\n }));\n },\n dispatchEventToSource: function dispatchEventToSource(_ref) {\n var _draggableRegistry$ge, _draggableRegistry$ge2;\n var eventName = _ref.eventName,\n payload = _ref.payload;\n // During a drag operation, a draggable can be:\n // - remounted with different functions\n // - removed completely\n // So we need to get the latest entry from the registry in order\n // to call the latest event functions\n\n (_draggableRegistry$ge = draggableRegistry.get(payload.source.element)) === null || _draggableRegistry$ge === void 0 || (_draggableRegistry$ge2 = _draggableRegistry$ge[eventName]) === null || _draggableRegistry$ge2 === void 0 || _draggableRegistry$ge2.call(_draggableRegistry$ge,\n // I cannot seem to get the types right here.\n // TS doesn't seem to like that one event can need `nativeSetDragImage`\n // @ts-expect-error\n payload);\n },\n onPostDispatch: honeyPotFix.getOnPostDispatch()\n});\nexport var dropTargetForElements = adapter.dropTarget;\n// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports\nexport var monitorForElements = adapter.monitor;\n\n// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports\nexport function draggable(args) {\n // Guardrail: warn if the drag handle is not contained in draggable element\n if (process.env.NODE_ENV !== 'production') {\n if (args.dragHandle && !args.element.contains(args.dragHandle)) {\n // eslint-disable-next-line no-console\n console.warn('Drag handle element must be contained in draggable element', {\n element: args.element,\n dragHandle: args.dragHandle\n });\n }\n }\n // Guardrail: warn if the draggable element is already registered\n if (process.env.NODE_ENV !== 'production') {\n var existing = draggableRegistry.get(args.element);\n if (existing) {\n // eslint-disable-next-line no-console\n console.warn('You have already registered a `draggable` on the same element', {\n existing: existing,\n proposed: args\n });\n }\n }\n var cleanup = combine(\n // making the draggable register the adapter rather than drop targets\n // this is because you *must* have a draggable element to start a drag\n // but you _might_ not have any drop targets immediately\n // (You might create drop targets async)\n adapter.registerUsage(), addToRegistry(args), addAttribute(args.element, {\n attribute: 'draggable',\n value: 'true'\n }));\n\n // Wrapping in `once` to prevent unexpected side effects if consumers call\n // the clean up function multiple times.\n return once(cleanup);\n}\n\n/** Common event payload for all events */\n\n/** A map containing payloads for all events */\n\n/** Common event payload for all drop target events */\n\n/** A map containing payloads for all events on drop targets */\n\n/** Arguments given to all feedback functions (eg `canDrag()`) on for a `draggable()` */\n\n/** Arguments given to all feedback functions (eg `canDrop()`) on a `dropTargetForElements()` */\n\n/** Arguments given to all monitor feedback functions (eg `canMonitor()`) for a `monitorForElements` */", "// pulling this into a separate file so adapter(s) that don't\n// need the honey pot can pay as little as possible for it.\nexport var honeyPotDataAttribute = 'data-pdnd-honey-pot';", "import { honeyPotDataAttribute } from './honey-pot-data-attribute';\nexport function isHoneyPotElement(target) {\n return target instanceof Element && target.hasAttribute(honeyPotDataAttribute);\n}", "import _slicedToArray from \"@babel/runtime/helpers/slicedToArray\";\nimport { isHoneyPotElement } from './is-honey-pot-element';\nexport function getElementFromPointWithoutHoneypot(client) {\n // eslint-disable-next-line no-restricted-syntax\n var _document$elementsFro = document.elementsFromPoint(client.x, client.y),\n _document$elementsFro2 = _slicedToArray(_document$elementsFro, 2),\n top = _document$elementsFro2[0],\n second = _document$elementsFro2[1];\n if (!top) {\n return null;\n }\n if (isHoneyPotElement(top)) {\n return second !== null && second !== void 0 ? second : null;\n }\n return top;\n}", "function _typeof(o) {\n \"@babel/helpers - typeof\";\n\n return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) {\n return typeof o;\n } : function (o) {\n return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o;\n }, _typeof(o);\n}\nexport { _typeof as default };", "import _typeof from \"./typeof.js\";\nfunction toPrimitive(t, r) {\n if (\"object\" != _typeof(t) || !t) return t;\n var e = t[Symbol.toPrimitive];\n if (void 0 !== e) {\n var i = e.call(t, r || \"default\");\n if (\"object\" != _typeof(i)) return i;\n throw new TypeError(\"@@toPrimitive must return a primitive value.\");\n }\n return (\"string\" === r ? String : Number)(t);\n}\nexport { toPrimitive as default };", "import _typeof from \"./typeof.js\";\nimport toPrimitive from \"./toPrimitive.js\";\nfunction toPropertyKey(t) {\n var i = toPrimitive(t, \"string\");\n return \"symbol\" == _typeof(i) ? i : i + \"\";\n}\nexport { toPropertyKey as default };", "import toPropertyKey from \"./toPropertyKey.js\";\nfunction _defineProperty(e, r, t) {\n return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {\n value: t,\n enumerable: !0,\n configurable: !0,\n writable: !0\n }) : e[r] = t, e;\n}\nexport { _defineProperty as default };", "import _defineProperty from \"@babel/runtime/helpers/defineProperty\";\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nimport { bind, bindAll } from 'bind-event-listener';\nimport { maxZIndex } from '../util/max-z-index';\nimport { popoverResetUserAgentStyles } from '../util/popover-reset-styles';\nimport { supportsPopover } from '../util/supports-popover';\nimport { honeyPotDataAttribute } from './honey-pot-data-attribute';\nvar honeyPotSize = 2;\nvar halfHoneyPotSize = honeyPotSize / 2;\n\n/**\n * `clientX` and `clientY` can be in sub pixels (eg `2.332`)\n * However, browser hitbox testing is commonly do to the closest pixel.\n *\n * \u2192 https://issues.chromium.org/issues/40940531\n *\n * To be sure that the honey pot will be over the `client` position,\n * we `.floor()` `clientX` and`clientY` and then make it `2px` in size.\n **/\nfunction floorToClosestPixel(point) {\n return {\n x: Math.floor(point.x),\n y: Math.floor(point.y)\n };\n}\n\n/**\n * We want to make sure the honey pot sits around the users position.\n * This seemed to be the most resilient while testing.\n */\nfunction pullBackByHalfHoneyPotSize(point) {\n return {\n x: point.x - halfHoneyPotSize,\n y: point.y - halfHoneyPotSize\n };\n}\n\n/**\n * Prevent the honey pot from changing the window size.\n * This is super unlikely to occur, but just being safe.\n */\nfunction preventGoingBackwardsOffScreen(point) {\n return {\n x: Math.max(point.x, 0),\n y: Math.max(point.y, 0)\n };\n}\n\n/**\n * Prevent the honey pot from changing the window size.\n * This is super unlikely to occur, but just being safe.\n */\nfunction preventGoingForwardsOffScreen(point) {\n return {\n x: Math.min(point.x, window.innerWidth - honeyPotSize),\n y: Math.min(point.y, window.innerHeight - honeyPotSize)\n };\n}\n\n/**\n * Create a `2x2` `DOMRect` around the `client` position\n */\nfunction getHoneyPotRectFor(_ref) {\n var client = _ref.client;\n var point = preventGoingForwardsOffScreen(preventGoingBackwardsOffScreen(pullBackByHalfHoneyPotSize(floorToClosestPixel(client))));\n\n // When debugging, it is helpful to\n // make this element a bit bigger\n return DOMRect.fromRect({\n x: point.x,\n y: point.y,\n width: honeyPotSize,\n height: honeyPotSize\n });\n}\nfunction getRectStyles(_ref2) {\n var clientRect = _ref2.clientRect;\n return {\n left: \"\".concat(clientRect.left, \"px\"),\n top: \"\".concat(clientRect.top, \"px\"),\n width: \"\".concat(clientRect.width, \"px\"),\n height: \"\".concat(clientRect.height, \"px\")\n };\n}\nfunction isWithin(_ref3) {\n var client = _ref3.client,\n clientRect = _ref3.clientRect;\n return (\n // is within horizontal bounds\n client.x >= clientRect.x && client.x <= clientRect.x + clientRect.width &&\n // is within vertical bounds\n client.y >= clientRect.y && client.y <= clientRect.y + clientRect.height\n );\n}\n/**\n * The honey pot fix is designed to get around a painful bug in all browsers.\n *\n * [Overview](https://www.youtube.com/watch?v=udE9qbFTeQg)\n *\n * **Background**\n *\n * When a drag starts, browsers incorrectly think that the users pointer is\n * still depressed where the drag started. Any element that goes under this position\n * will be entered into, causing `\"mouseenter\"` events and `\":hover\"` styles to be applied.\n *\n * _This is a violation of the spec_\n *\n * > \"From the moment that the user agent is to initiate the drag-and-drop operation,\n * > until the end \tof the drag-and-drop operation, device input events\n * > (e.g. mouse and keyboard events) must be suppressed.\"\n * >\n * > - https://html.spec.whatwg.org/multipage/dnd.html#drag-and-drop-processing-model\n *\n * _Some impacts_\n *\n * - `\":hover\"` styles being applied where they shouldn't (looks messy)\n * - components such as tooltips responding to `\"mouseenter\"` can show during a drag,\n * and on an element the user isn't even over\n *\n * Bug: https://issues.chromium.org/issues/41129937\n *\n * **Honey pot fix**\n *\n * 1. Create an element where the browser thinks the depressed pointer is\n * to absorb the incorrect pointer events\n * 2. Remove that element when it is no longer needed\n */\nfunction mountHoneyPot(_ref4) {\n var initial = _ref4.initial;\n var element = document.createElement('div');\n element.setAttribute(honeyPotDataAttribute, 'true');\n\n // Using popover=\"manual\" to place the element in the browser's top layer.\n // This ensures the honey pot is visually on top of everything else,\n // including elements using z-index and other stacking contexts.\n // \"manual\" means no light dismiss \u2014 we manage the lifecycle ourselves.\n // Falls back to position:fixed + maxZIndex when the popover API is not available.\n if (supportsPopover()) {\n element.setAttribute('popover', 'manual');\n }\n\n // can shift during the drag thanks to Firefox\n var clientRect = getHoneyPotRectFor({\n client: initial\n });\n Object.assign(element.style, _objectSpread(_objectSpread({\n position: 'fixed'\n }, supportsPopover() ?\n // needs to come first as it has 'inset: unset' which\n // needs to be overridden by our top / left values\n popoverResetUserAgentStyles : {\n // Fallback: using maximum possible z-index so that this element\n // will always be on top of other positioned content.\n zIndex: maxZIndex\n }), {}, {\n // Setting a background color explicitly to avoid any inherited styles.\n // Looks like this could be `opacity: 0`, but worried that _might_\n // cause the element to be ignored on some platforms.\n // When debugging, set backgroundColor to something like \"red\".\n backgroundColor: 'transparent',\n // Being explicit to avoid inheriting styles\n padding: 0,\n margin: 0,\n boxSizing: 'border-box',\n // We want this element to absorb pointer events,\n // it's kind of the whole point \uD83D\uDE09\n pointerEvents: 'auto'\n }, getRectStyles({\n clientRect: clientRect\n })));\n document.body.appendChild(element);\n if (supportsPopover()) {\n element.showPopover();\n }\n\n /**\n * \uD83E\uDD8A In firefox we can get `\"pointermove\"` events after the drag\n * has started, which is a spec violation.\n * The final `\"pointermove\"` will reveal where the \"depressed\" position\n * is for our honey pot fix.\n */\n var unbindPointerMove = bind(window, {\n type: 'pointermove',\n listener: function listener(event) {\n var client = {\n x: event.clientX,\n y: event.clientY\n };\n clientRect = getHoneyPotRectFor({\n client: client\n });\n Object.assign(element.style, getRectStyles({\n clientRect: clientRect\n }));\n },\n // using capture so we are less likely to be impacted by event stopping\n options: {\n capture: true\n }\n });\n return function finish(_ref5) {\n var current = _ref5.current;\n // Don't need this any more\n unbindPointerMove();\n\n // If the user is hover the honey pot, we remove it\n // so that the user can continue to interact with the page normally.\n if (isWithin({\n client: current,\n clientRect: clientRect\n })) {\n element.remove();\n return;\n }\n function cleanup() {\n unbindPostDragEvents();\n element.remove();\n }\n var unbindPostDragEvents = bindAll(window, [{\n type: 'pointerdown',\n listener: cleanup\n }, {\n type: 'pointermove',\n listener: cleanup\n }, {\n type: 'focusin',\n listener: cleanup\n }, {\n type: 'focusout',\n listener: cleanup\n },\n // a 'pointerdown' should happen before 'dragstart', but just being super safe\n {\n type: 'dragstart',\n listener: cleanup\n },\n // if the user has dragged something out of the window\n // and then is dragging something back into the window\n // the first events we will see are \"dragenter\" (and then \"dragover\").\n // So if we see any of these we need to clear the post drag fix.\n {\n type: 'dragenter',\n listener: cleanup\n }, {\n type: 'dragover',\n listener: cleanup\n }\n\n // Not adding a \"wheel\" event listener, as \"wheel\" by itself does not\n // resolve the bug.\n ], {\n // Using `capture` so less likely to be impacted by other code stopping events\n capture: true\n });\n };\n}\nexport function makeHoneyPotFix() {\n var latestPointerMove = null;\n function bindEvents() {\n // For sanity, only collecting this value from when events are first bound.\n // This prevents the case where a super old \"pointermove\" could be used\n // from a prior interaction.\n latestPointerMove = null;\n return bind(window, {\n type: 'pointermove',\n listener: function listener(event) {\n latestPointerMove = {\n x: event.clientX,\n y: event.clientY\n };\n },\n // listening for pointer move in capture phase\n // so we are less likely to be impacted by events being stopped.\n options: {\n capture: true\n }\n });\n }\n function getOnPostDispatch() {\n var finish = null;\n return function onPostEvent(_ref6) {\n var eventName = _ref6.eventName,\n payload = _ref6.payload;\n // We are adding the honey pot `onDragStart` so we don't\n // impact the creation of the native drag preview.\n if (eventName === 'onDragStart') {\n var input = payload.location.initial.input;\n\n // Sometimes there will be no latest \"pointermove\" (eg iOS).\n // In which case, we use the start position of the drag.\n var initial = latestPointerMove !== null && latestPointerMove !== void 0 ? latestPointerMove : {\n x: input.clientX,\n y: input.clientY\n };\n\n // Don't need to defensively call `finish()` as `onDrop` from\n // one interaction is guaranteed to be called before `onDragStart`\n // of the next.\n finish = mountHoneyPot({\n initial: initial\n });\n }\n if (eventName === 'onDrop') {\n var _finish;\n var _input = payload.location.current.input;\n (_finish = finish) === null || _finish === void 0 || _finish({\n current: {\n x: _input.clientX,\n y: _input.clientY\n }\n });\n finish = null;\n // this interaction is finished, we want to use\n // the latest \"pointermove\" for each interaction\n latestPointerMove = null;\n }\n };\n }\n return {\n bindEvents: bindEvents,\n getOnPostDispatch: getOnPostDispatch\n };\n}", "// Maximum possible z-index\n// https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index\nexport var maxZIndex = 2147483647;", "/**\n * Resets user agent styles for `[popover]` elements.\n *\n * Browsers apply these defaults to popovers (per the WHATWG HTML spec rendering section):\n * - `inset: 0` + `margin: auto` \u2192 centers the popover in the viewport\n * - `border: solid` \u2192 visible border\n * - `padding: 0.25em` \u2192 internal spacing\n * - `overflow: auto` \u2192 scrollbars when content overflows\n * - `color: CanvasText` + `background-color: Canvas` \u2192 system theme colors\n *\n * This object neutralizes those defaults so the popover behaves like a plain\n * positioned `<div>`, matching the sizing of the legacy (non-popover)\n * fallback container exactly.\n *\n * **Width and height (`auto`)**\n *\n * `width` and `height` override the spec user agent value of `fit-content`\n * with `auto`.\n *\n * _Why?_\n *\n * - When a `[popover]` is sized with `fit-content` and contains a flex\n * container, Safari collapses any flex item that uses `overflow: auto`\n * to `0px`.\n * - Setting the popover's `width` and `height` to `auto` skips the `fit-content`\n * pass and avoids the bug in Safari\n * - Chromium and Firefox tolerate `fit-content` here, but `auto` is safe\n * everywhere and matches our non-popover path\n */\nexport var popoverResetUserAgentStyles = {\n inset: 'unset',\n border: 'none',\n padding: 0,\n margin: 0,\n overflow: 'visible',\n color: 'inherit',\n background: 'transparent',\n width: 'auto',\n height: 'auto'\n};", "/** Provide a function that you only ever want to be called a single time */\nexport function once(fn) {\n var cache = null;\n return function wrapped() {\n if (!cache) {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n var result = fn.apply(this, args);\n cache = {\n result: result\n };\n }\n return cache.result;\n };\n}", "import { once } from '../public-utils/once';\n\n// Using `once` as the value won't change in a browser\n\n/**\n * Returns `true` if the browser supports the Popover API (top-layer).\n *\n * When supported, elements with `popover=\"manual\"` can be promoted to the\n * browser's top layer via `element.showPopover()`, which is more reliable\n * than `z-index` for ensuring an element renders above everything else.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Popover_API\n */\nexport var supportsPopover = once(function supportsPopover() {\n return typeof HTMLElement !== 'undefined' && typeof HTMLElement.prototype.showPopover === 'function';\n});", "import arrayLikeToArray from \"./arrayLikeToArray.js\";\nfunction _arrayWithoutHoles(r) {\n if (Array.isArray(r)) return arrayLikeToArray(r);\n}\nexport { _arrayWithoutHoles as default };", "function _iterableToArray(r) {\n if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r);\n}\nexport { _iterableToArray as default };", "function _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\nexport { _nonIterableSpread as default };", "import arrayWithoutHoles from \"./arrayWithoutHoles.js\";\nimport iterableToArray from \"./iterableToArray.js\";\nimport unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nimport nonIterableSpread from \"./nonIterableSpread.js\";\nfunction _toConsumableArray(r) {\n return arrayWithoutHoles(r) || iterableToArray(r) || unsupportedIterableToArray(r) || nonIterableSpread();\n}\nexport { _toConsumableArray as default };", "import _toConsumableArray from \"@babel/runtime/helpers/toConsumableArray\";\nimport { bindAll } from 'bind-event-listener';\nimport { getElementFromPointWithoutHoneypot } from '../honey-pot-fix/get-element-from-point-without-honey-pot';\nimport { isHoneyPotElement } from '../honey-pot-fix/is-honey-pot-element';\nimport { isLeavingWindow } from '../util/changing-window/is-leaving-window';\nimport { getBindingsForBrokenDrags } from '../util/detect-broken-drag';\nimport { getInput } from '../util/get-input';\nimport { makeDispatch } from './dispatch-consumer-event';\nvar globalState = {\n isActive: false\n};\nfunction canStart() {\n return !globalState.isActive;\n}\nfunction getNativeSetDragImage(event) {\n if (event.dataTransfer) {\n // need to use `.bind` as `setDragImage` is required\n // to be run with `event.dataTransfer` as the \"this\" context\n return event.dataTransfer.setDragImage.bind(event.dataTransfer);\n }\n return null;\n}\nfunction hasHierarchyChanged(_ref) {\n var current = _ref.current,\n next = _ref.next;\n if (current.length !== next.length) {\n return true;\n }\n // not checking stickiness, data or dropEffect,\n // just whether the hierarchy has changed\n for (var i = 0; i < current.length; i++) {\n if (current[i].element !== next[i].element) {\n return true;\n }\n }\n return false;\n}\nfunction start(_ref2) {\n var event = _ref2.event,\n dragType = _ref2.dragType,\n getDropTargetsOver = _ref2.getDropTargetsOver,\n dispatchEvent = _ref2.dispatchEvent;\n if (!canStart()) {\n return;\n }\n var initial = getStartLocation({\n event: event,\n dragType: dragType,\n getDropTargetsOver: getDropTargetsOver\n });\n globalState.isActive = true;\n var state = {\n current: initial\n };\n\n // Setting initial drop effect for the drag\n setDropEffectOnEvent({\n event: event,\n current: initial.dropTargets\n });\n var dispatch = makeDispatch({\n source: dragType.payload,\n dispatchEvent: dispatchEvent,\n initial: initial\n });\n function updateState(next) {\n // only looking at whether hierarchy has changed to determine whether something as 'changed'\n var hasChanged = hasHierarchyChanged({\n current: state.current.dropTargets,\n next: next.dropTargets\n });\n\n // Always updating the state to include latest data, dropEffect and stickiness\n // Only updating consumers if the hierarchy has changed in some way\n // Consumers can get the latest data by using `onDrag`\n state.current = next;\n if (hasChanged) {\n dispatch.dragUpdate({\n current: state.current\n });\n }\n }\n function onUpdateEvent(event) {\n var input = getInput(event);\n\n // If we are over the honey pot, we need to get the element\n // that the user would have been over if not for the honey pot\n var target = isHoneyPotElement(event.target) ? getElementFromPointWithoutHoneypot({\n x: input.clientX,\n y: input.clientY\n }) : event.target;\n var nextDropTargets = getDropTargetsOver({\n target: target,\n input: input,\n source: dragType.payload,\n current: state.current.dropTargets\n });\n if (nextDropTargets.length) {\n // \uD83E\uDE78 must call `event.preventDefault()` to allow a browser drop to occur\n event.preventDefault();\n setDropEffectOnEvent({\n event: event,\n current: nextDropTargets\n });\n }\n updateState({\n dropTargets: nextDropTargets,\n input: input\n });\n }\n function cancel() {\n // The spec behaviour is that when a drag is cancelled, or when dropping on no drop targets,\n // a \"dragleave\" event is fired on the active drop target before a \"dragend\" event.\n // We are replicating that behaviour in `cancel` if there are any active drop targets to\n // ensure consistent behaviour.\n //\n // Note: When cancelling, or dropping on no drop targets, a \"dragleave\" event\n // will have already cleared the dropTargets to `[]` (as that particular \"dragleave\" has a `relatedTarget` of `null`)\n\n if (state.current.dropTargets.length) {\n updateState({\n dropTargets: [],\n input: state.current.input\n });\n }\n dispatch.drop({\n current: state.current,\n updatedSourcePayload: null\n });\n finish();\n }\n function finish() {\n globalState.isActive = false;\n unbindEvents();\n }\n var unbindEvents = bindAll(window, [{\n // \uD83D\uDC4B Note: we are repurposing the `dragover` event as our `drag` event\n // this is because firefox does not publish pointer coordinates during\n // a `drag` event, but does for every other type of drag event\n // `dragover` fires on all elements that are being dragged over\n // Because we are binding to `window` - our `dragover` is effectively the same as a `drag`\n // \uD83E\uDD8A\uD83D\uDE24\n type: 'dragover',\n listener: function listener(event) {\n // We need to regularly calculate the drop targets in order to allow:\n // - dynamic `canDrop()` checks\n // - rapid updating `getData()` calls to attach data in response to user input (eg for edge detection)\n // Sadly we cannot schedule inspecting changes resulting from this event\n // we need to be able to conditionally cancel the event with `event.preventDefault()`\n // to enable the correct native drop experience.\n\n // 1. check to see if anything has changed\n onUpdateEvent(event);\n\n // 2. let consumers know a move has occurred\n // This will include the latest 'input' values\n dispatch.drag({\n current: state.current\n });\n }\n }, {\n type: 'dragenter',\n listener: onUpdateEvent\n }, {\n type: 'dragleave',\n listener: function listener(event) {\n if (!isLeavingWindow({\n dragLeave: event\n })) {\n return;\n }\n\n /**\n * At this point we don't know if a drag is being cancelled,\n * or if a drag is leaving the `window`.\n *\n * Both have:\n * 1. \"dragleave\" (with `relatedTarget: null`)\n * 2. \"dragend\" (a \"dragend\" can occur when outside the `window`)\n *\n * **Clearing drop targets**\n *\n * For either case we are clearing the the drop targets\n *\n * - cancelling: we clear drop targets in `\"dragend\"` anyway\n * - leaving the `window`: we clear the drop targets (to clear stickiness)\n *\n * **Leaving the window and finishing the drag**\n *\n * _internal drags_\n *\n * - The drag continues when the user is outside the `window`\n * and can resume if the user drags back over the `window`,\n * or end when the user drops in an external `window`.\n * - We will get a `\"dragend\"`, or we can listen for other\n * events to determine the drag is finished when the user re-enters the `window`).\n *\n * _external drags_\n *\n * - We conclude the drag operation.\n * - We have no idea if the user will drag back over the `window`,\n * or if the drag ends elsewhere.\n * - We will create a new drag if the user re-enters the `window`.\n *\n * **Not updating `input`**\n *\n * \uD83D\uDC1B Bug[Chrome] the final `\"dragleave\"` has default input values (eg `clientX == 0`)\n * Workaround: intentionally not updating `input` in \"dragleave\"\n * rather than the users current input values\n * - [Conversation](https://twitter.com/alexandereardon/status/1642697633864241152)\n * - [Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1429937)\n **/\n\n updateState({\n input: state.current.input,\n dropTargets: []\n });\n if (dragType.startedFrom === 'external') {\n cancel();\n }\n }\n }, {\n // A \"drop\" can only happen if the browser allowed the drop\n type: 'drop',\n listener: function listener(event) {\n // Capture the final input.\n // We are capturing the final `input` for the\n // most accurate honey pot experience\n state.current = {\n dropTargets: state.current.dropTargets,\n input: getInput(event)\n };\n\n /** If there are no drop targets, then we will get\n * a \"drop\" event if:\n * - `preventUnhandled()` is being used\n * - there is an unmanaged drop target (eg another library)\n * In these cases, it's up to the consumer\n * to handle the drop if it's not over one of our drop targets\n * - `preventUnhandled()` will cancel the \"drop\"\n * - unmanaged drop targets can handle the \"drop\" how they want to\n * We won't call `event.preventDefault()` in this call path */\n\n if (!state.current.dropTargets.length) {\n cancel();\n return;\n }\n event.preventDefault();\n\n // applying the latest drop effect to the event\n setDropEffectOnEvent({\n event: event,\n current: state.current.dropTargets\n });\n dispatch.drop({\n current: state.current,\n // When dropping something native, we need to extract the latest\n // `.items` from the \"drop\" event as it is now accessible\n updatedSourcePayload: dragType.type === 'external' ? dragType.getDropPayload(event) : null\n });\n finish();\n }\n }, {\n // \"dragend\" fires when on the drag source (eg a draggable element)\n // when the drag is finished.\n // \"dragend\" will fire after \"drop\" (if there was a successful drop)\n // \"dragend\" does not fire if the draggable source has been removed during the drag\n // or for external drag sources (eg files)\n\n // This \"dragend\" listener will not fire if there was a successful drop\n // as we will have already removed the event listener\n\n type: 'dragend',\n listener: function listener(event) {\n // In firefox, the position of the \"dragend\" event can\n // be a bit different to the last \"dragover\" event.\n // Updating the input so we can get the best possible\n // information for the honey pot.\n state.current = {\n dropTargets: state.current.dropTargets,\n input: getInput(event)\n };\n cancel();\n }\n }].concat(_toConsumableArray(getBindingsForBrokenDrags({\n onDragEnd: cancel\n }))),\n // Once we have started a managed drag operation it is important that we see / own all drag events\n // We got one adoption bug pop up where some code was stopping (`event.stopPropagation()`)\n // all \"drop\" events in the bubble phase on the `document.body`.\n // This meant that we never saw the \"drop\" event.\n {\n capture: true\n });\n dispatch.start({\n nativeSetDragImage: getNativeSetDragImage(event)\n });\n}\nfunction setDropEffectOnEvent(_ref3) {\n var _current$;\n var event = _ref3.event,\n current = _ref3.current;\n // setting the `dropEffect` to be the innerMost drop targets dropEffect\n var innerMost = (_current$ = current[0]) === null || _current$ === void 0 ? void 0 : _current$.dropEffect;\n if (innerMost != null && event.dataTransfer) {\n event.dataTransfer.dropEffect = innerMost;\n }\n}\nfunction getStartLocation(_ref4) {\n var event = _ref4.event,\n dragType = _ref4.dragType,\n getDropTargetsOver = _ref4.getDropTargetsOver;\n var input = getInput(event);\n\n // When dragging from outside of the browser,\n // the drag is not being sourced from any local drop targets\n if (dragType.startedFrom === 'external') {\n return {\n input: input,\n dropTargets: []\n };\n }\n var dropTargets = getDropTargetsOver({\n input: input,\n source: dragType.payload,\n target: event.target,\n current: []\n });\n return {\n input: input,\n dropTargets: dropTargets\n };\n}\nexport var lifecycle = {\n canStart: canStart,\n start: start\n};", "import { once } from '../public-utils/once';\n\n// using `cache` as our `isFirefox()` result will not change in a browser\n\n/**\n * Returns `true` if a `Firefox` browser\n * */\nexport var isFirefox = once(function isFirefox() {\n if (process.env.NODE_ENV === 'test') {\n return false;\n }\n return navigator.userAgent.includes('Firefox');\n});", "import { once } from '../public-utils/once';\n\n// using `cache` as our `isSafari()` result will not change in a browser\n\n/**\n * Returns `true` if a `Safari` browser.\n * Returns `true` if the browser is running on iOS (they are all Safari).\n *\n * Use `isSafariOnIOS` if you want to check if something is Safari + iOS\n * */\nexport var isSafari = once(function isSafari() {\n if (process.env.NODE_ENV === 'test') {\n return false;\n }\n var _navigator = navigator,\n userAgent = _navigator.userAgent;\n return userAgent.includes('AppleWebKit') && !userAgent.includes('Chrome');\n});", "import { bindAll } from 'bind-event-listener';\nimport { isSafari } from '../is-safari';\n\n/* For \"dragenter\" events, the browser should set `relatedTarget` to the previous element.\n * For external drag operations, our first \"dragenter\" event should have a `event.relatedTarget` of `null`.\n *\n * Unfortunately in Safari `event.relatedTarget` is *always* set to `null`\n * Safari bug: https://bugs.webkit.org/show_bug.cgi?id=242627\n * To work around this we count \"dragenter\" and \"dragleave\" events */\n\n// Using symbols for event properties so we don't clash with\n// anything on the `event` object\nvar symbols = {\n isLeavingWindow: Symbol('leaving'),\n isEnteringWindow: Symbol('entering')\n};\nexport function isEnteringWindowInSafari(_ref) {\n var dragEnter = _ref.dragEnter;\n if (!isSafari()) {\n return false;\n }\n return dragEnter.hasOwnProperty(symbols.isEnteringWindow);\n}\n\n// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports\nexport function isLeavingWindowInSafari(_ref2) {\n var dragLeave = _ref2.dragLeave;\n if (!isSafari()) {\n return false;\n }\n return dragLeave.hasOwnProperty(symbols.isLeavingWindow);\n}\n(function fixSafari() {\n // Don't do anything when server side rendering\n if (typeof window === 'undefined') {\n return;\n }\n\n // rather than checking the userAgent for \"jsdom\" we can do this check\n // so that the check will be removed completely in production code\n if (process.env.NODE_ENV === 'test') {\n return;\n }\n if (!isSafari()) {\n return;\n }\n function getInitialState() {\n return {\n enterCount: 0,\n isOverWindow: false\n };\n }\n var state = getInitialState();\n function resetState() {\n state = getInitialState();\n }\n\n // These event listeners are bound _forever_ and _never_ removed\n // We don't bother cleaning up these event listeners (for now)\n // as this workaround is only for Safari\n\n // This is how the event count works:\n //\n // lift (+1 enterCount)\n // - dragstart(draggable) [enterCount: 0]\n // - dragenter(draggable) [enterCount: 1]\n // leaving draggable (+0 enterCount)\n // - dragenter(document.body) [enterCount: 2]\n // - dragleave(draggable) [enterCount: 1]\n // leaving window (-1 enterCount)\n // - dragleave(document.body) [enterCount: 0] {leaving the window}\n\n // Things to note:\n // - dragenter and dragleave bubble\n // - the first dragenter when entering a window might not be on `window`\n // - it could be on an element that is pressed up against the window\n // - (so we cannot rely on `event.target` values)\n\n bindAll(window, [{\n type: 'dragstart',\n listener: function listener() {\n state.enterCount = 0;\n // drag start occurs in the source window\n state.isOverWindow = true;\n // When a drag first starts it will also trigger a \"dragenter\" on the draggable element\n }\n }, {\n type: 'drop',\n listener: resetState\n }, {\n type: 'dragend',\n listener: resetState\n }, {\n type: 'dragenter',\n listener: function listener(event) {\n if (!state.isOverWindow && state.enterCount === 0) {\n // Patching the `event` object\n // The `event` object is shared with all event listeners for the event\n event[symbols.isEnteringWindow] = true;\n }\n state.isOverWindow = true;\n state.enterCount++;\n }\n }, {\n type: 'dragleave',\n listener: function listener(event) {\n state.enterCount--;\n if (state.isOverWindow && state.enterCount === 0) {\n // Patching the `event` object as it is shared with all event listeners\n // The `event` object is shared with all event listeners for the event\n event[symbols.isLeavingWindow] = true;\n state.isOverWindow = false;\n }\n }\n }],\n // using `capture: true` so that adding event listeners\n // in bubble phase will have the correct symbols\n {\n capture: true\n });\n})();", "/**\n * Does the `EventTarget` look like a `Node` based on \"duck typing\".\n *\n * Helpful when the `Node` might be outside of the current document\n * so we cannot to an `target instanceof Node` check.\n */\nfunction isNodeLike(target) {\n return 'nodeName' in target;\n}\n\n/**\n * Is an `EventTarget` a `Node` from another `window`?\n */\nexport function isFromAnotherWindow(eventTarget) {\n return isNodeLike(eventTarget) && eventTarget.ownerDocument !== document;\n}", "import { isFirefox } from '../is-firefox';\nimport { isSafari } from '../is-safari';\nimport { isLeavingWindowInSafari } from './count-events-for-safari';\nimport { isFromAnotherWindow } from './is-from-another-window';\nexport function isLeavingWindow(_ref) {\n var dragLeave = _ref.dragLeave;\n var type = dragLeave.type,\n relatedTarget = dragLeave.relatedTarget;\n if (type !== 'dragleave') {\n return false;\n }\n if (isSafari()) {\n return isLeavingWindowInSafari({\n dragLeave: dragLeave\n });\n }\n\n // Standard check: if going to `null` we are leaving the `window`\n if (relatedTarget == null) {\n return true;\n }\n\n /**\n * \uD83E\uDD8A Exception: `iframe` in Firefox (`125.0`)\n *\n * Case 1: parent `window` \u2192 child `iframe`\n * `dragLeave.relatedTarget` is element _inside_ the child `iframe`\n * (foreign element)\n *\n * Case 2: child `iframe` \u2192 parent `window`\n * `dragLeave.relatedTarget` is the `iframe` in the parent `window`\n * (foreign element)\n */\n\n if (isFirefox()) {\n return isFromAnotherWindow(relatedTarget);\n }\n\n /**\n * \uD83C\uDF0F Exception: `iframe` in Chrome (`124.0`)\n *\n * Case 1: parent `window` \u2192 child `iframe`\n * `dragLeave.relatedTarget` is the `iframe` in the parent `window`\n *\n * Case 2: child `iframe` \u2192 parent `window`\n * `dragLeave.relatedTarget` is `null` *(standard check)*\n */\n\n // Case 2\n // Using `instanceof` check as the element will be in the same `window`\n return relatedTarget instanceof HTMLIFrameElement;\n}", "export function getBindingsForBrokenDrags(_ref) {\n var onDragEnd = _ref.onDragEnd;\n return [\n // ## Detecting drag ending for removed draggables\n //\n // If a draggable element is removed during a drag and the user drops:\n // 1. if over a valid drop target: we get a \"drop\" event to know the drag is finished\n // 2. if not over a valid drop target (or cancelled): we get nothing\n // The \"dragend\" event will not fire on the source draggable if it has been\n // removed from the DOM.\n // So we need to figure out if a drag operation has finished by looking at other events\n // We can do this by looking at other events\n\n // ### First detection: \"pointermove\" events\n\n // 1. \"pointermove\" events cannot fire during a drag and drop operation\n // according to the spec. So if we get a \"pointermove\" it means that\n // the drag and drop operations has finished. So if we get a \"pointermove\"\n // we know that the drag is over\n // 2. \uD83E\uDD8A\uD83D\uDE24 Drag and drop operations are _supposed_ to suppress\n // other pointer events. However, firefox will allow a few\n // pointer event to get through after a drag starts.\n // The most I've seen is 3\n {\n type: 'pointermove',\n listener: function () {\n var callCount = 0;\n return function listener() {\n // Using 20 as it is far bigger than the most observed (3)\n if (callCount < 20) {\n callCount++;\n return;\n }\n onDragEnd();\n };\n }()\n },\n // ### Second detection: \"pointerdown\" events\n\n // If we receive this event then we know that a drag operation has finished\n // and potentially another one is about to start.\n // Note: `pointerdown` fires on all browsers / platforms before \"dragstart\"\n {\n type: 'pointerdown',\n listener: onDragEnd\n }];\n}", "export function getInput(event) {\n return {\n altKey: event.altKey,\n button: event.button,\n buttons: event.buttons,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n clientX: event.clientX,\n clientY: event.clientY,\n pageX: event.pageX,\n pageY: event.pageY\n };\n}", "var rafSchd = function rafSchd(fn) {\n var lastArgs = [];\n var frameId = null;\n\n var wrapperFn = function wrapperFn() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n lastArgs = args;\n\n if (frameId) {\n return;\n }\n\n frameId = requestAnimationFrame(function () {\n frameId = null;\n fn.apply(void 0, lastArgs);\n });\n };\n\n wrapperFn.cancel = function () {\n if (!frameId) {\n return;\n }\n\n cancelAnimationFrame(frameId);\n frameId = null;\n };\n\n return wrapperFn;\n};\n\nexport default rafSchd;\n", "import rafSchd from 'raf-schd';\nvar scheduleOnDrag = rafSchd(function (fn) {\n return fn();\n});\nvar dragStart = function () {\n var scheduled = null;\n function schedule(fn) {\n var frameId = requestAnimationFrame(function () {\n scheduled = null;\n fn();\n });\n scheduled = {\n frameId: frameId,\n fn: fn\n };\n }\n function flush() {\n if (scheduled) {\n cancelAnimationFrame(scheduled.frameId);\n scheduled.fn();\n scheduled = null;\n }\n }\n return {\n schedule: schedule,\n flush: flush\n };\n}();\nexport function makeDispatch(_ref) {\n var source = _ref.source,\n initial = _ref.initial,\n dispatchEvent = _ref.dispatchEvent;\n var previous = {\n dropTargets: []\n };\n function safeDispatch(args) {\n dispatchEvent(args);\n previous = {\n dropTargets: args.payload.location.current.dropTargets\n };\n }\n var dispatch = {\n start: function start(_ref2) {\n var nativeSetDragImage = _ref2.nativeSetDragImage;\n // Ensuring that both `onGenerateDragPreview` and `onDragStart` get the same location.\n // We do this so that `previous` is`[]` in `onDragStart` (which is logical)\n var location = {\n current: initial,\n previous: previous,\n initial: initial\n };\n // a `onGenerateDragPreview` does _not_ add another entry for `previous`\n // onDragPreview\n safeDispatch({\n eventName: 'onGenerateDragPreview',\n payload: {\n source: source,\n location: location,\n nativeSetDragImage: nativeSetDragImage\n }\n });\n dragStart.schedule(function () {\n safeDispatch({\n eventName: 'onDragStart',\n payload: {\n source: source,\n location: location\n }\n });\n });\n },\n dragUpdate: function dragUpdate(_ref3) {\n var current = _ref3.current;\n dragStart.flush();\n scheduleOnDrag.cancel();\n safeDispatch({\n eventName: 'onDropTargetChange',\n payload: {\n source: source,\n location: {\n initial: initial,\n previous: previous,\n current: current\n }\n }\n });\n },\n drag: function drag(_ref4) {\n var current = _ref4.current;\n scheduleOnDrag(function () {\n dragStart.flush();\n var location = {\n initial: initial,\n previous: previous,\n current: current\n };\n safeDispatch({\n eventName: 'onDrag',\n payload: {\n source: source,\n location: location\n }\n });\n });\n },\n drop: function drop(_ref5) {\n var current = _ref5.current,\n updatedSourcePayload = _ref5.updatedSourcePayload;\n dragStart.flush();\n scheduleOnDrag.cancel();\n safeDispatch({\n eventName: 'onDrop',\n payload: {\n source: updatedSourcePayload !== null && updatedSourcePayload !== void 0 ? updatedSourcePayload : source,\n location: {\n current: current,\n previous: previous,\n initial: initial\n }\n }\n });\n }\n };\n return dispatch;\n}", "// Extending `Map` to allow us to link Key and Values together\n\nvar ledger = new Map();\nfunction registerUsage(_ref) {\n var typeKey = _ref.typeKey,\n mount = _ref.mount;\n var entry = ledger.get(typeKey);\n if (entry) {\n entry.usageCount++;\n return entry;\n }\n var initial = {\n typeKey: typeKey,\n unmount: mount(),\n usageCount: 1\n };\n ledger.set(typeKey, initial);\n return initial;\n}\nexport function register(args) {\n var entry = registerUsage(args);\n return function unregister() {\n entry.usageCount--;\n if (entry.usageCount > 0) {\n return;\n }\n // Only a single usage left, remove it\n entry.unmount();\n ledger.delete(args.typeKey);\n };\n}", "/** Create a new combined function that will call all the provided functions */\nexport function combine() {\n for (var _len = arguments.length, fns = new Array(_len), _key = 0; _key < _len; _key++) {\n fns[_key] = arguments[_key];\n }\n return function cleanup() {\n fns.forEach(function (fn) {\n return fn();\n });\n };\n}", "export function addAttribute(element, _ref) {\n var attribute = _ref.attribute,\n value = _ref.value;\n element.setAttribute(attribute, value);\n return function () {\n return element.removeAttribute(attribute);\n };\n}", "import _defineProperty from \"@babel/runtime/helpers/defineProperty\";\nimport _toConsumableArray from \"@babel/runtime/helpers/toConsumableArray\";\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nimport { combine } from '../public-utils/combine';\nimport { once } from '../public-utils/once';\nimport { addAttribute } from '../util/add-attribute';\nfunction copyReverse(array) {\n return array.slice(0).reverse();\n}\nexport function makeDropTarget(_ref) {\n var typeKey = _ref.typeKey,\n defaultDropEffect = _ref.defaultDropEffect;\n var registry = new WeakMap();\n var dropTargetDataAtt = \"data-drop-target-for-\".concat(typeKey);\n var dropTargetSelector = \"[\".concat(dropTargetDataAtt, \"]\");\n function addToRegistry(args) {\n registry.set(args.element, args);\n return function () {\n return registry.delete(args.element);\n };\n }\n function dropTargetForConsumers(args) {\n // Guardrail: warn if the draggable element is already registered\n if (process.env.NODE_ENV !== 'production') {\n var existing = registry.get(args.element);\n if (existing) {\n // eslint-disable-next-line no-console\n console.warn(\"You have already registered a [\".concat(typeKey, \"] dropTarget on the same element\"), {\n existing: existing,\n proposed: args\n });\n }\n if (args.element instanceof HTMLIFrameElement) {\n // eslint-disable-next-line no-console\n console.warn(\"\\n We recommend not registering <iframe> elements as drop targets\\n as it can result in some strange browser event ordering.\\n \" // Removing newlines and excessive whitespace\n .replace(/\\s{2,}/g, ' ').trim());\n }\n }\n var cleanup = combine(addAttribute(args.element, {\n attribute: dropTargetDataAtt,\n value: 'true'\n }), addToRegistry(args));\n\n // Wrapping in `once` to prevent unexpected side effects if consumers call\n // the clean up function multiple times.\n return once(cleanup);\n }\n function getActualDropTargets(_ref2) {\n var _args$getData, _args$getData2, _args$getDropEffect, _args$getDropEffect2;\n var source = _ref2.source,\n target = _ref2.target,\n input = _ref2.input,\n _ref2$result = _ref2.result,\n result = _ref2$result === void 0 ? [] : _ref2$result;\n if (target == null) {\n return result;\n }\n if (!(target instanceof Element)) {\n // For \"text-selection\" drags, the original `target`\n // is not an `Element`, so we need to start looking from\n // the parent element\n if (target instanceof Node) {\n return getActualDropTargets({\n source: source,\n target: target.parentElement,\n input: input,\n result: result\n });\n }\n\n // not sure what we are working with,\n // so we can exit.\n return result;\n }\n var closest = target.closest(dropTargetSelector);\n\n // Cannot find anything else\n if (closest == null) {\n return result;\n }\n var args = registry.get(closest);\n\n // error: something had a dropTargetSelector but we could not\n // find a match. For now, failing silently\n if (args == null) {\n return result;\n }\n var feedback = {\n input: input,\n source: source,\n element: args.element\n };\n\n // if dropping is not allowed, skip this drop target\n // and continue looking up the DOM tree\n if (args.canDrop && !args.canDrop(feedback)) {\n return getActualDropTargets({\n source: source,\n target: args.element.parentElement,\n input: input,\n result: result\n });\n }\n\n // calculate our new record\n var data = (_args$getData = (_args$getData2 = args.getData) === null || _args$getData2 === void 0 ? void 0 : _args$getData2.call(args, feedback)) !== null && _args$getData !== void 0 ? _args$getData : {};\n var dropEffect = (_args$getDropEffect = (_args$getDropEffect2 = args.getDropEffect) === null || _args$getDropEffect2 === void 0 ? void 0 : _args$getDropEffect2.call(args, feedback)) !== null && _args$getDropEffect !== void 0 ? _args$getDropEffect : defaultDropEffect;\n var record = {\n data: data,\n element: args.element,\n dropEffect: dropEffect,\n // we are collecting _actual_ drop targets, so these are\n // being applied _not_ due to stickiness\n isActiveDueToStickiness: false\n };\n return getActualDropTargets({\n source: source,\n target: args.element.parentElement,\n input: input,\n // Using bubble ordering. Same ordering as `event.getPath()`\n result: [].concat(_toConsumableArray(result), [record])\n });\n }\n function notifyCurrent(_ref3) {\n var eventName = _ref3.eventName,\n payload = _ref3.payload;\n var _iterator = _createForOfIteratorHelper(payload.location.current.dropTargets),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var _entry$eventName;\n var record = _step.value;\n var entry = registry.get(record.element);\n var args = _objectSpread(_objectSpread({}, payload), {}, {\n self: record\n });\n entry === null || entry === void 0 || (_entry$eventName = entry[eventName]) === null || _entry$eventName === void 0 || _entry$eventName.call(entry,\n // I cannot seem to get the types right here.\n // TS doesn't seem to like that one event can need `nativeSetDragImage`\n // @ts-expect-error\n args);\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n }\n var actions = {\n onGenerateDragPreview: notifyCurrent,\n onDrag: notifyCurrent,\n onDragStart: notifyCurrent,\n onDrop: notifyCurrent,\n onDropTargetChange: function onDropTargetChange(_ref4) {\n var payload = _ref4.payload;\n var isCurrent = new Set(payload.location.current.dropTargets.map(function (record) {\n return record.element;\n }));\n var visited = new Set();\n var _iterator2 = _createForOfIteratorHelper(payload.location.previous.dropTargets),\n _step2;\n try {\n for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n var _entry$onDropTargetCh;\n var record = _step2.value;\n visited.add(record.element);\n var entry = registry.get(record.element);\n var isOver = isCurrent.has(record.element);\n var args = _objectSpread(_objectSpread({}, payload), {}, {\n self: record\n });\n entry === null || entry === void 0 || (_entry$onDropTargetCh = entry.onDropTargetChange) === null || _entry$onDropTargetCh === void 0 || _entry$onDropTargetCh.call(entry, args);\n\n // if we cannot find the drop target in the current array, then it has been left\n if (!isOver) {\n var _entry$onDragLeave;\n entry === null || entry === void 0 || (_entry$onDragLeave = entry.onDragLeave) === null || _entry$onDragLeave === void 0 || _entry$onDragLeave.call(entry, args);\n }\n }\n } catch (err) {\n _iterator2.e(err);\n } finally {\n _iterator2.f();\n }\n var _iterator3 = _createForOfIteratorHelper(payload.location.current.dropTargets),\n _step3;\n try {\n for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {\n var _entry$onDropTargetCh2, _entry$onDragEnter;\n var _record = _step3.value;\n // already published an update to this drop target\n if (visited.has(_record.element)) {\n continue;\n }\n // at this point we have a new drop target that is being entered into\n var _args = _objectSpread(_objectSpread({}, payload), {}, {\n self: _record\n });\n var _entry = registry.get(_record.element);\n _entry === null || _entry === void 0 || (_entry$onDropTargetCh2 = _entry.onDropTargetChange) === null || _entry$onDropTargetCh2 === void 0 || _entry$onDropTargetCh2.call(_entry, _args);\n _entry === null || _entry === void 0 || (_entry$onDragEnter = _entry.onDragEnter) === null || _entry$onDragEnter === void 0 || _entry$onDragEnter.call(_entry, _args);\n }\n } catch (err) {\n _iterator3.e(err);\n } finally {\n _iterator3.f();\n }\n }\n };\n function dispatchEvent(args) {\n actions[args.eventName](args);\n }\n function getIsOver(_ref5) {\n var source = _ref5.source,\n target = _ref5.target,\n input = _ref5.input,\n current = _ref5.current;\n var actual = getActualDropTargets({\n source: source,\n target: target,\n input: input\n });\n\n // stickiness is only relevant when we have less\n // drop targets than we did before\n if (actual.length >= current.length) {\n return actual;\n }\n\n // less 'actual' drop targets than before,\n // we need to see if 'stickiness' applies\n\n // An old drop target will continue to be dropped on if:\n // 1. it has the same parent\n // 2. nothing exists in it's previous index\n\n var lastCaptureOrdered = copyReverse(current);\n var actualCaptureOrdered = copyReverse(actual);\n var resultCaptureOrdered = [];\n for (var index = 0; index < lastCaptureOrdered.length; index++) {\n var _argsForLast$getIsSti;\n var last = lastCaptureOrdered[index];\n var fresh = actualCaptureOrdered[index];\n\n // if a record is in the new index -> use that\n // it will have the latest data + dropEffect\n if (fresh != null) {\n resultCaptureOrdered.push(fresh);\n continue;\n }\n\n // At this point we have no drop target in the old spot\n // Check to see if we can use a previous sticky drop target\n\n // The \"parent\" is the one inside of `resultCaptureOrdered`\n // (the parent might be a drop target that was sticky)\n var parent = resultCaptureOrdered[index - 1];\n var lastParent = lastCaptureOrdered[index - 1];\n\n // Stickiness is based on parent relationships, so if the parent relationship has change\n // then we can stop our search\n if ((parent === null || parent === void 0 ? void 0 : parent.element) !== (lastParent === null || lastParent === void 0 ? void 0 : lastParent.element)) {\n break;\n }\n\n // We need to check whether the old drop target can still be dropped on\n\n var argsForLast = registry.get(last.element);\n\n // We cannot drop on a drop target that is no longer mounted\n if (!argsForLast) {\n break;\n }\n var feedback = {\n input: input,\n source: source,\n element: argsForLast.element\n };\n\n // We cannot drop on a drop target that no longer allows being dropped on\n if (argsForLast.canDrop && !argsForLast.canDrop(feedback)) {\n break;\n }\n\n // We cannot drop on a drop target that is no longer sticky\n if (!((_argsForLast$getIsSti = argsForLast.getIsSticky) !== null && _argsForLast$getIsSti !== void 0 && _argsForLast$getIsSti.call(argsForLast, feedback))) {\n break;\n }\n\n // Note: intentionally not recollecting `getData()` or `getDropEffect()`\n // Previous values for `data` and `dropEffect` will be borrowed\n // This is to prevent things like the 'closest edge' changing when\n // no longer over a drop target.\n // We could change our mind on this behaviour in the future\n\n resultCaptureOrdered.push(_objectSpread(_objectSpread({}, last), {}, {\n // making it clear to consumers this drop target is active due to stickiness\n isActiveDueToStickiness: true\n }));\n }\n\n // return bubble ordered result\n return copyReverse(resultCaptureOrdered);\n }\n return {\n dropTargetForConsumers: dropTargetForConsumers,\n getIsOver: getIsOver,\n dispatchEvent: dispatchEvent\n };\n}", "import _defineProperty from \"@babel/runtime/helpers/defineProperty\";\nfunction _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nimport { once } from '../public-utils/once';\nexport function makeMonitor() {\n var registry = new Set();\n var dragging = null;\n function tryAddToActive(monitor) {\n if (!dragging) {\n return;\n }\n // Monitor is allowed to monitor events if:\n // 1. It has no `canMonitor` function (default is that a monitor can listen to everything)\n // 2. `canMonitor` returns true\n if (!monitor.canMonitor || monitor.canMonitor(dragging.canMonitorArgs)) {\n dragging.active.add(monitor);\n }\n }\n function monitorForConsumers(args) {\n // We are giving each `args` a new reference so that you\n // can create multiple monitors with the same `args`.\n var entry = _objectSpread({}, args);\n registry.add(entry);\n\n // if there is an active drag we need to see if this new monitor is relevant\n tryAddToActive(entry);\n function cleanup() {\n registry.delete(entry);\n\n // We need to stop publishing events during a drag to this monitor!\n if (dragging) {\n dragging.active.delete(entry);\n }\n }\n\n // Wrapping in `once` to prevent unexpected side effects if consumers call\n // the clean up function multiple times.\n return once(cleanup);\n }\n function dispatchEvent(_ref) {\n var eventName = _ref.eventName,\n payload = _ref.payload;\n if (eventName === 'onGenerateDragPreview') {\n dragging = {\n canMonitorArgs: {\n initial: payload.location.initial,\n source: payload.source\n },\n active: new Set()\n };\n var _iterator = _createForOfIteratorHelper(registry),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var monitor = _step.value;\n tryAddToActive(monitor);\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n }\n\n // This should never happen.\n if (!dragging) {\n return;\n }\n\n // Creating an array from the set _before_ iterating\n // This is so that monitors added during the current event will not be called.\n // This behaviour matches native EventTargets where an event listener\n // cannot add another event listener during an active event to the same\n // event target in the same event (for us we have a single global event target)\n var active = Array.from(dragging.active);\n for (var _i = 0, _active = active; _i < _active.length; _i++) {\n var _monitor = _active[_i];\n // A monitor can be removed by another monitor during an event.\n // We need to check that the monitor is still registered before calling it\n if (dragging.active.has(_monitor)) {\n var _monitor$eventName;\n // @ts-expect-error: I cannot get this type working!\n (_monitor$eventName = _monitor[eventName]) === null || _monitor$eventName === void 0 || _monitor$eventName.call(_monitor, payload);\n }\n }\n if (eventName === 'onDrop') {\n dragging.active.clear();\n dragging = null;\n }\n }\n return {\n dispatchEvent: dispatchEvent,\n monitorForConsumers: monitorForConsumers\n };\n}", "import { lifecycle } from '../ledger/lifecycle-manager';\nimport { register } from '../ledger/usage-ledger';\nimport { makeDropTarget } from './make-drop-target';\nimport { makeMonitor } from './make-monitor';\nexport function makeAdapter(_ref) {\n var typeKey = _ref.typeKey,\n mount = _ref.mount,\n dispatchEventToSource = _ref.dispatchEventToSource,\n onPostDispatch = _ref.onPostDispatch,\n defaultDropEffect = _ref.defaultDropEffect;\n var monitorAPI = makeMonitor();\n var dropTargetAPI = makeDropTarget({\n typeKey: typeKey,\n defaultDropEffect: defaultDropEffect\n });\n function dispatchEvent(args) {\n // 1. forward the event to source\n dispatchEventToSource === null || dispatchEventToSource === void 0 || dispatchEventToSource(args);\n\n // 2. forward the event to relevant dropTargets\n dropTargetAPI.dispatchEvent(args);\n\n // 3. forward event to monitors\n monitorAPI.dispatchEvent(args);\n\n // 4. post consumer dispatch (used for honey pot fix)\n onPostDispatch === null || onPostDispatch === void 0 || onPostDispatch(args);\n }\n function start(_ref2) {\n var event = _ref2.event,\n dragType = _ref2.dragType;\n lifecycle.start({\n event: event,\n dragType: dragType,\n getDropTargetsOver: dropTargetAPI.getIsOver,\n dispatchEvent: dispatchEvent\n });\n }\n function registerUsage() {\n function mountAdapter() {\n var api = {\n canStart: lifecycle.canStart,\n start: start\n };\n return mount(api);\n }\n return register({\n typeKey: typeKey,\n mount: mountAdapter\n });\n }\n return {\n registerUsage: registerUsage,\n dropTarget: dropTargetAPI.dropTargetForConsumers,\n monitor: monitorAPI.monitorForConsumers\n };\n}", "import { once } from '../public-utils/once';\n\n// Using `once` as the value won't change in a browser\n\nexport var isAndroid = once(function isAndroid() {\n return navigator.userAgent.toLocaleLowerCase().includes('android');\n});\n\n// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports\nexport var androidFallbackText = 'pdnd:android-fallback';", "// Why we put the media types in their own files:\n//\n// - we are not putting them all in one file as not all adapters need all types\n// - we are not putting them in the external helpers as some things just need the\n// types and not the external functions code\nexport var textMediaType = 'text/plain';", "// Why we put the media types in their own files:\n//\n// - we are not putting them all in one file as not all adapters need all types\n// - we are not putting them in the external helpers as some things just need the\n// types and not the external functions code\nexport var URLMediaType = 'text/uri-list';", "/**\n * This key has been pulled into a separate module\n * so that the external adapter does not need to import\n * the element adapter\n */\nexport var elementAdapterNativeDataKey = 'application/vnd.pdnd';", "import _defineProperty from \"@babel/runtime/helpers/defineProperty\";\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nimport { monitorForElements } from '../../../adapter/element-adapter';\nimport { isSafari } from '../../../util/is-safari';\nimport { maxZIndex } from '../../../util/max-z-index';\nimport { popoverResetUserAgentStyles } from '../../../util/popover-reset-styles';\nimport { supportsPopover } from '../../../util/supports-popover';\n\n/** A function to remove the element that has been added to the `container`.\n * @example () => ReactDOM.unmountComponentAtNode(container)\n */\n\n/** A function that will render a preview element into a `container` `HTMLElement` */\n\n/** By default we use the build in values for the native drag preview: {x: 0, y: 0} */\nfunction defaultOffset() {\n return {\n x: 0,\n y: 0\n };\n}\n\n/** This function provides the ability to mount an element for it to be used as the native drag preview\n *\n * @example\n * draggable({\n * onGenerateDragPreview: ({ nativeSetDragImage }) => {\n * setCustomNativeDragPreview({\n * render: ({ container }) => {\n * ReactDOM.render(<Preview item={item} />, container);\n * return () => ReactDOM.unmountComponentAtNode(container);\n * },\n * nativeSetDragImage,\n * });\n * },\n * });\n */\nexport function setCustomNativeDragPreview(_ref) {\n var render = _ref.render,\n nativeSetDragImage = _ref.nativeSetDragImage,\n _ref$getOffset = _ref.getOffset,\n getOffset = _ref$getOffset === void 0 ? defaultOffset : _ref$getOffset;\n var container = document.createElement('div');\n\n // Using popover=\"manual\" to place the element in the browser's top layer.\n // This ensures the drag preview container is visually on top of everything else,\n // including elements using z-index and other stacking contexts.\n // \"manual\" means no light dismiss \u2014 we manage the lifecycle ourselves.\n // This element is only created for a single frame for the browser to take a\n // photo of it, and then it is destroyed.\n // Falls back to position:fixed + maxZIndex when the popover API is not available.\n // Note: the popover attribute must be set before the element is in the DOM.\n // `.showPopover()` is called further below after the element is appended to the body.\n if (supportsPopover()) {\n container.setAttribute('popover', 'manual');\n }\n Object.assign(container.style, _objectSpread(_objectSpread({\n // Ensuring we don't cause reflow when adding the element to the page\n // Using `position:fixed` rather than `position:absolute` so we are\n // positioned on the current viewport.\n // `position:fixed` also creates a new stacking context, so we don't need to do that here\n position: 'fixed'\n }, supportsPopover() ?\n // needs to come first as it has 'inset: unset' which\n // needs to be overridden by our top / left values\n popoverResetUserAgentStyles : {\n // Fallback: using maximum possible z-index so that this element\n // will always be on top of other positioned content.\n zIndex: maxZIndex\n }), {}, {\n // According to `mdn`, the element can be offscreen:\n // https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage#imgelement\n //\n // However, that information does not appear in the specs:\n // https://html.spec.whatwg.org/multipage/dnd.html#dom-datatransfer-setdragimage-dev\n //\n // If the element is _completely_ offscreen, Safari@17.1 will cancel the drag\n top: 0,\n left: 0,\n // Avoiding any additional events caused by the new element (being super safe)\n pointerEvents: 'none'\n }));\n document.body.append(container);\n\n // `.showPopover()` must be called after the element is in the DOM.\n if (supportsPopover()) {\n container.showPopover();\n }\n var unmount = render({\n container: container\n });\n\n /**\n * Some frameworks (eg `react`) don't render into the container until the next microtask.\n * - This will run before the browser takes it's picture of the element\n * - This will run before the animation frame that removes `container`.\n * */\n\n queueMicrotask(function () {\n var previewOffset = getOffset({\n container: container\n });\n\n /**\n * **Problem**\n * On `Safari@17.1` if a drag preview element has some opacity,\n * Safari will include elements behind the drag preview element\n * in the drag preview.\n * Bug: https://bugs.webkit.org/show_bug.cgi?id=266025\n *\n * **Fix**\n * We push the drag preview so it is _almost_ completely offscreen so that\n * there won't be any elements behind the drag preview element.\n * If the element is _completely_ offscreen, then the drag is cancelled by Safari.\n *\n * Using `-0.0001` so that any potential \"see through\" on the drag preview element\n * is effectively invisible \uD83D\uDC7B\n *\n * **Unsuccessful alternatives**\n * Setting a background color (eg \"white\") on the `container`\n * \u2192 Wrecks the opacity of the drag preview element\n *\n * Adding a parent element of the `container` with a background color (eg \"white\")\n * \u2192 Wrecks the opacity of the drag preview element\n */\n /**\n * Update: this bug fix is no longer needed in `Safari@26.4` (and maybe earlier)\n * We can remove it in a future release\n */\n if (isSafari()) {\n var rect = container.getBoundingClientRect();\n\n // We cannot apply this fix if nothing has been rendered into the `container`\n if (rect.width === 0) {\n return;\n }\n container.style.left = \"-\".concat(rect.width - 0.0001, \"px\");\n }\n nativeSetDragImage === null || nativeSetDragImage === void 0 || nativeSetDragImage(container, previewOffset.x, previewOffset.y);\n });\n function cleanup() {\n // No need to call `.hidePopover()`.\n // Removing the element from the DOM dismisses the popover\n unbindMonitor();\n unmount === null || unmount === void 0 || unmount();\n document.body.removeChild(container);\n }\n var unbindMonitor = monitorForElements({\n // Remove portal in the dragstart event so that the user will never see it\n onDragStart: cleanup,\n // Backup: remove portal when the drop finishes (this would be an error case)\n onDrop: cleanup\n });\n}", "import { once } from '../public-utils/once';\nimport { isSafari } from './is-safari';\n\n// Using `once` as the value won't change in a browser\n\n/**\n * **Notes**\n *\n * All browsers on iOS (Safari, Chrome, Firefox) use the same rendering engine (Safari / Webkit).\n *\n * \u2192 https://developer.apple.com/app-store/review/guidelines/ (see 2.5.6)\n *\n * There is some ongoing change in this space, and we might see some new browser\n * engines soon on iOS (at least in Europe)\n *\n * \u2192 https://developer.apple.com/support/alternative-browser-engines/\n **/\n\n/**\n * Returns `true` if browser is Safari (WebKit) on iOS.\n */\nexport var isSafariOnIOS = once(function isSafariOnIOS() {\n if (process.env.NODE_ENV === 'test') {\n return false;\n }\n return isSafari() && 'ontouchend' in document;\n});", "export var centerUnderPointer = function centerUnderPointer(_ref) {\n var container = _ref.container;\n var rect = container.getBoundingClientRect();\n return {\n x: rect.width / 2,\n y: rect.height / 2\n };\n};", "import { isAndroid } from '../../../util/android';\nimport { isSafariOnIOS } from '../../../util/is-safari-on-ios';\nimport { centerUnderPointer } from './center-under-pointer';\n\n/** Any valid CSS string value\n * @example `calc(var(--grid) * 2)\n */\n\n/**\n * Position the native drag preview **in front** of the users pointer.\n *\n * **Distance**\n *\n * If the total width of your preview (including the offset applied by this function)\n * exceeds `280px` then the drag preview will have more opacity applied on Windows.\n *\n * https://atlassian.design/components/pragmatic-drag-and-drop/web-platform-design-constraints\n *\n * **Direction**\n *\n * This function will position the drag preview on the _right hand side for left to right (`ltr`) interfaces_, and on the _left hand side for right to left (`rtl`) languages_.\n *\n * The direction will be calculated based on the direction (`dir`) being applied to the `container`\n * element (which will be a child of the `body` element).\n *\n * **iOS, iPadOS and Android**\n *\n * The drag preview will be centered under the users pointer rather than\n * pushed away on iOS due to platform limitations.\n */\nexport function pointerOutsideOfPreview(point) {\n return function getOffset(_ref) {\n var container = _ref.container;\n /**\n * **Approach: transparent borders.**\n *\n * The only reliable cross browser technique found to push a\n * drag preview away from the cursor is to use transparent borders on the container.\n *\n * **\uD83D\uDE45\uD83D\uDCF1 Not pushing the preview away on touch devices**\n *\n * _On iOS_\n *\n * Safari will set the transparent border color to be black\n *\n * `iOS@18.4.1` on May 7th 2025:\n * - If you set the background color on the `container` the border color will be that\n * - Setting a transparent background color on the `container` still results in a\n * black border\n * - The `<body>` text or background color does not change the black border color\n *\n * While dragging, the drag preview will shift under the center of the users pointer.\n * So if you start at {x: 0, y: 0} (top left), almost immediately the preview will move\n * to be under the middle of the users pointer.\n *\n * _On Android_\n *\n * Chrome will put the center of the drag preview under the users pointer immediately.\n *\n * Tested on `Chrome@137` on `Android 14` on June 20th 2025\n *\n * _What we do_\n *\n * We don't add the transparent border\n *\n * - Avoid the black color on iOS\n * - It isn't needed on Android anyway as the preview will be under the center\n * of the users pointer\n *\n * We put the center of the drag preview under the users pointer\n *\n * - Avoids the drag preview quickly moving from a top corner to be centered under\n * the users pointer on iOS\n * - It will be under the center on Android no matter what we do\n *\n * We previously had a isTouchDevice() check, but it felt safer for now\n * to have a more targeted check, as these are the devices that have been\n * tested on.\n */\n if (isSafariOnIOS() || isAndroid()) {\n return centerUnderPointer({\n container: container\n });\n }\n Object.assign(container.style, {\n borderInlineStart: \"\".concat(point.x, \" solid transparent\"),\n borderTop: \"\".concat(point.y, \" solid transparent\")\n });\n\n // Unfortunate that we need to use `getComputedStyle`,\n // but it's only a single call when the drag is starting.\n var computed = window.getComputedStyle(container);\n if (computed.direction === 'rtl') {\n // The DOMRect will include the new border we added\n var box = container.getBoundingClientRect();\n\n // Use the top right corner (including the new border) as the offset.\n // The border will push the preview away from the pointer.\n return {\n x: box.width,\n y: 0\n };\n }\n\n // Use the top left corner as the offset. The border will\n // push the preview away from the pointer.\n return {\n x: 0,\n y: 0\n };\n };\n}", "var ledger = new Map();\nvar requested = new Set();\nexport function markAndGetEngagement(element) {\n markEngagement(element);\n var entry = ledger.get(element);\n if (entry) {\n return entry;\n }\n var fresh = {\n timeOfEngagementStart: Date.now()\n };\n ledger.set(element, fresh);\n return fresh;\n}\nexport function markEngagement(element) {\n requested.add(element);\n}\nexport function clearUnusedEngagements(fn) {\n // make sure previous engagement requests don't linger\n requested.clear();\n\n // perform the required work\n fn();\n\n // if engagements where not requested, purge it\n ledger.forEach(function (_, element) {\n if (!requested.has(element)) {\n ledger.delete(element);\n }\n });\n\n // cleaning up after ourselves\n requested.clear();\n}\nexport function clearEngagementHistory() {\n ledger.clear();\n}", "import { getElementFromPointWithoutHoneypot } from '@atlaskit/pragmatic-drag-and-drop/private/get-element-from-point-without-honey-pot';\nimport { clearEngagementHistory, clearUnusedEngagements } from './engagement-history';\n// We keep this map so that \"over element\" scrolling and \"overflow\" scrolling\n// can leverage the same scheduler.\n// The 'monitor' is the key for looking up schedulers\nvar schedulers = new Map();\nexport function getScheduler(monitor) {\n var scheduler = schedulers.get(monitor);\n if (scheduler) {\n // @ts-expect-error: I don't know how to link the DragType generic between the key and the value when the\n // monitor itself is the key\n return scheduler;\n }\n var created = makeScheduler(monitor);\n schedulers.set(monitor, created);\n return created;\n}\nfunction makeScheduler(monitor) {\n var state = {\n type: 'idle'\n };\n var callbacks = [];\n function loop(timeLastFrameFinished) {\n if (state.type !== 'running') {\n return;\n }\n var timeSinceLastFrame = timeLastFrameFinished - state.timeLastFrameFinished;\n var _state = state,\n latestArgs = _state.latestArgs;\n\n // A common starting lookup point for determining\n // which auto scroller should be used, and what should be scrolled.\n var underUsersPointer = getElementFromPointWithoutHoneypot({\n x: latestArgs.location.current.input.clientX,\n y: latestArgs.location.current.input.clientY\n });\n clearUnusedEngagements(function () {\n callbacks.forEach(function (onFrame) {\n return onFrame({\n underUsersPointer: underUsersPointer,\n latestArgs: latestArgs,\n timeSinceLastFrame: timeSinceLastFrame\n });\n });\n });\n state.timeLastFrameFinished = timeLastFrameFinished;\n state.frameId = requestAnimationFrame(loop);\n }\n function reset() {\n if (state.type === 'idle') {\n return;\n }\n cancelAnimationFrame(state.frameId);\n clearEngagementHistory();\n state = {\n type: 'idle'\n };\n }\n function start(args) {\n if (state.type !== 'idle') {\n return;\n }\n state = {\n // Waiting a frame so we can accurately determine `timeSinceLastFrame`.\n type: 'initializing',\n latestArgs: args,\n frameId: requestAnimationFrame(function (timeLastFrameFinished) {\n if (state.type !== 'initializing') {\n return;\n }\n state = {\n type: 'running',\n timeLastFrameFinished: timeLastFrameFinished,\n latestArgs: state.latestArgs,\n frameId: requestAnimationFrame(loop)\n };\n })\n };\n }\n\n // this module might have been imported after a drag has started\n // We are starting the auto scroller if we get an update event and\n // the auto scroller has not started yet\n function update(args) {\n if (state.type === 'idle') {\n start(args);\n return;\n }\n state.latestArgs = args;\n }\n\n // Not exposing a way to stop listening\n monitor({\n onDragStart: start,\n onDropTargetChange: update,\n onDrag: update,\n onDrop: reset\n });\n var api = {\n onFrame: function onFrame(fn) {\n callbacks.push(fn);\n }\n };\n return api;\n}", "export var dataAttribute = 'data-auto-scrollable';\nexport var selector = \"[\".concat(dataAttribute, \"=\\\"true\\\"]\");\nexport function addScrollableAttribute(element) {\n element.setAttribute(dataAttribute, 'true');\n return function () {\n return element.removeAttribute(dataAttribute);\n };\n}", "import _defineProperty from \"@babel/runtime/helpers/defineProperty\";\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nvar baseConfig = {\n startHitboxAtPercentageRemainingOfElement: {\n top: 0.25,\n right: 0.25,\n bottom: 0.25,\n left: 0.25\n },\n maxScrollAtPercentageRemainingOfHitbox: {\n top: 0.5,\n right: 0.5,\n bottom: 0.5,\n left: 0.5\n },\n timeDampeningDurationMs: 400,\n // Too big and it's too easy to trigger auto scrolling\n // Too small and it's too hard \uD83D\uDE05\n maxMainAxisHitboxSize: 180\n};\n\n/** What the max scroll should be per second. Using \"per second\" rather than \"per frame\"\n * as we want a consistent scroll speed regardless of frame rate.\n *\n *\n * I explored trying to make the max scroll speed dynamic based on particular factors.\n * However, it ended up being difficult to find a _perfect_ formula.\n *\n * Likely the perfect answer would involve:\n * - the size of the scrollable element\n * - the size of the scrollable element relative to the screen size\n * - the size of the drag preview\n * - the size of elements being scrolled in scrollable elements (expensive and difficult to compute)\n */\nvar maxPixelScrollPerSecond = {\n // What the value would be if we were scrolling at 15px per frame at 60fps.\n // This is the default as it works well for most experiences.\n // In certain scenarios though it can feel a bit slow.\n standard: 15 * 60,\n // What the value would be if we were scrolling at 25px per frame at 60fps.\n // This is not the default as it feels too fast for a lot of experiences.\n fast: 25 * 60\n};\nexport function getInternalConfig(provided) {\n var _provided$maxScrollSp;\n return _objectSpread(_objectSpread({}, baseConfig), {}, {\n // only allowing limited control over the config at this stage\n maxPixelScrollPerSecond: maxPixelScrollPerSecond[(_provided$maxScrollSp = provided === null || provided === void 0 ? void 0 : provided.maxScrollSpeed) !== null && _provided$maxScrollSp !== void 0 ? _provided$maxScrollSp : 'standard']\n });\n}", "export var canScrollOnEdge = {\n // Notes:\n //\n // \uD83C\uDF0F Chrome 115.0: uses fractional units for `scrollLeft` and `scrollTop`\n // (and fractional units don't reach true integer maximum when zoomed in / out)\n // \uD83C\uDF4E Safari 16.5.2: no fractional units\n // \uD83E\uDD8A Firefox 115.0: no fractional units\n\n // we have some scroll we can move backwards into\n top: function top(element) {\n return element.scrollTop > 0;\n },\n // We have some scroll we can move forward into\n right: function right(element) {\n return Math.ceil(element.scrollLeft) + element.clientWidth < element.scrollWidth;\n },\n // We have some scroll we can move forwards into\n bottom: function bottom(element) {\n return Math.ceil(element.scrollTop) + element.clientHeight < element.scrollHeight;\n },\n // we have some scroll we can move back into.\n left: function left(element) {\n return element.scrollLeft > 0;\n }\n};", "export var edges = ['top', 'right', 'bottom', 'left'];\nexport var edgeAxisLookup = {\n top: 'vertical',\n right: 'horizontal',\n bottom: 'vertical',\n left: 'horizontal'\n};", "var vertical = {\n start: 'top',\n end: 'bottom',\n point: 'y',\n size: 'height'\n};\nvar horizontal = {\n start: 'left',\n end: 'right',\n point: 'x',\n size: 'width'\n};\nexport var axisLookup = {\n vertical: {\n mainAxis: vertical,\n crossAxis: horizontal\n },\n horizontal: {\n mainAxis: horizontal,\n crossAxis: vertical\n }\n};", "export var mainAxisSideLookup = {\n top: 'start',\n right: 'end',\n bottom: 'end',\n left: 'start'\n};", "import _defineProperty from \"@babel/runtime/helpers/defineProperty\";\nimport { axisLookup } from './axis';\nimport { mainAxisSideLookup } from './side';\nfunction makeGetHitbox(_ref) {\n var edge = _ref.edge,\n axis = _ref.axis;\n return function hitbox(_ref2) {\n var clientRect = _ref2.clientRect,\n config = _ref2.config;\n var _axisLookup$axis = axisLookup[axis],\n mainAxis = _axisLookup$axis.mainAxis,\n crossAxis = _axisLookup$axis.crossAxis;\n var side = mainAxisSideLookup[edge];\n var mainAxisHitboxSize = Math.min(\n // scale the size of the hitbox down for smaller elements\n config.startHitboxAtPercentageRemainingOfElement[edge] * clientRect[mainAxis.size],\n // Don't let the hitbox grow too big for big elements\n config.maxMainAxisHitboxSize);\n return DOMRect.fromRect(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, mainAxis.point, side === 'start' ?\n // begin from the start edge and grow inwards\n clientRect[mainAxis.point] :\n // begin from inside the end edge and grow towards the end edge\n clientRect[mainAxis.point] + clientRect[mainAxis.size] - mainAxisHitboxSize), crossAxis.point, clientRect[crossAxis.point]), mainAxis.size, mainAxisHitboxSize), crossAxis.size, clientRect[crossAxis.size]));\n };\n}\nexport var getOverElementHitbox = {\n top: makeGetHitbox({\n axis: 'vertical',\n edge: 'top'\n }),\n right: makeGetHitbox({\n axis: 'horizontal',\n edge: 'right'\n }),\n bottom: makeGetHitbox({\n axis: 'vertical',\n edge: 'bottom'\n }),\n left: makeGetHitbox({\n axis: 'horizontal',\n edge: 'left'\n })\n};", "export function getPercentageInRange(_ref) {\n var startOfRange = _ref.startOfRange,\n endOfRange = _ref.endOfRange,\n value = _ref.value;\n // checking inputs\n var isValid = startOfRange < endOfRange;\n if (!isValid) {\n return 0;\n }\n if (value < startOfRange) {\n return 0;\n }\n if (value > endOfRange) {\n return 1;\n }\n var range = endOfRange - startOfRange;\n return (value - startOfRange) / range;\n}", "import { axisLookup } from './axis';\nimport { getPercentageInRange } from './get-percentage-in-range';\nimport { mainAxisSideLookup } from './side';\n\n// We want a consistent scroll speed across devices, regardless of framerate\nfunction getMaxScrollChange(_ref) {\n var timeSinceLastFrame = _ref.timeSinceLastFrame,\n config = _ref.config;\n var targetScrollPerMs = config.maxPixelScrollPerSecond / 1000;\n\n // Adjusting out target scroll rate to match the frame rate of the target device\n // This will pull the scroll speed down on high frame rate devices\n // so we get a consistent visual scroll speed regardless of device.\n var proposed = Math.ceil(targetScrollPerMs * timeSinceLastFrame);\n\n // If lots of time as passed since that last frame (such on lower frame rate devices)\n // we don't want the scroll speed to be too fast, otherwise it can feel jumpy\n // We are capping the scroll speed at what it would be if we were hitting 60fps\n var maximum = config.maxPixelScrollPerSecond / 60;\n return Math.min(proposed, maximum);\n}\nfunction getDistanceDampening(_ref2) {\n var client = _ref2.client,\n axis = _ref2.axis,\n edge = _ref2.edge,\n hitbox = _ref2.hitbox,\n config = _ref2.config;\n var mainAxis = axisLookup[axis].mainAxis;\n var side = mainAxisSideLookup[edge];\n\n // We want to hit the max speed before the edge of the hitbox\n var maxSpeedBuffer = hitbox[mainAxis.size] * config.maxScrollAtPercentageRemainingOfHitbox[edge];\n if (side === 'end') {\n return getPercentageInRange({\n startOfRange: hitbox[mainAxis.start],\n endOfRange: hitbox[mainAxis.end] - maxSpeedBuffer,\n value: client[mainAxis.point]\n });\n }\n\n // Moving towards start edge\n\n var raw = getPercentageInRange({\n startOfRange: hitbox[mainAxis.start] + maxSpeedBuffer,\n endOfRange: hitbox[mainAxis.end],\n value: client[mainAxis.point]\n });\n // When moving near start edge\n // - the 'end' edge is where we start scrolling\n // - the 'start' edge is where we reach max speed\n // So we need to invert the percentage when moving backwards\n return 1 - raw;\n}\nexport function getScrollChange(_ref3) {\n var client = _ref3.client,\n timeSinceLastFrame = _ref3.timeSinceLastFrame,\n engagement = _ref3.engagement,\n axis = _ref3.axis,\n hitbox = _ref3.hitbox,\n edge = _ref3.edge,\n isDistanceDampeningEnabled = _ref3.isDistanceDampeningEnabled,\n config = _ref3.config;\n // We have two forms of speed dampening:\n // 1. \uD83D\uDDFA\uFE0F Distance\n // The closer you are to a hitbox edge, the faster the scroll speed will be\n // 2. \u23F1\uFE0F Time\n // When first entering a scroll container we want to dampening all scrolling\n // This is to prevent super fast auto scrolling when first entering into\n // a scroll container, or when lifting in a scroll container\n\n var maxScroll = getMaxScrollChange({\n timeSinceLastFrame: timeSinceLastFrame,\n config: config\n });\n var percentageDistanceDampening = isDistanceDampeningEnabled ? getDistanceDampening({\n client: client,\n edge: edge,\n hitbox: hitbox,\n axis: axis,\n config: config\n }) : 1;\n\n // Dampen speed by time\n var percentageThroughTimeDampening = getPercentageInRange({\n startOfRange: engagement.timeOfEngagementStart,\n endOfRange: engagement.timeOfEngagementStart + config.timeDampeningDurationMs,\n value: Date.now()\n });\n\n // Calculate how much of the max scroll we should apply based on dampening\n var percentageOfMaxScroll = percentageDistanceDampening * percentageThroughTimeDampening;\n\n // We _could_ ease this update (`Math.pow(percentageOfMaxSpeed, 2)`)\n // But linear is feeling really good\n // Always scrolling by at least one pixel, otherwise the scroll does nothing\n var scroll = Math.max(maxScroll * percentageOfMaxScroll, 1);\n var side = mainAxisSideLookup[edge];\n\n // When moving backwards, we will be scrolling backwards\n return side === 'end' ? scroll : -1 * scroll;\n}", "export function isAxisAllowed(axis, allowedAxis) {\n return allowedAxis === 'all' || axis === allowedAxis;\n}", "export function isWithin(_ref) {\n var client = _ref.client,\n clientRect = _ref.clientRect;\n return (\n // is within horizontal bounds\n client.x >= clientRect.x && client.x <= clientRect.x + clientRect.width &&\n // is within vertical bounds\n client.y >= clientRect.y && client.y <= clientRect.y + clientRect.height\n );\n}", "import { canScrollOnEdge } from '../shared/can-scroll-on-edge';\nimport { edgeAxisLookup, edges } from '../shared/edges';\nimport { getOverElementHitbox } from '../shared/get-over-element-hitbox';\nimport { getScrollChange } from '../shared/get-scroll-change';\nimport { isAxisAllowed } from '../shared/is-axis-allowed';\nimport { isWithin } from '../shared/is-within';\nfunction getRectDefault(element) {\n return element.getBoundingClientRect();\n}\nexport function getScrollBy(_ref) {\n var element = _ref.element,\n input = _ref.input,\n timeSinceLastFrame = _ref.timeSinceLastFrame,\n engagement = _ref.engagement,\n config = _ref.config,\n allowedAxis = _ref.allowedAxis,\n _ref$getRect = _ref.getRect,\n getRect = _ref$getRect === void 0 ? getRectDefault : _ref$getRect;\n var client = {\n x: input.clientX,\n y: input.clientY\n };\n var clientRect = getRect(element);\n var scrollableEdges = edges.reduce(function (map, edge) {\n var hitbox = getOverElementHitbox[edge]({\n clientRect: clientRect,\n config: config\n });\n var axis = edgeAxisLookup[edge];\n\n // Note: changing the allowed axis during a drag will not\n // reset time dampening. It was decided it would be too\n // complex to implement initially, and we can add it\n // later if needed.\n if (!isAxisAllowed(axis, allowedAxis)) {\n return map;\n }\n if (!isWithin({\n client: client,\n clientRect: hitbox\n })) {\n return map;\n }\n if (!canScrollOnEdge[edge](element)) {\n return map;\n }\n map.set(edge, {\n edge: edge,\n hitbox: hitbox\n });\n return map;\n }, new Map());\n var left = function () {\n var axis = 'horizontal';\n var leftEdge = scrollableEdges.get('left');\n if (leftEdge) {\n return getScrollChange({\n client: client,\n edge: leftEdge.edge,\n hitbox: leftEdge.hitbox,\n axis: axis,\n timeSinceLastFrame: timeSinceLastFrame,\n engagement: engagement,\n isDistanceDampeningEnabled: true,\n config: config\n });\n }\n var rightEdge = scrollableEdges.get('right');\n if (rightEdge) {\n return getScrollChange({\n client: client,\n edge: rightEdge.edge,\n hitbox: rightEdge.hitbox,\n axis: axis,\n timeSinceLastFrame: timeSinceLastFrame,\n engagement: engagement,\n isDistanceDampeningEnabled: true,\n config: config\n });\n }\n return 0;\n }();\n var top = function () {\n var axis = 'vertical';\n var bottomEdge = scrollableEdges.get('bottom');\n if (bottomEdge) {\n return getScrollChange({\n client: client,\n edge: bottomEdge.edge,\n hitbox: bottomEdge.hitbox,\n axis: axis,\n timeSinceLastFrame: timeSinceLastFrame,\n engagement: engagement,\n isDistanceDampeningEnabled: true,\n config: config\n });\n }\n var topEdge = scrollableEdges.get('top');\n if (topEdge) {\n return getScrollChange({\n client: client,\n edge: topEdge.edge,\n hitbox: topEdge.hitbox,\n axis: axis,\n timeSinceLastFrame: timeSinceLastFrame,\n engagement: engagement,\n isDistanceDampeningEnabled: true,\n config: config\n });\n }\n return 0;\n }();\n return {\n left: left,\n top: top\n };\n}", "function _createForOfIteratorHelper(r, e) { var t = \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && \"number\" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nimport { getInternalConfig } from '../shared/configuration';\nimport { markAndGetEngagement } from '../shared/engagement-history';\nimport { selector } from './data-attributes';\nimport { getScrollBy } from './get-scroll-by';\nfunction isScrollingAvailable(value) {\n return Boolean(value.top || value.left);\n}\nfunction tryScrollElements(_ref) {\n var _container$getConfigu, _container$getAllowed, _container$getAllowed2;\n var target = _ref.target,\n input = _ref.input,\n source = _ref.source,\n findEntry = _ref.findEntry,\n timeSinceLastFrame = _ref.timeSinceLastFrame,\n _ref$available = _ref.available,\n available = _ref$available === void 0 ? {\n top: true,\n left: true\n } : _ref$available;\n // we cannot do any more scrolling\n if (!isScrollingAvailable(available)) {\n return available;\n }\n\n // run out of parents to search\n if (!target) {\n return available;\n }\n var element = target.closest(selector);\n\n // cannot find any more scroll containers\n if (!element) {\n return available;\n }\n var container = findEntry(element);\n\n // cannot find registration, this is bad.\n // fail and just exit\n if (!container) {\n return available;\n }\n function continueSearchUp() {\n var _element$parentElemen;\n return tryScrollElements({\n target: (_element$parentElemen = element === null || element === void 0 ? void 0 : element.parentElement) !== null && _element$parentElemen !== void 0 ? _element$parentElemen : null,\n findEntry: findEntry,\n source: source,\n timeSinceLastFrame: timeSinceLastFrame,\n input: input,\n available: available\n });\n }\n var feedback = {\n input: input,\n source: source,\n element: element\n };\n\n // Engagement is not marked if scrolling is explicitly not allowed\n if (container.canScroll && !container.canScroll(feedback)) {\n return continueSearchUp();\n }\n\n // Marking engagement even if no edges are scrollable.\n // We are marking engagement as soon as the element is scrolled over\n var engagement = markAndGetEngagement(element);\n var config = getInternalConfig((_container$getConfigu = container.getConfiguration) === null || _container$getConfigu === void 0 ? void 0 : _container$getConfigu.call(container, feedback));\n var allowedAxis = (_container$getAllowed = (_container$getAllowed2 = container.getAllowedAxis) === null || _container$getAllowed2 === void 0 ? void 0 : _container$getAllowed2.call(container, feedback)) !== null && _container$getAllowed !== void 0 ? _container$getAllowed : 'all';\n var scrollBy = getScrollBy({\n element: element,\n engagement: engagement,\n input: input,\n timeSinceLastFrame: timeSinceLastFrame,\n allowedAxis: allowedAxis,\n config: config\n });\n\n // Only allow scrolling in directions that have not already been used\n var scroll = {\n top: 0,\n left: 0\n };\n if (available.top && scrollBy.top !== 0) {\n scroll.top = scrollBy.top;\n // can no longer scroll on the top after this\n available.top = false;\n }\n if (available.left && scrollBy.left !== 0) {\n scroll.left = scrollBy.left;\n // can no longer scroll on the left after this\n available.left = false;\n }\n\n // Only scroll if there is something to scroll\n if (scroll.top !== 0 || scroll.left !== 0) {\n element.scrollBy(scroll);\n }\n return continueSearchUp();\n}\nfunction tryScrollWindow(_ref2) {\n var input = _ref2.input,\n timeSinceLastFrame = _ref2.timeSinceLastFrame,\n available = _ref2.available,\n source = _ref2.source,\n entries = _ref2.entries;\n var element = document.documentElement;\n var feedback = {\n input: input,\n source: source,\n element: element\n };\n var _iterator = _createForOfIteratorHelper(entries),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var _entry$getConfigurati, _entry$getAllowedAxis, _entry$getAllowedAxis2;\n var entry = _step.value;\n // this entry is not allowing scrolling, we need to look for another\n if (entry.canScroll && !entry.canScroll(feedback)) {\n continue;\n }\n\n // Note: if we had an event for when the user is leaving a tab\n // we _could_ conceptually reset the engagement\n var engagement = markAndGetEngagement(element);\n var config = getInternalConfig((_entry$getConfigurati = entry.getConfiguration) === null || _entry$getConfigurati === void 0 ? void 0 : _entry$getConfigurati.call(entry, feedback));\n var allowedAxis = (_entry$getAllowedAxis = (_entry$getAllowedAxis2 = entry.getAllowedAxis) === null || _entry$getAllowedAxis2 === void 0 ? void 0 : _entry$getAllowedAxis2.call(entry, feedback)) !== null && _entry$getAllowedAxis !== void 0 ? _entry$getAllowedAxis : 'all';\n var scrollBy = getScrollBy({\n element: element,\n engagement: engagement,\n input: input,\n config: config,\n allowedAxis: allowedAxis,\n getRect: function getRect(element) {\n return DOMRect.fromRect({\n y: 0,\n x: 0,\n width: element.clientWidth,\n height: element.clientHeight\n });\n },\n timeSinceLastFrame: timeSinceLastFrame\n });\n var scroll = {\n top: available.top ? scrollBy.top : 0,\n left: available.left ? scrollBy.left : 0\n };\n\n // only trigger a scroll if we are actually scrolling\n if (scroll.top !== 0 || scroll.left !== 0) {\n element.scrollBy(scroll);\n }\n\n // We only want the window to scroll once\n break;\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n}\nexport function tryScroll(_ref3) {\n var input = _ref3.input,\n findEntry = _ref3.findEntry,\n timeSinceLastFrame = _ref3.timeSinceLastFrame,\n source = _ref3.source,\n getWindowScrollEntries = _ref3.getWindowScrollEntries,\n underUsersPointer = _ref3.underUsersPointer;\n // We are matching browser behaviour and scrolling inner elements\n // before outer ones. So we try to scroll scroller containers before\n // the window.\n var remainder = tryScrollElements({\n target: underUsersPointer,\n timeSinceLastFrame: timeSinceLastFrame,\n input: input,\n source: source,\n findEntry: findEntry\n });\n\n // Check if we can do any window scrolling\n if (!isScrollingAvailable(remainder)) {\n return;\n }\n tryScrollWindow({\n input: input,\n source: source,\n entries: getWindowScrollEntries(),\n timeSinceLastFrame: timeSinceLastFrame,\n available: remainder\n });\n}", "import _defineProperty from \"@babel/runtime/helpers/defineProperty\";\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nimport { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';\nimport { once } from '@atlaskit/pragmatic-drag-and-drop/once';\nimport { getScheduler } from '../shared/scheduler';\nimport { addScrollableAttribute } from './data-attributes';\nimport { tryScroll } from './try-scroll';\nexport function makeApi(_ref) {\n var monitor = _ref.monitor;\n var elementRegistry = new Map();\n var windowRegistry = new Set();\n function autoScroll(args) {\n // Warn during development if trying to add auto scroll to an element\n // that is not scrollable.\n // Note: this can produce a false positive when a scroll container is not\n // scrollable initially, but becomes scrollable during a drag.\n // I thought of adding the warning as I think it would be a more common pitfall\n // to accidentally register auto scrolling on the wrong element\n // If requested, we could provide a mechanism to opt out of this warning\n if (process.env.NODE_ENV !== 'production') {\n var _window$getComputedSt = window.getComputedStyle(args.element),\n overflowX = _window$getComputedSt.overflowX,\n overflowY = _window$getComputedSt.overflowY;\n var isScrollable = overflowX === 'auto' || overflowX === 'scroll' || overflowY === 'auto' || overflowY === 'scroll';\n if (!isScrollable) {\n // eslint-disable-next-line no-console\n console.warn('Auto scrolling has been attached to an element that appears not to be scrollable', {\n element: args.element,\n overflowX: overflowX,\n overflowY: overflowY\n });\n }\n }\n\n // Warn if there is an existing registration\n if (process.env.NODE_ENV !== 'production') {\n var existing = elementRegistry.get(args.element);\n if (existing) {\n // eslint-disable-next-line no-console\n console.warn('You have already registered autoScrolling on the same element', {\n existing: existing,\n proposed: args\n });\n }\n }\n elementRegistry.set(args.element, args);\n var cleanup = combine(addScrollableAttribute(args.element), function () {\n return elementRegistry.delete(args.element);\n });\n return once(cleanup);\n }\n function autoScrollWindow() {\n var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n // Putting `args` in a unique object so that\n // each call will create a unique entry, even if a consumer\n // shares the `args` object between calls.\n // Just being safe here.\n var unique = _objectSpread({}, args);\n windowRegistry.add(unique);\n function cleanup() {\n windowRegistry.delete(unique);\n }\n return once(cleanup);\n }\n function findEntry(element) {\n var _elementRegistry$get;\n return (_elementRegistry$get = elementRegistry.get(element)) !== null && _elementRegistry$get !== void 0 ? _elementRegistry$get : null;\n }\n function getWindowScrollEntries() {\n return Array.from(windowRegistry);\n }\n function onFrame(_ref2) {\n var latestArgs = _ref2.latestArgs,\n underUsersPointer = _ref2.underUsersPointer,\n timeSinceLastFrame = _ref2.timeSinceLastFrame;\n tryScroll({\n input: latestArgs.location.current.input,\n source: latestArgs.source,\n findEntry: findEntry,\n underUsersPointer: underUsersPointer,\n timeSinceLastFrame: timeSinceLastFrame,\n getWindowScrollEntries: getWindowScrollEntries\n });\n }\n getScheduler(monitor).onFrame(onFrame);\n return {\n autoScroll: autoScroll,\n autoScrollWindow: autoScrollWindow\n };\n}", "import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';\nimport { makeApi } from '../over-element/make-api';\nvar api = makeApi({\n monitor: monitorForElements\n});\nexport var autoScrollForElements = api.autoScroll;\nexport var autoScrollWindowForElements = api.autoScrollWindow;", "/**\n * Unit-sequence diff for the editor's incremental structural repaint.\n *\n * After a structural op (insert table/row, footnote, delete block, undo/redo)\n * the editor fetches the session's {@link RenderPlan} (`ListBlocks`) and diffs\n * each container's unit sequence against the DOM's, so unchanged blocks keep\n * their DOM nodes and only changed/created units re-render \u2014 replacing the\n * whole-document remount that cost seconds on large documents.\n *\n * Pure functions only: DOM walking, rendering, and fallback policy live in\n * `editor.ts` (`DocxEditor.reconcile`).\n */\n\n/** One top-level render unit: a body block (`p`/`h`/`li`), one whole table\n * (`tbl`), or one footnote/endnote definition (`fn`/`en`). Mirrors the wire\n * shape of `DocxSessionBridge.ListBlocks`. `sig` (container units only) is a\n * content signature: a table or note keeps its unid when content INSIDE it\n * changes, so the diff tokens must include it or a changed container would be\n * kept stale. */\nexport interface RenderUnit {\n id: string;\n kind: string;\n sig?: string;\n /** Index of the section wrapper (`[data-section-index]`) a body unit renders into. */\n section?: number;\n /** Ordinal of the border box the renderer groups adjacent bordered paragraphs into; units\n * sharing a group render inside one wrapper, so a windowed mount never splits one. */\n group?: number;\n}\n\n/** The diff token for a unit: unid plus the container content signature. The DOM\n * side composes the same token from a node's `data-anchor` + `data-render-sig`\n * stamp, so a container whose inside changed diffs as an in-place substitution. */\nexport function tokenOf(unit: RenderUnit): string {\n return unidOf(unit.id) + (unit.sig ? \"|\" + unit.sig : \"\");\n}\n\n/** Per-container render plan \u2014 the wire shape of `DocxSessionBridge.ListBlocks`. */\nexport interface RenderPlan {\n body: RenderUnit[];\n footnotes: RenderUnit[];\n endnotes: RenderUnit[];\n}\n\nexport interface UnitDiff {\n /** newIndex \u2192 oldIndex for units that keep their existing DOM node. */\n keep: Map<number, number>;\n /** Indices into the OLD DOM sequence whose nodes must be removed. */\n removed: number[];\n /** Indices into the NEW plan that need a fresh render. */\n added: number[];\n /**\n * added/removed pairs that are an IN-PLACE change (same number of kept units\n * on each side) \u2014 e.g. a text edit re-hashing a block's content-addressed\n * unid. A substituted list item keeps its list position, so it renumbers no\n * siblings and may reconcile where a pure li insert/remove may not.\n */\n substituted: Array<{ oldIndex: number; newIndex: number }>;\n /** Exact-token units whose existing DOM node moves to a new document slot. */\n moved: Array<{ oldIndex: number; newIndex: number }>;\n}\n\n/** unid (\"a1b2\u2026\") from a full anchor id (\"p:body:a1b2\u2026\"). */\nexport function unidOf(id: string): string {\n return id.substring(id.lastIndexOf(\":\") + 1);\n}\n\n/**\n * LCS diff of the DOM's unit-token sequence against the new plan's. Old entries\n * are tokens (see {@link tokenOf} \u2014 bare unids for leaf blocks, `unid|sig` for\n * containers). Equal tokens are interchangeable (content-addressed: equal token\n * \u21D2 equal content \u21D2 equal rendering, up to position-dependent chrome the caller\n * handles). O(n\u00B7m) \u2014 sequences are document block counts, a few hundred.\n */\nexport function diffUnits(oldUnids: string[], newUnits: RenderUnit[]): UnitDiff {\n const n = oldUnids.length;\n const m = newUnits.length;\n const newUnids = newUnits.map(tokenOf);\n\n // lcs[i][j] = LCS length of oldUnids[i..] vs newUnids[j..]\n const lcs: Int32Array[] = Array.from({ length: n + 1 }, () => new Int32Array(m + 1));\n for (let i = n - 1; i >= 0; i--) {\n for (let j = m - 1; j >= 0; j--) {\n lcs[i][j] =\n oldUnids[i] === newUnids[j]\n ? lcs[i + 1][j + 1] + 1\n : Math.max(lcs[i + 1][j], lcs[i][j + 1]);\n }\n }\n\n const keep = new Map<number, number>();\n const removed: number[] = [];\n const added: number[] = [];\n let i = 0;\n let j = 0;\n while (i < n && j < m) {\n if (oldUnids[i] === newUnids[j]) {\n keep.set(j, i);\n i++;\n j++;\n } else if (lcs[i + 1][j] >= lcs[i][j + 1]) {\n removed.push(i++);\n } else {\n added.push(j++);\n }\n }\n while (i < n) removed.push(i++);\n while (j < m) added.push(j++);\n\n // Substitutions: an added index and a removed index that are an IN-PLACE change\n // of one unit. Paired by UNID first \u2014 a block whose content changed keeps its\n // unid (unids are sticky in-session; only the content signature part of the\n // token moves), so an equal-unid add/remove pair is that block re-rendering in\n // place regardless of how many other units changed around it. Position-based\n // (kept-count) pairing is the fallback for genuine replacements; unid pairing\n // must run first or several same-position changes mispair, e.g. binding an\n // edited paragraph's fresh render to a NEIGHBOR's border-wrapped node \u2014 which\n // the DOM patcher can only resolve by bailing to a full remount.\n const bareUnid = (token: string): string => {\n const bar = token.indexOf(\"|\");\n return bar < 0 ? token : token.slice(0, bar);\n };\n const moved: Array<{ oldIndex: number; newIndex: number }> = [];\n const usedRemoved = new Set<number>();\n const usedAdded = new Set<number>();\n\n // An exact token on both sides is a relocation, not a replacement. Pair these\n // before same-unid substitutions so a pure reorder preserves its live DOM node.\n const removedByToken = new Map<string, number[]>();\n for (const oi of removed) {\n (removedByToken.get(oldUnids[oi]) ?? removedByToken.set(oldUnids[oi], []).get(oldUnids[oi])!).push(oi);\n }\n for (const nj of added) {\n const candidates = removedByToken.get(newUnids[nj]);\n const oi = candidates?.find((i) => !usedRemoved.has(i));\n if (oi !== undefined) {\n moved.push({ oldIndex: oi, newIndex: nj });\n usedRemoved.add(oi);\n usedAdded.add(nj);\n }\n }\n\n const substituted: Array<{ oldIndex: number; newIndex: number }> = [];\n const removedByUnid = new Map<string, number[]>();\n for (const oi of removed) {\n if (usedRemoved.has(oi)) continue;\n const u = bareUnid(oldUnids[oi]);\n (removedByUnid.get(u) ?? removedByUnid.set(u, []).get(u)!).push(oi);\n }\n const unmatchedAdded: number[] = [];\n for (const nj of added) {\n if (usedAdded.has(nj)) continue;\n const candidates = removedByUnid.get(bareUnid(newUnids[nj]));\n const oi = candidates?.find((i) => !usedRemoved.has(i));\n if (oi !== undefined) {\n substituted.push({ oldIndex: oi, newIndex: nj });\n usedRemoved.add(oi);\n } else {\n unmatchedAdded.push(nj);\n }\n }\n const keptBeforeOld = (oi: number): number => {\n let c = 0;\n for (const v of keep.values()) if (v < oi) c++;\n return c;\n };\n const keptBeforeNew = (nj: number): number => {\n let c = 0;\n for (const k of keep.keys()) if (k < nj) c++;\n return c;\n };\n for (const nj of unmatchedAdded) {\n const target = keptBeforeNew(nj);\n for (const oi of removed) {\n if (usedRemoved.has(oi)) continue;\n if (keptBeforeOld(oi) === target) {\n substituted.push({ oldIndex: oi, newIndex: nj });\n usedRemoved.add(oi);\n break;\n }\n }\n }\n\n return { keep, removed, added, substituted, moved };\n}\n\n/**\n * Whether this diff must fall back to a full remount:\n * - a PURE li insert or removal (not an in-place substitution) \u2014 sibling list\n * items renumber without their own XML changing, which a unit diff cannot see;\n * - total churn above `threshold` (a remount is cheaper and simpler than\n * rendering half the document block-by-block).\n *\n * `oldKinds[i]` is the kind of the old sequence's i-th unit (the DOM knows it).\n * An li substitution deliberately does NOT force a remount \u2014 its list position\n * is unchanged; the CALLER must still verify its list facts (numId/ilvl)\n * survived, and remount when they changed.\n */\nexport function needsRemount(\n diff: UnitDiff,\n newUnits: RenderUnit[],\n oldKinds: string[],\n threshold = 40,\n): boolean {\n if (diff.added.length + diff.removed.length > threshold) return true;\n const subNew = new Set(diff.substituted.map((s) => s.newIndex));\n const subOld = new Set(diff.substituted.map((s) => s.oldIndex));\n for (const j of diff.added) {\n if (!subNew.has(j) && newUnits[j]?.kind === \"li\") return true;\n }\n for (const i of diff.removed) {\n if (!subOld.has(i) && oldKinds[i] === \"li\") return true;\n }\n return false;\n}\n", "/**\n * In-place image patching for the editor's incremental reconcile.\n *\n * When a block's fresh render differs from its live DOM node only in the attributes\n * of `<img>` elements \u2014 a host replacing an image's media through the session, most\n * visibly the arcade's Doom cartridge writing a new framebuffer PNG every frame \u2014\n * the reconciler must NOT swap the node. Firefox and WebKit paint a freshly inserted\n * `<img>` as an empty box until its (data-URI) source is decoded, so a per-frame swap\n * strobes white between frames. Changing `src` on the element that is already on\n * screen keeps the previous bitmap visible until the new one is ready, in every\n * engine.\n *\n * Both functions are deliberately self-contained (no module-level state, no imports)\n * so a browser test can inject them into a page with `Function.prototype.toString`.\n */\n\n/** Attributes the editor stamps on live blocks after rendering; a fresh render never\n * carries them, so they are not a difference. Mirrors `DocxEditor.wireBlock`. Each\n * function repeats the list inline rather than defaulting to this constant so that\n * its source, injected into a page on its own, has no free variable. */\nexport const EDITOR_OWNED_ATTRIBUTES: readonly string[] = [\n \"contenteditable\", \"data-committed-text\", \"data-render-sig\", \"data-note-anchor\",\n];\n\n/**\n * The `[live, fresh]` `<img>` pairs when `live` and `fresh` are the same tree apart\n * from `<img>` attributes; `null` when anything else differs (tag, text, any other\n * attribute, child count), in which case the caller must swap nodes as before.\n *\n * Editor-owned attributes on the live side are ignored, as is the list-marker\n * separator element the editor injects into list blocks. Everything else must match\n * exactly \u2014 the patch is only ever taken when it is provably equivalent to a swap.\n */\nexport function imageOnlyDelta(\n live: Element,\n fresh: Element,\n ignoredAttributes?: readonly string[],\n): Array<[HTMLImageElement, HTMLImageElement]> | null {\n const ignored = new Set(\n ignoredAttributes ?? [\"contenteditable\", \"data-committed-text\", \"data-render-sig\", \"data-note-anchor\"],\n );\n const pairs: Array<[HTMLImageElement, HTMLImageElement]> = [];\n const attributeNames = (el: Element): string[] =>\n Array.from(el.attributes)\n .map((a) => a.name)\n .filter((n) => !ignored.has(n))\n .sort();\n const sameAttributes = (a: Element, b: Element): boolean => {\n const na = attributeNames(a);\n const nb = attributeNames(b);\n if (na.length !== nb.length) return false;\n for (let i = 0; i < na.length; i++) {\n if (na[i] !== nb[i] || a.getAttribute(na[i]) !== b.getAttribute(nb[i])) return false;\n }\n return true;\n };\n const liveChildren = (el: Element): ChildNode[] =>\n Array.from(el.childNodes).filter(\n (n) => !(n.nodeType === 1 && (n as Element).hasAttribute(\"data-editor-list-separator\")),\n );\n const walk = (a: Node, b: Node): boolean => {\n if (a.nodeType !== b.nodeType) return false;\n if (a.nodeType === 3) return a.nodeValue === b.nodeValue; // text\n if (a.nodeType !== 1) return true; // comments and the like carry no rendering\n const ea = a as Element;\n const eb = b as Element;\n if (ea.tagName !== eb.tagName) return false;\n if (ea.tagName === \"IMG\") {\n pairs.push([ea as HTMLImageElement, eb as HTMLImageElement]);\n return true;\n }\n if (!sameAttributes(ea, eb)) return false;\n const ca = liveChildren(ea);\n const cb = Array.from(eb.childNodes);\n if (ca.length !== cb.length) return false;\n for (let i = 0; i < ca.length; i++) if (!walk(ca[i], cb[i])) return false;\n return true;\n };\n return walk(live, fresh) ? pairs : null;\n}\n\n/**\n * Make `live` carry exactly `fresh`'s attributes, touching only what changed and\n * keeping the editor-owned stamps. `src` is set last, after any new dimensions, so\n * the box is already the right size when the new source starts loading. An unchanged\n * `src` is left alone \u2014 re-setting it would restart the load for nothing.\n */\nexport function patchImageAttributes(\n live: HTMLImageElement,\n fresh: HTMLImageElement,\n ignoredAttributes?: readonly string[],\n): void {\n const ignored = new Set(\n ignoredAttributes ?? [\"contenteditable\", \"data-committed-text\", \"data-render-sig\", \"data-note-anchor\"],\n );\n for (const attr of Array.from(live.attributes)) {\n if (!ignored.has(attr.name) && !fresh.hasAttribute(attr.name)) live.removeAttribute(attr.name);\n }\n for (const attr of Array.from(fresh.attributes)) {\n if (attr.name === \"src\") continue;\n if (live.getAttribute(attr.name) !== attr.value) live.setAttribute(attr.name, attr.value);\n }\n const src = fresh.getAttribute(\"src\");\n if (src !== null && live.getAttribute(\"src\") !== src) live.setAttribute(\"src\", src);\n}\n", "/**\n * DocxEditor \u2014 a framework-agnostic, in-browser DOCX block editor.\n *\n * Architecture (see docs/architecture/ir_editor_feasibility.md, \"Option B\"):\n * - model-of-record: a live DocxSession in WASM (lossless save);\n * - rendering: WmlToHtmlConverter HTML (faithful) stamped with data-anchor;\n * - editing: each block is contenteditable; on commit, the edit goes through\n * DocxSession by anchor, then ONLY that block is re-rendered from the live\n * session (session-attached RenderBlockHtml) and patched into the DOM.\n *\n * The IR/anchor system is the addressing spine; the live OOXML is the truth.\n * This is the pure-TypeScript core; a React wrapper can sit on top.\n *\n * MVP scope: per-block, commit-on-blur editing of paragraphs/headings. An edited\n * block's content is replaced from its plain text (inline formatting within an\n * edited block is not preserved \u2014 a documented MVP limit); UNTOUCHED blocks keep\n * full fidelity, and save() is lossless for them.\n */\n\nimport { paginateHtml } from \"./pagination.js\";\nimport { DocumentViewport } from \"./viewport.js\";\nimport type { ColumnWidth } from \"./viewport.js\";\nimport { HeaderFooterRegion } from \"./editor-headerfooter.js\";\nimport type { BandWhich } from \"./editor-headerfooter.js\";\nimport { CommentGutter, COMMENT_GUTTER_CSS } from \"./editor-comments.js\";\nimport type { CommentTarget } from \"./editor-comments.js\";\nimport {\n draggable,\n dropTargetForElements,\n monitorForElements,\n} from \"@atlaskit/pragmatic-drag-and-drop/element/adapter\";\nimport { setCustomNativeDragPreview } from \"@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview\";\nimport { pointerOutsideOfPreview } from \"@atlaskit/pragmatic-drag-and-drop/element/pointer-outside-of-preview\";\nimport {\n autoScrollForElements,\n autoScrollWindowForElements,\n} from \"@atlaskit/pragmatic-drag-and-drop-auto-scroll/element\";\nimport { TrackedChangeMode } from \"./types.js\";\nimport type {\n CommentListEntry,\n EditErrorCode,\n EditResult,\n FormattingInspection,\n HeaderFooterKind,\n HyperlinkInfo,\n ImageInsertOptions,\n ListFormat,\n NumberFormat,\n PageSetupOp,\n RevisionListEntry,\n SectionInfo,\n StyleInfo,\n TableBorderSpec,\n TableOfContentsOptions,\n} from \"./types.js\";\nimport { diffUnits, needsRemount, tokenOf, unidOf } from \"./editor-reconcile.js\";\nimport { imageOnlyDelta, patchImageAttributes } from \"./editor-image-patch.js\";\nimport type { RenderPlan, RenderUnit, UnitDiff } from \"./editor-reconcile.js\";\n\n/** The subset of WASM bridge exports the editor needs (as exposed on `window.Docxodus`). */\nexport interface DocxEditorExports {\n DocxSessionBridge: {\n GetVersion?: (handle: number) => string;\n OpenSession: (bytes: Uint8Array, settingsJson: string) => number;\n CloseSession: (handle: number) => void;\n CreateBlankDocx: () => Uint8Array;\n Project: (handle: number) => string;\n ReplaceText: (handle: number, anchor: string, md: string) => string;\n ReplaceTextAtSpan: (\n handle: number,\n anchor: string,\n spanStart: number,\n spanLength: number,\n replace: string,\n ) => string;\n SplitParagraph: (handle: number, anchor: string, offset: number) => string;\n MergeParagraphs: (handle: number, first: string, second: string) => string;\n DeleteBlock: (handle: number, anchor: string) => string;\n MoveBlock?: (handle: number, sourceAnchor: string, targetAnchor: string, pos: string) => string;\n /** JSON `{anchorId, before, after}[]`: where a block may legally move, per side. Optional \u2014\n * without it the drag UI offers every block and lets the engine refuse, as it did before. */\n ValidMoveTargets?: (handle: number, sourceAnchor: string) => string;\n InsertHorizontalRule: (handle: number, anchor: string, pos: string, ruleJson: string) => string;\n InsertTable: (\n handle: number,\n anchor: string,\n pos: string,\n rows: number,\n cols: number,\n optionsJson: string,\n ) => string;\n InsertTableRow: (handle: number, cellAnchor: string, pos: string) => string;\n InsertTableColumn: (handle: number, cellAnchor: string, pos: string) => string;\n DeleteTableRow: (handle: number, cellAnchor: string) => string;\n DeleteTableColumn: (handle: number, cellAnchor: string) => string;\n ApplyFormat: (handle: number, anchor: string, spanJson: string, opJson: string) => string;\n SetParagraphStyle: (handle: number, anchor: string, styleId: string) => string;\n SetParagraphFormat: (handle: number, anchor: string, opJson: string) => string;\n ApplyListFormat: (handle: number, anchor: string, kind: string) => string;\n SetListLevel: (handle: number, anchor: string, delta: number) => string;\n GetListMembership: (handle: number, anchor: string) => string;\n RenderBlockHtml: (\n handle: number,\n anchorId: string,\n cssPrefix: string,\n fabricateClasses: boolean,\n ) => string;\n RenderBlockHtmlForReview?: (\n handle: number,\n anchorId: string,\n cssPrefix: string,\n fabricateClasses: boolean,\n renderTrackedChanges: boolean,\n ) => string;\n /** Session-attached full-document render (optional: older WASM bundles lack it). */\n RenderHtml?: (\n handle: number,\n cssPrefix: string,\n fabricateClasses: boolean,\n paginated: boolean,\n scale: number,\n ) => string;\n RenderHtmlForReview?: (\n handle: number,\n cssPrefix: string,\n fabricateClasses: boolean,\n paginated: boolean,\n scale: number,\n renderTrackedChanges: boolean,\n ) => string;\n Save: (handle: number) => Uint8Array;\n /** Save keeping the projector's Unid bookkeeping \u2014 remount only, never a user download.\n * Optional so a bridge predating it still satisfies this type. */\n SaveWithAnchorIds?: (handle: number) => Uint8Array;\n Undo: (handle: number) => boolean;\n Redo: (handle: number) => boolean;\n /** Header/footer region: the section a body anchor belongs to (kind \u2192 part mapping). */\n GetSectionInfo: (handle: number, anchorId: string) => string;\n SetHeaderText: (handle: number, anchor: string, kind: string, markdown: string) => string;\n SetFooterText: (handle: number, anchor: string, kind: string, markdown: string) => string;\n InsertPageNumberField: (handle: number, anchor: string, field: string, format: string) => string;\n EnsureHeaderFooterVisible: (handle: number, anchor: string, kind: string) => string;\n SetPageNumbering: (handle: number, anchor: string, opJson: string) => string;\n ClearPageNumbering: (handle: number, anchor: string) => string;\n /** Note authoring (optional: older WASM bundles predate it). */\n InsertFootnote?: (\n handle: number,\n anchor: string,\n characterOffset: number,\n markdown: string,\n ) => string;\n InsertEndnote?: (\n handle: number,\n anchor: string,\n characterOffset: number,\n markdown: string,\n ) => string;\n /** Native comment authoring (optional: older WASM bundles predate it; issue #580). */\n AddComment?: (\n handle: number,\n anchor: string,\n spanJson: string,\n author: string,\n initials: string,\n date: string,\n markdown: string,\n ) => string;\n SetCommentResolved?: (handle: number, commentAnchor: string, resolved: boolean) => string;\n ListComments?: (handle: number) => string;\n AddCommentReply?: (\n handle: number,\n parentCommentAnchor: string,\n author: string,\n initials: string,\n date: string,\n markdown: string,\n ) => string;\n UpdateComment?: (handle: number, commentAnchor: string, markdown: string) => string;\n RemoveComment?: (handle: number, commentAnchor: string) => string;\n /** The editor's own render profile as one JSON object \u2014 the comment-aware twin of\n * RenderHtml / RenderBlockHtml / RenderBlocksHtml (optional: older bundles lack it). */\n RenderEditorHtml?: (handle: number, optionsJson: string) => string;\n RenderEditorBlockHtml?: (handle: number, anchorId: string, optionsJson: string) => string;\n RenderEditorBlocksHtml?: (handle: number, anchorIdsJson: string, optionsJson: string) => string;\n RenderEditorChromeHtml?: (handle: number, optionsJson: string) => string;\n RenderEditorRangeHtml?: (handle: number, anchorIdsJson: string, optionsJson: string) => string;\n /** Review-mode controls (optional). */\n SetTrackedChanges?: (handle: number, mode: number) => void;\n SetRevisionAuthor?: (handle: number, author: string) => void;\n ListRevisions?: (handle: number) => string;\n AcceptRevision?: (handle: number, revisionId: string) => string;\n RejectRevision?: (handle: number, revisionId: string) => string;\n AcceptAllRevisions?: (handle: number) => string;\n RejectAllRevisions?: (handle: number) => string;\n /** Links, images, references (optional). */\n ListHyperlinks?: (handle: number, scopes: number) => string;\n AddHyperlink?: (\n handle: number,\n anchor: string,\n start: number,\n length: number,\n kind: string,\n target: string,\n ) => string;\n RemoveHyperlink?: (handle: number, hyperlinkId: string) => string;\n InsertImage?: (\n handle: number,\n anchor: string,\n characterOffset: number,\n imageBase64: string,\n optionsJson: string,\n ) => string;\n InsertTableOfContents?: (handle: number, anchor: string, pos: string, optionsJson: string) => string;\n /** Table cell structure and appearance (optional). */\n MergeCells?: (handle: number, cellAnchor: string, rowSpan: number, colSpan: number, content: string) => string;\n UnmergeCells?: (handle: number, cellAnchor: string) => string;\n SetTableBorders?: (handle: number, cellAnchor: string, specJson: string) => string;\n SetCellShading?: (handle: number, cellAnchor: string, fill: string, scope: string) => string;\n SetRepeatHeaderRow?: (handle: number, cellAnchor: string, repeat: boolean) => string;\n /** Section page setup and header/footer flags (optional). */\n SetPageSetup?: (handle: number, anchor: string, opJson: string) => string;\n SetHeaderFooterKindEnabled?: (handle: number, anchor: string, kind: string, enabled: boolean) => string;\n /** Introspection (optional). */\n ListStyles?: (handle: number) => string;\n GetFormatting?: (handle: number, anchorId: string) => string;\n ReplaceTextRange?: (handle: number, anchor: string, find: string, replace: string, optionsJson: string) => string;\n /** Incremental-reconcile endpoints (optional: older WASM bundles predate them;\n * the editor falls back to full remounts / full projections without them). */\n ListBlocks?: (handle: number) => string;\n ListRenderedBlocks?: (handle: number, renderTrackedChanges: boolean) => string;\n ListNotes?: (handle: number, endnotes: boolean) => string;\n ListAnchors?: (handle: number) => string;\n RenderBlocksHtml?: (\n handle: number,\n anchorIdsJson: string,\n cssPrefix: string,\n fabricateClasses: boolean,\n ) => string;\n RenderBlocksHtmlForReview?: (\n handle: number,\n anchorIdsJson: string,\n cssPrefix: string,\n fabricateClasses: boolean,\n renderTrackedChanges: boolean,\n ) => string;\n };\n DocumentConverter: {\n ConvertDocxToHtmlComplete: (...args: any[]) => string;\n };\n}\n\nexport interface DocxEditorOptions {\n /** CSS class prefix for rendered HTML. Default \"docx-\". */\n cssPrefix?: string;\n /**\n * Fabricate CSS classes (vs inline styles). Default FALSE for the editor: a per-block\n * re-render must be self-contained, but fabricated class names are per-conversion and\n * have no matching stylesheet on the page, so re-rendered blocks would lose styling.\n * Inline styles keep every block's formatting intact on incremental re-render.\n */\n fabricateClasses?: boolean;\n /** Make paragraph/heading blocks editable. Default true. */\n editable?: boolean;\n /** Render block-flow pages (page boxes via pagination.ts) vs a continuous view. Default false. */\n paginated?: boolean;\n /** Author-pinned page render scale (1.0 = 100%). Default 1. */\n scale?: number;\n /**\n * How the continuous view sizes its text column. `\"section\"` (default) uses the width the\n * document's `w:sectPr` defines, so line breaking matches Word on every screen; `\"fluid\"`\n * lets the column follow the host, the pre-geometry behavior.\n */\n columnWidth?: ColumnWidth;\n /**\n * Zoom the page down to fit a host narrower than it, the way a word processor's\n * fit-to-width does, instead of letting it overflow. Default true.\n */\n fitToWidth?: boolean;\n /**\n * Render docked Header/Footer editing bands around the body flow. Default FALSE \u2014 with it off\n * the editor's DOM is unchanged, so existing consumers are unaffected. When on, the body flow\n * is wrapped in a `.docx-body-flow` element that becomes the edit root, keeping band blocks out\n * of the body's block list (which indexes remount focus).\n */\n headerFooter?: boolean;\n /** Enable the editor-owned block drag handle. Default false (the ribbon defaults it to true). */\n blockDrag?: boolean;\n /** How editor mutations are recorded. RenderInline enables native Word revisions. */\n trackedChanges?: TrackedChangeMode;\n /** Author stamped on native Word revisions. Default \"docxodus\". */\n revisionAuthor?: string;\n /**\n * Render comments Word-style: the commented range highlighted inline and each thread as a\n * bubble in a gutter beside the page. Default true. With it off the document renders without\n * comment markup at all (the pre-gutter behaviour).\n */\n comments?: boolean;\n /** Author stamped on comments posted from the gutter. Defaults to `revisionAuthor`. */\n commentAuthor?: string;\n /** Called after a block edit commits (with the affected anchor). */\n onEdit?: (info: { anchorId: string; unid: string }) => void;\n /**\n * Called when the engine rejects an edit. The editor has already put the affected block back\n * to the session's content, so the screen never shows text the document does not hold. When no\n * handler is set, the editor logs the rejection with `console.warn` instead.\n */\n onEditFailed?: (info: EditFailure) => void;\n /** Called after a successful block move. */\n onMove?: (info: { sourceAnchorId: string; destinationAnchorId: string }) => void;\n /** Called when the caret enters or leaves a header/footer story (`null` = back in the body). */\n onStoryChange?: (which: BandWhich | null) => void;\n /** Called after every comment-gutter layout with thread counts and the active thread. */\n onCommentsChange?: (info: { threads: number; open: number; active: string | null }) => void;\n}\n\n/** Options for {@link DocxEditor.openAsync}: the mount's window size and a progress callback. */\nexport interface DocxEditorOpenAsyncOptions extends DocxEditorOptions {\n /**\n * Body units (top-level paragraphs and tables) mounted per task before yielding to the event\n * loop. Default 24 \u2014 on the reference 17-page document that is a ~50 ms task. A window is\n * extended past the size so it never ends inside a border box the renderer groups adjacent\n * paragraphs into.\n */\n windowSize?: number;\n /** Called after each window lands with the count of body units mounted so far. */\n onProgress?: (mounted: number, total: number) => void;\n}\n\n/**\n * Word's Page Setup, as {@link DocxEditor.setPageSetup} takes it \u2014 the session's own\n * {@link PageSetupOp} (all twips; omit = unchanged), so the two cannot drift.\n */\nexport type EditorPageSetup = PageSetupOp;\n\n/** One hit from {@link DocxEditor.find}: a content-offset span inside an editable block. */\nexport interface EditorMatch {\n block: HTMLElement;\n start: number;\n length: number;\n}\n\ninterface AnchorTargetLite {\n unid: string;\n kind: string;\n scope: string;\n textPreview?: string;\n}\n\nconst EDITABLE_TAGS = new Set([\"P\", \"H1\", \"H2\", \"H3\", \"H4\", \"H5\", \"H6\"]);\n\nconst BLOCK_DRAG_TYPE = \"docxodus-block\";\nconst blockDragStyledDocuments = new WeakSet<Document>();\n\n/** One-line description of a block, for the handle's label and the drag preview chip. */\nfunction blockPreviewText(unit: HTMLElement): string {\n if (unit.tagName === \"TABLE\") return \"Table\";\n const text = (unit.textContent ?? \"\").trim().replace(/\\s+/g, \" \");\n return text.length > 48 ? `${text.slice(0, 48)}\u2026` : text;\n}\n\n/**\n * A capture-time snapshot of one movable block's box, in viewport coordinates.\n *\n * Taken once per drag: nothing reflows while a drag is in flight, so re-measuring every block on\n * every `dragover` would buy nothing. Scrolling (including drag autoscroll) moves the whole flow\n * rigidly, which `dropZoneShift` corrects for with one subtraction.\n */\ninterface BlockDropZone {\n unit: HTMLElement;\n anchorId: string;\n /** Position in `dropZones`, so a neighbour is one index away \u2014 see `dropEdgeY`. */\n index: number;\n top: number;\n bottom: number;\n left: number;\n width: number;\n /** Own outer margin, read only for the first/last zone \u2014 see `dropEdgeY`. */\n marginBefore: number;\n marginAfter: number;\n}\n\n/** The floating handle's own box and its gap to the block, as `ensureBlockDragStyles` sizes it. */\nconst BLOCK_HANDLE_WIDTH = 26;\nconst BLOCK_HANDLE_HEIGHT = 28;\nconst BLOCK_HANDLE_GAP = 6;\n\n/** `value` pulled into [`low`, `high`]; `low` wins when the range is narrower than the box. */\nfunction clampToRange(value: number, low: number, high: number): number {\n return Math.max(low, Math.min(value, high));\n}\n\nfunction ensureBlockDragStyles(doc: Document): void {\n if (blockDragStyledDocuments.has(doc)) return;\n blockDragStyledDocuments.add(doc);\n const style = doc.createElement(\"style\");\n style.dataset.docxodusBlockDrag = \"true\";\n style.textContent = `\n.docx-block-handle {\n position: fixed; z-index: 2147483000; display: none; width: 26px; height: 28px;\n align-items: center; justify-content: center; padding: 0; border: 1px solid #d0d5dd;\n border-radius: 6px; background: #fff; color: #667085; box-shadow: 0 1px 3px rgba(16,24,40,.12);\n cursor: grab; font: 700 17px/1 system-ui, sans-serif; user-select: none; touch-action: none;\n}\n.docx-block-handle:hover, .docx-block-handle:focus-visible { color: #344054; border-color: #98a2b3; outline: none; }\n.docx-block-handle[aria-pressed=\"true\"] { color: #175cd3; border-color: #84adff; background: #eff8ff; }\n.docx-block-handle.docx-block-dragging { cursor: grabbing; opacity: .35; }\n/* The block being carried. Dimming it is the \"a drag is happening\" signal that survives the\n pointer being anywhere on screen \u2014 the drop line only says where, not what. */\n.docx-block-drag-source { opacity: .38; transition: opacity 120ms ease-out; }\n/* Positioned by transform so tracking the pointer costs no layout. Flipping display none\u2192block\n restarts the fade \u2014 one cheap entry animation per appearance, none while it tracks. */\n.docx-block-drop-indicator {\n position: fixed; top: 0; left: 0; z-index: 2147482999; display: none; height: 0;\n pointer-events: none; border-top: 2px solid #2e90fa;\n filter: drop-shadow(0 1px 2px rgba(46,144,250,.5));\n animation: docx-block-drop-in 110ms ease-out;\n}\n.docx-block-drop-indicator::before {\n content: \"\"; position: absolute; top: -5px; left: -2px; width: 8px; height: 8px;\n border-radius: 50%; background: #2e90fa;\n}\n@keyframes docx-block-drop-in { from { opacity: 0; } to { opacity: 1; } }\n.docx-block-drag-preview {\n max-width: 320px; padding: 6px 10px; border: 1px solid #b2ddff; border-radius: 6px;\n background: #eff8ff; color: #175cd3; box-shadow: 0 6px 16px rgba(16,24,40,.18);\n font: 500 13px/1.35 system-ui, sans-serif; white-space: nowrap; overflow: hidden;\n text-overflow: ellipsis;\n}\n.docx-block-move-menu {\n position: fixed; z-index: 2147483001; display: none; min-width: 150px; padding: 5px;\n border: 1px solid #d0d5dd; border-radius: 8px; background: #fff;\n box-shadow: 0 8px 24px rgba(16,24,40,.18); font: 13px/1.35 system-ui, sans-serif;\n}\n.docx-block-move-menu button { display: block; width: 100%; padding: 7px 9px; border: 0; border-radius: 5px; background: transparent; color: #344054; text-align: left; }\n.docx-block-move-menu button:hover, .docx-block-move-menu button:focus-visible { background: #f2f4f7; outline: none; }\n.docx-block-move-menu button:disabled { color: #98a2b3; background: transparent; }\n.docx-block-move-flash { animation: docx-block-move-flash 800ms ease-out; }\n@keyframes docx-block-move-flash { from { box-shadow: 0 0 0 3px rgba(46,144,250,.55); } to { box-shadow: none; } }\n.docx-block-live-region { position: fixed; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }\n`;\n (doc.head ?? doc.documentElement).appendChild(style);\n}\n\n/**\n * Let the event loop run \u2014 input, rendering, and any other task \u2014 before the next window\n * of a mount. `scheduler.yield` where the browser has it (it keeps the continuation ahead of\n * other tasks), otherwise a frame followed by a macrotask.\n */\n/**\n * Give the page a turn between mount windows: a frame, so a paint and any input handling\n * happen, then a macrotask, so the host's own timers run too. `scheduler.yield()` is not used\n * on purpose \u2014 its continuation is scheduled ahead of timer tasks, so a progress spinner or a\n * poll the host drives with `setInterval` would not tick until the whole mount was done.\n */\n/** The anchor of the empty paragraphs a chrome render leaves where body content was\n * (`HtmlConversionOps.ChromeCarrierAnchor`); a windowed mount removes them before it fills\n * the sections. */\nconst CHROME_CARRIER_ANCHOR = \"chrome-carrier\";\n\nfunction yieldToEventLoop(): Promise<void> {\n return new Promise((resolve) => {\n const settle = (): void => { setTimeout(resolve, 0); };\n if (typeof requestAnimationFrame === \"function\") requestAnimationFrame(settle);\n else settle();\n });\n}\n\nfunction trackedChangeWireName(mode: TrackedChangeMode): \"accept\" | \"render_inline\" | \"strip_deletions\" {\n if (mode === TrackedChangeMode.RenderInline) return \"render_inline\";\n if (mode === TrackedChangeMode.StripDeletions) return \"strip_deletions\";\n return \"accept\";\n}\n\n// \u2500\u2500\u2500 M1: inline HTML \u2192 markdown (preserve formatting on edit) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface InlineSeg {\n text: string;\n bold: boolean;\n italic: boolean;\n href: string | null;\n}\n\nfunction fontWeightIsBold(w: string): boolean {\n if (w === \"bold\" || w === \"bolder\") return true;\n const n = parseInt(w, 10);\n return !Number.isNaN(n) && n >= 600;\n}\n\nfunction escapeInlineMarkdown(text: string): string {\n // Escape the markdown the projector subset is sensitive to; keep it minimal.\n return text.replace(/([\\\\`*_[\\]])/g, \"\\\\$1\");\n}\n\n/**\n * Escape block-construct markers at the start of every line of the assembled\n * payload (#571). The projector escapes literal markers on the way out\n * (`\\#\\# x`) and the parser unescapes `\\X` generically, so this is the\n * serializer's half of that contract: a typed leading `## `, `> `, `- `,\n * `+ `, `1. `, or `|` must commit as literal text, not be consumed as a\n * heading/quote/list marker \u2014 and a list marker after a soft break must not\n * be split into a second block the session then discards. Line starts only:\n * the parser detects block constructs at line start, and `*` needs no rule\n * here because a literal `*` is already inline-escaped, so an unescaped\n * leading `*` can only be our own emphasis emission.\n */\nfunction escapeLeadingBlockMarkers(md: string): string {\n return md\n .split(\"\\n\")\n .map((line) => {\n if (/^[#>|]/.test(line) || /^[-+] /.test(line)) return \"\\\\\" + line;\n if (/^\\d+\\. /.test(line)) return line.replace(\".\", \"\\\\.\");\n return line;\n })\n .join(\"\\n\");\n}\n\nfunction collectInlineSegments(node: Node, out: InlineSeg[]): void {\n node.childNodes.forEach((child) => {\n // Skip converter-generated chrome (list markers, note citation markers, note backrefs) \u2014\n // it isn't part of the paragraph's content and must never be committed as text.\n if (isGeneratedChrome(child)) return;\n if (isField(child)) {\n // A field serializes as its cached result (the session's own text for it).\n const text = fieldText(child);\n if (text) out.push({ text, bold: false, italic: false, href: null });\n return;\n }\n if (child.nodeType === 3 /* TEXT_NODE */) {\n const text = child.textContent ?? \"\";\n if (!text) return;\n const parent = child.parentElement;\n let bold = false;\n let italic = false;\n let href: string | null = null;\n if (parent && typeof getComputedStyle === \"function\") {\n const cs = getComputedStyle(parent);\n bold = fontWeightIsBold(cs.fontWeight);\n italic = cs.fontStyle === \"italic\" || cs.fontStyle === \"oblique\";\n const a = parent.closest(\"a\");\n href = a ? a.getAttribute(\"href\") : null;\n }\n out.push({ text, bold, italic, href });\n } else if (child.nodeType === 1 /* ELEMENT_NODE */) {\n const el = child as HTMLElement;\n if (el.tagName === \"BR\") {\n out.push({ text: \"\\n\", bold: false, italic: false, href: null });\n return;\n }\n collectInlineSegments(el, out);\n }\n });\n}\n\nfunction segToMarkdown(seg: InlineSeg): string {\n // A <br> segment is a hard line break \u2192 the canonical GFM \" \\n\", which the\n // DocxSession markdown parser turns into a real w:br (Word's intra-paragraph\n // line break) instead of a literal newline in w:t.\n if (seg.text === \"\\n\") return \" \\n\";\n let md = escapeInlineMarkdown(seg.text).replace(/[ \\t]*\\n/g, \" \\n\");\n if (/\\S/.test(seg.text)) {\n // Don't wrap pure whitespace \u2014 `** **` is not valid emphasis.\n if (seg.bold && seg.italic) md = `***${md}***`;\n else if (seg.bold) md = `**${md}**`;\n else if (seg.italic) md = `*${md}*`;\n }\n if (seg.href) md = `[${md}](${seg.href})`;\n return md;\n}\n\n/**\n * Serialize a block's inline content to the projector's markdown subset, preserving\n * bold / italic / links (emphasis detected via computed style). Used so an edit keeps\n * the block's formatting instead of flattening it to plain text. Formatting the markdown\n * subset cannot express (font size/color) is still dropped on an edited block.\n */\nexport function serializeInlineMarkdown(block: HTMLElement): string {\n const segs: InlineSeg[] = [];\n collectInlineSegments(block, segs);\n // Merge adjacent segments with identical formatting to avoid `**a****b**`.\n const merged: InlineSeg[] = [];\n for (const s of segs) {\n const prev = merged[merged.length - 1];\n if (\n prev &&\n prev.text !== \"\\n\" &&\n s.text !== \"\\n\" &&\n prev.bold === s.bold &&\n prev.italic === s.italic &&\n prev.href === s.href\n ) {\n prev.text += s.text;\n } else {\n merged.push({ ...s });\n }\n }\n // Leading whitespace is never content (a rendered empty paragraph carries a placeholder\n // space, and typing lands after it). Trailing whitespace usually is not either \u2014 the\n // browser's bogus trailing <br> serializes as a hard break \u2014 EXCEPT the single space a user\n // types before a page-number field goes in: \"Page \" + PAGE must not commit as \"Page\". The\n // engine writes it with xml:space=\"preserve\"; `trimBounds` counts it the same way.\n const md = merged.map(segToMarkdown).join(\"\").replace(/^\\s+/, \"\").replace(/\\s+$/, \"\");\n return escapeLeadingBlockMarkers(md + (keepsTrailingSpace(block) ? \" \" : \"\"));\n}\n\n/**\n * Whether a block's content text ends in a space the commit should keep: a plain or no-break\n * space (contenteditable turns a typed trailing space into U+00A0) after some non-whitespace\n * text. A whitespace-only block (the placeholder an empty paragraph renders as) keeps nothing.\n */\nfunction keepsTrailingSpace(block: HTMLElement): boolean {\n const text = blockContentText(block);\n if (text.trim().length === 0) return false;\n // An ordinary trailing space can only have come from the document (the converter renders\n // it from a preserved w:t), so it is content. A trailing NBSP is ambiguous: the browser\n // writes one for a typed space, but the placeholder an empty paragraph renders as is one\n // too, and typing at the start of such a paragraph leaves it dangling at the end. Only the\n // typed one counts, which `wireBlock` records from the input event.\n if (/ $/.test(text)) return true;\n return /\\u00a0$/.test(text) && block.dataset.typedTrailingSpace === \"1\";\n}\n\n/** Record whether the last input left a typed space at the end of the block \\u2014 see\n * {@link keepsTrailingSpace}. */\nfunction noteTypedSpace(block: HTMLElement, event: Event): void {\n const input = event as InputEvent;\n const typedSpace =\n input.inputType === \"insertText\" && typeof input.data === \"string\" && /[ \\u00a0]$/.test(input.data);\n const atEnd = typedSpace && caretOffsetIn(block) === blockContentText(block).length;\n if (atEnd) block.dataset.typedTrailingSpace = \"1\";\n else delete block.dataset.typedTrailingSpace;\n}\n\n// \u2500\u2500\u2500 M2: structural editing (split / merge) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface AnchorRef {\n id: string;\n kind: string;\n scope: string;\n unid: string;\n}\n\n/**\n * An `EditResult` as the editor reads it straight off the bridge. It is derived from the public\n * type the typed session wrapper (`session.ts`) returns, so a change to the wire shape surfaces\n * in both at compile time; the lists are optional because a malformed reply may omit them.\n */\ntype EditResultLite = Pick<EditResult, \"success\">\n & Partial<Pick<EditResult, \"created\" | \"removed\" | \"modified\" | \"error\">>;\n\n/** What {@link DocxEditorOptions.onEditFailed} receives when the engine rejects an edit. */\nexport interface EditFailure {\n /** The engine's error code, when it sent one. */\n code?: EditErrorCode;\n /** The engine's error message. */\n message: string;\n /** The anchor the engine named in its error, else the block being edited, when there is one. */\n anchorId: string | null;\n}\n\ninterface DomSelectionPoint {\n node: Node;\n offset: number;\n}\n\ninterface CrossBlockSelectionBookmark {\n startUnid: string;\n startOffset: number;\n endUnid: string;\n endOffset: number;\n}\n\ninterface CrossBlockDragSelection {\n anchor: DomSelectionPoint;\n origin: HTMLElement;\n crossedBlockBoundary: boolean;\n focus: DomSelectionPoint | null;\n frame: number | null;\n}\n\n/** True if `block` renders as a list item (has a generated marker as its first child). */\nfunction isListBlock(block: HTMLElement): boolean {\n return !!block.querySelector(\":scope > [data-list-marker]\");\n}\n\n/**\n * The converter's tab box must stay text-empty because any child changes its inline baseline.\n * Editable list items still need a textContent separator between generated marker chrome and an\n * empty body so typing produces \"2. BB\", not \"2.BB\". Keep that editor-only separator hidden and\n * generated, outside the converter-owned marker wrapper.\n */\nfunction ensureListMarkerSeparator(block: HTMLElement): void {\n const marker = block.querySelector<HTMLElement>(\":scope > [data-list-marker]\");\n if (!marker) return;\n const next = marker.nextElementSibling as HTMLElement | null;\n if (next?.hasAttribute(\"data-editor-list-separator\")) return;\n\n const separator = block.ownerDocument.createElement(\"span\");\n separator.setAttribute(\"data-editor-list-separator\", \"\");\n separator.setAttribute(\"data-list-marker\", \"true\");\n separator.setAttribute(\"aria-hidden\", \"true\");\n separator.style.display = \"none\";\n separator.textContent = \" \";\n marker.after(separator);\n}\n\n/**\n * Inline chrome the CONVERTER generates that is not part of a paragraph's run text: list\n * number/bullet markers, footnote/endnote citation markers\n * (`<a class=\"footnote-ref\"><sup>1</sup></a>`), and the note backrefs (`\u21A9`).\n *\n * The session's run text contains none of it. A citation is a zero-width\n * `w:footnoteReference` \u2014 the displayed number is computed by the renderer from document order \u2014\n * so every character of chrome the editor fails to exclude shifts its content-offset space away\n * from the session's. Each omission has its own failure mode: excluded from offsets but not from\n * serialization and the display number gets COMMITTED as literal text (destroying the citation\n * run); left editable and the user can delete a marker outright, orphaning the note.\n */\nconst GENERATED_CHROME_SELECTOR =\n '[data-list-marker], a.footnote-ref, a.endnote-ref, a[class$=\"-backref\"], a.comment-marker';\n\nfunction isGeneratedChrome(node: Node | null | undefined): boolean {\n return node?.nodeType === 1 && !!(node as Element).matches?.(GENERATED_CHROME_SELECTOR);\n}\n\n/**\n * A rendered field \u2014 PAGE / NUMPAGES in a running story, stamped `[data-field]` by the editor\n * render profile. Fields are ATOMIC for editing (`contenteditable=false`, the caret lands on\n * either side), and their content length is the field's CACHED result \u2014 the text the session\n * holds in the result run \u2014 even after the page view substituted the per-page number into the\n * DOM. Counting the substituted text instead would shift every offset after the field and make\n * the commit diff rewrite the field runs.\n */\nfunction fieldOf(node: Node | null): HTMLElement | null {\n const el = node && node.nodeType === 1 ? (node as Element) : node?.parentElement ?? null;\n return (el?.closest?.(\"[data-field]\") as HTMLElement | null) ?? null;\n}\n\nfunction isField(node: Node): node is HTMLElement {\n return node.nodeType === 1 && (node as HTMLElement).hasAttribute(\"data-field\");\n}\n\n/** The text a field counts for: the cached result the session holds, else what it shows. */\nfunction fieldText(field: HTMLElement): string {\n return field.dataset.fieldCached ?? field.textContent ?? \"\";\n}\n\n/** Freeze a field's rendered result as its cached text (once) and keep the caret out of it. */\nfunction adoptFields(block: HTMLElement): void {\n for (const field of Array.from(block.querySelectorAll<HTMLElement>(\"[data-field]\"))) {\n if (field.dataset.fieldCached === undefined) field.dataset.fieldCached = field.textContent ?? \"\";\n field.setAttribute(\"contenteditable\", \"false\");\n }\n}\n\n/** True if `node` is, or is inside, generated chrome (not editable content). */\nfunction isInMarker(node: Node | null): boolean {\n let el: Element | null = node && node.nodeType === 1 ? (node as Element) : node?.parentElement ?? null;\n while (el) {\n if (isGeneratedChrome(el)) return true;\n el = el.parentElement;\n }\n return false;\n}\n\n/**\n * Unicode bidi formatting marks the HTML converter injects to preserve visual order: LRM/RLM/ALM,\n * the embedding/override controls, and the isolates (see WmlToHtmlConverter \u2014 a paragraph/run gets\n * a leading U+200E or U+200F). They are presentation-only \u2014 NOT part of the paragraph's run text the\n * session holds \u2014 so the editor must exclude them from its content-offset space, the same way it\n * excludes generated list markers. Otherwise every caret offset is shifted by the leading mark and a\n * caret at end-of-line overshoots the session's text length, so SplitParagraph/ApplyFormat reject the\n * offset (symptom: Enter at the end of a Google-Docs-exported paragraph is silently dropped).\n */\n// LRM, RLM, ALM; the embedding/override controls (LRE RLE PDF LRO RLO); the isolates (LRI RLI FSI PDI).\nconst BIDI_MARK_CLASS = \"\\u200E\\u200F\\u061C\\u202A-\\u202E\\u2066-\\u2069\";\nconst BIDI_MARKS_RE_G = new RegExp(`[${BIDI_MARK_CLASS}]`, \"g\");\nconst BIDI_MARK_RE = new RegExp(`[${BIDI_MARK_CLASS}]`);\nfunction stripBidi(s: string): string {\n return s.replace(BIDI_MARKS_RE_G, \"\");\n}\n\n/** Raw string index in `s` for content offset `n` (content = chars excluding bidi marks). */\nfunction domOffsetForContentOffset(s: string, n: number): number {\n let content = 0;\n for (let i = 0; i < s.length; i++) {\n if (content >= n) return i;\n if (!BIDI_MARK_RE.test(s[i])) content++;\n }\n return s.length;\n}\n\n/**\n * Content-text offset of (container, offset) within `block`, EXCLUDING generated list-marker\n * text and injected bidi marks. This is the offset DocxSession ops expect (the paragraph's run\n * text, not the rendered number/bullet or bidi marks the converter injects).\n */\nfunction contentOffsetOf(block: HTMLElement, container: Node, offset: number): number {\n let count = 0;\n let done = false;\n const walk = (node: Node): void => {\n if (done) return;\n if (isField(node)) {\n // Atomic: a point inside a field resolves to the field's end; the field counts its\n // cached text either way.\n const inside = node === container || node.contains(container);\n if (!inside || offset > 0 || node !== container) count += stripBidi(fieldText(node)).length;\n if (inside) done = true;\n return;\n }\n if (node.nodeType === 3 /* TEXT_NODE */) {\n if (node === container) {\n if (!isInMarker(node)) count += stripBidi((node.textContent ?? \"\").slice(0, offset)).length;\n done = true; return;\n }\n if (!isInMarker(node)) count += stripBidi(node.textContent ?? \"\").length;\n } else {\n if (node === container) {\n // Element container: `offset` is a child index \u2014 count content up to that child.\n const kids = Array.from(node.childNodes);\n for (let i = 0; i < offset && i < kids.length; i++) walk(kids[i]);\n done = true;\n return;\n }\n node.childNodes.forEach(walk);\n }\n };\n walk(block);\n return count;\n}\n\n/** Content-text offset of the collapsed caret within `block` (excludes markers), or null. */\nfunction caretOffsetIn(block: HTMLElement): number | null {\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n if (!sel || sel.rangeCount === 0) return null;\n const range = sel.getRangeAt(0);\n if (!block.contains(range.startContainer)) return null;\n return contentOffsetOf(block, range.startContainer, range.startOffset);\n}\n\n/** Visible content text of `block`, excluding generated list-marker text (the same content\n * caretOffsetIn/contentOffsetOf count). */\nfunction blockContentText(block: HTMLElement): string {\n let out = \"\";\n const walk = (node: Node): void => {\n if (isField(node)) {\n out += stripBidi(fieldText(node));\n } else if (node.nodeType === 3 /* TEXT_NODE */) {\n if (!isInMarker(node)) out += stripBidi(node.textContent ?? \"\");\n } else {\n node.childNodes.forEach(walk);\n }\n };\n walk(block);\n return out;\n}\n\n/**\n * Map a DOM caret offset (from caretOffsetIn) into the run-text offset the session holds after a\n * commit. commitBlock/syncBlock commit `serializeInlineMarkdown(el)`, which `.trim()`s leading and\n * trailing whitespace, so the session's paragraph text is shorter than the DOM text whenever the\n * block has edge whitespace \u2014 e.g. a blank document renders its empty paragraph with a placeholder\n * space, and typing lands after it. Without this adjustment the caret offset overshoots the\n * committed length, SplitParagraph returns OffsetOutOfRange, and splitAtCaret silently drops the\n * Enter (no new paragraph). Subtracting the leading whitespace before the caret and clamping to the\n * trimmed length keeps the split offset consistent with what was committed.\n */\nfunction trimmedSplitOffset(block: HTMLElement, domOffset: number): number {\n const { leading, trimmedLen } = trimBounds(block);\n return Math.max(0, Math.min(domOffset - Math.min(domOffset, leading), trimmedLen));\n}\n\n/** How far `block`'s DOM content text is offset from, and longer than, its committed form. */\nfunction trimBounds(block: HTMLElement): { leading: number; trimmedLen: number } {\n const content = blockContentText(block);\n return {\n leading: content.length - content.replace(/^\\s+/, \"\").length,\n // Mirrors serializeInlineMarkdown: leading and trailing whitespace dropped, plus the one\n // trailing space a commit keeps.\n trimmedLen: content.trim().length + (keepsTrailingSpace(block) ? 1 : 0),\n };\n}\n\n/**\n * Map a DOM content SPAN into the run-text space the session holds after a commit \u2014 the span\n * analogue of {@link trimmedSplitOffset}, and for the same reason.\n *\n * A block rendered with edge whitespace produces a span longer than the text the commit stores:\n * an empty header/footer story renders as a lone NBSP placeholder, so typing into it leaves a\n * trailing NBSP that `serializeInlineMarkdown(...).trim()` removes (JS `trim()` treats U+00A0 as\n * whitespace). \"Select all, then Bold\" then asks `ApplyFormat` for [0, len+1) \u2014 one past the\n * committed end \u2014 and the op is REJECTED with OffsetOutOfRange, so the format silently does\n * nothing. The demo's format buttons preventDefault on mousedown to keep the selection alive,\n * which is exactly the path that computes the span before `syncBlock` commits, so this is the\n * ordinary case rather than an edge one.\n */\nfunction trimmedSpan(\n block: HTMLElement,\n span: { start: number; length: number },\n): { start: number; length: number } {\n const { leading, trimmedLen } = trimBounds(block);\n const start = Math.max(0, Math.min(span.start - Math.min(span.start, leading), trimmedLen));\n const end = Math.max(start, Math.min(span.start + span.length - leading, trimmedLen));\n return { start, length: end - start };\n}\n\n/**\n * DOM (node, offset) for content offset `offset` within `el` \u2014 the same content-offset\n * space as contentOffsetOf (marker text and injected bidi marks excluded). Clamps past-end\n * offsets to the end of the last text node (or the element itself when it has none), so a\n * caller can always build a Range from the result.\n */\nfunction contentPositionIn(el: HTMLElement, offset: number): { node: Node; offset: number } {\n let remaining = offset;\n let result: { node: Node; offset: number } | null = null;\n let lastText: Node | null = null;\n const walk = (node: Node): void => {\n if (result) return;\n if (isField(node)) {\n // Never land inside a field: an offset at its start sits before it, anything up to its\n // cached length sits after it.\n const len = stripBidi(fieldText(node)).length;\n const parent = node.parentNode;\n if (parent && remaining <= len) {\n const index = Array.prototype.indexOf.call(parent.childNodes, node);\n result = { node: parent, offset: index + (remaining > 0 ? 1 : 0) };\n return;\n }\n remaining -= len;\n return;\n }\n if (node.nodeType === 3 /* TEXT_NODE */) {\n if (isInMarker(node)) return;\n const raw = node.textContent ?? \"\";\n const len = stripBidi(raw).length;\n lastText = node;\n if (remaining <= len) {\n result = { node, offset: domOffsetForContentOffset(raw, remaining) };\n return;\n }\n remaining -= len;\n } else {\n node.childNodes.forEach(walk);\n }\n };\n walk(el);\n if (result) return result;\n if (lastText) return { node: lastText, offset: ((lastText as Node).textContent ?? \"\").length };\n return { node: el, offset: el.childNodes.length };\n}\n\n/**\n * Resolve a viewport coordinate to a DOM caret. Firefox exposes the standards-track\n * caretPositionFromPoint; Chromium/WebKit expose caretRangeFromPoint. Keeping the compatibility\n * shim here lets the editor bridge native mouse selection across its intentionally-independent\n * per-paragraph editing hosts without changing their commit boundaries.\n */\nfunction caretPointFromClient(\n doc: Document,\n clientX: number,\n clientY: number,\n): DomSelectionPoint | null {\n const caretDoc = doc as Document & {\n caretPositionFromPoint?: (x: number, y: number) => { offsetNode: Node; offset: number } | null;\n caretRangeFromPoint?: (x: number, y: number) => Range | null;\n };\n const position = caretDoc.caretPositionFromPoint?.(clientX, clientY);\n if (position) return { node: position.offsetNode, offset: position.offset };\n const range = caretDoc.caretRangeFromPoint?.(clientX, clientY);\n return range ? { node: range.startContainer, offset: range.startOffset } : null;\n}\n\n/**\n * Set a possibly-backward pair of points as one normalized DOM Range. Chromium's\n * Selection.setBaseAndExtent() exposes cross-contenteditable endpoints but clips toString() and\n * the effective contents to the originating host; addRange() carries the complete cross-block\n * contents. Direction is immaterial to editor commands, which consume normalized start/end.\n */\nfunction setSelectionBetween(anchor: DomSelectionPoint, focus: DomSelectionPoint): boolean {\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n if (!sel || !anchor.node.isConnected || !focus.node.isConnected) return false;\n try {\n const probe = document.createRange();\n probe.setStart(anchor.node, anchor.offset);\n probe.collapse(true);\n const focusIsBefore = probe.comparePoint(focus.node, focus.offset) < 0;\n const range = document.createRange();\n const start = focusIsBefore ? focus : anchor;\n const end = focusIsBefore ? anchor : focus;\n range.setStart(start.node, start.offset);\n range.setEnd(end.node, end.offset);\n sel.removeAllRanges();\n sel.addRange(range);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Place the caret at content offset `offset` within `el`, skipping marker text. */\nfunction placeCaretAtOffset(el: HTMLElement, offset: number): void {\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n // A remount can detach the block between a caller's lookup and this call; addRange on a\n // detached node throws \"the given range isn't in document\".\n if (!sel || !el.isConnected) return;\n el.focus();\n const range = document.createRange();\n // contentPositionIn clamps a past-end offset to the end of the last text node, and never\n // lands inside marker chrome or a field \u2014 the same rules every other offset helper uses.\n const pos = contentPositionIn(el, offset);\n try {\n range.setStart(pos.node, pos.offset);\n } catch {\n range.selectNodeContents(el);\n range.collapse(false);\n }\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\n// \u2500\u2500\u2500 M5: formatting controls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type FormatKey = \"bold\" | \"italic\" | \"underline\" | \"strike\" | \"code\" | \"superscript\" | \"subscript\";\n\n/** Paragraph alignment passed to DocxEditor.setAlignment. */\nexport type EditorAlignment = \"left\" | \"center\" | \"right\" | \"justify\";\n\n/** The selection's content-text {start,length} within `block` (excludes markers), or null. */\nfunction selectionSpanIn(block: HTMLElement): { start: number; length: number } | null {\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n if (!sel || sel.rangeCount === 0) return null;\n const range = sel.getRangeAt(0);\n if (range.collapsed) return null;\n if (!block.contains(range.startContainer) || !block.contains(range.endContainer)) return null;\n const start = contentOffsetOf(block, range.startContainer, range.startOffset);\n const end = contentOffsetOf(block, range.endContainer, range.endOffset);\n // Normalized into the committed run-text space: every consumer feeds this straight to a\n // DocxSession op, which rejects a span that overshoots the committed length.\n const span = trimmedSpan(block, { start: Math.min(start, end), length: Math.abs(end - start) });\n return span.length > 0 ? span : null;\n}\n\n/**\n * A DOM Range over the content text spanning [start, start+length) within `el` (skips markers),\n * or null when the block is detached or the offsets do not resolve. Building the range is kept\n * separate from selecting it so a caller that only wants to PAINT a span (find preview) does not\n * have to touch the selection \u2014 and therefore focus \u2014 at all.\n */\nfunction contentRangeIn(el: HTMLElement, start: number, length: number): Range | null {\n // The block may have been swapped out of the document by a re-render before this runs\n // (e.g. a focus-stealing toolbar control firing twice). addRange on a detached range\n // throws \"the given range isn't in document\" \u2014 skip rather than warn.\n if (!el.isConnected) return null;\n const doc = el.ownerDocument;\n const range = doc.createRange();\n const from = contentPositionIn(el, start);\n const to = contentPositionIn(el, start + length);\n try {\n range.setStart(from.node, from.offset);\n range.setEnd(to.node, to.offset);\n } catch {\n return null;\n }\n return range;\n}\n\n/** Restore a content-text selection spanning [start, start+length) within `el` (skips markers). */\nfunction selectRange(el: HTMLElement, start: number, length: number): void {\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n if (!sel || !el.isConnected) return;\n el.focus();\n const range = contentRangeIn(el, start, length);\n if (!range) return;\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\n// \u2500\u2500\u2500 Find painting \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// A find box has to show WHERE the hits are while the user is still typing into it, so it cannot\n// express \"the current match\" as a selection: putting a caret in a contenteditable block focuses\n// that block, and the next keystroke lands in the document instead of the search field. These\n// highlights paint the same information with no focus and no DOM mutation \u2014 the CSS Custom\n// Highlight API takes plain Ranges over the live text and styles them from the stylesheet.\n\n/** Every match currently on screen. */\nconst FIND_HIGHLIGHT = \"docxodus-find\";\n/** The one the find bar's counter is pointing at. */\nconst FIND_HIGHLIGHT_ACTIVE = \"docxodus-find-active\";\n/** Ranges are cheap, but a pathological query (\"e\" in a book) is not worth painting in full. */\nconst FIND_PAINT_LIMIT = 500;\n\nconst findHighlightStyledDocuments = new WeakSet<Document>();\n/**\n * Which editor last painted into the shared registry. Only that instance may clear it, so a\n * second surface on the page cannot wipe the first one's find painting when its own find bar\n * closes. Two live searches still share one painting \u2014 the newer one wins, which is what a\n * single visible \"current match\" should mean.\n */\nlet findPaintOwner: object | null = null;\n\nfunction ensureFindHighlightStyles(doc: Document): void {\n if (findHighlightStyledDocuments.has(doc)) return;\n findHighlightStyledDocuments.add(doc);\n const style = doc.createElement(\"style\");\n style.dataset.docxodusFindHighlight = \"true\";\n style.textContent = `\n::highlight(${FIND_HIGHLIGHT}) { background-color: rgba(15, 118, 110, .16); }\n::highlight(${FIND_HIGHLIGHT_ACTIVE}) { background-color: rgba(15, 118, 110, .38); }\n`;\n (doc.head ?? doc.documentElement).appendChild(style);\n}\n\n/** The highlight registry is global to the document, so two editors on one page share it. */\ninterface HighlightRegistry {\n set(name: string, highlight: unknown): void;\n delete(name: string): void;\n}\n\nfunction highlightRegistry(): HighlightRegistry | null {\n if (typeof CSS === \"undefined\") return null;\n const registry = (CSS as unknown as { highlights?: HighlightRegistry }).highlights;\n const ctor = (globalThis as unknown as { Highlight?: unknown }).Highlight;\n return registry && typeof ctor === \"function\" ? registry : null;\n}\n\nfunction makeHighlight(ranges: Range[]): unknown {\n const ctor = (globalThis as unknown as {\n Highlight: new (...ranges: Range[]) => unknown;\n }).Highlight;\n return new ctor(...ranges);\n}\n\n/**\n * True when `el`'s immediate parent is a paragraph-border `<div>` the full render wrapped it in\n * (CreateBorderDivs groups visibly-bordered paragraphs into a div). The body wrapper div has no\n * border. Splitting/merging such a block must re-render the whole document so the converter can\n * re-group the border boxes \u2014 an in-place node swap would leave the new (often borderless)\n * paragraph stranded inside the stale border div, drawing the rule's line under its text.\n */\nfunction inBorderWrapper(el: HTMLElement): boolean {\n const style = el.parentElement?.getAttribute(\"style\") ?? \"\";\n return /border-(top|bottom|left|right):\\s*(?!none)[^;]+/i.test(style);\n}\n\n/** Whether the current selection's start already carries `key`, read from computed style. */\nfunction selectionHasFormat(key: FormatKey, fallback: HTMLElement): boolean {\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n let el: HTMLElement | null = fallback;\n if (sel && sel.rangeCount > 0) {\n const n = sel.getRangeAt(0).startContainer;\n el = n.nodeType === 3 ? n.parentElement : (n as HTMLElement);\n }\n if (!el || typeof getComputedStyle !== \"function\") return false;\n const cs = getComputedStyle(el);\n switch (key) {\n case \"bold\": return fontWeightIsBold(cs.fontWeight);\n case \"italic\": return cs.fontStyle === \"italic\" || cs.fontStyle === \"oblique\";\n case \"underline\": return cs.textDecorationLine.includes(\"underline\");\n case \"strike\": return cs.textDecorationLine.includes(\"line-through\");\n case \"code\": return /mono|courier|consolas/i.test(cs.fontFamily);\n case \"superscript\": return cs.verticalAlign === \"super\" || !!el.closest(\"sup\");\n case \"subscript\": return cs.verticalAlign === \"sub\" || !!el.closest(\"sub\");\n default: return false;\n }\n}\n\n/** Build the full ConvertDocxToHtmlComplete arg list (revisionPresentation = last arg). */\nfunction completeArgs(\n bytes: Uint8Array,\n cssPrefix: string,\n fabricate: boolean,\n paginated: boolean,\n scale: number,\n renderTrackedChanges: boolean,\n comments: boolean,\n): any[] {\n return [\n // Comment mode 1 = Inline: the commented runs are wrapped in highlight spans and the\n // reference becomes an (editor-hidden) marker, which is what the comment gutter positions\n // its bubbles against. -1 renders no comment markup at all.\n bytes, \"Document\", cssPrefix, fabricate, \"\", comments ? 1 : -1, \"comment-\",\n /* paginationMode */ paginated ? 1 : 0, /* paginationScale */ scale, \"page-\",\n false, 0, \"annot-\",\n // Footnotes/endnotes ON: they are document content, and the editor makes the rendered note\n // paragraphs editable. Must stay in step with DocxSessionOps.RenderHtml (the remount path),\n // whose output has to match this first paint byte-for-byte.\n /* renderFootnotesAndEndnotes */ true, /* renderHeadersAndFooters */ paginated,\n renderTrackedChanges, true, true, false, null, /* stampAnchors */ true,\n /* revisionPresentation: Docxodus (block renders keep it) */ 0,\n ];\n}\n\nexport class DocxEditor {\n private readonly exports: DocxEditorExports;\n private container: HTMLElement;\n private readonly handle: number;\n private readonly options: Required<\n Omit<DocxEditorOptions, \"onEdit\" | \"onEditFailed\" | \"onMove\" | \"onStoryChange\" | \"onCommentsChange\">\n > &\n Pick<DocxEditorOptions, \"onEdit\" | \"onEditFailed\" | \"onMove\" | \"onStoryChange\" | \"onCommentsChange\">;\n /** Map a block's current bare unid \u2192 its full kind:scope:unid (DocxSession anchor). */\n private readonly unidToFullId = new Map<string, string>();\n /** The element whose [data-anchor] descendants are the editable blocks (container or page container). */\n private editRoot: HTMLElement;\n /** The most recently focused editable block \u2014 the target for ribbon/format commands. */\n private activeBlock: HTMLElement | null = null;\n private closed = false;\n /**\n * Re-entrancy guard for node replacement. Replacing a contenteditable block that still holds\n * focus removes the focused node, which fires a SYNCHRONOUS `blur` \u2192 re-enters commitBlock; the\n * interleaved second replaceWith then throws NotFoundError (\"node ... no longer a child\") and the\n * structural edit (split/merge/format) is lost. While this flag is set, commitBlock no-ops.\n */\n private replacing = false;\n\n /** Editor-owned block-move chrome. It is deliberately outside the rendered unit tree. */\n private blockDragHandle: HTMLElement | null = null;\n private blockDropIndicator: HTMLElement | null = null;\n private blockMoveMenu: HTMLElement | null = null;\n private blockMoveLive: HTMLElement | null = null;\n private blockDragSource: HTMLElement | null = null;\n /** Whether hover or focus currently wants a handle for `blockDragSource`.\n * Tracked apart from the handle's `display`, which the viewport clip also drives: a handle\n * withdrawn because its block scrolled out of view has to come back when it scrolls in. */\n private blockHandleWanted = false;\n private blockDragCleanup: Array<() => void> = [];\n /** Block boxes measured at drag start \u2014 see `BlockDropZone`. Empty when no drag is in flight. */\n private dropZones: BlockDropZone[] = [];\n /** Combined scroll offset when `dropZones` was measured, and the scroller measured against. */\n private dropZoneOrigin = 0;\n private dropZoneScroller: HTMLElement | null = null;\n private blockDragging = false;\n private blockDragPointerDown = false;\n /** Anchors the current drag source may legally move next to, per the engine's own rules.\n * Null when the bridge predates ValidMoveTargets \u2014 then every block is offered, as before. */\n private blockMoveTargets: Map<string, { before: boolean; after: boolean }> | null = null;\n /** Memoized `ValidMoveTargets` answers, keyed by source anchor and dropped whenever an edit\n * lands. The legal-target set is a property of the document, so hovering back and forth over\n * the same blocks between edits must not re-ask the engine. */\n private blockMoveTargetCache = new Map<string, Map<string, { before: boolean; after: boolean }> | null>();\n /** Cancels the pending idle prefetch of the hovered block's targets \u2014 see `showBlockHandle`. */\n private blockMoveTargetPrefetch: (() => void) | null = null;\n /** Why the last move was refused, verbatim from the engine \u2014 diagnostics, not announcement copy. */\n lastMoveError: string | null = null;\n\n /**\n * The last real (non-collapsed) text selection inside an editable block. A toolbar control that\n * must take focus to be used \u2014 the font-size combobox \u2014 blurs the block and collapses the live\n * selection, so without this an operation triggered from such a control could only target the\n * whole paragraph (S-1 smoke-test finding 3). Refreshed whenever a non-empty selection sits in a\n * block, and cleared when a caret is collapsed inside a block (so it never goes stale).\n */\n private lastSelection: { unid: string; span: { start: number; length: number } } | null = null;\n\n /**\n * Stable bookmark for a selection spanning independent editable blocks. Native controls such as\n * a font-size combobox can take focus and collapse the live DOM selection; block ids + content\n * offsets let the command restore that same range before applying. This is the multi-block\n * counterpart to lastSelection above.\n */\n private lastCrossBlockSelection: CrossBlockSelectionBookmark | null = null;\n\n /** State for the mouse-selection bridge between independent contenteditable block hosts. */\n private dragSelection: CrossBlockDragSelection | null = null;\n\n /** The docked header/footer bands, when `options.headerFooter` is on. */\n private region: HeaderFooterRegion | null = null;\n\n /** The comment gutter, when `options.comments` is on. */\n private gutter: CommentGutter | null = null;\n\n /** Story host the caret is in (page view / band), published for chrome via `onStoryChange`. */\n private activeStory: BandWhich | null = null;\n\n /** Page geometry + fit-to-width zoom for the mounted document. Re-attached on every mount. */\n private readonly viewport: DocumentViewport;\n\n /** Why the last reconcile() fell back to a full remount (null = it patched). For\n * diagnostics/specs; not part of the public API. */\n private lastReconcileFallback: string | null = null;\n\n private constructor(\n container: HTMLElement,\n exports: DocxEditorExports,\n handle: number,\n options: DocxEditor[\"options\"],\n ) {\n this.container = container;\n this.exports = exports;\n this.handle = handle;\n this.options = options;\n this.editRoot = container;\n this.viewport = new DocumentViewport(container, {\n columnWidth: options.columnWidth,\n fitToWidth: options.fitToWidth,\n scale: options.scale,\n });\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"selectionchange\", this.onSelectionChange);\n document.addEventListener(\"mousedown\", this.onMouseDown, true);\n document.addEventListener(\"mousemove\", this.onMouseMove, true);\n document.addEventListener(\"mouseup\", this.onMouseUp, true);\n }\n }\n\n /** Track the last meaningful selection so focus-stealing toolbar controls can still target it. */\n private readonly onSelectionChange = (): void => {\n if (this.closed) return;\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n if (!sel || sel.rangeCount === 0) return; // no selection info \u2014 keep the cache as-is\n const range = sel.getRangeAt(0);\n const startBlock = this.editableBlockOf(range.startContainer);\n const endBlock = this.editableBlockOf(range.endContainer);\n const block = startBlock ?? endBlock;\n if (!block) return; // selection is outside the editor (e.g. a toolbar field) \u2014 keep the cache\n if (range.collapsed) {\n this.lastSelection = null; // an explicit caret in a block \u2014 drop any stale selection\n this.lastCrossBlockSelection = null;\n return;\n }\n if (\n startBlock && endBlock && startBlock !== endBlock &&\n this.ownerRoot(startBlock) === this.ownerRoot(endBlock)\n ) {\n const startUnid = startBlock.getAttribute(\"data-anchor\");\n const endUnid = endBlock.getAttribute(\"data-anchor\");\n if (startUnid && endUnid) {\n this.lastSelection = null;\n this.lastCrossBlockSelection = {\n startUnid,\n startOffset: contentOffsetOf(startBlock, range.startContainer, range.startOffset),\n endUnid,\n endOffset: contentOffsetOf(endBlock, range.endContainer, range.endOffset),\n };\n }\n return;\n }\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n this.lastCrossBlockSelection = null;\n const span = selectionSpanIn(block);\n if (span) this.lastSelection = { unid, span };\n };\n\n /** Start tracking a normal primary-button text drag inside one editable block. */\n private readonly onMouseDown = (event: MouseEvent): void => {\n if (this.closed || !this.options.editable || event.button !== 0) return;\n const target = event.target instanceof Node ? event.target : null;\n const origin = this.editableBlockOf(target);\n if (!origin || isInMarker(target)) return;\n const anchor = caretPointFromClient(document, event.clientX, event.clientY);\n if (!anchor || this.editableBlockOf(anchor.node) !== origin) return;\n this.clearDragSelection();\n this.dragSelection = {\n anchor,\n origin,\n crossedBlockBoundary: false,\n focus: null,\n frame: null,\n };\n };\n\n /**\n * Apply the latest cross-block endpoint after the browser finishes its native mousemove\n * selection update. Firefox rewrites Selection back into the originating contenteditable after\n * event dispatch even when mousemove is cancelled; writing in requestAnimationFrame wins that\n * race and happens before paint. Coalescing also avoids rebuilding a Range for every raw pointer\n * event when the mouse is moving faster than the display can refresh.\n */\n private queueDragSelection(drag: CrossBlockDragSelection, focus: DomSelectionPoint): void {\n drag.focus = focus;\n if (drag.frame !== null) return;\n const view = this.container.ownerDocument.defaultView;\n if (!view) {\n setSelectionBetween(drag.anchor, focus);\n return;\n }\n drag.frame = view.requestAnimationFrame(() => {\n drag.frame = null;\n if (this.dragSelection !== drag || !drag.focus) return;\n setSelectionBetween(drag.anchor, drag.focus);\n });\n }\n\n /** Cancel a queued repaint and discard the current gesture. */\n private clearDragSelection(): void {\n const drag = this.dragSelection;\n if (drag && drag.frame !== null) {\n this.container.ownerDocument.defaultView?.cancelAnimationFrame(drag.frame);\n }\n this.dragSelection = null;\n }\n\n /**\n * Browsers fence native mouse selection at a contenteditable host boundary. Once a drag reaches\n * another block in the same OOXML story, take over just that gesture and create the cross-block\n * Selection the editor's existing multi-block command path consumes. Intra-block selection stays\n * entirely native, and separate hosts remain intact for safe per-anchor commits.\n */\n private readonly onMouseMove = (event: MouseEvent): void => {\n const drag = this.dragSelection;\n if (!drag) return;\n if ((event.buttons & 1) === 0) {\n this.clearDragSelection();\n return;\n }\n const focus = caretPointFromClient(document, event.clientX, event.clientY);\n if (!focus || isInMarker(focus.node)) return;\n const focusBlock = this.editableBlockOf(focus.node);\n if (!focusBlock || this.ownerRoot(focusBlock) !== this.ownerRoot(drag.origin)) return;\n if (focusBlock !== drag.origin) drag.crossedBlockBoundary = true;\n if (!drag.crossedBlockBoundary) return;\n event.preventDefault();\n this.queueDragSelection(drag, focus);\n };\n\n /** Commit the final cross-block endpoint before releasing the gesture state. */\n private readonly onMouseUp = (event: MouseEvent): void => {\n const drag = this.dragSelection;\n if (!drag) return;\n if (drag.crossedBlockBoundary) {\n const focus = caretPointFromClient(document, event.clientX, event.clientY);\n const focusBlock = focus ? this.editableBlockOf(focus.node) : null;\n if (focus && focusBlock && this.ownerRoot(focusBlock) === this.ownerRoot(drag.origin)) {\n event.preventDefault();\n setSelectionBetween(drag.anchor, focus);\n }\n }\n this.clearDragSelection();\n };\n\n /** The editable block (contenteditable [data-anchor]) containing `node`, if any, within this editor.\n * Fenced by `container`, not `editRoot`, so header/footer band blocks \u2014 which live outside the\n * body edit root by design \u2014 also register. The fence still rejects other editors on the page. */\n private editableBlockOf(node: Node | null): HTMLElement | null {\n if (!node) return null;\n const start = node.nodeType === 1 ? (node as HTMLElement) : node.parentElement;\n const block = start?.closest<HTMLElement>('[data-anchor][contenteditable=\"true\"]') ?? null;\n return block && this.container.contains(block) ? block : null;\n }\n\n /**\n * The root owning `el`'s sibling block list: its header/footer band's story container, else the\n * body edit root. Keeps a multi-block selection from spanning a band and the body, whose block\n * lists belong to different OOXML parts.\n */\n private ownerRoot(el: HTMLElement): HTMLElement {\n return this.region?.blockRootOf(el) ?? this.editRoot;\n }\n\n /** True when `el` is a header/footer band block rather than a body block. */\n private isBandBlock(el: HTMLElement): boolean {\n return !!this.region?.contains(el);\n }\n\n /**\n * Repaint after an edit to `block` that would otherwise remount the whole document: a band\n * repaints only itself (a story is one to three paragraphs), leaving the body DOM \u2014 and the\n * user's place in it \u2014 untouched; a body edit reconciles incrementally. `forceRemount` is\n * for ops whose repaint provably needs whole-document context the reconciler cannot see:\n * list membership/level changes (sibling numbering shifts without sibling XML changing)\n * and border-div regrouping (HR insert, clearBorders).\n */\n private refreshAfter(block: HTMLElement, focusIndex: number, caretAtEnd = false, forceRemount = false): void {\n const band = this.region?.bandOf(block);\n if (band) {\n this.region!.refresh(this.region!.whichOf(band));\n return;\n }\n if (forceRemount) this.remount(focusIndex, caretAtEnd);\n else this.reconcile(focusIndex, caretAtEnd);\n }\n\n /** Open a document, render it into `container`, and wire up editing. */\n static open(\n container: HTMLElement,\n bytes: Uint8Array,\n exports: DocxEditorExports,\n options: DocxEditorOptions = {},\n ): DocxEditor {\n const opts = DocxEditor.resolveOptions(options);\n const editor = DocxEditor.openSession(container, bytes, exports, opts);\n try {\n editor.refreshAnchorMap();\n if (opts.headerFooter) editor.createRegion();\n // First paint goes through the session-attached editor render when the bundle has it, so\n // the comment markup (and everything else in the profile) is exactly what a remount will\n // produce; older bundles take the bytes path with the same profile.\n const fullHtml = editor.renderFullHtml(bytes);\n if (opts.paginated) editor.mountPaginated(fullHtml);\n else editor.mountHtml(fullHtml);\n editor.finishMount();\n return editor;\n } catch (error) {\n editor.close();\n throw error;\n }\n }\n\n /**\n * Open a document without holding the main thread for the whole mount (issue #776).\n *\n * {@link open} renders and wires the entire document in one synchronous task, which on a\n * long document is the largest single block of a reading-and-editing session. This variant\n * pays only the session open up front, then mounts the document in windows of body units,\n * yielding to the event loop between them: the chrome \u2014 stylesheet, section wrappers with\n * their page geometry, footnote and endnote sections \u2014 comes from one cheap engine render\n * that sees no body content, and each window from the engine's block renderer, which lays\n * units out exactly as the full render does (the plan's border-box grouping is never split).\n * The DOM that results is the one {@link open} produces; blocks already mounted are editable\n * while later windows are still landing, and edits made meanwhile are honoured because every\n * window renders from the live session.\n *\n * Paginated mounts assemble the windows off-screen and paginate once at the end, since\n * pagination is a one-shot flow over the whole document; the main thread is still free\n * between windows, and `onProgress` lets a host show the fill.\n *\n * A bundle that predates the windowed renders mounts synchronously, exactly like {@link open}.\n */\n static async openAsync(\n container: HTMLElement,\n bytes: Uint8Array,\n exports: DocxEditorExports,\n options: DocxEditorOpenAsyncOptions = {},\n ): Promise<DocxEditor> {\n const bridge = exports.DocxSessionBridge;\n if (\n typeof bridge.RenderEditorChromeHtml !== \"function\"\n || typeof bridge.RenderEditorRangeHtml !== \"function\"\n || typeof bridge.ListRenderedBlocks !== \"function\"\n ) {\n return DocxEditor.open(container, bytes, exports, options);\n }\n const opts = DocxEditor.resolveOptions(options);\n const editor = DocxEditor.openSession(container, bytes, exports, opts);\n try {\n editor.refreshAnchorMap();\n if (opts.headerFooter) editor.createRegion();\n await editor.mountWindowed(\n Math.max(1, Math.floor(options.windowSize ?? 24)),\n options.onProgress,\n );\n editor.finishMount();\n return editor;\n } catch (error) {\n editor.close();\n throw error;\n }\n }\n\n private static resolveOptions(options: DocxEditorOptions): DocxEditor[\"options\"] {\n return {\n cssPrefix: options.cssPrefix ?? \"docx-\",\n fabricateClasses: options.fabricateClasses ?? false,\n editable: options.editable ?? true,\n paginated: options.paginated ?? false,\n scale: options.scale ?? 1,\n columnWidth: options.columnWidth ?? \"section\",\n fitToWidth: options.fitToWidth ?? true,\n headerFooter: options.headerFooter ?? false,\n blockDrag: options.blockDrag ?? false,\n trackedChanges: options.trackedChanges ?? TrackedChangeMode.Accept,\n revisionAuthor: options.revisionAuthor ?? \"docxodus\",\n comments: options.comments ?? true,\n commentAuthor: options.commentAuthor ?? options.revisionAuthor ?? \"Reviewer\",\n onEdit: options.onEdit,\n onEditFailed: options.onEditFailed,\n onMove: options.onMove,\n onStoryChange: options.onStoryChange,\n onCommentsChange: options.onCommentsChange,\n };\n }\n\n private static openSession(\n container: HTMLElement,\n bytes: Uint8Array,\n exports: DocxEditorExports,\n opts: DocxEditor[\"options\"],\n ): DocxEditor {\n // NOT persistAnchorIds: that setting applies to every Save on the session, so it put the\n // projector's Unid bookkeeping into the bytes the USER downloads \u2014 ~6x the file size for\n // attributes no renderer reads. Only the remount's re-render needs id stability across a\n // save/re-render hop, and it asks for that per call via SaveWithAnchorIds.\n // emitMarkdownPatch off: the editor re-renders from HTML, never from markdown patches,\n // so paying a whole-document re-projection per op would be dead weight.\n const handle = exports.DocxSessionBridge.OpenSession(bytes, JSON.stringify({\n emitMarkdownPatch: false,\n trackedChanges: trackedChangeWireName(opts.trackedChanges),\n revisionAuthor: opts.revisionAuthor,\n }));\n return new DocxEditor(container, exports, handle, opts);\n }\n\n /** The steps every mount ends with once the body is in the DOM. */\n private finishMount(): void {\n this.syncRegionToBody();\n this.setupBlockDrag();\n if (this.options.comments) this.createGutter();\n }\n\n /**\n * The windowed mount behind {@link openAsync}: chrome first, then body units in plan order,\n * a group-aligned window per task. See {@link openAsync} for the contract.\n */\n private async mountWindowed(\n windowSize: number,\n onProgress?: (mounted: number, total: number) => void,\n ): Promise<void> {\n const bridge = this.exports.DocxSessionBridge;\n // The full render stamps source anchor ids on every unit; the windows must too, or the DOM\n // would differ from open()'s by exactly that attribute.\n const profile = JSON.stringify({ ...JSON.parse(this.editorRenderProfile()), stampAnchors: true });\n const chrome = bridge.RenderEditorChromeHtml!(this.handle, profile);\n if (chrome.trimStart().startsWith(\"{\")) {\n throw new Error((JSON.parse(chrome) as { error?: string }).error ?? \"chrome render failed\");\n }\n const parsed = new DOMParser().parseFromString(chrome, \"text/html\");\n // The chrome renders an empty carrier paragraph where each section break and note reference\n // was; those are not units and go before anything lands. Everything else inside a section\n // wrapper is chrome that stays \u2014 page view puts the endnotes section in the last one.\n parsed.body.querySelectorAll<HTMLElement>(`[data-section-index] > [data-anchor=\"${CHROME_CARRIER_ANCHOR}\"]`)\n .forEach((el) => el.remove());\n const styles = Array.from(parsed.querySelectorAll(\"style\")).map((s) => s.outerHTML).join(\"\");\n const flow = document.createElement(\"div\");\n flow.className = \"docx-body-flow\";\n flow.innerHTML = parsed.body.innerHTML;\n const hosts = new Map<number, HTMLElement>();\n flow.querySelectorAll<HTMLElement>(\"[data-section-index]\").forEach((el) =>\n hosts.set(Number(el.getAttribute(\"data-section-index\")), el));\n const attachNow = !this.options.paginated;\n // A flow mount wires blocks as they land \u2014 the chrome's own (footnote and endnote\n // paragraphs) now, each window's as it arrives \u2014 the way open() wires everything under\n // the flow. A paginated mount hands the paginator unwired HTML and wires the page clones\n // afterwards, exactly as open() does; wiring first would leave the paginator's\n // contenteditable=\"false\" stamp on every band paragraph.\n const wireNow = attachNow && this.options.editable;\n if (wireNow) this.wireBlocks(flow);\n if (attachNow) {\n this.region?.detachPages();\n this.container.innerHTML = styles;\n this.readoptGutter();\n this.container.appendChild(flow);\n this.editRoot = flow;\n }\n\n const plan = JSON.parse(this.renderPlanJson()) as RenderPlan & { error?: string };\n if (plan.error) throw new Error(plan.error);\n const units = plan.body;\n const sectionOf = new Map(units.map((u) => [unidOf(u.id), u.section ?? 0]));\n const mounted = new Set<string>();\n const place = (el: HTMLElement, sameHostAs?: HTMLElement): HTMLElement => {\n // Per-block converter output carries the XHTML xmlns; a full render only has it on the\n // document root, and open()'s DOM is the contract.\n el.removeAttribute(\"xmlns\");\n const unit = el.hasAttribute(\"data-anchor\") ? el : el.querySelector<HTMLElement>(\"[data-anchor]\");\n const unid = unit?.getAttribute(\"data-anchor\") ?? \"\";\n const host = sameHostAs ?? hosts.get(sectionOf.get(unid) ?? 0) ?? hosts.values().next().value ?? flow;\n // Units precede the chrome a section wrapper already holds (page view's endnotes section).\n host.insertBefore(el, host.querySelector(\":scope > section.endnotes\"));\n if (wireNow) {\n // wireBlocks wires a root's descendants; the node itself may be the unit.\n if (el.hasAttribute(\"data-anchor\")) this.wireBlock(el);\n this.wireBlocks(el);\n }\n unit && mounted.add(unid);\n el.querySelectorAll(\"[data-anchor]\").forEach((n) => mounted.add(n.getAttribute(\"data-anchor\")!));\n return host;\n };\n for (let start = 0; start < units.length;) {\n let end = Math.min(start + windowSize, units.length);\n // Never cut through a border box: extend to the end of the group the window stopped in.\n while (end < units.length && units[end].group !== undefined && units[end].group === units[end - 1].group) end++;\n const window = units.slice(start, end);\n const rendered = JSON.parse(bridge.RenderEditorRangeHtml!(\n this.handle, JSON.stringify(window.map((u) => u.id)), profile,\n )) as string[] | { error?: string };\n if (!Array.isArray(rendered)) throw new Error(rendered.error ?? \"window render failed\");\n for (const html of rendered) {\n // One rendered node can parse into several elements: the HTML parser closes a paragraph\n // at a block-level child (page view's page-break marker div), exactly as it does for the\n // full render's string, so every element it produced lands in order in the unit's section.\n let host: HTMLElement | undefined;\n for (const el of Array.from(new DOMParser().parseFromString(html, \"text/html\").body.children)) {\n host = place(el as HTMLElement, host);\n }\n }\n // A unit the range render could not place (a box that would have straddled the window)\n // still lands, on its own, through the per-block renderer.\n for (const unit of window) {\n if (mounted.has(unidOf(unit.id))) continue;\n const el = this.renderInto(unit.id);\n if (el) place(el);\n }\n start = end;\n onProgress?.(start, units.length);\n if (start < units.length) await yieldToEventLoop();\n }\n\n if (attachNow) {\n this.stampPlanState();\n if (this.region) this.dockBands(flow);\n this.viewport.attach(flow, true);\n } else {\n // Pagination is a one-shot flow over the whole document: hand it the assembled document\n // the way open() hands it the full render \u2014 head content (the meta tags, the title and\n // the stylesheet, which the paginator keeps in the flow) followed by the body.\n this.mountPaginated(parsed.head.innerHTML + flow.innerHTML);\n }\n }\n\n /**\n * Open a fresh, blank document (a \"New document\" \u2014 single empty paragraph, Normal style,\n * US-Letter section) and wire up editing. The seed bytes come from the WASM bridge so the\n * result opens cleanly in Word too.\n */\n static openBlank(\n container: HTMLElement,\n exports: DocxEditorExports,\n options: DocxEditorOptions = {},\n ): DocxEditor {\n return DocxEditor.open(container, exports.DocxSessionBridge.CreateBlankDocx(), exports, options);\n }\n\n /** Lossless DOCX bytes reflecting all edits. */\n save(): Uint8Array {\n this.assertOpen();\n return this.exports.DocxSessionBridge.Save(this.handle);\n }\n\n /** Monotonic committed document version, when supported by the loaded engine. */\n get version(): number | null {\n this.assertOpen();\n const value = this.exports.DocxSessionBridge.GetVersion?.(this.handle);\n return value ? (JSON.parse(value) as { version: number }).version : null;\n }\n\n /** Release the underlying WASM session. The editor is unusable afterward. */\n close(): void {\n if (this.closed) return;\n this.closed = true;\n if (typeof document !== \"undefined\") {\n document.removeEventListener(\"selectionchange\", this.onSelectionChange);\n document.removeEventListener(\"mousedown\", this.onMouseDown, true);\n document.removeEventListener(\"mousemove\", this.onMouseMove, true);\n document.removeEventListener(\"mouseup\", this.onMouseUp, true);\n }\n this.clearDragSelection();\n this.clearFindMatches();\n this.teardownBlockDrag();\n this.gutter?.dispose();\n this.gutter = null;\n this.region?.detachPages();\n this.viewport.dispose();\n this.exports.DocxSessionBridge.CloseSession(this.handle);\n }\n\n /**\n * Switch between continuous and paginated rendering WITHOUT losing edits. Re-renders from the\n * LIVE session, so every committed edit (and the undo/redo history) survives the toggle \u2014 unlike\n * re-opening the original bytes, which silently discards session edits. No-op if already `value`.\n */\n setPaginated(value: boolean): void {\n this.assertOpen();\n if (this.options.paginated === value) return;\n this.options.paginated = value;\n this.remount();\n }\n\n /** The editor's current DOM (for inspection/tests). */\n get root(): HTMLElement {\n return this.container;\n }\n\n /**\n * Move a fully rendered candidate into the host's stable public surface.\n * Internal editor chrome that binds directly to the container is recreated there;\n * document blocks and their listeners move with the DOM nodes.\n */\n adoptContainer(container: HTMLElement): void {\n this.assertOpen();\n if (container === this.container) return;\n this.teardownBlockDrag();\n this.gutter?.dispose();\n this.gutter = null;\n const previous = this.container;\n container.replaceChildren(...Array.from(previous.childNodes));\n this.container = container;\n this.viewport.adoptHost(container);\n this.setupBlockDrag();\n if (this.options.comments) this.createGutter();\n }\n\n /**\n * The zoom the viewport is currently applying (1 = 100%). Below 1 the page is wider than the\n * host and has been scaled to fit rather than reflowed \u2014 the honest thing to show a user who\n * is wondering why a phone shows the whole page.\n */\n get zoom(): number {\n return this.viewport.scale;\n }\n\n /**\n * The live `DocxSession` handle backing this editor \u2014 the model of record.\n *\n * Surfaced because chrome around the editor (the anchor rail) reports it as engine\n * state, and reaching into the private field from a host page only worked because\n * the bundle erases TypeScript's visibility.\n */\n get sessionHandle(): number {\n return this.handle;\n }\n\n /**\n * Repaint from the live session after it was mutated OUTSIDE the editor's own\n * commands \u2014 a host driving {@link sessionHandle} directly (an agent pipeline,\n * `raw.replaceXml`, a batch import). Continuous mode patches incrementally from\n * the render plan (a Unid-preserving single-block mutation repaints just that\n * block); paginated mode \u2014 or anything the reconciler cannot prove \u2014 remounts.\n * The editor cannot observe external mutations, so the host owns calling this\n * once per mutation batch.\n */\n refresh(): void {\n this.assertOpen();\n this.reconcile();\n }\n\n /** Move one top-level body block relative to another and repaint from the live session. */\n moveBlock(\n sourceAnchorId: string,\n targetAnchorId: string,\n position: \"before\" | \"after\",\n ): boolean {\n this.assertOpen();\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.MoveBlock !== \"function\") return false;\n const res = this.parseEdit(\n bridge.MoveBlock(this.handle, sourceAnchorId, targetAnchorId, position),\n );\n if (!res.success) {\n // The engine's message names an OOXML construct (\"a section-break paragraph\"); the live\n // region is read aloud, so announce the outcome and keep the raw reason for debugging.\n this.lastMoveError = res.error?.message ?? null;\n this.announceBlockMove(\"This block cannot be moved there.\");\n return false;\n }\n if (\n (res.created?.length ?? 0) === 0 &&\n (res.modified?.length ?? 0) === 0 &&\n (res.removed?.length ?? 0) === 0\n ) {\n this.announceBlockMove(\"The block is already in that position.\");\n return true;\n }\n\n const destination = res.created?.[0] ?? res.modified?.[0];\n // Both modes reconcile. A direct move relocates the existing element, so the reconciler moves\n // the exact DOM node it already has. Review rendering additionally rewrites the SOURCE in\n // place \u2014 it becomes the move-from half \u2014 and that is visible to the diff because the plan\n // signs every unit with a content hash, so the source diffs as an in-place substitution.\n // This used to remount, which on a real charter is seconds for a one-block change.\n this.reconcile();\n\n const moved = destination\n ? this.bodyUnitNodes().find((el) => el.getAttribute(\"data-anchor\") === destination.unid)\n : null;\n if (moved) {\n moved.classList.add(\"docx-block-move-flash\");\n moved.addEventListener(\"animationend\", () => moved.classList.remove(\"docx-block-move-flash\"), {\n once: true,\n });\n const focusTarget = EDITABLE_TAGS.has(moved.tagName)\n ? moved\n : moved.querySelector<HTMLElement>('[data-anchor][contenteditable=\"true\"]');\n if (focusTarget) {\n this.activeBlock = focusTarget;\n focusTarget.focus({ preventScroll: true });\n }\n }\n this.options.onMove?.({\n sourceAnchorId,\n destinationAnchorId: destination?.id ?? sourceAnchorId,\n });\n this.announceBlockMove(\"Block moved.\");\n return true;\n }\n\n /** Resolve any rendered descendant to its top-level body move unit (tables stay whole). */\n private blockUnitOf(target: EventTarget | Node | null): HTMLElement | null {\n const node = target instanceof Node ? target : null;\n const el = node?.nodeType === Node.ELEMENT_NODE\n ? node as HTMLElement\n : node?.parentElement;\n if (!el || !this.editRoot.contains(el)) return null;\n // Climb rather than scan: this runs on every pointer move over the document, and listing\n // every anchored node to find the one containing the pointer is linear in the document.\n let unit: HTMLElement | null = null;\n for (\n let candidate = el.closest<HTMLElement>(\"[data-anchor]\");\n candidate && this.editRoot.contains(candidate);\n candidate = candidate.parentElement?.closest<HTMLElement>(\"[data-anchor]\") ?? null\n ) {\n unit = candidate;\n }\n if (!unit || unit.closest(\"section.footnotes, section.endnotes\")) return null;\n return unit;\n }\n\n private isMovableBlockUnit(unit: HTMLElement | null): unit is HTMLElement {\n if (!unit || !this.anchorIdOf(unit)) return false;\n // A source representation of an existing tracked move/deletion is evidence, not a new\n // editable block. Its accepted counterpart remains draggable.\n if (unit.matches(\"[class$='row-del'], [class*='row-del ']\") ||\n unit.querySelector(\"tr[class$='row-del'], tr[class*='row-del '], del[class$='move-from'], del[class*='move-from ']\")\n ) return false;\n return unit.tagName === \"TABLE\" || EDITABLE_TAGS.has(unit.tagName);\n }\n\n private currentBlockDragSource(): HTMLElement | null {\n if (this.isMovableBlockUnit(this.blockDragSource) && this.blockDragSource.isConnected)\n return this.blockDragSource;\n const fromActive = this.blockUnitOf(this.activeBlock);\n if (this.isMovableBlockUnit(fromActive)) {\n this.blockDragSource = fromActive;\n return fromActive;\n }\n return null;\n }\n\n /**\n * The rectangle the floating handle may occupy: the window, narrowed by every ancestor that\n * clips its overflow.\n *\n * The handle is `position: fixed`, so it is placed in viewport coordinates and no ancestor's\n * overflow clips it for us. But the editor is routinely mounted inside a bounded scroller \u2014\n * the ribbon puts its surface in one, inside a clipped card \u2014 and a block scrolled out of that\n * scroller has to take its handle with it rather than leave it parked over the host's chrome.\n *\n * Gated on the computed `overflow` rather than on whether an element scrolls right now, so the\n * answer does not depend on how much content happens to be loaded.\n */\n private blockHandleClipRect(): { top: number; right: number; bottom: number; left: number } {\n const view = this.container.ownerDocument.defaultView;\n const clip = {\n top: 0,\n left: 0,\n right: view?.innerWidth ?? Number.MAX_SAFE_INTEGER,\n bottom: view?.innerHeight ?? Number.MAX_SAFE_INTEGER,\n };\n for (let el: HTMLElement | null = this.editRoot; el; el = el.parentElement) {\n const style = view?.getComputedStyle(el);\n if (!style || (style.overflowX === \"visible\" && style.overflowY === \"visible\")) continue;\n const box = el.getBoundingClientRect();\n if (style.overflowY !== \"visible\") {\n clip.top = Math.max(clip.top, box.top);\n clip.bottom = Math.min(clip.bottom, box.bottom);\n }\n if (style.overflowX !== \"visible\") {\n clip.left = Math.max(clip.left, box.left);\n clip.right = Math.min(clip.right, box.right);\n }\n }\n return clip;\n }\n\n private showBlockHandle(unit: HTMLElement): void {\n const handle = this.blockDragHandle;\n if (!handle || !this.isMovableBlockUnit(unit)) return;\n const changed = unit !== this.blockDragSource;\n this.blockDragSource = unit;\n this.blockHandleWanted = true;\n // A block the engine will not move anywhere \u2014 one owning a section break, or already carrying\n // revision markup a tracked move would have to re-wrap \u2014 gets no handle rather than a handle\n // that always fails. Asking costs an engine round trip, so hovering only ever CONSUMES a\n // cached answer and schedules the ask for idle time; the drag start and the menu ask for\n // real. Merely moving the pointer across the document must not run document-scale work.\n const known = this.blockMoveTargetsFor(unit, { cachedOnly: true });\n if (known?.size === 0) {\n handle.style.display = \"none\";\n return;\n }\n if (changed && known === undefined) this.prefetchBlockMoveTargets(unit);\n const rect = unit.getBoundingClientRect();\n // The handle belongs to the editor's viewport, not the window's. A block scrolled out of that\n // viewport gets no handle at all: clamping one back into view would leave a grip sitting next\n // to a block that is not there \u2014 and clamping to the WINDOW, as this used to, parked it on\n // whatever chrome the host draws above the editor.\n const clip = this.blockHandleClipRect();\n if (\n rect.bottom <= clip.top || rect.top >= clip.bottom\n || rect.right <= clip.left || rect.left >= clip.right\n ) {\n // A gesture in flight owns the handle: it is the drag's own source element, and an open\n // move menu is anchored to it and hands focus back to it on Escape. Withdrawing it\n // mid-gesture is the same mistake as leaving it behind \u2014 mirror `hideBlockHandle`'s guard\n // and leave it where the gesture put it.\n if (!this.blockDragging && this.blockMoveMenu?.style.display !== \"block\")\n handle.style.display = \"none\";\n return;\n }\n handle.style.display = \"flex\";\n // A block only partly in view keeps its handle, pulled to the edge it is disappearing past.\n const top = rect.top\n + (unit.tagName === \"TABLE\" ? 6 : Math.max(0, (rect.height - BLOCK_HANDLE_HEIGHT) / 2));\n handle.style.left = `${clampToRange(\n rect.left - (BLOCK_HANDLE_WIDTH + BLOCK_HANDLE_GAP),\n clip.left,\n clip.right - BLOCK_HANDLE_WIDTH,\n )}px`;\n handle.style.top = `${clampToRange(top, clip.top, clip.bottom - BLOCK_HANDLE_HEIGHT)}px`;\n const preview = blockPreviewText(unit);\n handle.setAttribute(\"aria-label\", preview ? `Move block: ${preview}` : \"Move block\");\n }\n\n private hideBlockHandle(): void {\n if (this.blockDragging || this.blockMoveMenu?.style.display === \"block\") return;\n this.blockHandleWanted = false;\n if (this.blockDragHandle) this.blockDragHandle.style.display = \"none\";\n }\n\n private positionBlockHandle(): void {\n const source = this.currentBlockDragSource();\n if (source && this.blockHandleWanted) this.showBlockHandle(source);\n }\n\n /** Draw the drop line on `zone`'s requested edge, or take it away when there is no target. */\n private paintDropIndicator(data: Record<string | symbol, unknown>): void {\n const indicator = this.blockDropIndicator;\n const zone = data.zone as BlockDropZone | undefined;\n if (!indicator) return;\n if (!zone) {\n this.hideDropIndicator();\n return;\n }\n const y = Math.round(this.dropEdgeY(zone, data.position === \"after\" ? \"after\" : \"before\")\n + this.dropZoneShift()) - 1;\n // Position before revealing, so the entry fade never plays at a stale spot.\n indicator.style.transform = `translate3d(${Math.round(zone.left)}px, ${y}px, 0)`;\n indicator.style.width = `${Math.max(24, Math.round(zone.width))}px`;\n indicator.style.display = \"block\";\n }\n\n /**\n * Where to draw the line for an insertion on `position` of `zone` \u2014 the MIDDLE of the gap to\n * the neighbour on that side, not the zone's own border-box edge. A paragraph's `w:spacing`\n * becomes a CSS margin, which sits outside the box, so drawing on the edge underlines the\n * block's last line instead of reading as a gap between two blocks. Falls back to the raw edge\n * at the ends of the flow, and degrades to the same value when blocks are contiguous.\n */\n private dropEdgeY(zone: BlockDropZone, position: \"before\" | \"after\"): number {\n const neighbour = this.dropZones[zone.index + (position === \"after\" ? 1 : -1)];\n // At the ends of the flow there is nothing to bisect against, so half the block's own\n // margin stands in for half the gap \u2014 the same position, one contributor instead of two.\n if (!neighbour) {\n return position === \"after\"\n ? zone.bottom + zone.marginAfter / 2\n : zone.top - zone.marginBefore / 2;\n }\n return position === \"after\"\n ? (zone.bottom + neighbour.top) / 2\n : (neighbour.bottom + zone.top) / 2;\n }\n\n private hideDropIndicator(): void {\n if (this.blockDropIndicator) this.blockDropIndicator.style.display = \"none\";\n }\n\n private announceBlockMove(message: string): void {\n const live = this.blockMoveLive;\n if (!live) return;\n live.textContent = \"\";\n this.container.ownerDocument.defaultView?.setTimeout(() => { live.textContent = message; }, 0);\n }\n\n /**\n * Ask the engine which anchors the current source may move next to. One call per drag source,\n * so the UI offers only drops MoveBlock will accept \u2014 a document with section breaks is\n * partitioned into regions, and drawing an indicator across one only to fail the drop was the\n * behaviour this replaces. Null (no bridge support) keeps the previous offer-everything path.\n */\n private refreshBlockMoveTargets(source: HTMLElement | null): void {\n this.blockMoveTargets = source ? this.blockMoveTargetsFor(source) ?? null : null;\n }\n\n /**\n * This block's legal destinations, from the memo when it is there. Returns `undefined` \u2014 not\n * `null` \u2014 for \"not asked yet\", so a caller can tell an unknown answer from the engine's\n * \"no bridge support, offer everything\" one.\n */\n private blockMoveTargetsFor(\n source: HTMLElement,\n options: { cachedOnly?: boolean } = {},\n ): Map<string, { before: boolean; after: boolean }> | null | undefined {\n const bridge = this.exports.DocxSessionBridge;\n const sourceId = this.anchorIdOf(source);\n if (!sourceId || typeof bridge.ValidMoveTargets !== \"function\") return null;\n if (this.blockMoveTargetCache.has(sourceId)) return this.blockMoveTargetCache.get(sourceId);\n if (options.cachedOnly) return undefined;\n\n let targets: Map<string, { before: boolean; after: boolean }> | null;\n try {\n const parsed = JSON.parse(bridge.ValidMoveTargets(this.handle, sourceId)) as Array<\n { anchorId: string; before: boolean; after: boolean }\n >;\n targets = new Map(parsed.map((t) => [t.anchorId, { before: t.before, after: t.after }]));\n } catch {\n targets = null;\n }\n this.blockMoveTargetCache.set(sourceId, targets);\n return targets;\n }\n\n /**\n * Ask for the hovered block's destinations off the interaction path, and hide the handle if\n * the answer comes back empty and that block is still the one under the pointer. The handle\n * therefore appears immediately on hover and withdraws a beat later on the rare immovable\n * block, instead of every hover paying for the query up front.\n */\n private prefetchBlockMoveTargets(source: HTMLElement): void {\n const view = this.container.ownerDocument.defaultView;\n if (!view) return;\n this.blockMoveTargetPrefetch?.();\n const run = (): void => {\n this.blockMoveTargetPrefetch = null;\n // The pointer has moved on (or the DOM was repainted) \u2014 the answer is no longer wanted.\n if (this.closed || !source.isConnected || this.blockDragSource !== source) return;\n if (this.blockMoveTargetsFor(source)?.size === 0 && this.blockDragHandle)\n this.blockDragHandle.style.display = \"none\";\n };\n const idle = (view as unknown as {\n requestIdleCallback?: (cb: () => void, opts?: { timeout: number }) => number;\n cancelIdleCallback?: (id: number) => void;\n });\n if (idle.requestIdleCallback && idle.cancelIdleCallback) {\n const id = idle.requestIdleCallback(run, { timeout: 500 });\n this.blockMoveTargetPrefetch = () => idle.cancelIdleCallback!(id);\n } else {\n const id = view.setTimeout(run, 0);\n this.blockMoveTargetPrefetch = () => view.clearTimeout(id);\n }\n }\n\n /**\n * Whether `unit` is a legal destination for the current drag source \u2014 for a SPECIFIC side when\n * one is given. A cross-block range or a section break between the blocks can make one side\n * legal and the other not, so \"this target is reachable\" is not enough to pick a position.\n */\n private isValidMoveTarget(unit: HTMLElement, position?: \"before\" | \"after\"): boolean {\n if (!this.blockMoveTargets) return true; // no bridge support: engine stays the only gate\n const id = this.anchorIdOf(unit);\n const sides = id ? this.blockMoveTargets.get(id) : undefined;\n if (!sides) return false;\n return position ? sides[position] : sides.before || sides.after;\n }\n\n /** Measure every movable block once, at drag start. See `BlockDropZone`. */\n private captureDropZones(): void {\n const view = this.container.ownerDocument.defaultView;\n this.dropZoneScroller = this.scrollContainer();\n this.dropZoneOrigin = this.scrollOffsetSum();\n this.dropZones = [];\n const boxes: HTMLElement[] = [];\n for (const unit of this.bodyUnitNodes()) {\n const anchorId = this.isMovableBlockUnit(unit) ? this.anchorIdOf(unit) : null;\n if (!anchorId) continue;\n const box = this.unitWrapperOf(unit);\n const rect = box.getBoundingClientRect();\n boxes.push(box);\n this.dropZones.push({\n unit, anchorId, index: this.dropZones.length,\n top: rect.top, bottom: rect.bottom, left: rect.left, width: rect.width,\n marginBefore: 0, marginAfter: 0,\n });\n }\n // Only the flow's two ends ever consult a margin, so only they are worth a style read.\n const ends = new Set([0, this.dropZones.length - 1].filter((i) => i >= 0 && i < boxes.length));\n for (const i of ends) {\n const style = view?.getComputedStyle(boxes[i]);\n this.dropZones[i].marginBefore = parseFloat(style?.marginTop ?? \"0\") || 0;\n this.dropZones[i].marginAfter = parseFloat(style?.marginBottom ?? \"0\") || 0;\n }\n }\n\n private scrollOffsetSum(): number {\n const view = this.container.ownerDocument.defaultView;\n return (view?.scrollY ?? 0) + (this.dropZoneScroller?.scrollTop ?? 0);\n }\n\n /** How far the measured boxes have travelled since capture, from scrolling (drag autoscroll). */\n private dropZoneShift(): number {\n return this.dropZoneOrigin - this.scrollOffsetSum();\n }\n\n /**\n * Where a drop at `clientY` lands, or null when nothing there is legal.\n *\n * Resolution is by VERTICAL GEOMETRY over the measured blocks, not by which element the pointer\n * is over: the drag handle floats in the page margin, so a drag straight down the gutter \u2014 the\n * natural gesture \u2014 never crosses a paragraph box, and element hit testing gave those drags no\n * indicator and no drop at all. The nearest block by vertical distance is the target; the half\n * the pointer is in picks the side, snapped to the other side when only that one is legal\n * (a section break or a cross-block range usually makes exactly one side illegal). When neither\n * side is legal \u2014 the pointer is in a region this block cannot reach \u2014 there is no drop, and\n * nothing is drawn.\n */\n private resolveDropAt(clientY: number): { zone: BlockDropZone; position: \"before\" | \"after\" } | null {\n const y = clientY - this.dropZoneShift();\n let best: BlockDropZone | null = null;\n let bestGap = Infinity;\n for (const zone of this.dropZones) {\n const gap = y < zone.top ? zone.top - y : y > zone.bottom ? y - zone.bottom : 0;\n if (gap < bestGap) {\n best = zone;\n bestGap = gap;\n }\n if (gap === 0) break; // inside this block; zones are in document order and never overlap\n }\n if (!best || best.unit === this.blockDragSource) return null;\n const preferred = y < (best.top + best.bottom) / 2 ? \"before\" : \"after\";\n if (this.isValidMoveTarget(best.unit, preferred)) return { zone: best, position: preferred };\n const other = preferred === \"before\" ? \"after\" : \"before\";\n return this.isValidMoveTarget(best.unit, other) ? { zone: best, position: other } : null;\n }\n\n private closeBlockMoveMenu(restoreFocus = false): void {\n if (!this.blockMoveMenu || !this.blockDragHandle) return;\n this.blockMoveMenu.style.display = \"none\";\n this.blockDragHandle.setAttribute(\"aria-expanded\", \"false\");\n this.blockDragHandle.setAttribute(\"aria-pressed\", \"false\");\n if (restoreFocus) this.blockDragHandle.focus({ preventScroll: true });\n }\n\n private openBlockMoveMenu(): void {\n const menu = this.blockMoveMenu;\n const handle = this.blockDragHandle;\n const source = this.currentBlockDragSource();\n if (!menu || !handle || !source) return;\n this.refreshBlockMoveTargets(source);\n menu.querySelectorAll<HTMLButtonElement>(\"button[data-move]\").forEach((button) => {\n button.disabled = !this.blockMoveDestination(source, button.dataset.move ?? \"\");\n });\n const rect = handle.getBoundingClientRect();\n menu.style.display = \"block\";\n menu.style.left = `${Math.max(4, rect.right + 6)}px`;\n menu.style.top = `${Math.max(4, rect.top)}px`;\n handle.setAttribute(\"aria-expanded\", \"true\");\n handle.setAttribute(\"aria-pressed\", \"true\");\n menu.querySelector<HTMLButtonElement>(\"button:not(:disabled)\")?.focus({ preventScroll: true });\n }\n\n /**\n * Resolve a move-menu action to the block it should land against, considering only destinations\n * the engine accepts. \"Top\"/\"bottom\" therefore mean the ends of the source's own movable region\n * \u2014 on a document with section breaks that is the section, not the document, which is what makes\n * the commands work at all there instead of always failing.\n */\n private blockMoveDestination(\n source: HTMLElement,\n action: string,\n ): { target: HTMLElement; position: \"before\" | \"after\" } | null {\n const units = this.bodyUnitNodes().filter((el) => this.isMovableBlockUnit(el));\n const index = units.indexOf(source);\n if (index < 0) return null;\n\n // Only pairs the engine accepts: a target can be reachable on one side and refused on the\n // other, so the SIDE is part of what makes a candidate valid.\n const position: \"before\" | \"after\" = action === \"up\" || action === \"top\" ? \"before\" : \"after\";\n const side = position === \"before\" ? units.slice(0, index) : units.slice(index + 1);\n const candidates = side.filter((el) => this.isValidMoveTarget(el, position));\n if (candidates.length === 0) return null;\n\n if (action === \"up\") return { target: candidates[candidates.length - 1], position };\n if (action === \"down\") return { target: candidates[0], position };\n if (action === \"top\") return { target: candidates[0], position };\n if (action === \"bottom\") return { target: candidates[candidates.length - 1], position };\n return null;\n }\n\n private runBlockMoveMenuAction(action: string): void {\n const source = this.currentBlockDragSource();\n if (!source) return;\n const destination = this.blockMoveDestination(source, action);\n this.closeBlockMoveMenu();\n if (!destination) return;\n const sourceId = this.anchorIdOf(source);\n const targetId = this.anchorIdOf(destination.target);\n if (sourceId && targetId) this.moveBlock(sourceId, targetId, destination.position);\n }\n\n /** The nearest ancestor that actually scrolls the document flow, for drag autoscroll. */\n private scrollContainer(): HTMLElement | null {\n const view = this.container.ownerDocument.defaultView;\n for (let el: HTMLElement | null = this.editRoot; el; el = el.parentElement) {\n const overflowY = view?.getComputedStyle(el).overflowY ?? \"visible\";\n if ((overflowY === \"auto\" || overflowY === \"scroll\") && el.scrollHeight > el.clientHeight)\n return el;\n }\n return null;\n }\n\n /** Mount one floating handle; PDD owns pointer dragging while the menu owns keyboard moves. */\n private setupBlockDrag(): void {\n if (!this.options.blockDrag || this.options.paginated || this.closed || this.blockDragHandle)\n return;\n const doc = this.container.ownerDocument;\n ensureBlockDragStyles(doc);\n\n const handle = doc.createElement(\"div\");\n handle.className = \"docx-block-handle\";\n handle.textContent = \"\u283F\";\n handle.tabIndex = 0;\n handle.setAttribute(\"role\", \"button\");\n handle.setAttribute(\"contenteditable\", \"false\");\n handle.setAttribute(\"aria-haspopup\", \"menu\");\n handle.setAttribute(\"aria-expanded\", \"false\");\n handle.setAttribute(\"aria-pressed\", \"false\");\n\n const indicator = doc.createElement(\"div\");\n indicator.className = \"docx-block-drop-indicator\";\n const menu = doc.createElement(\"div\");\n menu.className = \"docx-block-move-menu\";\n menu.setAttribute(\"role\", \"menu\");\n menu.innerHTML = `\n <button type=\"button\" role=\"menuitem\" data-move=\"up\">Move up</button>\n <button type=\"button\" role=\"menuitem\" data-move=\"down\">Move down</button>\n <button type=\"button\" role=\"menuitem\" data-move=\"top\">Move to top</button>\n <button type=\"button\" role=\"menuitem\" data-move=\"bottom\">Move to bottom</button>`;\n const live = doc.createElement(\"div\");\n live.className = \"docx-block-live-region\";\n live.setAttribute(\"role\", \"status\");\n live.setAttribute(\"aria-live\", \"polite\");\n this.container.append(handle, indicator, menu, live);\n this.blockDragHandle = handle;\n this.blockDropIndicator = indicator;\n this.blockMoveMenu = menu;\n this.blockMoveLive = live;\n\n const onPointerMove = (event: PointerEvent): void => {\n // Keep the floating draggable stationary between pointerdown and native dragstart.\n // Repositioning it under the pointer during the browser's drag threshold cancels\n // drag initiation before PDD can receive dragstart.\n if (this.blockDragging || this.blockDragPointerDown) return;\n const unit = this.blockUnitOf(event.target);\n if (this.isMovableBlockUnit(unit)) this.showBlockHandle(unit);\n };\n const onFocusIn = (event: FocusEvent): void => {\n const unit = this.blockUnitOf(event.target);\n if (this.isMovableBlockUnit(unit)) this.showBlockHandle(unit);\n };\n const onPointerLeave = (event: PointerEvent): void => {\n const next = event.relatedTarget instanceof Node ? event.relatedTarget : null;\n if (next && (handle.contains(next) || menu.contains(next))) return;\n this.hideBlockHandle();\n };\n const onViewportChange = (): void => this.positionBlockHandle();\n this.container.addEventListener(\"pointermove\", onPointerMove);\n this.container.addEventListener(\"focusin\", onFocusIn);\n this.container.addEventListener(\"pointerleave\", onPointerLeave);\n doc.addEventListener(\"scroll\", onViewportChange, true);\n doc.defaultView?.addEventListener(\"resize\", onViewportChange);\n this.blockDragCleanup.push(\n () => this.container.removeEventListener(\"pointermove\", onPointerMove),\n () => this.container.removeEventListener(\"focusin\", onFocusIn),\n () => this.container.removeEventListener(\"pointerleave\", onPointerLeave),\n () => doc.removeEventListener(\"scroll\", onViewportChange, true),\n () => doc.defaultView?.removeEventListener(\"resize\", onViewportChange),\n );\n\n const onHandleClick = (): void => {\n if (menu.style.display === \"block\") this.closeBlockMoveMenu();\n else this.openBlockMoveMenu();\n };\n const onHandlePointerDown = (): void => { this.blockDragPointerDown = true; };\n const onPointerUp = (): void => { this.blockDragPointerDown = false; };\n const onHandleKeydown = (event: KeyboardEvent): void => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n onHandleClick();\n };\n const onMenuClick = (event: MouseEvent): void => {\n const button = (event.target as Element | null)?.closest<HTMLButtonElement>(\"button[data-move]\");\n if (button && !button.disabled) this.runBlockMoveMenuAction(button.dataset.move ?? \"\");\n };\n const onMenuKeydown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") { event.preventDefault(); this.closeBlockMoveMenu(true); }\n };\n handle.addEventListener(\"click\", onHandleClick);\n handle.addEventListener(\"pointerdown\", onHandlePointerDown);\n handle.addEventListener(\"keydown\", onHandleKeydown);\n menu.addEventListener(\"click\", onMenuClick);\n menu.addEventListener(\"keydown\", onMenuKeydown);\n doc.addEventListener(\"pointerup\", onPointerUp, true);\n doc.addEventListener(\"pointercancel\", onPointerUp, true);\n this.blockDragCleanup.push(\n () => handle.removeEventListener(\"click\", onHandleClick),\n () => handle.removeEventListener(\"pointerdown\", onHandlePointerDown),\n () => handle.removeEventListener(\"keydown\", onHandleKeydown),\n () => menu.removeEventListener(\"click\", onMenuClick),\n () => menu.removeEventListener(\"keydown\", onMenuKeydown),\n () => doc.removeEventListener(\"pointerup\", onPointerUp, true),\n () => doc.removeEventListener(\"pointercancel\", onPointerUp, true),\n );\n\n this.blockDragCleanup.push(draggable({\n element: handle,\n canDrag: () => !!this.currentBlockDragSource(),\n getInitialData: () => {\n const source = this.currentBlockDragSource();\n return { type: BLOCK_DRAG_TYPE, sourceAnchorId: source ? this.anchorIdOf(source) : undefined };\n },\n // The browser would otherwise ghost the 26px grip, which says nothing about what is moving.\n onGenerateDragPreview: ({ nativeSetDragImage }) => {\n const source = this.currentBlockDragSource();\n setCustomNativeDragPreview({\n nativeSetDragImage,\n getOffset: pointerOutsideOfPreview({ x: \"14px\", y: \"10px\" }),\n render: ({ container }) => {\n const chip = doc.createElement(\"div\");\n chip.className = \"docx-block-drag-preview\";\n chip.textContent = (source && blockPreviewText(source)) || \"Move block\";\n container.appendChild(chip);\n return () => chip.remove();\n },\n });\n },\n onDragStart: () => {\n const source = this.currentBlockDragSource();\n this.blockDragging = true;\n handle.classList.add(\"docx-block-dragging\");\n // After the preview snapshot, so the chip is not dimmed too.\n source?.classList.add(\"docx-block-drag-source\");\n this.closeBlockMoveMenu();\n this.refreshBlockMoveTargets(source);\n this.captureDropZones();\n },\n onDrop: () => {\n this.blockDragging = false;\n this.blockDragPointerDown = false;\n this.dropZones = [];\n handle.classList.remove(\"docx-block-dragging\");\n // Cleared by selector rather than from a captured reference: a completed move may have\n // re-rendered the block, and the node that carries the class outlives either handle on it.\n doc.querySelectorAll(\".docx-block-drag-source\")\n .forEach((el) => el.classList.remove(\"docx-block-drag-source\"));\n this.hideDropIndicator();\n },\n }));\n // ONE drop target for the whole flow. Which block a drop belongs to is decided by\n // `resolveDropAt` from the pointer's vertical position, so the gutter the handle is dragged\n // down counts as being over the document \u2014 see that method.\n this.blockDragCleanup.push(dropTargetForElements({\n element: this.editRoot,\n canDrop: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,\n getData: ({ input }) => {\n const hit = this.resolveDropAt(input.clientY);\n return hit\n ? { type: BLOCK_DRAG_TYPE, targetAnchorId: hit.zone.anchorId, position: hit.position, zone: hit.zone }\n : { type: BLOCK_DRAG_TYPE };\n },\n onDragEnter: ({ self }) => this.paintDropIndicator(self.data),\n onDrag: ({ self }) => this.paintDropIndicator(self.data),\n onDragLeave: () => this.hideDropIndicator(),\n }));\n this.blockDragCleanup.push(monitorForElements({\n canMonitor: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,\n onDrop: ({ source, location }) => {\n this.hideDropIndicator();\n const drop = location.current.dropTargets[0]?.data;\n const sourceId = source.data.sourceAnchorId;\n const targetId = drop?.targetAnchorId;\n const position = drop?.position === \"after\" ? \"after\" : \"before\";\n if (typeof sourceId === \"string\" && typeof targetId === \"string\")\n this.moveBlock(sourceId, targetId, position);\n else\n // Released outside any valid target. Say so \u2014 a silent no-op reads as a broken drag.\n this.announceBlockMove(\"Move cancelled \u2014 the block was not dropped on a valid position.\");\n },\n }));\n // Register on the element that actually scrolls. editRoot is the document flow \u2014 in the\n // ribbon surface the scroller is an ancestor of it, and registering the flow made Pragmatic\n // log \"attached to an element that appears not to be scrollable\" on every document open\n // while doing nothing.\n const scroller = this.scrollContainer();\n if (scroller) {\n this.blockDragCleanup.push(autoScrollForElements({\n element: scroller,\n canScroll: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,\n getAllowedAxis: () => \"vertical\",\n }));\n }\n this.blockDragCleanup.push(autoScrollWindowForElements({\n canScroll: ({ source }) => source.data.type === BLOCK_DRAG_TYPE,\n getAllowedAxis: () => \"vertical\",\n }));\n }\n\n private teardownBlockDrag(): void {\n this.blockMoveTargetPrefetch?.();\n this.blockMoveTargetPrefetch = null;\n this.blockMoveTargetCache.clear();\n this.dropZones = [];\n this.dropZoneScroller = null;\n for (const cleanup of this.blockDragCleanup.splice(0)) cleanup();\n this.blockDragHandle?.remove();\n this.blockDropIndicator?.remove();\n this.blockMoveMenu?.remove();\n this.blockMoveLive?.remove();\n this.blockDragHandle = null;\n this.blockDropIndicator = null;\n this.blockMoveMenu = null;\n this.blockMoveLive = null;\n this.blockDragSource = null;\n this.blockHandleWanted = false;\n this.blockDragging = false;\n this.blockDragPointerDown = false;\n }\n\n // \u2500\u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private assertOpen(): void {\n if (this.closed) throw new Error(\"DocxEditor is closed\");\n }\n\n /**\n * Rebuild unid \u2192 full-anchor-id from the live session projection.\n *\n * Unids are CONTENT-ADDRESSED, so blocks with identical content in DIFFERENT parts collide \u2014\n * e.g. a document with empty default/first/even header stories has one unid for several\n * header parts. A collision must resolve to the BODY entry: body blocks carry only\n * `data-anchor` (the bare unid) and have nothing else to resolve through, whereas a\n * header/footer band block carries its full anchor in `data-hf-anchor` and is resolved from\n * that (see `anchorIdOf`). Letting a non-body scope win here would silently redirect a body\n * edit into a header part.\n */\n private refreshAnchorMap(): void {\n const bridge = this.exports.DocxSessionBridge;\n // ListAnchors returns the same {anchorIndex} object WITHOUT the markdown payload \u2014\n // marshaling the full projection (a couple hundred KB on a real document) made\n // this refresh the single biggest term of every incremental repaint.\n const raw =\n typeof bridge.ListAnchors === \"function\"\n ? bridge.ListAnchors(this.handle)\n : bridge.Project(this.handle);\n const proj = JSON.parse(raw) as {\n anchorIndex: Record<string, AnchorTargetLite>;\n };\n this.unidToFullId.clear();\n const bodyOwned = new Set<string>();\n for (const [fullId, target] of Object.entries(proj.anchorIndex)) {\n const isBody = target.scope === \"body\";\n if (!isBody && bodyOwned.has(target.unid)) continue;\n this.unidToFullId.set(target.unid, fullId);\n if (isBody) bodyOwned.add(target.unid);\n }\n }\n\n /**\n * The full `kind:scope:unid` anchor for a rendered block. A header/footer band block carries\n * its own \u2014 the unid map cannot disambiguate one, since several parts' story paragraphs can\n * share a content-addressed unid (a real Word document with empty default/first/even stories\n * does exactly that, and a unid-keyed lookup would land the edit in the wrong header part).\n */\n private anchorIdOf(el: HTMLElement): string | undefined {\n const stamped = el.getAttribute(\"data-hf-anchor\");\n if (stamped) return stamped;\n const unid = el.getAttribute(\"data-anchor\");\n return unid ? this.unidToFullId.get(unid) : undefined;\n }\n\n /** Build the header/footer region (called once, before the first mount). */\n private createRegion(): void {\n this.region = new HeaderFooterRegion(\n this.exports.DocxSessionBridge,\n this.handle,\n {\n wireBlock: (el) => this.wireBlock(el),\n renderBlock: (anchorId) => this.renderInto(anchorId),\n refreshAnchorMap: () => this.refreshAnchorMap(),\n bodyAnchorIdOf: (unid) => this.unidToFullId.get(unid),\n remount: () => {\n if (!this.closed) this.remount();\n },\n onActiveChange: (_host, which) => {\n this.activeStory = which;\n this.options.onStoryChange?.(which);\n },\n },\n );\n }\n\n /** Build the comment gutter over the container (called once, after the first mount). */\n private createGutter(): void {\n ensureCommentGutterStyles(this.container.ownerDocument);\n this.gutter = new CommentGutter(\n {\n container: this.container,\n commentAuthor: this.options.commentAuthor,\n listComments: () => this.listComments(),\n addComment: (markdown, author, target) => this.addComment(markdown, author, target),\n addCommentReply: (parent, markdown, author) => this.addCommentReply(parent, markdown, author),\n updateComment: (anchorId, markdown) => this.updateComment(anchorId, markdown),\n removeComment: (anchorId) => this.removeComment(anchorId),\n setCommentResolved: (anchorId, resolved) => this.setCommentResolved(anchorId, resolved),\n commentTarget: () => this.commentTarget(),\n },\n { onChange: (info) => this.options.onCommentsChange?.(info) },\n );\n }\n\n /**\n * Point the bands at the section governing the current focus (or the first body block).\n * Called after every mount, and on focus of a body block, so a multi-section document shows\n * the stories that actually apply where the caret is.\n */\n private syncRegionToBody(fromBlock?: HTMLElement): void {\n if (!this.region) return;\n const block = fromBlock ?? this.editableList()[0];\n const unid = block?.getAttribute(\"data-anchor\");\n const id = unid ? this.unidToFullId.get(unid) : undefined;\n this.region.syncToBody(id ?? null);\n }\n\n /**\n * Insert the bands around `bodyRoot` and make `bodyRoot` the edit root. Band blocks must stay\n * OUT of the edit root: `editableList()`/`blockIndex()` enumerate it to compute remount focus\n * indices, and band blocks in that list would shift every index.\n */\n private dockBands(bodyRoot: HTMLElement): void {\n if (!this.region) return;\n bodyRoot.before(this.region.headerBand);\n bodyRoot.after(this.region.footerBand);\n this.region.refreshAll();\n }\n\n /**\n * Continuous (non-paginated) mount: inject the converter's styles + body, wire blocks.\n *\n * The body always gets its own `.docx-body-flow` wrapper \u2014 not only when bands are docked.\n * It is the sheet: the element the viewport gives page geometry to and zooms, and the one\n * the bands dock around. Without it the container would have to be both the scrolling host\n * and the scaled page, which are different boxes.\n */\n private mountHtml(fullHtml: string): void {\n this.region?.detachPages();\n const parsed = new DOMParser().parseFromString(fullHtml, \"text/html\");\n const styles = Array.from(parsed.querySelectorAll(\"style\"))\n .map((s) => s.outerHTML)\n .join(\"\");\n this.container.innerHTML = styles;\n this.readoptGutter();\n const flow = document.createElement(\"div\");\n flow.className = \"docx-body-flow\";\n flow.innerHTML = parsed.body.innerHTML;\n this.container.appendChild(flow);\n this.editRoot = flow;\n if (this.options.editable) this.wireBlocks(flow);\n this.stampPlanState();\n if (this.region) this.dockBands(flow);\n this.viewport.attach(flow, true);\n }\n\n /** Paginated mount: flow blocks into page boxes via pagination.ts, wire the page clones. */\n private mountPaginated(fullHtml: string): void {\n this.region?.detachPages();\n // Pagination writes into its own wrapper so the container can also hold the comment gutter\n // (and so pagination's innerHTML reset can never eat it).\n this.container.innerHTML = \"\";\n this.readoptGutter();\n const target = document.createElement(\"div\");\n target.className = \"docx-body-flow\";\n this.container.appendChild(target);\n // Fragmented paragraphs intentionally have only one addressable head and\n // are therefore unsuitable for the editor's one-block editing model.\n paginateHtml(fullHtml, target, {\n scale: this.options.scale,\n cssPrefix: \"page-\",\n fragmentParagraphs: false,\n });\n // pagination.ts measures the hidden #pagination-staging subtree ONCE, then flows CLONES of its\n // blocks into the visible page boxes. Leaving staging in the live DOM is a trap: every\n // data-anchor exists twice (staging + page-box copy), so document.querySelector('[data-anchor]')\n // is ambiguous (hits the hidden copy first), and the staging copy goes stale because edits land\n // only on the page-box copy \u2014 a future reflow-from-staging would silently revert them. Staging\n // is a transient measurement scaffold; drop it so the page-box copies are the single source of\n // truth. A remount (setPaginated, list/undo edits) rebuilds staging fresh from the live session.\n this.container.querySelector(\"#pagination-staging, .page-staging\")?.remove();\n const pageRoot = target.querySelector<HTMLElement>(\"#pagination-container\") ?? target;\n this.editRoot = pageRoot;\n if (this.options.editable) this.wireBlocks(pageRoot);\n // The page boxes render their own header/footer margins as inert clones; the region turns\n // the clicked one into the live story in place (Word's edit-in-the-margin), so there is\n // still exactly one addressable node per story paragraph at any time.\n if (this.region) this.region.attachPages(pageRoot);\n // Page boxes already carry the section's dimensions, so the viewport contributes only the\n // fit zoom \u2014 a full page is far wider than a phone, and clipping it is not an option.\n this.viewport.attach(pageRoot, false);\n }\n\n private wireBlocks(root: HTMLElement): void {\n root.querySelectorAll<HTMLElement>(\"[data-anchor]\").forEach((el) => this.wireBlock(el));\n }\n\n private wireBlock(el: HTMLElement): void {\n if (!EDITABLE_TAGS.has(el.tagName)) return;\n if (\n el.closest(\"tr[class$='row-del'], tr[class*='row-del ']\") ||\n el.querySelector(\":scope > del[class$='move-from'], :scope > del[class*='move-from ']\")\n ) {\n el.setAttribute(\"contenteditable\", \"false\");\n return;\n }\n const unid = el.getAttribute(\"data-anchor\");\n // Only blocks the markdown projection addresses are editable via the text path. This INCLUDES\n // table-cell paragraphs (the projection indexes them), so cell text IS editable. Table-aware\n // key handling keeps structural edits safe while still providing Word-style cell navigation\n // (see onKeydown). Anything the projection does not index (unstamped content) stays read-only.\n // A band block is authoritative via its stamped `data-hf-anchor` even when the unid map\n // resolves that unid to a different part (content-addressed unids collide across parts).\n if (!unid || !this.anchorIdOf(el)) return;\n el.setAttribute(\"contenteditable\", \"true\");\n ensureListMarkerSeparator(el);\n // Generated chrome (list number/bullet, footnote/endnote citation markers, note backrefs) is\n // not editable content \u2014 keep the caret out so offsets stay aligned with the run text, and so\n // a citation marker can't be deleted directly (which would orphan its note definition).\n el.querySelectorAll<HTMLElement>(GENERATED_CHROME_SELECTOR)\n .forEach((m) => m.setAttribute(\"contenteditable\", \"false\"));\n // Page-number fields are atomic, and remember their cached result so per-page substitution\n // in the page view never shifts the offset space (see `fieldText`).\n adoptFields(el);\n // Baseline for the commit diff: CONTENT text (list markers + injected bidi marks excluded),\n // matching the session's flat run-text offset space.\n el.dataset.committedText = blockContentText(el);\n el.addEventListener(\"focus\", () => {\n this.activeBlock = el;\n // Follow the caret's section so a cover-page-plus-body document shows the stories that\n // actually apply. Focusing a BAND block must not re-sync: it has no governing section of\n // its own, and re-resolving would clobber the user's kind selection.\n if (this.region && !this.isBandBlock(el)) this.syncRegionToBody(el);\n this.region?.noteFocus(el);\n });\n el.addEventListener(\"blur\", () => this.commitBlock(el));\n el.addEventListener(\"input\", (ev) => noteTypedSpace(el, ev));\n el.addEventListener(\"keydown\", (ev) => this.onKeydown(el, ev as KeyboardEvent));\n // A band block re-rendered by an incremental swap is a fresh DOM node; re-adopt it (with the\n // anchor its caller already stamped) so the band chrome can still address it.\n const stamped = el.getAttribute(\"data-hf-anchor\");\n if (stamped && this.region?.contains(el)) this.region.adoptBlock(el, stamped);\n }\n\n /**\n * Replace `oldEl` with `newNodes`, suppressing the re-entrant blur\u2192commit that removing a focused\n * block fires (see `replacing`), AND tolerating the case where a synchronous blur during focus\n * transfer detaches `oldEl` between the caller's checks and here. `replaceWith` then throws\n * NotFoundError (\"node \u2026 no longer a child \u2026 moved in a blur event handler\") \u2014 `isConnected`\n * alone doesn't catch this race. The session is already updated, so a skipped/failed visual swap\n * leaves correct content (the typed DOM); the next commit or remount reconciles it. This is why\n * the catch is silent rather than rethrowing \u2014 there's no lost data, only a deferred re-render.\n * Returns true if the swap happened.\n */\n private replaceNode(oldEl: HTMLElement, ...newNodes: Node[]): boolean {\n const prev = this.replacing;\n this.replacing = true;\n try {\n if (!oldEl.parentNode) return false;\n oldEl.replaceWith(...newNodes);\n return true;\n } catch {\n return false;\n } finally {\n this.replacing = prev;\n }\n }\n\n /** Commit a block edit on blur: diff \u2192 run-preserving session op \u2192 re-render only this block. */\n private commitBlock(el: HTMLElement): void {\n if (this.closed || this.replacing) return;\n const unid = el.getAttribute(\"data-anchor\");\n if (!unid) return;\n const fullId = this.anchorIdOf(el);\n if (!fullId) return;\n\n const result = this.commitTextChange(el, fullId);\n if (!result) return; // no change\n if (!result.success) {\n this.restoreBlock(el, fullId);\n return;\n }\n\n const newAnchor = result.modified?.[0]?.id ?? fullId;\n const newUnid = result.modified?.[0]?.unid ?? unid;\n\n // List items: do NOT re-render on a text commit. Re-rendering replaces the node *during* the\n // blur, cancelling the browser's in-flight focus transfer when the user clicks straight to\n // another bullet; numbering also needs whole-document context a single-block render lacks. The\n // DOM already shows what the user typed with the correct marker \u2014 sync the baseline only.\n if (el.querySelector(\":scope > [data-list-marker]\")) {\n el.dataset.committedText = blockContentText(el);\n this.options.onEdit?.({ anchorId: newAnchor, unid: newUnid });\n return;\n }\n\n // Plain block: re-render ONLY this block from the live session for canonical HTML. Swapping the\n // just-blurred node here is safe (verified \u2014 focus stays on the newly-clicked block).\n const html = this.renderBlockHtml(newAnchor);\n if (html.charCodeAt(0) !== 0x7b /* not an error object */) {\n const fresh = new DOMParser().parseFromString(html, \"text/html\").body.firstElementChild as HTMLElement | null;\n const inBand = this.isBandBlock(el);\n if (fresh && this.replaceNode(el, fresh)) {\n // Band blocks resolve through `data-hf-anchor`; their unid can collide with another\n // part's, so writing it into the map would corrupt that entry (see anchorIdOf).\n if (inBand) {\n this.region!.adoptBlock(fresh, newAnchor);\n } else {\n this.unidToFullId.delete(unid);\n this.unidToFullId.set(newUnid, newAnchor);\n }\n this.wireBlock(fresh);\n if (this.activeBlock === el) this.activeBlock = fresh; // keep ribbon target valid\n // The throwaway render numbers citation markers from 1 \u2014 repair in place.\n this.maybeRenumberNotes(fresh);\n if (inBand) this.region!.afterStoryEdit(fresh);\n }\n }\n\n this.options.onEdit?.({ anchorId: newAnchor, unid: newUnid });\n }\n\n // \u2500\u2500\u2500 M2: structural editing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private onKeydown(el: HTMLElement, ev: KeyboardEvent): void {\n if (this.closed) return;\n // Common formatting / history shortcuts.\n if ((ev.ctrlKey || ev.metaKey) && !ev.altKey) {\n const k = ev.key.toLowerCase();\n const fmt: Record<string, FormatKey> = { b: \"bold\", i: \"italic\", u: \"underline\" };\n if (fmt[k]) { ev.preventDefault(); this.format(fmt[k]); return; }\n if (k === \"z\") { ev.preventDefault(); ev.shiftKey ? this.redo() : this.undo(); return; }\n if (k === \"y\") { ev.preventDefault(); this.redo(); return; }\n }\n // Inside a table cell, Backspace at the cell's start does not merge across the cell\n // boundary (mid-text Backspace still deletes normally). Enter splits the cell paragraph\n // WITHIN the same cell \u2014 the engine keeps the new w:p in the w:tc, so the grid is unchanged.\n // Tab navigation is handled explicitly below; at the final cell it uses the existing safe\n // whole-table row insertion path to match Word's add-a-row behavior.\n const inTableCell = !!el.closest(\"table\");\n\n // Plain Tab / Shift+Tab moves between table cells. Outside tables it retains list\n // nest/un-nest behavior. Modified Tab chords remain available to the browser/platform.\n if (ev.key === \"Tab\" && !ev.ctrlKey && !ev.metaKey && !ev.altKey && !ev.isComposing) {\n if (inTableCell) {\n ev.preventDefault();\n this.navigateTableCell(el, ev.shiftKey);\n return;\n }\n if (isListBlock(el)) {\n ev.preventDefault();\n this.activeBlock = el;\n this.setListLevel(ev.shiftKey ? -1 : 1);\n return;\n }\n }\n // Shift+Enter inserts an intra-paragraph line break (a real w:br on commit),\n // not a paragraph split. Deterministic across browsers and allowed in cells\n // (a line break changes no table structure).\n if (ev.key === \"Enter\" && ev.shiftKey && !ev.isComposing) {\n ev.preventDefault();\n this.insertLineBreakAtCaret();\n return;\n }\n if (ev.key === \"Enter\" && !ev.shiftKey && !ev.isComposing) {\n ev.preventDefault();\n // Splits at the caret \u2014 in a cell this stacks a second paragraph within the same\n // w:tc (grid unchanged); in the body it splits the paragraph as before.\n this.splitAtCaret(el);\n } else if (ev.key === \"Backspace\") {\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n if (sel && sel.isCollapsed && caretOffsetIn(el) === 0 && !inTableCell) {\n const prev = this.previousEditable(el);\n if (prev) {\n ev.preventDefault();\n this.mergeWithPrevious(prev, el);\n }\n }\n }\n }\n\n /** Editable cells in visual document order, excluding cells from any nested table. */\n private tableCellsFor(el: HTMLElement): { cells: HTMLElement[]; index: number } | null {\n const cell = el.closest<HTMLElement>(\"td, th\");\n const table = cell?.closest<HTMLTableElement>(\"table\");\n if (!cell || !table) return null;\n const cells = Array.from(table.querySelectorAll<HTMLElement>(\"td, th\"))\n .filter((candidate) => candidate.closest(\"table\") === table);\n const index = cells.indexOf(cell);\n return index >= 0 ? { cells, index } : null;\n }\n\n /** First addressable paragraph in a cell, fenced against nested-table descendants. */\n private editableInCell(cell: HTMLElement): HTMLElement | null {\n return Array.from(\n cell.querySelectorAll<HTMLElement>('[data-anchor][contenteditable=\"true\"]'),\n ).find((block) => block.closest(\"td, th\") === cell) ?? null;\n }\n\n /** Word-style cell navigation: Shift+Tab goes back, Tab goes forward, and Tab at the\n * final cell appends a row before entering its first cell. The first cell is a hard\n * boundary for Shift+Tab so focus never leaks out of the editor table. */\n private navigateTableCell(el: HTMLElement, backwards: boolean): void {\n const state = this.tableCellsFor(el);\n if (!state) return;\n const adjacent = state.cells[state.index + (backwards ? -1 : 1)];\n if (adjacent) {\n const target = this.editableInCell(adjacent);\n if (target) placeCaretAtOffset(target, 0);\n return;\n }\n if (backwards) return;\n\n // The current block may contain uncommitted typing. insertTableRow flushes it before the\n // structural edit, then reconcile/remount restores focus by block index. Resolve the new\n // adjacent cell from that fresh DOM rather than retaining a node from the replaced table.\n this.activeBlock = el;\n this.insertTableRow(\"below\");\n const fresh = this.activeBlock ? this.tableCellsFor(this.activeBlock) : null;\n if (!fresh) return;\n const target = fresh.cells[fresh.index + 1];\n const block = target ? this.editableInCell(target) : null;\n if (block) placeCaretAtOffset(block, 0);\n }\n\n /** Shift+Enter: insert an intra-paragraph line break at the caret. Delegates to the\n * native `insertLineBreak` command, which inserts a <br> AND positions the caret\n * after it correctly (handling the browser's bogus trailing-<br> rule) so typing\n * continues on the new line. Commits (on blur) as a w:br via the \" \\n\" hard break\n * the serializer emits for a <br>. */\n private insertLineBreakAtCaret(): void {\n if (typeof document !== \"undefined\" && typeof document.execCommand === \"function\") {\n document.execCommand(\"insertLineBreak\");\n }\n }\n\n /** Enter: split the block at the caret into two paragraphs. */\n private splitAtCaret(el: HTMLElement): void {\n const rawOffset = caretOffsetIn(el);\n const unid = el.getAttribute(\"data-anchor\");\n if (rawOffset == null || !unid) return;\n let fullId = this.anchorIdOf(el);\n if (!fullId) return;\n // The session commits trimmed text, so map the DOM caret offset into the trimmed run-text\n // offset (else an overshoot \u2014 e.g. a placeholder leading space \u2014 is rejected and Enter is lost).\n const offset = trimmedSplitOffset(el, rawOffset);\n\n const idx = this.blockIndex(el); // capture before the op (for list remount focus)\n // Whether this paragraph is rendered inside a border <div> \u2014 captured before the DOM mutates.\n const wrappedInBorder = inBorderWrapper(el);\n fullId = this.syncBlock(el, fullId); // flush any uncommitted typing first\n if (!fullId) return;\n const res = this.parseEdit(this.exports.DocxSessionBridge.SplitParagraph(this.handle, fullId, offset));\n if (!res.success) return;\n const first = res.modified?.[0];\n const second = res.created?.[0];\n if (!first || !second) return;\n\n // Splitting a list item makes a continuing list item, and splitting a bordered paragraph (e.g.\n // a horizontal rule) yields a new paragraph whose border status differs \u2014 both need a whole-\n // document re-render so numbering continues / border <div>s regroup correctly. An in-place node\n // swap would leave the new paragraph inside the old border div (the rule's line under its text).\n if (this.affectsList(res) || wrappedInBorder) {\n this.refreshAfter(el, idx + 1, false);\n this.options.onEdit?.({ anchorId: second.id, unid: second.unid });\n return;\n }\n\n const [firstEl, secondEl] = this.renderTwo(first.id, second.id);\n if (!firstEl || !secondEl) return;\n\n // el is the focused block \u2014 replaceNode guards the re-entrant blur\u2192commit and tolerates a\n // node detached mid-focus-transfer; replacing with both new blocks at once keeps them adjacent.\n const inBand = this.isBandBlock(el);\n if (!this.replaceNode(el, firstEl, secondEl)) return;\n // Band blocks resolve through `data-hf-anchor` (their unids can collide across parts).\n if (inBand) {\n this.region!.adoptBlock(firstEl, first.id);\n this.region!.adoptBlock(secondEl, second.id);\n } else {\n this.unidToFullId.delete(unid);\n this.unidToFullId.set(first.unid, first.id);\n this.unidToFullId.set(second.unid, second.id);\n }\n this.wireBlock(firstEl);\n this.wireBlock(secondEl);\n if (inBand) this.region!.afterStoryEdit(secondEl);\n placeCaretAtOffset(secondEl, 0);\n this.options.onEdit?.({ anchorId: second.id, unid: second.unid });\n }\n\n /** Backspace at block start: merge this block into the previous one. */\n private mergeWithPrevious(prev: HTMLElement, el: HTMLElement): void {\n const prevUnid = prev.getAttribute(\"data-anchor\");\n const thisUnid = el.getAttribute(\"data-anchor\");\n if (!prevUnid || !thisUnid) return;\n let prevId = this.anchorIdOf(prev);\n let thisId = this.anchorIdOf(el);\n if (!prevId || !thisId) return;\n\n const prevIdx = this.blockIndex(prev); // capture before the op\n // Either side rendered inside a border <div> means the merge changes border grouping \u2014 captured\n // before the DOM mutates so the post-merge branch can force a full re-render.\n const wrappedInBorder = inBorderWrapper(prev) || inBorderWrapper(el);\n prevId = this.syncBlock(prev, prevId);\n thisId = this.syncBlock(el, thisId);\n if (!prevId || !thisId) return;\n const caret = (prev.textContent ?? \"\").length; // merge boundary\n\n const res = this.parseEdit(this.exports.DocxSessionBridge.MergeParagraphs(this.handle, prevId, thisId));\n if (!res.success) return;\n const merged = res.modified?.[0];\n if (!merged) return;\n\n // Merging list items renumbers the list, and merging across a border <div> boundary changes the\n // border grouping \u2014 both need a whole-document re-render (caret at the merge boundary).\n if (this.affectsList(res) || wrappedInBorder) {\n this.refreshAfter(el, prevIdx, true);\n this.options.onEdit?.({ anchorId: merged.id, unid: merged.unid });\n return;\n }\n\n const mergedEl = this.renderInto(merged.id);\n if (!mergedEl) return;\n\n // prev may be focused \u2014 replaceNode guards re-entrancy and tolerates a detached node.\n const inBand = this.isBandBlock(prev);\n if (!this.replaceNode(prev, mergedEl)) return;\n el.remove();\n // Band blocks resolve through `data-hf-anchor` (their unids can collide across parts).\n if (inBand) {\n this.region!.adoptBlock(mergedEl, merged.id);\n } else {\n this.unidToFullId.delete(prevUnid);\n this.unidToFullId.delete(thisUnid);\n this.unidToFullId.set(merged.unid, merged.id);\n }\n this.wireBlock(mergedEl);\n if (inBand) this.region!.afterStoryEdit(mergedEl);\n placeCaretAtOffset(mergedEl, caret);\n this.options.onEdit?.({ anchorId: merged.id, unid: merged.unid });\n }\n\n /**\n * Apply the block's pending text change to the session with full inline-formatting fidelity.\n * Diffs the committed content text (markers + bidi excluded) against the current content text\n * and rewrites only the changed span via ReplaceTextAtSpan \u2014 every untouched run keeps its exact\n * rPr, and typed text inherits the boundary run's formatting. Returns the parsed EditResult, or\n * null when there is no change. Empty/whitespace-only baselines (e.g. the placeholder space the\n * converter renders for an empty paragraph, whose DOM text doesn't line up with the session's\n * empty run text) are rebuilt via ReplaceText \u2014 there is no inline formatting to preserve there.\n */\n private commitTextChange(el: HTMLElement, fullId: string): EditResultLite | null {\n // `old` mirrors the session's flat run-text: strip bidi marks (blockContentText strips them,\n // but wireBlock may have stored textContent before this Task 2 change, and the bidi test\n // explicitly stores textContent). Using stripBidi keeps the baseline consistent with the\n // session's offset space regardless of how committedText was stored.\n // contenteditable keeps a typed trailing space as U+00A0 so it stays visible; the document\n // wants an ordinary space there (Word's own), and the two are the same length, so the\n // offset space is unchanged. Both sides are normalized the same way, so an untouched\n // placeholder (the NBSP an empty paragraph renders as) never reads as an edit \\u2014 a blur that\n // committed \"\" over a paragraph another op just filled would wipe that op's work.\n const old = stripBidi(el.dataset.committedText ?? \"\").replace(/\\u00a0$/, \" \");\n const next = blockContentText(el).replace(/\\u00a0$/, \" \");\n if (old === next) return null;\n\n // A whitespace-only baseline means the paragraph was (or rendered as) empty, so the typed\n // text replaces it wholesale \u2014 unless it holds a field whose cached result is empty (a PAGE\n // field in a tool-generated footer): that is content, and the span path below keeps it\n // while inserting the typed text beside it.\n if (old.trim().length === 0 && !el.querySelector(\"[data-field]\")) {\n return this.parseEdit(\n this.exports.DocxSessionBridge.ReplaceText(this.handle, fullId, serializeInlineMarkdown(el)),\n );\n }\n\n const minLen = Math.min(old.length, next.length);\n let p = 0;\n while (p < minLen && old[p] === next[p]) p++;\n let s = 0;\n while (s < minLen - p && old[old.length - 1 - s] === next[next.length - 1 - s]) s++;\n\n let start = p;\n let len = old.length - p - s;\n let middle = next.slice(p, next.length - s);\n\n if (len === 0) {\n // A pure insertion. The engine inserts a NEW run at a run boundary (and steps outside a\n // field's chrome, so typing after \"Page X of Y\" never lands inside the NUMPAGES result);\n // an offset inside a run's text is not a boundary and is refused, as is the op on an\n // older engine build. Then anchor a neighbour char so the span is non-empty and the\n // inserted text inherits an adjacent run's rPr (the LEFT run when there is one, matching\n // contenteditable; the first run at the very start).\n const inserted = this.parseEdit(\n this.exports.DocxSessionBridge.ReplaceTextAtSpan(this.handle, fullId, start, 0, middle),\n { expectRejection: true }, // a refusal here only selects the fallback below\n );\n if (inserted.success) return inserted;\n if (start > 0) { start -= 1; len = 1; middle = old[start] + middle; }\n else { len = 1; middle = middle + old[0]; }\n }\n\n return this.parseEdit(\n this.exports.DocxSessionBridge.ReplaceTextAtSpan(this.handle, fullId, start, len, middle),\n );\n }\n\n /**\n * Flush a block's current (uncommitted) text to the session; returns the live full id, or\n * undefined when the engine rejected the text. The block is then restored from the session, and the\n * caller must stop: the operation it was about to run would act on text the document does not\n * hold, at offsets measured in the rejected DOM.\n */\n private syncBlock(el: HTMLElement, fullId: string): string | undefined {\n const result = this.commitTextChange(el, fullId);\n if (!result) return fullId;\n if (!result.success) {\n this.restoreBlock(el, fullId);\n return undefined;\n }\n el.dataset.committedText = blockContentText(el);\n return result.modified?.[0]?.id ?? fullId;\n }\n\n /**\n * The session refused an edit to `el`, so re-render the block from the session to discard the\n * DOM the user typed but the document never accepted.\n */\n private restoreBlock(el: HTMLElement, fullId: string): void {\n const fresh = this.renderInto(fullId);\n if (fresh && this.replaceNode(el, fresh)) {\n this.wireBlock(fresh);\n if (this.activeBlock === el) this.activeBlock = fresh;\n }\n }\n\n /** Render a block by anchor and parse it into a detached element (null on error). */\n private renderInto(anchorId: string): HTMLElement | null {\n const html = this.renderBlockHtml(anchorId);\n if (html.charCodeAt(0) === 0x7b /* error object */) return null;\n return new DOMParser().parseFromString(html, \"text/html\").body.firstElementChild as HTMLElement | null;\n }\n\n private get renderTrackedChanges(): boolean {\n return this.options.trackedChanges === TrackedChangeMode.RenderInline;\n }\n\n private renderBlockHtml(anchorId: string): string {\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.RenderEditorBlockHtml === \"function\") {\n return bridge.RenderEditorBlockHtml(this.handle, anchorId, this.editorRenderProfile());\n }\n if (typeof bridge.RenderBlockHtmlForReview === \"function\") {\n return bridge.RenderBlockHtmlForReview(\n this.handle, anchorId, this.options.cssPrefix, this.options.fabricateClasses,\n this.renderTrackedChanges,\n );\n }\n return bridge.RenderBlockHtml(\n this.handle, anchorId, this.options.cssPrefix, this.options.fabricateClasses,\n );\n }\n\n private renderPlanJson(): string {\n const bridge = this.exports.DocxSessionBridge;\n return typeof bridge.ListRenderedBlocks === \"function\"\n ? bridge.ListRenderedBlocks(this.handle, this.renderTrackedChanges)\n : bridge.ListBlocks!(this.handle);\n }\n\n /** Batch-render `idsJson` anchors through the richest endpoint the bundle carries; the JSON\n * maps each anchor to its HTML (null when it failed to resolve), or carries `error`. */\n private renderBlocksJson(idsJson: string): string {\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.RenderEditorBlocksHtml === \"function\") {\n return bridge.RenderEditorBlocksHtml(this.handle, idsJson, this.editorRenderProfile());\n }\n if (typeof bridge.RenderBlocksHtmlForReview === \"function\") {\n return bridge.RenderBlocksHtmlForReview(\n this.handle, idsJson, this.options.cssPrefix, this.options.fabricateClasses,\n this.renderTrackedChanges,\n );\n }\n return bridge.RenderBlocksHtml!(\n this.handle, idsJson, this.options.cssPrefix, this.options.fabricateClasses,\n );\n }\n\n /** Render two blocks in ONE batched bridge call when the bundle carries RenderBlocksHtml \u2014\n * the per-render shell/converter setup is paid once instead of twice, which matters on the\n * Enter path (split renders both halves synchronously under the keystroke). Falls back to\n * two per-block renders on older bundles. Output is renderInto-identical per block (both\n * routes share the same extraction). */\n private renderTwo(a: string, b: string): [HTMLElement | null, HTMLElement | null] {\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.RenderBlocksHtml === \"function\") {\n try {\n const idsJson = JSON.stringify([a, b]);\n const json = this.renderBlocksJson(idsJson);\n const map = JSON.parse(json) as Record<string, string | null> & { error?: string };\n if (!map.error) {\n const parse = (h: string | null | undefined): HTMLElement | null =>\n h\n ? (new DOMParser().parseFromString(h, \"text/html\").body\n .firstElementChild as HTMLElement | null)\n : null;\n const fa = parse(map[a]);\n const fb = parse(map[b]);\n if (fa && fb) return [fa, fb];\n }\n } catch {\n /* fall through to per-block renders */\n }\n }\n return [this.renderInto(a), this.renderInto(b)];\n }\n\n /** The editable block immediately before `el` within its own root, or null. */\n private previousEditable(el: HTMLElement): HTMLElement | null {\n const all = Array.from(\n this.ownerRoot(el).querySelectorAll<HTMLElement>('[data-anchor][contenteditable=\"true\"]'),\n );\n const i = all.indexOf(el);\n return i > 0 ? all[i - 1] : null;\n }\n\n /**\n * Read the result of a session mutation. Every editor mutation's result passes through here, so\n * this is where a rejection is reported (see {@link DocxEditorOptions.onEditFailed}), once, for\n * all of them. A caller probing an op it expects may be refused passes `expectRejection`.\n */\n private parseEdit(json: string, opts?: { expectRejection?: boolean }): EditResultLite {\n let result: EditResultLite;\n try {\n result = JSON.parse(json) as EditResultLite;\n } catch {\n result = { success: false };\n }\n if (result.success) {\n this.invalidateBlockMoveTargets();\n this.gutter?.schedule();\n } else if (!opts?.expectRejection) {\n this.reportEditFailure(result.error);\n }\n return result;\n }\n\n private reportEditFailure(error: EditResultLite[\"error\"]): void {\n const active = this.activeBlock;\n const failure: EditFailure = {\n code: error?.code,\n message: error?.message ?? \"The engine rejected the edit, or returned an unreadable result\",\n anchorId: error?.anchorId ?? (active ? this.anchorIdOf(active) ?? null : null),\n };\n if (this.options.onEditFailed) this.options.onEditFailed(failure);\n else console.warn(`[DocxEditor] the engine rejected an edit${failure.code ? ` (${failure.code})` : \"\"}: ${failure.message}`);\n }\n\n /**\n * Drop the memoized `ValidMoveTargets` answers. Which blocks a block may move next to is a\n * fact about the DOCUMENT, so it survives hovering but not editing \u2014 and the two places a\n * document changes are `parseEdit` (every mutation that returns an `EditResult`) and\n * undo/redo, which return a bare boolean and so cannot go through it.\n */\n private invalidateBlockMoveTargets(): void {\n this.blockMoveTargetCache.clear();\n }\n\n // \u2500\u2500\u2500 M5: formatting commands (ribbon) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n // \u2500\u2500\u2500 Multi-block selection helpers (format a whole stack of paragraphs at once) \u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Restore a cross-block selection after a native toolbar control took focus. The bookmark uses\n * stable anchor ids and content offsets, so it also survives incremental block swaps.\n */\n private restoreCrossBlockSelection(): boolean {\n const bookmark = this.lastCrossBlockSelection;\n const active = this.activeBlock;\n if (!bookmark || !active) return false;\n const all = Array.from(\n this.ownerRoot(active).querySelectorAll<HTMLElement>('[data-anchor][contenteditable=\"true\"]'),\n );\n const first = all.find((block) => block.getAttribute(\"data-anchor\") === bookmark.startUnid);\n const last = all.find((block) => block.getAttribute(\"data-anchor\") === bookmark.endUnid);\n if (!first || !last || first === last || all.indexOf(first) > all.indexOf(last)) return false;\n const start = contentPositionIn(first, bookmark.startOffset);\n const end = contentPositionIn(last, bookmark.endOffset);\n return setSelectionBetween(start, end);\n }\n\n /** Editable blocks the current selection covers, in document order. Uses Range.comparePoint\n * (robust to a selection boundary that normalized onto a wrapper element rather than a block\n * or text node \u2014 Range.intersectsNode misses the end block at a `(block, childCount)` boundary).\n * A collapsed or single-block selection yields just the active block. */\n private selectedBlocks(): HTMLElement[] {\n let sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n if ((!sel || sel.rangeCount === 0 || sel.isCollapsed) && this.lastCrossBlockSelection) {\n this.restoreCrossBlockSelection();\n sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n }\n // Enumerate the ACTIVE block's own root \u2014 a band's story container, else the body edit root \u2014\n // so a selection can never span a band and the body (different OOXML parts).\n const root = this.activeBlock ? this.ownerRoot(this.activeBlock) : this.editRoot;\n const all = Array.from(\n root.querySelectorAll<HTMLElement>('[data-anchor][contenteditable=\"true\"]'),\n );\n if (sel && sel.rangeCount > 0 && !sel.isCollapsed) {\n const range = sel.getRangeAt(0);\n const hit = all.filter((b) => {\n try {\n const startsAfterEnd = range.comparePoint(b, 0) > 0; // block begins after the selection ends\n const endsBeforeStart = range.comparePoint(b, b.childNodes.length) < 0; // block ends before it starts\n return !startsAfterEnd && !endsBeforeStart;\n } catch {\n return false;\n }\n });\n if (hit.length > 1) return hit;\n }\n return this.activeBlock ? [this.activeBlock] : [];\n }\n\n /** The selection's span within `block`, clipped to the block (for inline ops across blocks):\n * the first block runs selection-start\u2192end-of-block, middle blocks are whole, the last block\n * runs start-of-block\u2192selection-end. Returns null for a whole-block apply. */\n private blockSpanForSelection(block: HTMLElement): { start: number; length: number } | null {\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return null;\n const range = sel.getRangeAt(0);\n const hasStart = block.contains(range.startContainer);\n const hasEnd = block.contains(range.endContainer);\n if (hasStart && hasEnd) return selectionSpanIn(block);\n // Partial/whole slices are normalized into the committed run-text space for the same reason\n // selectionSpanIn is (see trimmedSpan): a session op rejects a span past the committed end.\n const contentLen = blockContentText(block).length;\n if (hasStart) {\n const start = contentOffsetOf(block, range.startContainer, range.startOffset);\n return trimmedSpan(block, { start, length: Math.max(0, contentLen - start) });\n }\n if (hasEnd) {\n const end = contentOffsetOf(block, range.endContainer, range.endOffset);\n return trimmedSpan(block, { start: 0, length: end });\n }\n return trimmedSpan(block, { start: 0, length: contentLen }); // fully-spanned middle block\n }\n\n /** Apply an inline ApplyFormat op to each block's slice of the selection, then reconcile\n * the DOM incrementally (see {@link finishMultiBlockOp} \u2014 a full remount costs a whole-\n * document convert, seconds on a large doc, where per-block swaps are ~10 ms each).\n * Returns false (caller falls back to the single-block path) for a 1-block selection. */\n private applyInlineOpAcrossBlocks(blocks: HTMLElement[], op: object): boolean {\n if (blocks.length <= 1) return false;\n const targets = this.multiBlockTargets(blocks);\n for (const t of targets) {\n if (!t.fullId || (t.span && t.span.length === 0)) continue;\n const synced = this.syncBlock(t.block, t.fullId);\n if (!synced) continue;\n const res = this.parseEdit(this.exports.DocxSessionBridge.ApplyFormat(\n this.handle, synced, t.span ? JSON.stringify(t.span) : \"\", JSON.stringify(op),\n ));\n if (res.success) t.res = res;\n }\n this.finishMultiBlockOp(targets, false);\n return true;\n }\n\n /** Apply a whole-block (paragraph-level) op to each selected block, then reconcile the DOM\n * incrementally ({@link finishMultiBlockOp}). `forceRemount` is for ops whose rendering\n * needs whole-document context (e.g. border-div regrouping after clearBorders). Returns\n * false for a 1-block selection (caller uses the single-block path). */\n private applyParagraphOpAcrossBlocks(\n blocks: HTMLElement[],\n run: (fullId: string) => string,\n forceRemount = false,\n ): boolean {\n if (blocks.length <= 1) return false;\n const targets = this.multiBlockTargets(blocks);\n for (const t of targets) {\n if (!t.fullId) continue;\n const synced = this.syncBlock(t.block, t.fullId);\n if (!synced) continue;\n const res = this.parseEdit(run(synced));\n if (res.success) t.res = res;\n }\n this.finishMultiBlockOp(targets, forceRemount);\n return true;\n }\n\n /** Snapshot each selected block's identity + selection slice BEFORE any session op runs\n * (ops never mutate the DOM, so spans captured here stay valid until the swap phase). */\n private multiBlockTargets(blocks: HTMLElement[]): Array<{\n block: HTMLElement;\n unid: string | null;\n fullId: string | undefined;\n span: { start: number; length: number } | null;\n res: EditResultLite | null;\n }> {\n return blocks.map((b) => {\n const unid = b.getAttribute(\"data-anchor\");\n return {\n block: b,\n unid,\n fullId: this.anchorIdOf(b),\n span: this.blockSpanForSelection(b),\n res: null,\n };\n });\n }\n\n /**\n * Reconcile the DOM after a multi-block op. Fidelity-identical to the single-block path by\n * construction: each edited block is swapped for its own session-attached single-block\n * render \u2014 exactly what format()/setFontSize()/applyParagraphFormat() do for one block \u2014\n * so a multi-block apply is N single-block applies, not one whole-document re-render\n * (which froze the UI for the full-document convert time on every ribbon action). Falls\n * back to ONE full remount when the op touched a list item (numbering continuation needs\n * whole-document context) or the caller forced it. Restores the cross-block selection so\n * consecutive ribbon actions (center, then bold) keep targeting the same range.\n */\n private finishMultiBlockOp(\n targets: Array<{\n block: HTMLElement;\n unid: string | null;\n span: { start: number; length: number } | null;\n res: EditResultLite | null;\n }>,\n forceRemount: boolean,\n ): void {\n const edited = targets.filter((t) => t.res && t.unid);\n if (edited.length === 0) return;\n // Paginated mode: a multi-block format change can alter block heights, and page boxes\n // need a reflow \u2014 keep the (pre-existing) full remount there until M4 lands a scoped\n // re-paginate. Continuous mode reconciles incrementally.\n if (forceRemount || this.options.paginated || edited.some((t) => this.affectsList(t.res!))) {\n this.refreshAfter(edited[0].block, -1, false);\n return;\n }\n const swapped: Array<{ el: HTMLElement; span: { start: number; length: number } | null }> = [];\n for (const t of edited) {\n const fresh = this.swapBlock(t.block, t.unid!, t.res!.modified?.[0]);\n swapped.push({ el: fresh ?? t.block, span: t.span });\n }\n const first = swapped[0];\n const last = swapped[swapped.length - 1];\n if (!first.el.isConnected || !last.el.isConnected) return;\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n if (!sel) return;\n const startOff = first.span?.start ?? 0;\n const endOff = last.span ? last.span.start + last.span.length : blockContentText(last.el).length;\n const startPos = contentPositionIn(first.el, startOff);\n const endPos = contentPositionIn(last.el, endOff);\n try {\n const range = document.createRange();\n range.setStart(startPos.node, startPos.offset);\n range.setEnd(endPos.node, endPos.offset);\n sel.removeAllRanges();\n sel.addRange(range);\n } catch {\n /* selection restore is best-effort \u2014 the edits themselves are already committed */\n }\n }\n\n /**\n * Toggle (or set) an inline format on the current selection in the active block.\n * A selection spanning multiple blocks applies to each. With no selection, applies to\n * the whole paragraph. Routes through DocxSession (`ApplyFormat`) so it is lossless and\n * supports underline/strike, not just markdown.\n */\n format(key: FormatKey, value?: boolean): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n const blocks = this.selectedBlocks();\n if (blocks.length > 1) {\n const on0 = value ?? !selectionHasFormat(key, blocks[0]);\n const multiOp =\n key === \"superscript\" || key === \"subscript\"\n ? { vertAlign: on0 ? key : \"\" }\n : { [key]: on0 };\n if (this.applyInlineOpAcrossBlocks(blocks, multiOp)) return;\n }\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n\n const span = selectionSpanIn(block);\n const on = value ?? !selectionHasFormat(key, block);\n // Super/subscript map to the single-valued w:vertAlign; the rest are boolean toggles.\n const op =\n key === \"superscript\" || key === \"subscript\"\n ? { vertAlign: on ? key : \"\" }\n : { [key]: on };\n fullId = this.syncBlock(block, fullId); // don't clobber uncommitted typing\n if (!fullId) return;\n const res = this.parseEdit(\n this.exports.DocxSessionBridge.ApplyFormat(\n this.handle,\n fullId,\n span ? JSON.stringify(span) : \"\",\n JSON.stringify(op),\n ),\n );\n if (!res.success) return;\n if (this.affectsList(res)) { this.refreshAfter(block, this.blockIndex(block), false); return; }\n const fresh = this.swapBlock(block, unid, res.modified?.[0]);\n if (fresh && span) selectRange(fresh, span.start, span.length);\n else fresh?.focus();\n }\n\n /**\n * Set the font size (in points) of the current selection in the active block; with no\n * selection, applies to the whole paragraph. `pts <= 0` clears the explicit size. Routes\n * through DocxSession `ApplyFormat` (`w:sz`), so it is lossless and survives save.\n */\n setFontSize(pts: number): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n const blocks = this.selectedBlocks();\n if (blocks.length > 1 && this.applyInlineOpAcrossBlocks(blocks, { fontSizePts: pts })) return;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n // Use the live selection; if the font-size combobox stole focus and collapsed it, fall back to\n // the last real selection cached for this block so a sub-range still sizes (finding 3).\n let span = selectionSpanIn(block);\n if (!span && this.lastSelection && this.lastSelection.unid === unid) span = this.lastSelection.span;\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return;\n const res = this.parseEdit(\n this.exports.DocxSessionBridge.ApplyFormat(\n this.handle,\n fullId,\n span ? JSON.stringify(span) : \"\",\n JSON.stringify({ fontSizePts: pts }),\n ),\n );\n if (!res.success) return;\n if (this.affectsList(res)) { this.refreshAfter(block, this.blockIndex(block), false); return; }\n const fresh = this.swapBlock(block, unid, res.modified?.[0]);\n if (fresh && span) selectRange(fresh, span.start, span.length);\n else fresh?.focus();\n }\n\n /**\n * Set the font family of the current selection in the active block; with no selection,\n * applies to the whole paragraph. `\"\"` clears the explicit font (inherits the style/default).\n * Routes through DocxSession `ApplyFormat` (`w:rFonts`), so it is lossless and survives save.\n * Multi-block + last-selection plumbing matches {@link setFontSize} (a focus-stealing font\n * dropdown still applies to the real sub-range).\n */\n setFontFamily(name: string): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n const blocks = this.selectedBlocks();\n if (blocks.length > 1 && this.applyInlineOpAcrossBlocks(blocks, { fontFamily: name })) return;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n let span = selectionSpanIn(block);\n if (!span && this.lastSelection && this.lastSelection.unid === unid) span = this.lastSelection.span;\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return;\n const res = this.parseEdit(\n this.exports.DocxSessionBridge.ApplyFormat(\n this.handle,\n fullId,\n span ? JSON.stringify(span) : \"\",\n JSON.stringify({ fontFamily: name }),\n ),\n );\n if (!res.success) return;\n if (this.affectsList(res)) { this.refreshAfter(block, this.blockIndex(block), false); return; }\n const fresh = this.swapBlock(block, unid, res.modified?.[0]);\n if (fresh && span) selectRange(fresh, span.start, span.length);\n else fresh?.focus();\n }\n\n /** Set paragraph alignment (left/center/right/justify) on the active block. */\n setAlignment(alignment: EditorAlignment): void {\n this.applyParagraphFormat({ alignment });\n }\n\n /**\n * Insert an S-1-style horizontal rule (an empty paragraph with a bottom border) after the\n * active block. `weight` is the rule thickness in eighths of a point (default 12 \u2248 1.5pt).\n * Re-renders fully (a new block needs whole-document context to lay out).\n */\n insertHorizontalRule(weight = 12, style = \"single\", position: \"above\" | \"below\" = \"below\"): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n const idx = this.blockIndex(block);\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return;\n const res = this.parseEdit(\n this.exports.DocxSessionBridge.InsertHorizontalRule(\n this.handle,\n fullId,\n position === \"above\" ? \"before\" : \"after\",\n JSON.stringify({ style, size: weight, color: \"auto\" }),\n ),\n );\n if (!res.success) return;\n // Remount from the active block's index re-renders the new rule whether it landed just\n // above (at idx) or just below (at idx+1) the active block. Forced: a rule is a bordered\n // paragraph, and border-div grouping is whole-document render context.\n this.refreshAfter(block, idx, false, /* forceRemount */ true);\n }\n\n /**\n * Insert a `rows`\u00D7`cols` table after the active block. `options.cellContents` (row-major\n * markdown) seeds the cells, `options.borderless` makes an invisible layout table, and\n * `options.cellAlignment` aligns every cell. Re-renders fully (tables need document context).\n */\n insertTable(\n rows: number,\n cols: number,\n options?: {\n borderless?: boolean;\n cellContents?: string[];\n cellAlignment?: EditorAlignment;\n columnWidths?: number[];\n },\n ): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n const idx = this.blockIndex(block);\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return;\n // If the caret is on an empty paragraph (not a table cell), insert the table BEFORE it so the\n // empty paragraph becomes the editable line BELOW the table \u2014 no stray blank line above it, and\n // a reachable paragraph below (S-1 smoke-test findings 2 + 4). Otherwise insert after.\n const emptyHere =\n !block.closest(\"table\") && blockContentText(block).replace(/[\\s\u00A0]+/g, \"\").length === 0;\n const res = this.parseEdit(\n this.exports.DocxSessionBridge.InsertTable(\n this.handle,\n fullId,\n emptyHere ? \"before\" : \"after\",\n rows,\n cols,\n options ? JSON.stringify(options) : \"\",\n ),\n );\n if (!res.success) return;\n this.refreshAfter(block, idx, false);\n }\n\n // \u2500\u2500\u2500 Table row / column editing (active block must be inside a table cell) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Run a table-structure op on the active cell's canonical tc anchor and re-render. */\n private tableEdit(run: (cellAnchor: string) => string): void {\n const block = this.activeBlock;\n const cell = block?.closest<HTMLElement>(\"td, th\");\n if (this.closed || !block || !cell || !block.closest(\"table\")) return;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n const paragraphId = this.anchorIdOf(block);\n const cellId = this.anchorIdOf(cell);\n if (!paragraphId || !cellId) return;\n const idx = this.blockIndex(block);\n if (!this.syncBlock(block, paragraphId)) return; // flush uncommitted cell text first\n const res = this.parseEdit(run(cellId));\n if (!res.success) return;\n this.refreshAfter(block, idx, false);\n }\n\n /** Insert a row above/below the active cell's row. No-op outside a table. */\n insertTableRow(where: \"above\" | \"below\"): void {\n this.tableEdit((a) =>\n this.exports.DocxSessionBridge.InsertTableRow(this.handle, a, where === \"above\" ? \"before\" : \"after\"),\n );\n }\n\n /** Insert a column left/right of the active cell's column. No-op outside a table. */\n insertTableColumn(where: \"left\" | \"right\"): void {\n this.tableEdit((a) =>\n this.exports.DocxSessionBridge.InsertTableColumn(this.handle, a, where === \"left\" ? \"before\" : \"after\"),\n );\n }\n\n /** Delete the active cell's row (deleting the last row removes the table). No-op outside a table. */\n deleteTableRow(): void {\n this.tableEdit((a) => this.exports.DocxSessionBridge.DeleteTableRow(this.handle, a));\n }\n\n /** Delete the active cell's column (deleting the last column removes the table). No-op outside a table. */\n deleteTableColumn(): void {\n this.tableEdit((a) => this.exports.DocxSessionBridge.DeleteTableColumn(this.handle, a));\n }\n\n /**\n * Indent/outdent the active block. On a LIST item this changes the list NESTING LEVEL\n * (`SetListLevel`) so numbering nests (e.g. 1, 2 \u2192 a sub-level) rather than the item just\n * shifting sideways with flat numbering. On a plain paragraph it adjusts the left indent by\n * `deltaTwips` (default \u00B1720 = 0.5\"), clamped at 0.\n */\n indent(deltaTwips = 720): void {\n if (this.activeBlock && isListBlock(this.activeBlock)) {\n this.setListLevel(deltaTwips >= 0 ? 1 : -1);\n return;\n }\n this.applyParagraphFormat({ indentDelta: deltaTwips });\n }\n\n /** Change the active list item's nesting level by `delta` (+1 deeper, \u22121 shallower). */\n private setListLevel(delta: number): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n const idx = this.blockIndex(block);\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return;\n const res = this.parseEdit(this.exports.DocxSessionBridge.SetListLevel(this.handle, fullId, delta));\n if (!res.success) return;\n // A level change ripples through the whole list's numbering \u2014 re-render with full document\n // context (sibling numbers shift without sibling XML changing), keeping the caret in place.\n this.refreshAfter(block, idx, false, /* forceRemount */ true);\n }\n\n /** Toggle (or set) page-break-before on the active block. */\n pageBreakBefore(value = true): void {\n this.applyParagraphFormat({ pageBreakBefore: value });\n }\n\n /**\n * Toggle the active block between a bullet/numbered list item and a plain paragraph.\n * Clicking the same kind it already is removes the list; any other state applies the kind.\n */\n toggleList(kind: \"bullet\" | \"decimal\"): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n\n let membership: { format?: string } | null = null;\n try {\n membership = JSON.parse(this.exports.DocxSessionBridge.GetListMembership(this.handle, fullId));\n } catch { /* treat as not-a-list */ }\n const isThisKind =\n !!membership && typeof membership.format === \"string\" &&\n membership.format.toLowerCase().startsWith(kind === \"bullet\" ? \"bullet\" : \"decimal\");\n\n const idx = this.blockIndex(block); // capture before the op\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return;\n const res = this.parseEdit(\n this.exports.DocxSessionBridge.ApplyListFormat(this.handle, fullId, isThisKind ? \"none\" : kind),\n );\n if (!res.success) return;\n // Numbering continuation across the list needs whole-document context \u2014 re-render fully\n // (sibling numbers shift without sibling XML changing).\n this.refreshAfter(block, idx, false, /* forceRemount */ true);\n }\n\n /** Clear all paragraph borders (e.g. remove an inserted horizontal rule) on the active block \u2014\n * or every block in a multi-block selection. The engine/wire already accept `clearBorders`;\n * this surfaces it on the editor so an HR border is removable (S-1 smoke-test finding 1b). */\n clearParagraphBorders(): void {\n this.applyParagraphFormat({ clearBorders: true });\n }\n\n /**\n * Delete the active block (e.g. a stray empty paragraph left above/below a table). Routes\n * through DocxSession `DeleteBlock` + re-render, focusing the previous block. No-op when the\n * caret is inside a table (remove cells via the table toolbar's delete row/column instead) and\n * no-op when it is the only editable block (don't empty the document). Closes the S-1\n * smoke-test \"no block-delete affordance\" gap.\n */\n deleteBlock(): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n if (block.closest(\"table\")) return; // cells are removed via the table toolbar, not here\n if (this.editableList().length <= 1) return; // never delete the last editable block\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n const fullId = this.anchorIdOf(block);\n if (!fullId) return;\n const idx = this.blockIndex(block);\n const res = this.parseEdit(this.exports.DocxSessionBridge.DeleteBlock(this.handle, fullId));\n if (!res.success) return;\n this.refreshAfter(block, Math.max(0, idx - 1), true);\n }\n\n /**\n * Cite a new footnote from the caret position in the active body block. The note definition is\n * created (writing the whole Word scaffold \u2014 part, reserved separator notes, settings\n * declaration, styles \u2014 on a document that has none yet) and its body renders as ordinary\n * editable `data-anchor` blocks in the notes section, so editing it afterwards needs no new op.\n *\n * Body blocks only: Word disallows a note reference inside a header/footer story or inside\n * another note, and the session rejects those with `AnchorWrongKind`. Reconciliation creates\n * the first notes section when needed and renumbers every affected citation in place.\n */\n insertFootnote(markdown = \"New footnote.\"): void {\n this.insertNote(\"footnote\", markdown);\n }\n\n /** Cite a new endnote from the caret \u2014 see {@link insertFootnote}; writes the endnotes part. */\n insertEndnote(markdown = \"New endnote.\"): void {\n this.insertNote(\"endnote\", markdown);\n }\n\n private insertNote(kind: \"footnote\" | \"endnote\", markdown: string): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n // A note reference is legal only in the main story: not in a header/footer band, and not\n // inside an existing note's body (both render as editable blocks here).\n if (this.isBandBlock(block) || block.closest(\".footnotes, .endnotes\")) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n const idx = this.blockIndex(block);\n // Offset first: syncBlock re-renders the block and would drop the live selection.\n const raw = caretOffsetIn(block);\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return;\n const offset = trimmedSplitOffset(block, raw ?? (block.textContent ?? \"\").length);\n const bridge = this.exports.DocxSessionBridge;\n const call = kind === \"footnote\" ? bridge.InsertFootnote : bridge.InsertEndnote;\n if (!call) return; // bridge predates note authoring\n const res = this.parseEdit(call.call(bridge, this.handle, fullId, offset, markdown));\n if (!res.success) return;\n this.reconcile(idx, false);\n }\n\n /**\n * Add a native Word comment on the current selection in the active block \u2014 or on the whole\n * block when the selection is collapsed (a null span comments the paragraph). The definition,\n * threading parts, and body-side range markers are written by the session's `AddComment`\n * (issue #300); the re-render shows the marker chrome the converter already draws. The\n * annotation type legal review runs on, finally authorable from the shipped surface\n * (issue #580).\n */\n addComment(\n markdown = \"New comment.\",\n author = this.options.commentAuthor,\n target?: CommentTarget,\n ): CommentListEntry | null {\n let block = target?.block.isConnected ? target.block : this.activeBlock;\n let span = target ? target.span : null;\n if (target && !target.block.isConnected) {\n // The draft's block was swapped since it was captured \u2014 the click that posts a draft\n // blurs and commits the paragraph. Find the same paragraph by anchor rather than taking\n // whatever block is active now, and keep the span only while the text it was measured\n // on is unchanged; otherwise comment the whole paragraph rather than the wrong characters.\n const live = target.anchor === undefined ? null : this.blockByAnchor(target.anchor);\n if (live) block = live;\n if (!live || target.text === undefined || blockContentText(live) !== target.text) span = null;\n }\n if (this.closed || !block) return null;\n const bridge = this.exports.DocxSessionBridge;\n if (!bridge.AddComment) return null; // bridge predates comment authoring\n let fullId = this.anchorIdOf(block);\n if (!fullId) return null;\n const idx = this.blockIndex(block);\n // Span first: syncBlock re-renders the block and would drop the live selection. A target\n // captured earlier (the gutter's draft bubble) wins over whatever the selection is now.\n if (!target) span = selectionSpanIn(block);\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return null;\n const res = this.parseEdit(\n bridge.AddComment(\n this.handle, fullId, span ? JSON.stringify(span) : \"\", author, \"\", \"\", markdown,\n ),\n );\n if (!res.success) return null;\n const created = res.created?.find((a) => a.kind === \"cmt\")?.id ?? null;\n // Comment markup lands inside the host paragraph, so it re-renders like any text edit; the\n // gutter then picks the new highlight up on its next layout.\n if (this.isBandBlock(block)) this.refreshAfter(block, idx, false);\n else this.reconcile(idx, false);\n const entry = created ? this.listComments().find((c) => c.anchorId === created) ?? null : null;\n return entry;\n }\n\n /** Reply to a thread root (or any comment) as a native Word reply (`commentsExtended`). */\n addCommentReply(parentAnchorId: string, markdown: string, author = this.options.commentAuthor): boolean {\n if (this.closed) return false;\n const bridge = this.exports.DocxSessionBridge;\n if (!bridge.AddCommentReply) return false;\n const res = this.parseEdit(\n bridge.AddCommentReply(this.handle, parentAnchorId, author, \"\", \"\", markdown),\n );\n if (!res.success) return false;\n // A reply adds a reference run beside the parent's, so the host paragraph re-renders.\n this.reconcile();\n return true;\n }\n\n /** Replace a comment's body text; author/date are preserved. */\n updateComment(commentAnchorId: string, markdown: string): boolean {\n if (this.closed) return false;\n const bridge = this.exports.DocxSessionBridge;\n if (!bridge.UpdateComment) return false;\n return this.parseEdit(bridge.UpdateComment(this.handle, commentAnchorId, markdown)).success;\n }\n\n /** Delete a comment: the definition and its range markers everywhere. */\n removeComment(commentAnchorId: string): boolean {\n if (this.closed) return false;\n const bridge = this.exports.DocxSessionBridge;\n if (!bridge.RemoveComment) return false;\n const res = this.parseEdit(bridge.RemoveComment(this.handle, commentAnchorId));\n if (!res.success) return false;\n this.reconcile();\n return true;\n }\n\n /** What \"New comment\" would comment on right now: the active block and the selection in it. */\n commentTarget(): CommentTarget | null {\n const block = this.activeBlock;\n if (this.closed || !block || !block.isConnected) return null;\n let span = selectionSpanIn(block);\n const unid = block.getAttribute(\"data-anchor\");\n if (!span && this.lastSelection && this.lastSelection.unid === unid) span = this.lastSelection.span;\n return { block, span, anchor: this.anchorIdOf(block), text: blockContentText(block) };\n }\n\n /** The live block for a full anchor id, or null when no mounted block resolves to it. */\n private blockByAnchor(anchor: string): HTMLElement | null {\n for (const el of Array.from(this.container.querySelectorAll<HTMLElement>(\"[data-anchor]\"))) {\n if (this.anchorIdOf(el) === anchor) return el;\n }\n return null;\n }\n\n /** Open a draft comment bubble beside the selection (Word's \"New Comment\"). */\n beginComment(): boolean {\n return this.gutter?.beginDraft() ?? false;\n }\n\n cancelComment(): void {\n this.gutter?.cancelDraft();\n }\n\n /** Activate a thread by `cmt` anchor id or numeric comment id (null clears). */\n activateComment(id: string | null): void {\n this.gutter?.setActive(id, { scrollBubble: true, scrollAnchor: true });\n }\n\n /** Step to the next (+1) / previous (\u22121) thread in document order. */\n stepComment(direction: 1 | -1): CommentListEntry | null {\n return this.gutter?.step(direction) ?? null;\n }\n\n /** The active thread root's anchor id, or null. */\n get activeComment(): string | null {\n return this.gutter?.active ?? null;\n }\n\n /** Show or hide the comment gutter (the markup stays in the document). */\n showComments(visible: boolean): void {\n this.gutter?.setVisible(visible);\n }\n\n get commentsVisible(): boolean {\n return this.gutter?.isVisible ?? false;\n }\n\n /** Force the gutter to lay out now (tests). */\n layoutComments(): void {\n this.gutter?.layout();\n }\n\n /** The document's native comment threads (session truth), for review UIs \u2014 flat entries\n * with `parentAnchorId` linking replies and `resolved` carrying thread state. */\n listComments(): CommentListEntry[] {\n if (this.closed) return [];\n const bridge = this.exports.DocxSessionBridge;\n if (!bridge.ListComments) return [];\n try {\n return JSON.parse(bridge.ListComments(this.handle)) as CommentListEntry[];\n } catch {\n return [];\n }\n }\n\n /** Resolve or reopen a comment thread by its `cmt` anchor id (from {@link listComments}).\n * Resolution is thread metadata (`commentsExtended`), not body markup, so no re-render is\n * needed \u2014 a review UI re-reads {@link listComments} for the new state. */\n setCommentResolved(commentAnchorId: string, resolved: boolean): boolean {\n if (this.closed) return false;\n const bridge = this.exports.DocxSessionBridge;\n if (!bridge.SetCommentResolved) return false;\n return this.parseEdit(bridge.SetCommentResolved(this.handle, commentAnchorId, resolved)).success;\n }\n\n private applyParagraphFormat(op: {\n alignment?: EditorAlignment;\n indentDelta?: number;\n firstLineIndent?: number;\n hangingIndent?: number;\n spacingBefore?: number;\n spacingAfter?: number;\n lineSpacing?: number;\n lineSpacingRule?: \"auto\" | \"exact\" | \"atLeast\";\n pageBreakBefore?: boolean;\n clearBorders?: boolean;\n }): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n const blocks = this.selectedBlocks();\n if (\n blocks.length > 1 &&\n this.applyParagraphOpAcrossBlocks(\n blocks,\n (id) => this.exports.DocxSessionBridge.SetParagraphFormat(this.handle, id, JSON.stringify(op)),\n // A border change regroups the wrapping border <div>s \u2014 whole-document context.\n !!op.clearBorders,\n )\n )\n return;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n const idx = this.blockIndex(block);\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return;\n const res = this.parseEdit(\n this.exports.DocxSessionBridge.SetParagraphFormat(this.handle, fullId, JSON.stringify(op)),\n );\n if (!res.success) return;\n // A border change adds/removes the wrapping border <div>, so a single-block swap can't restructure\n // it correctly \u2014 re-render fully (like list edits) so the wrapper appears/disappears cleanly.\n if (this.affectsList(res) || op.clearBorders) { this.refreshAfter(block, idx, false, true); return; }\n this.swapBlock(block, unid, res.modified?.[0])?.focus();\n }\n\n /** Set the paragraph style of the active block \u2014 or of every block in a multi-block selection\n * (e.g. \"Heading1\", \"Heading2\", \"Normal\"). */\n setParagraphStyle(styleId: string): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n const blocks = this.selectedBlocks();\n if (\n blocks.length > 1 &&\n this.applyParagraphOpAcrossBlocks(blocks, (id) =>\n this.exports.DocxSessionBridge.SetParagraphStyle(this.handle, id, styleId),\n )\n )\n return;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n const idx = this.blockIndex(block);\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return;\n const res = this.parseEdit(this.exports.DocxSessionBridge.SetParagraphStyle(this.handle, fullId, styleId));\n if (!res.success) return;\n if (this.affectsList(res)) { this.refreshAfter(block, idx, false, true); return; }\n this.swapBlock(block, unid, res.modified?.[0])?.focus();\n }\n\n /** Undo the last edit (incremental repaint; falls back to a full re-render). */\n undo(): void {\n if (this.closed) return;\n if (!this.exports.DocxSessionBridge.Undo(this.handle)) return;\n this.invalidateBlockMoveTargets();\n this.reconcile();\n }\n\n /** Redo the last undone edit (incremental repaint; falls back to a full re-render). */\n redo(): void {\n if (this.closed) return;\n if (!this.exports.DocxSessionBridge.Redo(this.handle)) return;\n this.invalidateBlockMoveTargets();\n this.reconcile();\n }\n\n // \u2500\u2500\u2500 Header/footer region commands (no-ops unless `headerFooter` is on) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Select which story kind a band edits (`\"default\"` / `\"first\"` / `\"even\"`). A kind with no\n * existing part is created empty, so the band always presents something editable. `\"first\"`\n * sets the section's `w:titlePg`; `\"even\"` sets the document-global `w:evenAndOddHeaders`\n * (which also governs footers \u2014 the band surfaces that caveat inline).\n */\n setHeaderFooterKind(which: BandWhich, kind: HeaderFooterKind): void {\n this.assertOpen();\n this.region?.setKind(which, kind);\n }\n\n /** The story kind a band is currently editing, or null when the region is off. */\n headerFooterKind(which: BandWhich): HeaderFooterKind | null {\n return this.region?.kindOf(which) ?? null;\n }\n\n /**\n * Append a page-number field to the focused header/footer story paragraph (falling back to the\n * band's last paragraph \u2014 Word's convention). No-op outside a band.\n */\n insertPageNumber(field: \"currentPage\" | \"totalPages\" | \"pageOfTotal\" = \"currentPage\"): void {\n this.assertOpen();\n if (!this.region) return;\n const block = this.activeBlock;\n const band = block ? this.region.bandOf(block) : null;\n const anchorId = block?.getAttribute(\"data-hf-anchor\");\n if (block && band && anchorId) {\n // Flush uncommitted typing first: the field appends to the SESSION paragraph, and the\n // story repaint that follows would otherwise blur-commit stale DOM text over it.\n const synced = this.syncBlock(block, anchorId);\n if (!synced) return;\n this.region.insertPageNumber(this.region.whichOf(band), synced, field);\n return;\n }\n // No band block focused \u2014 target the footer, where page numbers overwhelmingly live.\n this.region.insertPageNumberInBand(\"footer\", field);\n }\n\n /**\n * Set the page numbering of the section the bands describe (`w:pgNumType`) \u2014 Word's *Format Page\n * Numbers\u2026*: `start` restarts numbering at that number, `format` chooses `1, 2, 3` vs\n * `i, ii, iii` etc. Omitted fields are left unchanged. Requires the header/footer region\n * (`{ headerFooter: true }`); a no-op otherwise.\n *\n * Inserted page-number fields are plain, so they render through this. The editor's own view still\n * shows each field's cached result \u2014 Word recomputes on open \u2014 but `{ paginated: true }`\n * substitutes the real per-page number and so reflects the change immediately.\n */\n setPageNumbering(op: { start?: number; format?: NumberFormat }): void {\n this.assertOpen();\n this.region?.setPageNumbering(op);\n }\n\n /** Remove the section's page-numbering start/format: it reverts to continuing the previous\n * section's numbering in Word's default `1, 2, 3`. */\n clearPageNumbering(): void {\n this.assertOpen();\n this.region?.clearPageNumbering();\n }\n\n /** This section's page numbering as the document currently states it \u2014 `{}` when the section\n * sets neither (it continues the previous section in the default format). */\n pageNumbering(): { start?: number; format?: NumberFormat } {\n return this.region?.pageNumbering() ?? {};\n }\n\n // \u2500\u2500\u2500 Font group \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Apply one inline `FormatOp` to the selection: a sub-range of the active block, the whole\n * block when the caret is collapsed, or every block of a multi-block selection. The last real\n * selection is used when a focus-stealing control (a colour picker) collapsed the live one.\n */\n private applyInlineFormat(op: Record<string, unknown>): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n const blocks = this.selectedBlocks();\n if (blocks.length > 1 && this.applyInlineOpAcrossBlocks(blocks, op)) return;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n let span = selectionSpanIn(block);\n if (!span && this.lastSelection && this.lastSelection.unid === unid) span = this.lastSelection.span;\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return;\n const res = this.parseEdit(\n this.exports.DocxSessionBridge.ApplyFormat(\n this.handle, fullId, span ? JSON.stringify(span) : \"\", JSON.stringify(op),\n ),\n );\n if (!res.success) return;\n if (this.affectsList(res)) { this.refreshAfter(block, this.blockIndex(block), false); return; }\n const fresh = this.swapBlock(block, unid, res.modified?.[0]);\n if (fresh && span) selectRange(fresh, span.start, span.length);\n else fresh?.focus();\n }\n\n /** Font colour as a hex triplet (with or without '#'); `\"\"` clears the explicit colour. */\n setFontColor(hex: string): void {\n this.applyInlineFormat({ color: hex.replace(/^#/, \"\").toUpperCase() });\n }\n\n /** Word highlight colour name (`\"yellow\"`, `\"green\"`, \u2026); `\"\"` removes the highlight. */\n setHighlight(name: string): void {\n this.applyInlineFormat({ highlight: name });\n }\n\n setAllCaps(on: boolean): void {\n this.applyInlineFormat({ caps: on });\n }\n\n setSmallCaps(on: boolean): void {\n this.applyInlineFormat({ smallCaps: on });\n }\n\n /** Word's \"Clear All Formatting\": drop every direct run property on the selection. */\n clearFormatting(): void {\n this.applyInlineFormat({\n bold: false, italic: false, underline: false, strike: false, code: false, color: \"\",\n highlight: \"\", vertAlign: \"\", fontSizePts: 0, fontFamily: \"\", runStyle: \"\",\n caps: false, smallCaps: false,\n });\n }\n\n /** The caret's rendered font size in points (from computed style), or null. */\n fontSizeAtCaret(): number | null {\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n let el: HTMLElement | null = this.activeBlock;\n if (sel && sel.rangeCount > 0) {\n const n = sel.getRangeAt(0).startContainer;\n const candidate = n.nodeType === 3 ? n.parentElement : (n as HTMLElement);\n if (candidate && this.container.contains(candidate)) el = candidate;\n }\n if (!el || typeof getComputedStyle !== \"function\") return null;\n const px = parseFloat(getComputedStyle(el).fontSize);\n return px > 0 ? Math.round(px * 0.75 * 2) / 2 : null;\n }\n\n /** Grow (+) or shrink (\u2212) the selection's font size by `delta` points (Word's A\u2191 / A\u2193). */\n adjustFontSize(delta: number): void {\n const size = this.fontSizeAtCaret();\n if (size == null) return;\n this.setFontSize(Math.max(1, Math.round((size + delta) * 2) / 2));\n }\n\n // \u2500\u2500\u2500 Paragraph group \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Line spacing as a multiple of single (1, 1.15, 1.5, 2 \u2026) \u2014 `w:spacing/@w:line` under `auto`. */\n setLineSpacing(multiple: number): void {\n this.applyParagraphFormat({ lineSpacing: Math.round(multiple * 240), lineSpacingRule: \"auto\" });\n }\n\n /** Space before/after the paragraph, in POINTS (Word's Paragraph dialog units). */\n setParagraphSpacing(op: { beforePt?: number; afterPt?: number }): void {\n const payload: { spacingBefore?: number; spacingAfter?: number } = {};\n if (op.beforePt != null) payload.spacingBefore = Math.max(0, Math.round(op.beforePt * 20));\n if (op.afterPt != null) payload.spacingAfter = Math.max(0, Math.round(op.afterPt * 20));\n if (Object.keys(payload).length === 0) return;\n this.applyParagraphFormat(payload);\n }\n\n /** First-line indent in twips (0 = none); removes any hanging indent. */\n setFirstLineIndent(twips: number): void {\n this.applyParagraphFormat({ firstLineIndent: Math.max(0, twips) });\n }\n\n /** Hanging indent in twips (0 = none); removes any first-line indent. */\n setHangingIndent(twips: number): void {\n this.applyParagraphFormat({ hangingIndent: Math.max(0, twips) });\n }\n\n /**\n * Make the active block (or every selected block) a list item of `kind` \u2014 the full Word\n * numbering gallery, not just bullets/decimal \u2014 or a plain paragraph with `\"none\"`.\n */\n setListFormat(kind: ListFormat): void {\n const block = this.activeBlock;\n if (this.closed || !block) return;\n const blocks = this.selectedBlocks();\n if (\n blocks.length > 1 &&\n this.applyParagraphOpAcrossBlocks(\n blocks,\n (id) => this.exports.DocxSessionBridge.ApplyListFormat(this.handle, id, kind),\n true,\n )\n )\n return;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return;\n const idx = this.blockIndex(block);\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return;\n const res = this.parseEdit(this.exports.DocxSessionBridge.ApplyListFormat(this.handle, fullId, kind));\n if (!res.success) return;\n this.refreshAfter(block, idx, false, /* forceRemount */ true);\n }\n\n /** The active block's list format (`\"bullet\"`, `\"decimal\"`, \u2026), or null when it is not a list item. */\n listFormatAtCaret(): string | null {\n const block = this.activeBlock;\n if (this.closed || !block || !isListBlock(block)) return null;\n const fullId = this.anchorIdOf(block);\n if (!fullId) return null;\n try {\n const membership = JSON.parse(this.exports.DocxSessionBridge.GetListMembership(this.handle, fullId)) as { format?: string } | null;\n return membership?.format ?? null;\n } catch {\n return null;\n }\n }\n\n /** Paragraph formatting (direct + effective) of the active block, for ribbon state. */\n paragraphFormatting(): FormattingInspection | null {\n const block = this.activeBlock;\n const bridge = this.exports.DocxSessionBridge;\n if (this.closed || !block || typeof bridge.GetFormatting !== \"function\") return null;\n const fullId = this.anchorIdOf(block);\n if (!fullId) return null;\n try {\n const parsed = JSON.parse(bridge.GetFormatting(this.handle, fullId)) as FormattingInspection | null;\n return parsed && typeof parsed === \"object\" && \"effectiveParagraph\" in parsed ? parsed : null;\n } catch {\n return null;\n }\n }\n\n // \u2500\u2500\u2500 Links, images, references \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Wrap the selection in a hyperlink (external URL, or an internal bookmark name). */\n insertHyperlink(target: string, kind: \"external\" | \"internal\" = \"external\"): boolean {\n const block = this.activeBlock;\n const bridge = this.exports.DocxSessionBridge;\n if (this.closed || !block || typeof bridge.AddHyperlink !== \"function\") return false;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return false;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return false;\n let span = selectionSpanIn(block);\n if (!span && this.lastSelection && this.lastSelection.unid === unid) span = this.lastSelection.span;\n if (!span) return false; // Word needs a range to link\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return false;\n const res = this.parseEdit(\n bridge.AddHyperlink(this.handle, fullId, span.start, span.length, kind, target),\n );\n if (!res.success) return false;\n const fresh = this.swapBlock(block, unid, res.modified?.[0]);\n if (fresh) selectRange(fresh, span.start, span.length);\n return true;\n }\n\n /** The hyperlink the caret (or selection start) sits in, or null. */\n hyperlinkAtCaret(): HyperlinkInfo | null {\n const block = this.activeBlock;\n const bridge = this.exports.DocxSessionBridge;\n if (this.closed || !block || typeof bridge.ListHyperlinks !== \"function\") return null;\n const fullId = this.anchorIdOf(block);\n if (!fullId) return null;\n const sel = typeof window !== \"undefined\" ? window.getSelection() : null;\n let offset = 0;\n if (sel && sel.rangeCount > 0 && block.contains(sel.getRangeAt(0).startContainer)) {\n const r = sel.getRangeAt(0);\n offset = contentOffsetOf(block, r.startContainer, r.startOffset);\n }\n try {\n const links = JSON.parse(bridge.ListHyperlinks(this.handle, 63)) as HyperlinkInfo[];\n return (\n links.find(\n (l) => l.anchorId === fullId && offset >= l.span.start && offset <= l.span.start + l.span.length,\n ) ?? null\n );\n } catch {\n return null;\n }\n }\n\n /** Remove the hyperlink at the caret, keeping its text. */\n removeHyperlink(): boolean {\n const link = this.hyperlinkAtCaret();\n const bridge = this.exports.DocxSessionBridge;\n const block = this.activeBlock;\n if (!link || !block || typeof bridge.RemoveHyperlink !== \"function\") return false;\n const unid = block.getAttribute(\"data-anchor\");\n const res = this.parseEdit(bridge.RemoveHyperlink(this.handle, link.id));\n if (!res.success) return false;\n if (unid) this.swapBlock(block, unid, res.modified?.[0]);\n return true;\n }\n\n /** Insert an inline image (base64 bytes) at the caret in the active body block. */\n insertImage(imageBase64: string, options: ImageInsertOptions = {}): boolean {\n const block = this.activeBlock;\n const bridge = this.exports.DocxSessionBridge;\n if (this.closed || !block || typeof bridge.InsertImage !== \"function\") return false;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return false;\n const idx = this.blockIndex(block);\n const raw = caretOffsetIn(block);\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return false;\n const offset = trimmedSplitOffset(block, raw ?? (block.textContent ?? \"\").length);\n const res = this.parseEdit(\n bridge.InsertImage(this.handle, fullId, offset, imageBase64, JSON.stringify(options)),\n );\n if (!res.success) return false;\n // Image parts are not in the block-render shell, so a single-block swap would drop the\n // picture; the full render is the only path that shows it.\n this.refreshAfter(block, idx, true, /* forceRemount */ true);\n return true;\n }\n\n /** Read a picked file and insert it as an inline image. */\n async insertImageFile(file: Blob, options: ImageInsertOptions = {}): Promise<boolean> {\n const bytes = new Uint8Array(await file.arrayBuffer());\n let binary = \"\";\n const chunk = 0x8000;\n for (let i = 0; i < bytes.length; i += chunk) {\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk));\n }\n return this.insertImage(btoa(binary), options);\n }\n\n /** Insert a table of contents (a real TOC field) before the active block. */\n insertTableOfContents(options: TableOfContentsOptions = {}): boolean {\n const block = this.activeBlock;\n const bridge = this.exports.DocxSessionBridge;\n if (this.closed || !block || typeof bridge.InsertTableOfContents !== \"function\") return false;\n if (this.isBandBlock(block) || block.closest(\"table, .footnotes, .endnotes\")) return false;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return false;\n const idx = this.blockIndex(block);\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return false;\n const res = this.parseEdit(\n bridge.InsertTableOfContents(this.handle, fullId, \"before\", JSON.stringify(options)),\n );\n if (!res.success) return false;\n this.refreshAfter(block, idx, false, /* forceRemount */ true);\n return true;\n }\n\n // \u2500\u2500\u2500 Table group (extended) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Merge the active cell with `rowSpan`\u00D7`colSpan` neighbours (down and right). */\n mergeCells(rowSpan: number, colSpan: number): void {\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.MergeCells !== \"function\") return;\n this.tableEdit((a) => bridge.MergeCells!(this.handle, a, rowSpan, colSpan, \"\"));\n }\n\n /** Split a merged cell back into its grid cells. */\n unmergeCells(): void {\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.UnmergeCells !== \"function\") return;\n this.tableEdit((a) => bridge.UnmergeCells!(this.handle, a));\n }\n\n /** Set (or with `style: \"none\"` remove) the borders of the active cell's table. */\n setTableBorders(spec: TableBorderSpec): void {\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.SetTableBorders !== \"function\") return;\n this.tableEdit((a) => bridge.SetTableBorders!(this.handle, a, JSON.stringify(spec)));\n }\n\n /** Shade the active cell (or its row/column/table) with a hex fill; `\"\"` clears. */\n setCellShading(fill: string, scope: \"cell\" | \"row\" | \"column\" | \"table\" = \"cell\"): void {\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.SetCellShading !== \"function\") return;\n this.tableEdit((a) => bridge.SetCellShading!(this.handle, a, fill.replace(/^#/, \"\"), scope));\n }\n\n /** Repeat the active cell's row at the top of every page the table spans. */\n setRepeatHeaderRow(repeat: boolean): void {\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.SetRepeatHeaderRow !== \"function\") return;\n this.tableEdit((a) => bridge.SetRepeatHeaderRow!(this.handle, a, repeat));\n }\n\n /** Delete the whole table the caret is in. */\n deleteTable(): void {\n const block = this.activeBlock;\n const table = block?.closest<HTMLElement>(\"table\");\n if (this.closed || !block || !table) return;\n const tableId = this.anchorIdOf(table);\n if (!tableId) return;\n const idx = this.blockIndex(block);\n const res = this.parseEdit(this.exports.DocxSessionBridge.DeleteBlock(this.handle, tableId));\n if (!res.success) return;\n this.refreshAfter(block, Math.max(0, idx - 1), true);\n }\n\n // \u2500\u2500\u2500 Review group \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** How edits are being recorded right now. */\n get trackedChanges(): TrackedChangeMode {\n return this.options.trackedChanges;\n }\n\n /**\n * Switch tracked-changes mode mid-session (Word's \"Track Changes\" toggle). Undo history and\n * edits survive; the document re-renders so revisions show (or stop showing) inline.\n */\n setTrackedChanges(mode: TrackedChangeMode): void {\n this.assertOpen();\n if (this.options.trackedChanges === mode) return;\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.SetTrackedChanges !== \"function\") return;\n bridge.SetTrackedChanges(this.handle, mode);\n this.options.trackedChanges = mode;\n this.remount();\n }\n\n setRevisionAuthor(author: string): void {\n this.assertOpen();\n this.options.revisionAuthor = author;\n this.exports.DocxSessionBridge.SetRevisionAuthor?.(this.handle, author);\n }\n\n /** Every tracked revision in the document, from the session's registry. */\n listRevisions(): RevisionListEntry[] {\n const bridge = this.exports.DocxSessionBridge;\n if (this.closed || typeof bridge.ListRevisions !== \"function\") return [];\n try {\n const parsed = JSON.parse(bridge.ListRevisions(this.handle)) as RevisionListEntry[] | { error?: string };\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n }\n\n acceptRevision(revisionId: string): boolean {\n return this.resolveRevision(\"AcceptRevision\", revisionId);\n }\n\n rejectRevision(revisionId: string): boolean {\n return this.resolveRevision(\"RejectRevision\", revisionId);\n }\n\n acceptAllRevisions(): boolean {\n return this.resolveRevision(\"AcceptAllRevisions\");\n }\n\n rejectAllRevisions(): boolean {\n return this.resolveRevision(\"RejectAllRevisions\");\n }\n\n private resolveRevision(\n op: \"AcceptRevision\" | \"RejectRevision\" | \"AcceptAllRevisions\" | \"RejectAllRevisions\",\n revisionId?: string,\n ): boolean {\n const bridge = this.exports.DocxSessionBridge;\n if (this.closed) return false;\n const idx = this.activeBlock ? this.blockIndex(this.activeBlock) : -1;\n let json: string;\n if (op === \"AcceptRevision\" || op === \"RejectRevision\") {\n const fn = bridge[op];\n if (typeof fn !== \"function\" || !revisionId) return false;\n json = fn(this.handle, revisionId);\n } else {\n const fn = bridge[op];\n if (typeof fn !== \"function\") return false;\n json = fn(this.handle);\n }\n const res = this.parseEdit(json);\n if (!res.success) return false;\n // Resolution rewrites markup across the document; the reconciler proves what it can.\n this.reconcile(idx, false);\n return true;\n }\n\n /** Rendered revision marks in document order \u2014 what Previous/Next step through. */\n revisionElements(): HTMLElement[] {\n return Array.from(\n this.container.querySelectorAll<HTMLElement>(\n 'ins[class*=\"-ins\"], del[class*=\"-del\"], ins[class*=\"move-to\"], del[class*=\"move-from\"], ' +\n 'tr[class*=\"row-ins\"], tr[class*=\"row-del\"]',\n ),\n ).filter((el) => !el.closest(\"#pagination-staging, .docx-comment-gutter\"));\n }\n\n /** The registry entry a rendered revision mark belongs to (matched by block, then by text). */\n revisionAt(el: HTMLElement): RevisionListEntry | null {\n const block = el.closest<HTMLElement>(\"[data-anchor]\");\n const unid = block?.getAttribute(\"data-anchor\");\n const candidates = this.listRevisions().filter((r) => r.resolutionStatus === \"supported\");\n if (!unid) return candidates[0] ?? null;\n const inBlock = candidates.filter(\n (r) => r.anchorId?.endsWith(unid) || r.affectedAnchors?.some((a) => a.unid === unid),\n );\n if (inBlock.length === 0) return null;\n const text = (el.textContent ?? \"\").trim();\n return inBlock.find((r) => text && r.text.trim() === text) ?? inBlock[0];\n }\n\n // \u2500\u2500\u2500 Find & replace \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Every occurrence of `query` in the editable blocks, in document order. */\n find(query: string, options: { matchCase?: boolean } = {}): EditorMatch[] {\n if (!query) return [];\n const needle = options.matchCase ? query : query.toLowerCase();\n const blocks = this.editableList().concat(\n Array.from(this.container.querySelectorAll<HTMLElement>('[data-hf-band] [data-anchor][contenteditable=\"true\"]')),\n );\n const out: EditorMatch[] = [];\n for (const block of blocks) {\n const text = blockContentText(block);\n const hay = options.matchCase ? text : text.toLowerCase();\n let from = 0;\n for (;;) {\n const at = hay.indexOf(needle, from);\n if (at < 0) break;\n out.push({ block, start: at, length: query.length });\n from = at + Math.max(1, query.length);\n }\n }\n return out;\n }\n\n /**\n * Select a match, focus its block and scroll it into view \u2014 the caret lands on the hit, so\n * typing continues in the document. A find box that is still being typed into wants\n * `showFindMatches` instead; this is the commit step (closing the bar, jumping in to edit).\n */\n selectMatch(match: EditorMatch): void {\n if (!match.block.isConnected) return;\n this.clearFindMatches();\n this.activeBlock = match.block;\n selectRange(match.block, match.start, match.length);\n match.block.scrollIntoView({ block: \"center\", behavior: \"smooth\" });\n }\n\n /**\n * Paint `matches` and scroll the one at `activeIndex` into view WITHOUT moving focus or the\n * caret. This is what a find field calls on every keystroke: the document shows where the hits\n * are and rides to the current one, while the keyboard stays in the search box.\n *\n * Falls back to the document selection where the CSS Custom Highlight API is missing \u2014 still\n * without focusing the block, so the next character typed goes to the search field either way.\n */\n showFindMatches(matches: EditorMatch[], activeIndex: number): void {\n const active = matches[activeIndex];\n this.clearFindMatches();\n if (!active || !active.block.isConnected) return;\n this.activeBlock = active.block;\n const activeRange = contentRangeIn(active.block, active.start, active.length);\n const registry = highlightRegistry();\n if (registry && activeRange) {\n ensureFindHighlightStyles(this.container.ownerDocument);\n const rest: Range[] = [];\n for (let i = 0; i < matches.length && rest.length < FIND_PAINT_LIMIT; i++) {\n if (i === activeIndex) continue;\n const range = contentRangeIn(matches[i].block, matches[i].start, matches[i].length);\n if (range) rest.push(range);\n }\n if (rest.length > 0) registry.set(FIND_HIGHLIGHT, makeHighlight(rest));\n registry.set(FIND_HIGHLIGHT_ACTIVE, makeHighlight([activeRange]));\n findPaintOwner = this;\n } else if (activeRange) {\n // No highlight registry (older Firefox/Safari): the document selection is the only paint\n // available. It is not registry-owned, so `clearFindMatches` leaves it \u2014 the next\n // `showFindMatches` or the closing `selectMatch` overwrites it.\n const sel = this.container.ownerDocument.defaultView?.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(activeRange);\n }\n active.block.scrollIntoView({ block: \"center\", behavior: \"smooth\" });\n }\n\n /** Drop the find painting (closing the find bar, or committing a match to the caret). */\n clearFindMatches(): void {\n if (findPaintOwner !== this) return;\n const registry = highlightRegistry();\n registry?.delete(FIND_HIGHLIGHT);\n registry?.delete(FIND_HIGHLIGHT_ACTIVE);\n findPaintOwner = null;\n }\n\n /**\n * Replace one match's text (formatting of the surrounding run is inherited). `focus: false`\n * leaves the keyboard where it is \u2014 a Replace button pressed from the find bar must not drag\n * the caret into the document mid-search.\n */\n replaceMatch(\n match: EditorMatch,\n replacement: string,\n options: { focus?: boolean } = {},\n ): boolean {\n const block = match.block;\n if (this.closed || !block.isConnected) return false;\n const unid = block.getAttribute(\"data-anchor\");\n if (!unid) return false;\n let fullId = this.anchorIdOf(block);\n if (!fullId) return false;\n fullId = this.syncBlock(block, fullId);\n if (!fullId) return false;\n const span = trimmedSpan(block, { start: match.start, length: match.length });\n if (span.length === 0) return false;\n const res = this.parseEdit(\n this.exports.DocxSessionBridge.ReplaceTextAtSpan(\n this.handle, fullId, span.start, span.length, replacement,\n ),\n );\n if (!res.success) return false;\n const fresh = this.swapBlock(block, unid, res.modified?.[0]);\n if (fresh && options.focus !== false) selectRange(fresh, span.start, replacement.length);\n return true;\n }\n\n /** Replace every occurrence; returns how many were replaced. */\n replaceAll(\n query: string,\n replacement: string,\n options: { matchCase?: boolean; focus?: boolean } = {},\n ): number {\n if (this.closed || !query) return 0;\n const matches = this.find(query, options);\n let count = 0;\n // Group by block and replace from the END so earlier offsets stay valid.\n const byBlock = new Map<HTMLElement, EditorMatch[]>();\n for (const m of matches) {\n const list = byBlock.get(m.block) ?? [];\n list.push(m);\n byBlock.set(m.block, list);\n }\n for (const [block, list] of byBlock) {\n let current: HTMLElement = block;\n for (const m of list.slice().sort((a, b) => b.start - a.start)) {\n if (!current.isConnected) break;\n const before = current;\n if (this.replaceMatch(\n { block: current, start: m.start, length: m.length }, replacement, { focus: options.focus },\n )) {\n count++;\n // swapBlock replaced the node; keep following it.\n current = this.activeBlock && this.activeBlock !== before ? this.activeBlock : current;\n }\n }\n }\n return count;\n }\n\n // \u2500\u2500\u2500 View \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Set the author-pinned zoom (1 = 100%). Fit-to-width still caps it on narrow hosts. */\n setZoom(scale: number): void {\n this.assertOpen();\n this.viewport.setScale(scale);\n this.gutter?.schedule();\n }\n\n /** The zoom the user asked for (what a zoom control shows), before fit-to-width caps it. */\n get requestedZoom(): number {\n return this.viewport.requestedScale;\n }\n\n /** Word count over the body's editable text. */\n wordCount(): number {\n let count = 0;\n for (const block of this.editableList()) {\n // Notes are not body words in either view (the paginator's per-page note block carries\n // the \"page-footnotes\" class; the continuous view's sections are \".footnotes\"/\".endnotes\").\n if (block.closest('.footnotes, .endnotes, [class$=\"-footnotes\"], [class$=\"-endnotes\"]')) continue;\n const text = blockContentText(block);\n const words = text.match(/[\\p{L}\\p{N}][\\p{L}\\p{N}'\u2019.-]*/gu);\n count += words ? words.length : 0;\n }\n return count;\n }\n\n /** In page view, the active block's page and the page total; null in continuous view. */\n pageInfo(): { page: number; total: number } | null {\n if (!this.options.paginated) return null;\n const boxes = this.editRoot.querySelectorAll<HTMLElement>(\".page-box:not([data-section-filler])\");\n const total = boxes.length;\n const box = this.activeBlock?.closest<HTMLElement>(\".page-box\");\n const page = box ? parseInt(box.dataset.pageNumber || \"1\", 10) : 1;\n return { page, total };\n }\n\n // \u2500\u2500\u2500 Layout: section page setup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** The section governing the active block (or the first body block). */\n sectionInfo(): SectionInfo | null {\n if (this.closed) return null;\n const block =\n this.activeBlock && !this.isBandBlock(this.activeBlock) ? this.activeBlock : this.editableList()[0];\n const unid = block?.getAttribute(\"data-anchor\");\n const fullId = unid ? this.unidToFullId.get(unid) : undefined;\n if (!fullId) return null;\n try {\n const parsed = JSON.parse(this.exports.DocxSessionBridge.GetSectionInfo(this.handle, fullId)) as SectionInfo | null;\n return parsed && typeof parsed.sectionUnid === \"string\" ? parsed : null;\n } catch {\n return null;\n }\n }\n\n /** Word's Page Setup on the section holding the caret: size, orientation, margins. */\n setPageSetup(op: EditorPageSetup): boolean {\n this.assertOpen();\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.SetPageSetup !== \"function\") return false;\n const info = this.sectionInfo();\n if (!info) return false;\n const res = this.parseEdit(bridge.SetPageSetup(this.handle, info.anchorId, JSON.stringify(op)));\n if (!res.success) return false;\n // Geometry is whole-document context (sheet width, page boxes).\n this.remount(this.activeBlock ? this.blockIndex(this.activeBlock) : -1, false);\n return true;\n }\n\n // \u2500\u2500\u2500 Header & footer (extended) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Word's \"Different first page\" (`first`) / \"Different odd & even pages\" (`even`). */\n setHeaderFooterKindEnabled(kind: \"first\" | \"even\", enabled: boolean): boolean {\n this.assertOpen();\n return this.region?.setKindEnabled(kind, enabled) ?? false;\n }\n\n headerFooterKindEnabled(kind: \"first\" | \"even\"): boolean {\n return this.region?.kindEnabled(kind) ?? false;\n }\n\n /** \"First Page Header\", \"Footer\", \u2026 for the story a band (or the active page area) shows. */\n headerFooterStoryLabel(which: BandWhich): string {\n return this.region?.storyLabel(which) ?? (which === \"header\" ? \"Header\" : \"Footer\");\n }\n\n /** Put the caret in the header or footer (Word's \"Go to Header / Go to Footer\"). */\n goToHeaderFooter(which: BandWhich): boolean {\n this.assertOpen();\n return this.region?.focusStory(which, this.activeBlock) ?? false;\n }\n\n /** Leave the header/footer and put the caret back in the body. */\n closeHeaderFooter(): void {\n this.assertOpen();\n this.region?.close();\n const body = this.editableList();\n const target =\n this.activeBlock && !this.isBandBlock(this.activeBlock) && this.activeBlock.isConnected\n ? this.activeBlock\n : body[0];\n if (target) placeCaretAtOffset(target, 0);\n }\n\n /** Which story the caret is in, or null in the body. */\n get activeStoryKind(): BandWhich | null {\n return this.activeStory;\n }\n\n // \u2500\u2500\u2500 Introspection for chrome \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** The document's style definitions (for a styles gallery); empty on older bundles. */\n styles(): StyleInfo[] {\n const bridge = this.exports.DocxSessionBridge;\n if (this.closed || typeof bridge.ListStyles !== \"function\") return [];\n try {\n const parsed = JSON.parse(bridge.ListStyles(this.handle)) as StyleInfo[] | { error?: string };\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n }\n\n /** The active block's paragraph style id (from the render), or null. */\n styleAtCaret(): string | null {\n const info = this.paragraphFormatting();\n return info?.effectiveParagraph.styleId ?? info?.directParagraph.styleId ?? null;\n }\n\n /** Which inline formats the current selection carries \u2014 for ribbon button highlighting. */\n queryFormatState(): Record<FormatKey, boolean> {\n const block = this.activeBlock ?? this.editRoot;\n return {\n bold: selectionHasFormat(\"bold\", block),\n italic: selectionHasFormat(\"italic\", block),\n underline: selectionHasFormat(\"underline\", block),\n strike: selectionHasFormat(\"strike\", block),\n code: selectionHasFormat(\"code\", block),\n superscript: selectionHasFormat(\"superscript\", block),\n subscript: selectionHasFormat(\"subscript\", block),\n };\n }\n\n /** Re-render one block from the live session by EditResult ref, swapping it in place. */\n private swapBlock(oldEl: HTMLElement, oldUnid: string, ref?: AnchorRef): HTMLElement | null {\n const inBand = this.isBandBlock(oldEl);\n const anchorId = ref?.id ?? this.anchorIdOf(oldEl);\n const newUnid = ref?.unid ?? oldUnid;\n if (!anchorId) return null;\n const fresh = this.renderInto(anchorId);\n if (!fresh || !this.replaceNode(oldEl, fresh)) return null;\n // A band block resolves through its stamped `data-hf-anchor`, never the unid map \u2014 and its\n // unid can collide with another part's, so writing it here would corrupt that entry.\n if (!inBand) {\n this.unidToFullId.delete(oldUnid);\n this.unidToFullId.set(newUnid, anchorId);\n }\n // Stamp BEFORE wiring so wireBlock's own resolution sees the authoritative id.\n if (inBand) this.region!.adoptBlock(fresh, anchorId);\n this.wireBlock(fresh);\n this.activeBlock = fresh;\n // The throwaway render numbers citation markers from 1 \u2014 repair in place.\n this.maybeRenumberNotes(fresh);\n if (inBand) this.region!.afterStoryEdit(fresh);\n this.options.onEdit?.({ anchorId, unid: newUnid });\n return fresh;\n }\n\n /**\n * Full-document HTML from the live session. Prefers the session-attached\n * `RenderHtml` bridge \u2014 the saved bytes never cross the JS/WASM boundary\n * (two multi-MB copies per remount on a large doc) \u2014 and falls back to\n * Save + ConvertDocxToHtmlComplete for older WASM bundles. Both paths use\n * the same option profile, so the rendered HTML is identical.\n */\n /** The editor's render profile, as the comment-aware bridge endpoints take it. */\n private editorRenderProfile(): string {\n return JSON.stringify({\n cssPrefix: this.options.cssPrefix,\n fabricateClasses: this.options.fabricateClasses,\n paginated: this.options.paginated,\n scale: this.options.scale,\n renderTrackedChanges: this.renderTrackedChanges,\n comments: this.options.comments,\n });\n }\n\n /**\n * Full-document HTML from the live session. Prefers the session-attached\n * `RenderEditorHtml` (comment-aware) or `RenderHtml` bridge \u2014 the saved bytes never cross the\n * JS/WASM boundary \u2014 and falls back to `ConvertDocxToHtmlComplete` over `bytes` (the opened\n * document on first paint, else a fresh save) for older WASM bundles. Every path uses the\n * same option profile, so the rendered HTML is identical.\n */\n private renderFullHtml(bytes?: Uint8Array): string {\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.RenderEditorHtml === \"function\") {\n const html = bridge.RenderEditorHtml(this.handle, this.editorRenderProfile());\n if (html.charCodeAt(0) !== 0x7b) return html;\n }\n if (this.options.comments) {\n // Only the bytes path can render comment markup on a bundle without RenderEditorHtml.\n const source =\n bytes ??\n (typeof bridge.SaveWithAnchorIds === \"function\"\n ? bridge.SaveWithAnchorIds(this.handle)\n : bridge.Save(this.handle));\n return this.exports.DocumentConverter.ConvertDocxToHtmlComplete(\n ...completeArgs(\n source, this.options.cssPrefix, this.options.fabricateClasses,\n this.options.paginated, this.options.scale, this.renderTrackedChanges, true,\n ),\n );\n }\n if (typeof bridge.RenderHtmlForReview === \"function\") {\n const html = bridge.RenderHtmlForReview(\n this.handle,\n this.options.cssPrefix,\n this.options.fabricateClasses,\n this.options.paginated,\n this.options.scale,\n this.renderTrackedChanges,\n );\n if (html.charCodeAt(0) !== 0x7b) return html;\n }\n if (typeof bridge.RenderHtml === \"function\") {\n const html = bridge.RenderHtml(\n this.handle,\n this.options.cssPrefix,\n this.options.fabricateClasses,\n this.options.paginated,\n this.options.scale,\n );\n if (html.charCodeAt(0) !== 0x7b /* not an error object */) return html;\n }\n // Fallback only (no RenderHtml on this bridge, or it errored). These bytes are re-rendered and\n // discarded, and the re-render has to resolve to the SAME anchors the live session holds \u2014 a\n // content change re-derives a block's content-hashed unid, which would leave it unwired. So ask\n // for the Unid-bearing save here, and here only; DocxEditor.save() stays clean.\n const source =\n bytes ??\n (typeof bridge.SaveWithAnchorIds === \"function\"\n ? bridge.SaveWithAnchorIds(this.handle)\n : bridge.Save(this.handle));\n return this.exports.DocumentConverter.ConvertDocxToHtmlComplete(\n ...completeArgs(\n source, this.options.cssPrefix, this.options.fabricateClasses,\n this.options.paginated, this.options.scale, this.renderTrackedChanges, false,\n ),\n );\n }\n\n /** Editable BODY blocks in document order (band blocks are enumerated by `ownerRoot`). In page\n * view a live story sits INSIDE a page box, so it is excluded here explicitly \u2014 a remount\n * rebuilds the pages without it, and a focus index that counted it would land one block off. */\n private editableList(): HTMLElement[] {\n return Array.from(\n this.editRoot.querySelectorAll<HTMLElement>('[data-anchor][contenteditable=\"true\"]'),\n ).filter((el) => !el.closest(\"[data-hf-band]\"));\n }\n\n private blockIndex(el: HTMLElement): number {\n return Array.from(\n this.ownerRoot(el).querySelectorAll<HTMLElement>('[data-anchor][contenteditable=\"true\"]'),\n ).indexOf(el);\n }\n\n /**\n * True when an edit produced or touched a list item (kind \"li\"). List markers and\n * numbering CONTINUATION need whole-document context, which a single-block render lacks\n * (every item would render as \"1.\"), so such edits re-render the whole document.\n */\n private affectsList(res: EditResultLite): boolean {\n return [...(res.modified ?? []), ...(res.created ?? [])].some((r) => r.kind === \"li\");\n }\n\n // \u2500\u2500\u2500 Incremental structural reconcile \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n //\n // After a structural op (insert table/row/col, footnote, delete block, undo/redo)\n // the DOM is patched from a unit-sequence diff against the session's render plan\n // instead of remounting the whole document (~3 s of full-document conversion on a\n // 350-block file). Full remount remains the universal FALLBACK: any ambiguity,\n // unsupported bridge, paginated mode, list-membership change, or thrown error\n // lands there \u2014 correctness never depends on the diff being right.\n\n /** True when the bridge carries the reconcile trio and the mode allows patching. */\n private canReconcile(): boolean {\n const b = this.exports.DocxSessionBridge;\n return (\n !this.options.paginated &&\n typeof b.ListBlocks === \"function\" &&\n typeof b.RenderBlocksHtml === \"function\" &&\n typeof b.ListNotes === \"function\"\n );\n }\n\n /** The body's top-level unit nodes in document order: `[data-anchor]` elements not\n * nested in another unit (cell paragraphs collapse into their table) and not in the\n * notes sections. */\n private bodyUnitNodes(): HTMLElement[] {\n const all = Array.from(this.editRoot.querySelectorAll<HTMLElement>(\"[data-anchor]\"));\n return all.filter((el) => {\n if (el.closest(\"section.footnotes, section.endnotes\")) return false;\n const ancestor = el.parentElement?.closest(\"[data-anchor]\");\n return !(ancestor && this.editRoot.contains(ancestor));\n });\n }\n\n /** The DOM diff token for a body unit node (see editor-reconcile.tokenOf). */\n private static domTokenOf(el: HTMLElement): string {\n const unid = el.getAttribute(\"data-anchor\") ?? \"\";\n const sig = el.getAttribute(\"data-render-sig\");\n return sig ? `${unid}|${sig}` : unid;\n }\n\n /** The kind a body unit node would have in the plan (only 'li'/'tbl' matter to the\n * remount guard). */\n private static domKindOf(el: HTMLElement): string {\n if (el.tagName === \"TABLE\") return \"tbl\";\n return el.querySelector(\":scope > [data-list-marker]\") ? \"li\" : \"p\";\n }\n\n private static listMarkerText(el: Element | null): string | null {\n const m = el?.querySelector(\":scope > [data-list-marker]\");\n return m ? m.textContent : null;\n }\n\n /**\n * Incrementally patch the DOM from the session's render plan; falls back to\n * {@link remount} whenever it cannot prove the patch correct. Same focus contract\n * as remount.\n */\n private reconcile(focusIndex = -1, caretAtEnd = false): void {\n if (!this.canReconcile()) {\n this.remount(focusIndex, caretAtEnd);\n return;\n }\n try {\n if (!this.reconcileCore()) {\n this.remount(focusIndex, caretAtEnd);\n return;\n }\n } catch (err) {\n this.lastReconcileFallback = `threw: ${err instanceof Error ? err.message : String(err)}`;\n this.remount(focusIndex, caretAtEnd);\n return;\n }\n if (focusIndex >= 0) {\n const blocks = this.editableList();\n const target = blocks[Math.min(focusIndex, blocks.length - 1)];\n if (target) {\n this.activeBlock = target;\n placeCaretAtOffset(target, caretAtEnd ? (target.textContent ?? \"\").length : 0);\n }\n }\n this.syncRegionToBody(this.activeBlock ?? undefined);\n this.gutter?.schedule();\n }\n\n /** The patch itself. Returns false to request the remount fallback. */\n private reconcileCore(): boolean {\n const bridge = this.exports.DocxSessionBridge;\n // Refresh the unid \u2192 anchor map FIRST: wiring freshly rendered nodes (wireBlock)\n // resolves through it, and the map must reflect the post-op session.\n this.refreshAnchorMap();\n const plan = JSON.parse(this.renderPlanJson()) as RenderPlan & { error?: string };\n if (plan.error) return this.bail(`plan error: ${plan.error}`);\n\n const oldNodes = this.bodyUnitNodes();\n const oldTokens = oldNodes.map(DocxEditor.domTokenOf);\n const oldKinds = oldNodes.map(DocxEditor.domKindOf);\n const bodyDiff = diffUnits(oldTokens, plan.body);\n if (needsRemount(bodyDiff, plan.body, oldKinds)) {\n // Name the shape, not just the verdict: \"churn\" and \"a list item moved in or out\" are very\n // different findings when a repaint unexpectedly costs a whole-document render.\n return this.bail(\n `needsRemount (li change or churn): +${bodyDiff.added.length} -${bodyDiff.removed.length} ` +\n `~${bodyDiff.substituted.length} moved=${bodyDiff.moved.length} of ${plan.body.length}`,\n );\n }\n\n const fnState = this.notesDiff(\"footnotes\", plan.footnotes);\n const enState = this.notesDiff(\"endnotes\", plan.endnotes);\n if (fnState === null || enState === null) return this.bail(\"notes container unstampable/missing\");\n\n // One batch render for everything that needs fresh HTML.\n const movedBodyNew = new Set(bodyDiff.moved.map((m) => m.newIndex));\n const addedBodyIds = bodyDiff.added\n .filter((j) => !movedBodyNew.has(j))\n .map((j) => plan.body[j].id);\n const addedNoteIds = fnState.diff.added\n .map((j) => plan.footnotes[j].id)\n .concat(enState.diff.added.map((j) => plan.endnotes[j].id));\n const allIds = addedBodyIds.concat(addedNoteIds);\n let rendered: Record<string, string | null> = {};\n if (allIds.length > 0) {\n const idsJson = JSON.stringify(allIds);\n const renderedJson = this.renderBlocksJson(idsJson);\n rendered = JSON.parse(renderedJson);\n if ((rendered as { error?: string }).error) return this.bail(`render error: ${(rendered as { error?: string }).error}`);\n for (const id of allIds) if (!rendered[id]) return this.bail(`unrenderable: ${id}`);\n }\n\n // A substituted list item may only swap in place if its rendered marker matches\n // the old node's \u2014 a marker change (level/membership/numbering) means sibling\n // numbers shifted too, which only a remount repaints.\n const parse = (html: string): HTMLElement | null => {\n const el = new DOMParser().parseFromString(html, \"text/html\").body\n .firstElementChild as HTMLElement | null;\n // Per-block converter output carries the XHTML xmlns; a full render only has it\n // on the document root, so drop it to keep reconciled DOM \u2261 remounted DOM.\n el?.removeAttribute(\"xmlns\");\n return el;\n };\n const freshBody = new Map<number, HTMLElement>();\n for (const j of bodyDiff.added.filter((j) => !movedBodyNew.has(j))) {\n const el = parse(rendered[plan.body[j].id]!);\n if (!el) return this.bail(`unparseable render: ${plan.body[j].id}`);\n freshBody.set(j, el);\n }\n for (const { oldIndex, newIndex } of bodyDiff.substituted) {\n const freshRoot = freshBody.get(newIndex);\n const oldMarker = DocxEditor.listMarkerText(oldNodes[oldIndex]);\n const newMarker = DocxEditor.listMarkerText(\n freshRoot ? DocxEditor.anchorElOf(freshRoot) : null,\n );\n if (oldMarker !== newMarker) return this.bail(\"substituted li marker drift\");\n }\n\n const bodyApply = this.applyBodyDiff(oldNodes, plan.body, bodyDiff, freshBody);\n if (bodyApply !== true) return this.bail(`applyBodyDiff bail: ${bodyApply}`);\n this.applyNotesDiff(\"footnotes\", plan.footnotes, fnState, rendered);\n this.applyNotesDiff(\"endnotes\", plan.endnotes, enState, rendered);\n\n // Note chrome (marker sup text / hrefs / li values) is position-derived and NOT\n // covered by the unit diff \u2014 renumber whenever notes changed or any fresh body\n // node carries a citation marker.\n const freshHasMarker = [...freshBody.values()].some((el) =>\n el.querySelector(\"a.footnote-ref, a.endnote-ref\"),\n );\n if (fnState.diff.added.length + fnState.diff.removed.length > 0 || freshHasMarker)\n this.renumberNoteChrome(\"footnote\");\n if (enState.diff.added.length + enState.diff.removed.length > 0 || freshHasMarker)\n this.renumberNoteChrome(\"endnote\");\n this.lastReconcileFallback = null;\n return true;\n }\n\n private bail(reason: string): false {\n this.lastReconcileFallback = reason;\n return false;\n }\n\n /** The generated single-child wrapper chain around a unit node (a table's alignment\n * <div>). Climbs while the parent is an anchor-less DIV whose ONLY element child is\n * the current node \u2014 never a section div (multi-child) or the edit root. */\n private unitWrapperOf(el: HTMLElement): HTMLElement {\n let n: HTMLElement = el;\n while (\n n.parentElement &&\n n.parentElement !== this.editRoot &&\n n.parentElement.tagName === \"DIV\" &&\n !n.parentElement.hasAttribute(\"data-section-index\") &&\n !n.parentElement.hasAttribute(\"data-anchor\") &&\n n.parentElement.childElementCount === 1\n ) {\n n = n.parentElement;\n }\n return n;\n }\n\n /** The `[data-anchor]` element of a fresh render root (the root itself for a leaf\n * block, its descendant for a wrapper-shaped render like a table's align div). */\n private static anchorElOf(root: HTMLElement): HTMLElement | null {\n return root.hasAttribute(\"data-anchor\")\n ? root\n : root.querySelector<HTMLElement>(\"[data-anchor]\");\n }\n\n /** Insert/remove/swap body unit nodes per the diff. Returns `true` on success or a\n * bail-reason string (parent ambiguity, order violation, wrapper semantics) \u2014 the\n * session is already correct, so bailing just means a full repaint. */\n private applyBodyDiff(\n oldNodes: HTMLElement[],\n units: RenderUnit[],\n diff: UnitDiff,\n fresh: Map<number, HTMLElement>,\n ): true | string {\n // In-place substitutions first: replace at WRAPPER level so a table swaps with its\n // alignment div. A LEAF render replacing a wrapped node would break the wrapper's\n // semantics (border <div> grouping) \u2014 that is remount territory.\n const subOldByNew = new Map(diff.substituted.map((s) => [s.newIndex, s.oldIndex]));\n for (const [nj, oi] of subOldByNew) {\n const freshRoot = fresh.get(nj)!;\n const oldWrapper = this.unitWrapperOf(oldNodes[oi]);\n // A render that differs from the live node ONLY in <img> attributes (a host replacing\n // an image's media through the session \u2014 the arcade's Doom cartridge does it every\n // frame) patches those attributes on the elements already on screen instead of\n // swapping nodes. Firefox and WebKit paint a freshly inserted <img> as an empty box\n // until its data URI is decoded, so a per-frame swap strobes white between frames;\n // an in-place src change keeps the previous bitmap up until the new one is ready.\n // The live node stays wired, so only its signature stamp needs refreshing. Any\n // other difference (or a border-wrapper change) falls through to the swap below.\n const leaf = freshRoot.hasAttribute(\"data-anchor\");\n const imagePairs = imageOnlyDelta(leaf ? oldNodes[oi] : oldWrapper, freshRoot);\n if (imagePairs) {\n for (const [live, next] of imagePairs) patchImageAttributes(live, next);\n const sig = units[nj].sig;\n if (sig) oldNodes[oi].setAttribute(\"data-render-sig\", sig);\n continue;\n }\n if (!freshRoot.hasAttribute(\"data-anchor\")) {\n oldWrapper.replaceWith(freshRoot); // wrapper-shaped render (table) \u21C4 wrapper\n } else if (oldWrapper === oldNodes[oi]) {\n oldNodes[oi].replaceWith(freshRoot);\n } else if (\n !oldNodes[oi].hasAttribute(\"data-render-sig\") &&\n unidOf(units[nj].id) === oldNodes[oi].getAttribute(\"data-anchor\")\n ) {\n // Same block, leaf render, wrapped slot, and the old node carries NO signature:\n // a sig-less node is one a SINGLE-BLOCK swap placed (mount and reconcile both\n // stamp signatures), and those swaps never change border grouping \u2014 every\n // border-changing op forces a full remount. The wrapper is therefore still\n // valid; swap the leaf inside it, exactly as the single-block path itself does\n // for a bordered paragraph. A STAMPED wrapped slot whose content changed stays\n // remount territory \u2014 the change could be the border itself.\n oldNodes[oi].replaceWith(freshRoot);\n } else {\n // border-div semantics, remount\n return `leaf render into wrapped slot (unit ${units[nj].id.slice(0, 24)})`;\n }\n this.wireUnit(freshRoot, units[nj]);\n }\n\n const movedOldByNew = new Map(diff.moved.map((m) => [m.newIndex, m.oldIndex]));\n const movedNew = new Set(diff.moved.map((m) => m.newIndex));\n const movedOld = new Set(diff.moved.map((m) => m.oldIndex));\n const pureAdded = diff.added.filter((j) => !subOldByNew.has(j) && !movedNew.has(j));\n const pureRemoved = diff.removed.filter(\n (i) => !diff.substituted.some((s) => s.oldIndex === i) && !movedOld.has(i),\n );\n // DOMParser roots report isConnected=true because they belong to their detached\n // HTMLDocument. Track only fresh additions actually inserted into the live editor;\n // otherwise a later not-yet-applied sibling looks like a neighbor in another parent.\n const appliedFresh = new Set<number>();\n const nodeAt = (j: number): HTMLElement | null => {\n const oi = diff.keep.get(j);\n if (oi !== undefined) return oldNodes[oi];\n const movedOi = movedOldByNew.get(j);\n if (movedOi !== undefined) return oldNodes[movedOi];\n if (subOldByNew.has(j)) return fresh.get(j)!;\n const f = fresh.get(j);\n return f && appliedFresh.has(j) ? f : null;\n };\n\n // Preserve the established incremental insertion path: body render output may\n // legitimately use several wrapper parents (for example border groups), so it is\n // not valid to normalize the whole body against one common parent.\n for (const j of pureAdded) {\n const el = fresh.get(j)!;\n let prev: HTMLElement | null = null;\n for (let k = j - 1; k >= 0 && !prev; k--) prev = nodeAt(k);\n let next: HTMLElement | null = null;\n for (let k = j + 1; k < units.length && !next; k++) next = nodeAt(k);\n const prevW = prev ? this.unitWrapperOf(prev) : null;\n const nextW = next ? this.unitWrapperOf(next) : null;\n if (prevW && nextW && prevW.parentElement !== nextW.parentElement)\n return \"insert neighbors in different parents\";\n if (prevW) prevW.after(el);\n else if (nextW) nextW.before(el);\n else return \"insert with no anchored neighbor\";\n appliedFresh.add(j);\n this.wireUnit(el, units[j]);\n }\n\n // Pure removals take their now-empty generated wrappers with them. Exact-token\n // move sources remain live even though the LCS also reports them as removed.\n for (const i of pureRemoved) {\n this.unitWrapperOf(oldNodes[i]).remove();\n }\n\n // A block move changes one exact-token unit's slot. Move only that existing\n // wrapper beside its final neighbor; this preserves identity without disturbing\n // unrelated nodes or assuming every rendered unit shares one DOM parent.\n for (const { newIndex } of [...diff.moved].sort((a, b) => a.newIndex - b.newIndex)) {\n const moving = nodeAt(newIndex);\n if (!moving?.isConnected) return \"move source is not connected\";\n const movingW = this.unitWrapperOf(moving);\n let prevW: HTMLElement | null = null;\n for (let k = newIndex - 1; k >= 0 && !prevW; k--) {\n const n = nodeAt(k);\n if (n?.isConnected) prevW = this.unitWrapperOf(n);\n }\n let nextW: HTMLElement | null = null;\n for (let k = newIndex + 1; k < units.length && !nextW; k++) {\n const n = nodeAt(k);\n if (n?.isConnected) nextW = this.unitWrapperOf(n);\n }\n if (prevW && prevW !== movingW && prevW.parentElement === movingW.parentElement) {\n prevW.after(movingW);\n } else if (nextW && nextW !== movingW && nextW.parentElement === movingW.parentElement) {\n nextW.before(movingW);\n } else {\n return \"move neighbors in different parents\";\n }\n }\n return true;\n }\n\n /** Wire a freshly rendered unit root (and its nested blocks) and stamp the unit's\n * content signature on its `[data-anchor]` element \u2014 the element the next\n * reconcile's DOM walk reads tokens from. */\n private wireUnit(root: HTMLElement, unit: RenderUnit): void {\n const anchorEl = DocxEditor.anchorElOf(root);\n if (anchorEl && unit.sig) anchorEl.setAttribute(\"data-render-sig\", unit.sig);\n if (anchorEl) this.wireBlock(anchorEl);\n root.querySelectorAll<HTMLElement>(\"[data-anchor]\").forEach((b) => this.wireBlock(b));\n }\n\n /** Old-sequence diff state for one notes section. `null` requests remount when an\n * existing list is not stampable; an absent list is the valid first-note case. */\n private notesDiff(\n sectionClass: \"footnotes\" | \"endnotes\",\n units: RenderUnit[],\n ): { lis: HTMLElement[]; diff: UnitDiff } | null {\n const ol = this.editRoot.querySelector<HTMLElement>(`section.${sectionClass} > ol`);\n const lis = ol ? (Array.from(ol.children).filter((c) => c.tagName === \"LI\") as HTMLElement[]) : [];\n if (units.length === 0 && lis.length === 0) return { lis, diff: diffUnits([], []) };\n // Full render omits empty note sections. Treat the first note as an insertion into\n // an empty list; applyNotesDiff creates the converter-equivalent section + list.\n if (!ol) return { lis, diff: diffUnits([], units) };\n const tokens: string[] = [];\n for (const li of lis) {\n const unid = li.getAttribute(\"data-note-anchor\");\n if (!unid) return null; // unstamped DOM (older mount) \u2014 remount restamps\n const sig = li.getAttribute(\"data-render-sig\");\n tokens.push(sig ? `${unid}|${sig}` : unid);\n }\n return { lis, diff: diffUnits(tokens, units) };\n }\n\n /** Apply a notes-section diff: rebuild the `<ol>`'s li list, preserving kept nodes. */\n private applyNotesDiff(\n sectionClass: \"footnotes\" | \"endnotes\",\n units: RenderUnit[],\n state: { lis: HTMLElement[]; diff: UnitDiff },\n rendered: Record<string, string | null>,\n ): void {\n if (state.diff.added.length === 0 && state.diff.removed.length === 0) return;\n // Removing the LAST note removes the whole section \u2014 a full render emits no\n // section for a document without notes, and equivalence with remount is the pin.\n if (units.length === 0) {\n this.editRoot.querySelector(`section.${sectionClass}`)?.remove();\n return;\n }\n let section = this.editRoot.querySelector<HTMLElement>(`:scope > section.${sectionClass}`);\n let ol = section?.querySelector<HTMLOListElement>(`:scope > ol`) ?? null;\n if (!ol) {\n if (!section) {\n section = document.createElement(\"section\");\n section.className = sectionClass;\n const following = sectionClass === \"footnotes\"\n ? this.editRoot.querySelector<HTMLElement>(`:scope > section.endnotes`)\n : null;\n if (following) following.before(section);\n else this.editRoot.append(section);\n }\n if (!section.querySelector(\":scope > hr\")) section.prepend(document.createElement(\"hr\"));\n ol = document.createElement(\"ol\");\n section.append(ol);\n }\n const prefix = sectionClass === \"footnotes\" ? \"fn\" : \"en\";\n const nodes: HTMLElement[] = [];\n for (let j = 0; j < units.length; j++) {\n const oi = state.diff.keep.get(j);\n if (oi !== undefined) {\n nodes.push(state.lis[oi]);\n continue;\n }\n nodes.push(this.buildNoteLi(prefix, units[j], rendered[units[j].id]!));\n }\n ol.replaceChildren(...nodes);\n }\n\n /** Build a notes-section `<li>` for a freshly rendered note \u2014 replicating the\n * converter's chrome (id/value are re-stamped by the renumber pass; the backref\n * goes inside the last paragraph, matching RenderFootnoteItem). */\n private buildNoteLi(prefix: \"fn\" | \"en\", unit: RenderUnit, html: string): HTMLElement {\n const li = document.createElement(\"li\");\n li.setAttribute(\"data-note-anchor\", unidOf(unit.id));\n if (unit.sig) li.setAttribute(\"data-render-sig\", unit.sig);\n li.innerHTML = html;\n const paras = li.querySelectorAll<HTMLElement>(\":scope > p\");\n const last = paras[paras.length - 1];\n if (last) {\n const backref = document.createElement(\"a\");\n backref.setAttribute(\"class\", `${prefix}-backref`);\n backref.setAttribute(\"contenteditable\", \"false\");\n // The separator space must live INSIDE the chrome element. As a bare text\n // node in the paragraph it was counted by blockContentText, giving the\n // committed baseline a phantom trailing character the session's flat text\n // does not have \u2014 every later span commit then computed offsets one past\n // the session text and died with offset_out_of_range, silently reverting\n // the user's note edit (#583).\n backref.textContent = \" \u21A9\";\n last.append(backref);\n }\n li.querySelectorAll<HTMLElement>(\"[data-anchor]\").forEach((b) => this.wireBlock(b));\n return li;\n }\n\n /**\n * Rewrite position-derived note chrome from the session's citation-ordered note\n * list: the k-th marker in document order IS note k (ids ascend in reference\n * order), so marker sup text, hrefs/ids, li ids/values and backref hrefs are all\n * re-derived positionally. Pure attribute/text patching of generated chrome.\n */\n private renumberNoteChrome(kind: \"footnote\" | \"endnote\"): void {\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.ListNotes !== \"function\") return;\n const prefix = kind === \"footnote\" ? \"fn\" : \"en\";\n let notes: Array<{ id: string; defAnchorId: string; ordinal: number }>;\n try {\n notes = JSON.parse(bridge.ListNotes(this.handle, kind === \"endnote\"));\n } catch {\n return;\n }\n if (!Array.isArray(notes)) return;\n const markers = Array.from(\n this.editRoot.querySelectorAll<HTMLElement>(`a.${kind}-ref`),\n ).filter((a) => !a.closest(\"section.footnotes, section.endnotes\"));\n markers.forEach((a, k) => {\n const n = notes[k];\n if (!n) return;\n a.setAttribute(\"href\", `#${prefix}-${n.id}`);\n a.id = `${prefix}-ref-${n.id}`;\n if (kind === \"footnote\") a.setAttribute(\"data-footnote-id\", n.id);\n const sup = a.querySelector(\"sup\");\n if (sup) sup.textContent = String(n.ordinal);\n });\n // Match list items by their stamped note anchor, NOT position: the section can\n // hold rendered-but-never-cited notes (Word's continuationNotice) that ListNotes\n // \u2014 a citation walk \u2014 does not list; positional pairing would relabel them.\n const byUnid = new Map(notes.map((n) => [unidOf(n.defAnchorId), n]));\n const lis = this.editRoot.querySelectorAll<HTMLElement>(`section.${kind}s > ol > li`);\n lis.forEach((li) => {\n const unid = li.getAttribute(\"data-note-anchor\");\n const n = unid ? byUnid.get(unid) : undefined;\n if (!n) return;\n li.id = `${prefix}-${n.id}`;\n li.setAttribute(\"value\", String(n.ordinal));\n li.querySelectorAll<HTMLElement>(`a.${prefix}-backref`).forEach((b) =>\n b.setAttribute(\"href\", `#${prefix}-ref-${n.id}`),\n );\n });\n }\n\n /** After an incremental block swap, stale marker chrome in the swapped node (the\n * throwaway render numbers citations from 1) is repaired in place. */\n private maybeRenumberNotes(fresh: HTMLElement): void {\n if (fresh.querySelector(\"a.footnote-ref\")) this.renumberNoteChrome(\"footnote\");\n if (fresh.querySelector(\"a.endnote-ref\")) this.renumberNoteChrome(\"endnote\");\n }\n\n /** Stamp the DOM state the reconciler diffs against: container signatures on body\n * tables and `data-note-anchor` + signature on notes-section items. Called after\n * every full mount; reconcile stamps its own insertions. */\n private stampPlanState(): void {\n const bridge = this.exports.DocxSessionBridge;\n if (typeof bridge.ListBlocks !== \"function\") return;\n try {\n const plan = JSON.parse(this.renderPlanJson()) as RenderPlan & { error?: string };\n if (plan.error) return;\n // Positional pairing: a fresh full mount renders exactly the plan's units in\n // order (verified invariant). On any mismatch, leave unstamped \u2014 an unstamped\n // unit just diffs as changed and re-renders once.\n const nodes = this.bodyUnitNodes();\n if (nodes.length === plan.body.length) {\n nodes.forEach((el, k) => {\n if (plan.body[k].sig && el.getAttribute(\"data-anchor\") === unidOf(plan.body[k].id))\n el.setAttribute(\"data-render-sig\", plan.body[k].sig!);\n });\n }\n const stampNotes = (sectionClass: string, units: RenderUnit[]): void => {\n const lis = this.editRoot.querySelectorAll<HTMLElement>(`section.${sectionClass} > ol > li`);\n if (lis.length !== units.length) return; // inconsistent \u2014 leave unstamped (reconcile will remount)\n lis.forEach((li, k) => {\n li.setAttribute(\"data-note-anchor\", unidOf(units[k].id));\n if (units[k].sig) li.setAttribute(\"data-render-sig\", units[k].sig!);\n });\n };\n stampNotes(\"footnotes\", plan.footnotes);\n stampNotes(\"endnotes\", plan.endnotes);\n } catch {\n /* stamping is best-effort; unstamped DOM just falls back to remount */\n }\n }\n\n /**\n * Full re-render from current session state (after undo/redo, and after list edits where\n * single-block rendering can't compute numbering). Optionally focus the editable block at\n * `focusIndex` (caret at start, or end if `caretAtEnd`) \u2014 addressed by index because a\n * block's content-hashed unid changes across the save/reproject a remount performs.\n */\n private remount(focusIndex = -1, caretAtEnd = false): void {\n this.teardownBlockDrag();\n this.refreshAnchorMap();\n const fullHtml = this.renderFullHtml();\n this.activeBlock = null;\n if (this.options.paginated) this.mountPaginated(fullHtml);\n else this.mountHtml(fullHtml);\n if (focusIndex >= 0) {\n const blocks = this.editableList();\n const target = blocks[Math.min(focusIndex, blocks.length - 1)];\n if (target) {\n this.activeBlock = target;\n placeCaretAtOffset(target, caretAtEnd ? (target.textContent ?? \"\").length : 0);\n }\n }\n // A remount rebuilds the body from the live session; re-resolve the section so undo/redo of a\n // section-affecting edit (or a pagination toggle) leaves the bands describing the right one.\n this.syncRegionToBody(this.activeBlock ?? undefined);\n this.setupBlockDrag();\n this.gutter?.schedule();\n }\n\n /** Re-append the gutter after a mount emptied the container (mounts replace `innerHTML`). */\n private readoptGutter(): void {\n this.gutter?.reattach();\n }\n}\n\nconst commentGutterStyledDocuments = new WeakSet<Document>();\nfunction ensureCommentGutterStyles(doc: Document): void {\n if (commentGutterStyledDocuments.has(doc)) return;\n commentGutterStyledDocuments.add(doc);\n const style = doc.createElement(\"style\");\n style.dataset.docxodusCommentGutter = \"true\";\n style.textContent = COMMENT_GUTTER_CSS;\n (doc.head ?? doc.documentElement).appendChild(style);\n}\n", "import { HistoryCheckpoints } from './history-checkpoints.js';\nimport { mountHistoryControls, historyControlError } from './history-controls.js';\nimport type { HistoryControls } from './history-controls.js';\nimport { openIndexedDbHistoryStore } from './history-indexeddb.js';\nimport type { IndexedDbHistoryStore } from './history-indexeddb.js';\nimport { DocxHistoryError, MAX_HISTORY_ARCHIVE_BYTES } from './history.js';\nimport type { DocxHistoryArchive, DocxHistoryClient, HistoryStorage } from './history.js';\nimport type { RibbonEditor } from './ribbon.js';\n\nexport interface RibbonHistoryOptions {\n /** Browser database shared by this app's editors. No document bytes are stored until Save version. */\n storageName?: string;\n /** Stable host-owned workspace key. Reopens its last saved document across reloads. */\n workspaceId?: string;\n author?: string;\n}\n\n/** Low-level hosts supply their initialized history and preview services. createRibbonEditor wires these automatically. */\nexport interface RibbonHistoryBinding extends RibbonHistoryOptions {\n openHistory(storage: HistoryStorage): DocxHistoryClient;\n openArchive(bytes: Uint8Array): Promise<DocxHistoryArchive>;\n preview(container: HTMLElement, bytes: Uint8Array): Promise<{ destroy(): void }>;\n}\n\ninterface DocumentIdentity { id: string; name: string }\ninterface SavedDocument extends DocumentIdentity { checkpoints: HistoryCheckpoints }\n\n/** Shared ribbon lifecycle, browser persistence and separate previews. No autosave or network sync. */\nexport class RibbonHistory {\n private readonly dialog: HTMLDialogElement;\n private readonly previewDialog: HTMLDialogElement;\n private readonly body: HTMLElement;\n private readonly status: HTMLElement;\n private readonly source: HTMLElement;\n private readonly recent: HTMLSelectElement;\n private readonly back: HTMLButtonElement;\n private readonly resumeButton: HTMLButtonElement;\n private readonly events = new AbortController();\n private readonly prefix: string;\n private readonly lastKey: string;\n private store?: IndexedDbHistoryStore;\n private client?: DocxHistoryClient;\n private draft?: SavedDocument;\n private identity: DocumentIdentity = { id: crypto.randomUUID(), name: 'Untitled.docx' };\n private archive?: { reader: DocxHistoryArchive; bytes: Uint8Array; name: string };\n private panel?: HistoryControls;\n private preview?: { destroy(): void };\n private active?: Promise<void>;\n private destroyed = false;\n private installing = false;\n private dirty = false;\n private generation = 0;\n private captured = -1;\n private savedVersion: number | null = null;\n private observedVersion: number | null = null;\n private capturedVersion: number | null = null;\n private capturedBytes?: Uint8Array;\n private readonly panelObserver: MutationObserver;\n\n constructor(private readonly ribbon: RibbonEditor, private readonly options: RibbonHistoryBinding) {\n const doc = ribbon.element.ownerDocument;\n this.prefix = `docxodus:versions:${options.storageName ?? 'docxodus-editor'}:document:`;\n this.lastKey = `docxodus:versions:${options.storageName ?? 'docxodus-editor'}:workspace:${options.workspaceId ?? crypto.randomUUID()}`;\n const style = doc.createElement('style'); style.textContent = HISTORY_DRAWER_CSS;\n this.dialog = doc.createElement('dialog');\n this.dialog.className = 'dxr-history-dialog';\n this.dialog.setAttribute('aria-label', 'Version history');\n const header = doc.createElement('div'); header.className = 'dxr-history-header'; this.dialog.append(header);\n const close = this.button('Close version history', () => this.dialog.close(), header);\n close.className = 'dxr-history-close'; close.textContent = 'Close \u2715';\n this.source = doc.createElement('p'); this.source.className = 'dxr-history-source';\n this.status = doc.createElement('p'); this.status.setAttribute('role', 'status');\n this.status.className = 'dxr-history-status';\n const recentLabel = doc.createElement('label'); recentLabel.textContent = 'Saved documents on this device';\n this.recent = doc.createElement('select'); this.recent.setAttribute('aria-label', recentLabel.textContent);\n recentLabel.append(this.recent);\n this.recent.addEventListener('change', () => this.command(async () => {\n const selectedId = this.recent.value;\n this.recent.value = this.identity.id;\n const selected = this.readIdentity(localStorage.getItem(this.prefix + selectedId));\n if (!selected || !this.confirmReplace()) return;\n await this.loadSaved(selected);\n await this.mountPanel();\n this.updateRecent();\n }), { signal: this.events.signal });\n this.dialog.append(this.source, this.status, recentLabel);\n this.resumeButton = this.button('Continue editing this document', () => this.command(() => this.importArchive()), this.dialog);\n this.back = this.button('Back to my document', () => this.command(async () => {\n await this.closeArchive(); await this.mountPanel();\n }), this.dialog);\n this.body = doc.createElement('div'); this.dialog.append(this.body);\n this.previewDialog = doc.createElement('dialog'); this.previewDialog.className = 'dxr-version-preview';\n this.previewDialog.setAttribute('aria-label', 'Version preview');\n this.panelObserver = new MutationObserver(() => this.syncBusy());\n ribbon.element.append(style, this.dialog, this.previewDialog);\n for (const dialog of [this.dialog, this.previewDialog]) {\n dialog.addEventListener('keydown', event => event.stopPropagation(), { signal: this.events.signal });\n dialog.addEventListener('click', event => { if (event.target === dialog) {\n const rect = dialog.getBoundingClientRect();\n if (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom) dialog.close();\n } }, { signal: this.events.signal });\n }\n this.dialog.addEventListener('close', () => ribbon.control('history')?.focus(), { signal: this.events.signal });\n ribbon.control('history')?.addEventListener('click', () => { void this.show(); }, { signal: this.events.signal });\n doc.defaultView?.addEventListener('beforeunload', event => {\n if (this.hasUnsavedChanges || this.busy) event.preventDefault();\n }, { signal: this.events.signal });\n doc.defaultView?.addEventListener('pagehide', event => {\n if (!event.persisted) void this.destroy();\n }, { signal: this.events.signal });\n }\n\n get busy(): boolean { return !!this.active || this.panel?.element.getAttribute('aria-busy') === 'true'; }\n private get hasUnsavedChanges(): boolean {\n return this.dirty || (this.ribbon.editor?.version ?? null) !== this.savedVersion;\n }\n\n /** Called by the ribbon before a programmatic replacement. */\n beforeOpen(): void {\n if (!this.installing && this.busy) throw new DocxHistoryError('Busy', 'Finish the version action before opening another document.');\n }\n\n /** A new DOCX is a new document identity, even if its filename matches another document. */\n documentOpened(name: string): void {\n if (this.installing) return;\n this.identity = { id: crypto.randomUUID(), name };\n this.draft = undefined; this.dirty = false; this.generation++;\n this.savedVersion = this.observedVersion = this.ribbon.editor?.version ?? null;\n this.dialog.close(); this.previewDialog.close();\n void this.closeArchive();\n }\n\n edited(): void {\n const version = this.ribbon.editor?.version ?? null;\n if (version !== null && version === this.observedVersion) return;\n this.observedVersion = version; this.dirty = true; this.generation++;\n }\n\n /** Restores a saved workspace only when requested by the host, before exposing the editor. */\n async resume(): Promise<void> {\n if (!this.options.workspaceId) return;\n try {\n const previous = this.readIdentity(localStorage.getItem(this.lastKey));\n if (previous) await this.run(() => this.loadSaved(previous));\n } catch (error) {\n // Storage denial/corruption must not prevent an ordinary document from opening.\n this.ribbon.setStatus('Your document is open. Version history is unavailable on this device.');\n this.status.textContent = this.explain(error);\n }\n }\n\n async show(): Promise<void> {\n if (this.destroyed) return;\n if (!this.dialog.open) this.dialog.showModal();\n if (this.busy) return;\n await this.run(async () => { await this.mountPanel(); this.updateRecent(); }).catch(() => {});\n }\n\n async openFile(file: File): Promise<void> {\n await this.run(async () => {\n if (/\\.docxhistory$/i.test(file.name)) {\n if (file.size > MAX_HISTORY_ARCHIVE_BYTES) throw new DocxHistoryError('ResourceLimit', 'History file is too large.');\n const bytes = new Uint8Array(await file.arrayBuffer());\n const reader = await this.options.openArchive(bytes);\n try { await reader.read(); }\n catch (error) { reader.close(); throw error; }\n await this.closeArchive();\n this.archive = { reader, bytes, name: file.name };\n if (!this.dialog.open) this.dialog.showModal();\n await this.mountPanel(); this.updateRecent();\n } else {\n if (!/\\.docx$/i.test(file.name)) throw new Error('Choose a Word document or a document with version history.');\n if (!this.confirmReplace()) return;\n const bytes = new Uint8Array(await file.arrayBuffer());\n this.install(bytes, { id: crypto.randomUUID(), name: file.name });\n this.draft = undefined; this.dirty = true;\n await this.closeArchive(); this.dialog.close();\n }\n }).catch(() => {});\n }\n\n async newDocument(): Promise<void> {\n await this.run(async () => {\n if (!this.confirmReplace()) return;\n this.installing = true;\n try { this.ribbon.openBlank('Untitled.docx'); }\n finally { this.installing = false; }\n this.identity = { id: crypto.randomUUID(), name: 'Untitled.docx' };\n this.draft = undefined; this.dirty = false; this.generation++;\n this.savedVersion = this.observedVersion = this.ribbon.editor?.version ?? null;\n // Choosing New survives a reload instead of silently reopening the previous document.\n try { localStorage.removeItem(this.lastKey); } catch { /* editing does not require storage */ }\n await this.closeArchive(); this.dialog.close();\n }).catch(() => {});\n }\n\n async destroy(): Promise<void> {\n if (this.destroyed) return;\n this.destroyed = true; this.events.abort(); this.dialog.remove(); this.previewDialog.remove();\n this.panelObserver.disconnect();\n await this.active?.catch(() => {}); await this.closeArchive();\n this.preview?.destroy(); this.client?.close(); this.store?.close();\n }\n\n private async ensureStorage(): Promise<void> {\n if (this.client) return;\n const store = await openIndexedDbHistoryStore(this.options.storageName ?? 'docxodus-editor');\n try { this.client = this.options.openHistory(store.storage); this.store = store; }\n catch (error) { store.close(); throw error; }\n }\n\n private async ensureDraft(): Promise<SavedDocument> {\n await this.ensureStorage();\n if (!this.draft) {\n const document = this.client!.document(this.identity.id);\n this.draft = { ...this.identity, checkpoints: await HistoryCheckpoints.open(document, this.store!.journal(this.identity.id)) };\n }\n return this.draft;\n }\n\n private async loadSaved(identity: DocumentIdentity): Promise<void> {\n await this.ensureStorage();\n const document = this.client!.document(identity.id);\n const checkpoints = await HistoryCheckpoints.open(document, this.store!.journal(identity.id));\n const pending = checkpoints.pendingRequest;\n const view = checkpoints.view;\n if (!view && pending?.kind !== 'save') throw new Error('This saved document is no longer on this device.');\n const bytes = pending?.kind === 'save' ? pending.bytes : await document.exportDocx(view!.version.id);\n this.install(bytes, identity); this.draft = { ...identity, checkpoints };\n this.dirty = pending?.kind === 'save';\n if (pending?.kind === 'save') this.captureState(pending.bytes);\n await this.closeArchive(); this.remember();\n }\n\n private install(bytes: Uint8Array, identity: DocumentIdentity): void {\n if (this.destroyed) throw new DocxHistoryError('Closed', 'The editor is closed.');\n this.installing = true;\n try { this.ribbon.open(bytes, identity.name); }\n finally { this.installing = false; }\n this.identity = identity; this.dirty = false; this.generation++;\n this.savedVersion = this.observedVersion = this.ribbon.editor?.version ?? null;\n }\n\n private async mountPanel(): Promise<void> {\n const current = this.archive ?? await this.ensureDraft();\n const writable = 'checkpoints' in current;\n const holder = this.body.ownerDocument.createElement('div');\n const panel = mountHistoryControls(holder, {\n reader: writable ? current.checkpoints.document : current.reader,\n checkpoints: writable ? current.checkpoints : undefined,\n author: this.options.author, documentName: current.name,\n capture: writable ? () => {\n const bytes = this.ribbon.save(); if (!bytes) throw new Error('Open a document first.');\n // Remember the identity before publication, so uncertain saves can recover after reload.\n this.remember(); this.captureState(bytes); return bytes;\n } : undefined,\n confirmRestore: writable ? title => this.confirm(`Restore ${title}?${this.hasUnsavedChanges ? '\\n\\nYour unsaved changes will be replaced.' : ''}\\n\\nAll saved versions will be kept.`) : undefined,\n onCheckpoint: async (view, action, request) => {\n if (this.destroyed) return;\n const savedCapture = action === 'save' || (action === 'retry' && request?.kind === 'save'\n && this.capturedBytes && sameBytes(this.capturedBytes, request.bytes));\n if (savedCapture && this.captured === this.generation && this.capturedVersion === (this.ribbon.editor?.version ?? null)) {\n this.dirty = false; this.savedVersion = this.capturedVersion;\n }\n this.captured = -1; this.capturedBytes = undefined;\n if ((action === 'restore' || (action === 'retry' && request?.kind === 'restore')) && writable)\n this.install(await current.checkpoints.document.exportDocx(view.version.id), this.identity);\n this.remember(); this.updateRecent();\n },\n restoreUpdatesDraft: true,\n preview: (bytes, title) => this.showPreview(bytes, title),\n });\n try { await panel.ready; }\n catch (error) { await panel.destroy(); throw error; }\n if (this.destroyed) { await panel.destroy(); return; }\n await this.panel?.destroy(); this.panel = panel; this.body.replaceChildren(holder);\n this.panelObserver.disconnect();\n this.panelObserver.observe(panel.element, { attributes: true, attributeFilter: ['aria-busy'] });\n this.source.textContent = current.name;\n this.resumeButton.hidden = this.back.hidden = writable;\n this.status.textContent = writable\n ? 'Your saved versions stay on this device.'\n : 'You\u2019re browsing a history file. Your open document is safe.';\n }\n\n private async showPreview(bytes: Uint8Array, title: string): Promise<void> {\n const doc = this.previewDialog.ownerDocument;\n const holder = doc.createElement('div'); holder.className = 'dxr-version-paper';\n const preview = await this.options.preview(holder, bytes);\n if (this.destroyed) { preview.destroy(); return; }\n const heading = doc.createElement('h2'); heading.textContent = title;\n const actions = doc.createElement('div'); actions.className = 'dxr-version-actions';\n this.button('Back to version history', () => this.previewDialog.close(), actions);\n if (!this.archive) this.button('Use as draft', () => this.command(async () => {\n if (!this.confirmReplace()) return;\n this.install(bytes, this.identity); this.dirty = true; this.previewDialog.close(); this.dialog.close();\n }), actions);\n this.button('Download this version', () => download(bytes, 'version.docx', doc), actions);\n this.preview?.destroy(); this.preview = preview;\n this.previewDialog.replaceChildren(heading, actions, holder);\n if (!this.previewDialog.open) this.previewDialog.showModal();\n }\n\n private async importArchive(): Promise<void> {\n if (!this.archive || !this.confirmReplace()) return;\n await this.ensureStorage();\n const imported = await this.client!.importHistoryArchive(this.archive.bytes);\n const identity = { id: imported.archive.documentId, name: this.archive.name.replace(/\\.docxhistory$/i, '.docx') };\n const document = this.client!.document(identity.id);\n const checkpoints = await HistoryCheckpoints.open(document, this.store!.journal(identity.id), imported.view);\n this.install(await document.exportDocx(imported.view.version.id), identity);\n this.draft = { ...identity, checkpoints }; this.remember();\n await this.closeArchive(); await this.mountPanel(); this.updateRecent();\n }\n\n private async closeArchive(): Promise<void> {\n this.panelObserver.disconnect();\n const panel = this.panel; this.panel = undefined;\n const archive = this.archive; this.archive = undefined;\n await panel?.destroy();\n archive?.reader.close();\n }\n\n private remember(): void {\n localStorage.setItem(this.prefix + this.identity.id, JSON.stringify(this.identity));\n localStorage.setItem(this.lastKey, JSON.stringify(this.identity));\n }\n\n private readIdentity(value: string | null): DocumentIdentity | null {\n if (!value) return null;\n const identity = JSON.parse(value);\n if (typeof identity?.id !== 'string' || !identity.id || typeof identity?.name !== 'string') return null;\n return { id: identity.id, name: identity.name };\n }\n\n private updateRecent(): void {\n this.recent.replaceChildren(new Option('Choose a saved document\u2026', ''));\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i)!;\n if (!key.startsWith(this.prefix)) continue;\n try { const identity = this.readIdentity(localStorage.getItem(key));\n if (identity) this.recent.append(new Option(identity.name, identity.id));\n } catch { /* a damaged catalog entry does not hide other saved documents */ }\n }\n this.recent.value = this.identity.id;\n this.recent.parentElement!.hidden = this.recent.options.length <= 1;\n }\n\n private confirm(message: string): boolean { return this.dialog.ownerDocument.defaultView?.confirm(message) ?? false; }\n private captureState(bytes: Uint8Array): void {\n this.captured = this.generation; this.capturedVersion = this.ribbon.editor?.version ?? null; this.capturedBytes = bytes.slice();\n }\n private confirmReplace(): boolean { return !this.hasUnsavedChanges || this.confirm('Replace your open document? Save a version or download it first to keep your unsaved changes.'); }\n private explain(error: unknown): string { return historyControlError(error, this.draft?.checkpoints.hasPending); }\n private command(action: () => Promise<void>): void { void this.run(action).catch(() => {}); }\n\n private syncBusy(): void {\n const busy = this.busy;\n // Closing the drawer while publication runs must not enable edits that a restore would replace.\n this.ribbon.surface.inert = busy;\n const chrome = this.ribbon.element.querySelector<HTMLElement>('.dxr-chrome'); if (chrome) chrome.inert = busy;\n this.recent.disabled = this.resumeButton.disabled = this.back.disabled = busy;\n const file = this.ribbon.control<HTMLInputElement>('file'); if (file) file.disabled = busy;\n const create = this.ribbon.control<HTMLButtonElement>('new'); if (create) create.disabled = busy;\n }\n\n private async run(action: () => Promise<void>): Promise<void> {\n if (this.destroyed || this.busy) return;\n const work = Promise.resolve().then(action); this.active = work;\n this.dialog.setAttribute('aria-busy', 'true'); this.body.inert = true;\n this.syncBusy();\n this.ribbon.element.querySelector<HTMLElement>('.dxr-chrome')!.inert = true;\n this.ribbon.surface.inert = true;\n try { await work; }\n catch (error) { this.status.textContent = this.explain(error); this.ribbon.setStatus(this.explain(error)); throw error; }\n finally {\n this.active = undefined; this.body.inert = false; this.dialog.setAttribute('aria-busy', 'false');\n this.syncBusy();\n this.ribbon.element.querySelector<HTMLElement>('.dxr-chrome')?.removeAttribute('inert');\n this.ribbon.surface.inert = false;\n }\n }\n\n private button(label: string, action: () => void, parent: HTMLElement): HTMLButtonElement {\n const button = parent.ownerDocument.createElement('button'); button.type = 'button'; button.textContent = label;\n button.setAttribute('aria-label', label); button.addEventListener('click', action, { signal: this.events.signal });\n parent.append(button); return button;\n }\n}\n\nfunction download(bytes: Uint8Array, name: string, doc: Document): void {\n const url = URL.createObjectURL(new Blob([bytes.slice()], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }));\n const link = doc.createElement('a'); link.href = url; link.download = name; link.click();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n}\n\nfunction sameBytes(left: Uint8Array, right: Uint8Array): boolean {\n return left.length === right.length && left.every((value, index) => value === right[index]);\n}\n\nconst HISTORY_DRAWER_CSS = `\n.dxr-history-dialog,.dxr-version-preview{box-sizing:border-box;color:#243b42;background:#fff;border:1px solid #dce5e5;box-shadow:0 24px 80px #163f4033;font:14px/1.5 system-ui,sans-serif;padding:24px;overscroll-behavior:contain}\n.dxr-history-dialog{width:min(420px,calc(100vw - 24px));max-height:calc(100dvh - 24px);margin:12px 12px 12px auto;border-radius:18px}\n.dxr-history-dialog::backdrop,.dxr-version-preview::backdrop{background:#16323333;backdrop-filter:blur(2px)}\n.dxr-history-dialog [hidden],.dxr-version-preview [hidden]{display:none!important}\n.dxr-history-dialog button,.dxr-version-preview button{font:inherit;color:inherit;border:1px solid #cbd9d9;background:#fff;border-radius:9px;min-height:40px;padding:8px 12px;cursor:pointer}\n.dxr-history-dialog button:hover,.dxr-version-preview button:hover{background:#eff8f6}\n.dxr-history-dialog :focus-visible,.dxr-version-preview :focus-visible{outline:3px solid #0f766e;outline-offset:3px}\n.dxr-history-header{display:flex;justify-content:flex-end;position:sticky;top:0;z-index:2;background:#fff;box-shadow:0 0 0 6px #fff}\n.dxr-history-dialog .dxr-history-close{border:0;font-size:13px;background:#fff}\n.dxr-history-source{font-weight:600;overflow-wrap:anywhere;margin:12px 0 4px}\n.dxr-history-status{color:#597273;margin:4px 0 18px}\n.dxr-history-dialog>label{display:block;font-size:12px;color:#597273;margin:12px 0}\n.dxr-history-dialog>label select{display:block;width:100%;font:inherit;padding:8px;border:1px solid #cbd9d9;border-radius:8px;background:#fff;color:#243b42}\n.dxr-history-dialog .dx-history{padding:0;border:0;border-radius:0;background:transparent}\n.dxr-history-dialog .dx-history h2{font-size:24px;letter-spacing:-.6px;margin:12px 0}\n.dxr-history-dialog .dx-history button[data-history-action=save]{background:#0f766e;border-color:#0f766e;color:#fff;font-weight:600}\n.dxr-history-dialog .dx-history select{border-radius:9px;background:#f8fbfa}\n.dxr-history-dialog .dx-history option{padding:10px;font-size:13px}\n.dxr-version-preview{width:min(1080px,calc(100vw - 24px));max-height:calc(100dvh - 24px);border-radius:18px}\n.dxr-version-preview h2{font-size:20px;margin:0 0 12px;overflow-wrap:anywhere}\n.dxr-version-actions{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px}\n.dxr-version-paper{max-height:70dvh;overflow:auto;background:#f2f6f5;padding:20px;border-radius:10px}\n@media(max-width:520px){.dxr-history-dialog,.dxr-version-preview{padding:16px}.dxr-version-paper{padding:8px}}\n@media(prefers-reduced-motion:no-preference){.dxr-history-dialog[open]{animation:dxr-history-in .16s ease-out}@keyframes dxr-history-in{from{opacity:0;transform:translateX(16px)}to{opacity:1;transform:translateX(0)}}}\n`;\n", "/**\n * The ribbon surface's markup and stylesheet \u2014 the two static assets `ribbon.ts`\n * wires behaviour onto.\n *\n * They live in their own module because they are *data*: one HTML template and\n * one stylesheet, both authored to be read as a unit. Keeping them out of\n * `ribbon.ts` leaves that file as pure wiring.\n *\n * \u2500\u2500 Addressing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * Every control carries `data-dxr=\"<name>\"`. `ribbon.ts` walks those on mount\n * and stamps `id = idPrefix + name`, so the historical element ids from the\n * standalone demo page survive (specs and bookmarklets keep working) while a\n * second ribbon on the same page can take a prefix and stay collision-free.\n * `data-dxr-list` does the same job for the `<input list>` \u2192 `<datalist id>`\n * link, which is by-id and cannot use a data attribute directly.\n *\n * \u2500\u2500 Shape \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * Word's: a title bar, a tab strip (Home \u00B7 Insert \u00B7 Layout \u00B7 References \u00B7\n * Review \u00B7 View, plus the contextual Table and Header & Footer tabs), the panel\n * for the active tab, the document with its comment gutter, and a status bar\n * that carries the anchor rail, the page/word counts and the zoom control.\n *\n * \u2500\u2500 Responsiveness \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * Layout keys off `data-chrome` on the root (\"full\" | \"compact\"), which\n * `ribbon.ts` sets from a ResizeObserver on the ROOT rather than from viewport\n * media queries. A narrow embed inside a wide desktop page is narrow, and only\n * container measurement gets that right. Compact is the base (mobile-first);\n * `[data-chrome=\"full\"]` adds back the desktop affordances.\n */\n\n/** Bumped whenever RIBBON_CSS changes, so a stale injected stylesheet is replaced. */\nexport const RIBBON_STYLE_VERSION = \"11\";\nexport const RIBBON_STYLE_ATTR = \"data-docxodus-ribbon-styles\";\n\n/** Width of the comment gutter the surface reserves beside the sheet, in px. */\nexport const COMMENT_GUTTER_WIDTH = 264;\n\n/**\n * The ribbon stylesheet. Every rule is scoped under `.dxr` so injecting it is\n * safe on a host page we do not control \u2014 the same guarantee `embed.ts` gives\n * for the converter's document CSS, achieved here by authoring rather than by\n * rewriting.\n */\nexport const RIBBON_CSS = `\n.dxr {\n /* OS-Legal design tokens (github.com/Open-Source-Legal/OS-Legal-Style):\n deep-teal accent, slate foreground scale, warm neutral surfaces, and\n \"light touch\" shadows at 0.03-0.06 opacity \u2014 structure over decoration. */\n --dxr-ink: #1e293b;\n --dxr-sheet: #ffffff;\n --dxr-chrome: #ffffff;\n --dxr-chrome-sunk: #f8fafc;\n --dxr-rule: #e2e8f0;\n --dxr-rule-strong: #cbd5e1;\n --dxr-accent: #0f766e;\n --dxr-accent-hover: #0d9488;\n --dxr-accent-active: #115e59;\n --dxr-wash: #f0fdfa;\n --dxr-wash-on: #ccfbf1;\n --dxr-muted: #475569;\n --dxr-faint: #94a3b8;\n --dxr-data: #0f766e;\n --dxr-danger: #dc2626;\n --dxr-danger-wash: #fef2f2;\n --dxr-desk: #eef2f6;\n --dxr-ui: \"Inter\", system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n --dxr-serif: Georgia, \"Times New Roman\", serif;\n --dxr-mono: ui-monospace, SFMono-Regular, \"Cascadia Mono\", Consolas, monospace;\n --dxr-shadow-sm: 0 1px 2px rgba(15, 23, 42, .04);\n --dxr-shadow-md: 0 1px 3px rgba(15, 23, 42, .06), 0 4px 6px rgba(15, 23, 42, .03);\n --dxr-shadow-lg: 0 4px 6px rgba(15, 23, 42, .05), 0 10px 15px rgba(15, 23, 42, .04);\n --dxr-shadow-xl: 0 8px 16px rgba(15, 23, 42, .06), 0 20px 25px rgba(15, 23, 42, .05);\n --dxr-ease: cubic-bezier(.4, 0, .2, 1);\n --dxr-tap: 28px;\n --dxr-gutter: ${COMMENT_GUTTER_WIDTH}px;\n\n position: relative;\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n isolation: isolate;\n font-family: var(--dxr-ui);\n color: var(--dxr-ink);\n background: var(--dxr-desk);\n -webkit-text-size-adjust: 100%;\n text-size-adjust: 100%;\n}\n.dxr *, .dxr *::before, .dxr *::after { box-sizing: border-box; }\n\n/* \u2500\u2500 Card frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n A drop-in embed carries its OWN boundary instead of hoping the host clips it:\n rounded corners, a hairline, and the house elevation. overflow: clip keeps\n the sticky chrome, scrollbars, and the loading overlay inside the curve.\n Full-bleed hosts mount with data-frame=\"flush\" and stay edge-to-edge. */\n.dxr[data-frame=\"card\"] {\n border: 1px solid var(--dxr-rule);\n border-radius: 14px;\n box-shadow: var(--dxr-shadow-xl);\n overflow: clip;\n}\n\n/* Touch devices get bigger hit targets everywhere the token is used. */\n@media (pointer: coarse) { .dxr { --dxr-tap: 40px; } }\n\n/* \u2500\u2500 Scroll-edge affordances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n The chrome's strips (title bar, tabs, panels, rail) scroll horizontally\n rather than squashing or wrapping \u2014 the compact rule is \"no command is\n removed, the strip scrolls\". But a hard clip mid-control reads as a broken\n layout, especially on a phone, so ribbon.ts measures every strip and stamps\n data-fade with the edges that hide more content (\"l\", \"r\", or both). The\n mask dissolves content at exactly those edges \u2014 the horizontal twin of\n .dxr-scroll's gradient veils \u2014 and lifts entirely once the strip fits, so\n nothing is ever faded unless there is more behind it. */\n.dxr-titlebar, .dxr-tabs, .dxr-panel, .dxr-rail, .dxr-findbar { --dxr-fade-l: 0px; --dxr-fade-r: 0px; }\n.dxr [data-fade] {\n -webkit-mask-image: linear-gradient(to right,\n transparent, #000 var(--dxr-fade-l),\n #000 calc(100% - var(--dxr-fade-r)), transparent);\n mask-image: linear-gradient(to right,\n transparent, #000 var(--dxr-fade-l),\n #000 calc(100% - var(--dxr-fade-r)), transparent);\n}\n.dxr [data-fade~=\"l\"] { --dxr-fade-l: 28px; }\n.dxr [data-fade~=\"r\"] { --dxr-fade-r: 28px; }\n\n/* \u2500\u2500 Chrome shell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.dxr-chrome {\n position: sticky;\n top: 0;\n z-index: 10;\n flex: 0 0 auto;\n background: var(--dxr-chrome);\n border-bottom: 1px solid var(--dxr-rule);\n}\n\n/* Scrolls in EVERY density (compact just tightens it): the fade affordance\n marks any overflowing strip as scrollable, so it must actually be. */\n.dxr-titlebar {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 6px 10px 0;\n overflow-x: auto;\n scrollbar-width: none;\n}\n.dxr-titlebar::-webkit-scrollbar { display: none; }\n.dxr-brand {\n display: flex;\n align-items: baseline;\n gap: 7px;\n min-width: 0;\n font-size: 13px;\n font-weight: 600;\n letter-spacing: -.01em;\n}\n/* A filled circle, echoing the OS-Legal \"Node\" motif rather than a diamond. */\n.dxr-brand .dxr-mark {\n flex: 0 0 auto;\n width: 9px;\n height: 9px;\n border-radius: 50%;\n background: var(--dxr-accent);\n}\n.dxr-brand .dxr-docname {\n overflow: hidden;\n max-width: 22ch;\n color: var(--dxr-muted);\n font-size: 12px;\n font-weight: 400;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dxr-quick { flex: 0 0 auto; display: flex; align-items: center; gap: 3px; }\n.dxr-titlebar .dxr-spacer { flex: 1; }\n.dxr-status {\n overflow: hidden;\n max-width: 42ch;\n color: var(--dxr-muted);\n font-family: var(--dxr-mono);\n font-size: 11.5px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* \u2500\u2500 Tab strip \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.dxr-tabs {\n display: flex;\n gap: 1px;\n padding: 4px 10px 0;\n overflow-x: auto;\n scrollbar-width: none;\n}\n.dxr-tabs::-webkit-scrollbar { display: none; }\n/* Line-variant tabs (the house Tabs default): no boxes, no fills \u2014 the selected\n tab is a 2px accent underline sitting on the panel's own hairline. */\n.dxr-tab {\n flex: 0 0 auto;\n padding: 6px 13px 7px;\n border: none;\n background: none;\n color: var(--dxr-muted);\n font: inherit;\n font-size: 12.5px;\n font-weight: 500;\n cursor: pointer;\n transition: color .15s var(--dxr-ease), box-shadow .15s var(--dxr-ease);\n}\n.dxr-tab:hover { color: var(--dxr-ink); }\n.dxr-tab[aria-selected=\"true\"] {\n color: var(--dxr-ink);\n font-weight: 600;\n box-shadow: inset 0 -2px 0 var(--dxr-accent);\n}\n/* Contextual tabs \u2014 present only while the caret is in a table / a header or footer story. */\n.dxr-tab[data-contextual] { color: var(--dxr-accent); }\n.dxr-tab[data-contextual]::before { content: \"\\\\2022\"; margin-right: 6px; opacity: .6; }\n.dxr-tab[hidden] { display: none; }\n\n/* \u2500\u2500 Ribbon panels \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.dxr-ribbon { background: var(--dxr-chrome-sunk); border-top: 1px solid var(--dxr-rule); }\n.dxr-ribbon[aria-disabled=\"true\"] { opacity: .45; pointer-events: none; }\n.dxr-panel {\n display: none;\n align-items: stretch;\n padding: 6px 10px 7px;\n overflow-x: auto;\n overscroll-behavior-x: contain;\n}\n.dxr-panel[data-active] { display: flex; }\n/* Group label sits ABOVE its controls (a spec-sheet reading), with hairline\n dividers rather than boxes \u2014 lighter than the boxed, label-under convention. */\n.dxr-group {\n flex: 0 0 auto;\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 0 12px;\n border-right: 1px solid var(--dxr-rule);\n}\n.dxr-group:last-child { border-right: none; }\n.dxr-group:first-child { padding-left: 0; }\n.dxr-glabel {\n color: var(--dxr-faint);\n font-size: 9.5px;\n font-weight: 600;\n letter-spacing: .11em;\n text-transform: uppercase;\n}\n.dxr-row { display: flex; gap: 3px; align-items: center; }\n.dxr-row + .dxr-row { margin-top: 1px; }\n\n/* \u2500\u2500 Controls \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n/* One button family, house-style: every control is a ghost \u2014 no borders, no\n fills, no per-button boxes. Hover paints a quiet slate wash; the active\n (toggled) state paints a teal one. Save alone is the flat primary, so the\n surface has exactly one accent-colored action. */\n.dxr button, .dxr label.dxr-btn {\n min-height: var(--dxr-tap);\n padding: 4px 8px;\n border: none;\n border-radius: 6px;\n background: none;\n color: var(--dxr-ink);\n font: inherit;\n font-size: 12.5px;\n font-weight: 500;\n line-height: 1.15;\n cursor: pointer;\n transition: background-color .15s var(--dxr-ease), color .15s var(--dxr-ease),\n box-shadow .15s var(--dxr-ease), transform .15s var(--dxr-ease);\n}\n.dxr label.dxr-btn { display: inline-flex; align-items: center; }\n.dxr button:hover, .dxr label.dxr-btn:hover { background: #f1f5f9; }\n.dxr button:active { background: #e2e8f0; }\n.dxr button:disabled { opacity: .38; cursor: default; background: none; }\n.dxr button.dxr-on, .dxr button[aria-pressed=\"true\"] { color: var(--dxr-accent); background: var(--dxr-wash-on); }\n.dxr-quick button, .dxr-quick label.dxr-btn { padding: 4px 10px; font-size: 12.5px; }\n/* Save \u2014 the house primary: flat accent, sm shadow, the 1px lift on hover. */\n.dxr-quick button[data-dxr=\"save\"]:not(:disabled) {\n background: var(--dxr-accent);\n color: #fff;\n font-weight: 600;\n box-shadow: var(--dxr-shadow-sm);\n}\n.dxr-quick button[data-dxr=\"save\"]:not(:disabled):hover {\n background: var(--dxr-accent-hover);\n box-shadow: var(--dxr-shadow-md);\n transform: translateY(-1px);\n}\n.dxr-quick button[data-dxr=\"save\"]:not(:disabled):active {\n background: var(--dxr-accent-active);\n box-shadow: var(--dxr-shadow-sm);\n transform: translateY(0);\n}\n/* Icon controls sit quieter than text ones until touched (house IconButton). */\n.dxr button.dxr-icon { min-width: var(--dxr-tap); padding: 4px 6px; text-align: center; color: var(--dxr-muted); }\n.dxr button.dxr-icon:hover:not(:disabled) { color: var(--dxr-ink); }\n.dxr button.dxr-icon.dxr-on { color: var(--dxr-accent); }\n/* Icons are inline SVG drawn from the same shapes the control acts on (text lines,\n rules), so alignment and indent read at a glance instead of relying on arrow\n glyphs that collide with undo/redo. currentColor keeps them in step with state. */\n.dxr button svg { display: block; margin: 0 auto; fill: currentColor; }\n.dxr button.dxr-wide { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }\n.dxr button.dxr-danger:hover { color: var(--dxr-danger); background: var(--dxr-danger-wash); }\n.dxr select, .dxr input[type=\"number\"], .dxr input[type=\"text\"], .dxr input[type=\"search\"], .dxr input[type=\"url\"] {\n min-height: var(--dxr-tap);\n padding: 3px 6px;\n border: 1px solid var(--dxr-rule);\n border-radius: 6px;\n background: var(--dxr-sheet);\n color: var(--dxr-ink);\n font: inherit;\n font-size: 12.5px;\n}\n.dxr select:hover, .dxr input:hover { border-color: var(--dxr-rule-strong); }\n.dxr select:focus-visible, .dxr input:focus-visible, .dxr button:focus-visible,\n.dxr .dxr-tab:focus-visible, .dxr label.dxr-btn:focus-within {\n outline: 2px solid var(--dxr-accent);\n outline-offset: 1px;\n}\n.dxr [data-dxr=\"fontsize\"] { width: 58px; }\n.dxr [data-dxr=\"fontfamily\"] { width: 138px; }\n.dxr [data-dxr=\"style\"] { width: 148px; }\n.dxr [data-dxr=\"pgstart\"], .dxr [data-dxr=\"spacebefore\"], .dxr [data-dxr=\"spaceafter\"],\n.dxr [data-dxr=\"specialindentval\"] { width: 62px; }\n.dxr [data-dxr=\"linespacing\"], .dxr [data-dxr=\"listmenu\"], .dxr [data-dxr=\"highlight\"],\n.dxr [data-dxr=\"markup\"], .dxr [data-dxr=\"zoom\"], .dxr [data-dxr=\"margins\"],\n.dxr [data-dxr=\"orientation\"], .dxr [data-dxr=\"pagesize\"], .dxr [data-dxr=\"specialindent\"] { max-width: 150px; }\n.dxr-toggle {\n display: inline-flex;\n gap: 5px;\n align-items: center;\n min-height: var(--dxr-tap);\n color: var(--dxr-ink);\n font-size: 12.5px;\n white-space: nowrap;\n cursor: pointer;\n}\n.dxr-toggle input[type=\"checkbox\"] { accent-color: var(--dxr-accent); margin: 0; }\n.dxr-note { color: var(--dxr-muted); font-size: 11.5px; }\n.dxr-kbd { color: var(--dxr-faint); font-family: var(--dxr-mono); font-size: 10px; }\n\n/* Colour swatch buttons: the button shows the current colour as a bar under its glyph and\n opens the native picker that sits (visually hidden) inside it. */\n.dxr-swatch { position: relative; display: inline-flex; flex-direction: column; align-items: center; gap: 2px; }\n.dxr-swatch > button { padding-bottom: 6px; }\n.dxr-swatch .dxr-swatch-bar {\n position: absolute; left: 7px; right: 7px; bottom: 4px; height: 3px; border-radius: 2px;\n background: var(--dxr-swatch, #1e293b); pointer-events: none;\n}\n.dxr-swatch input[type=\"color\"] {\n position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; border: 0; padding: 0;\n}\n.dxr-swatch [data-dxr=\"highlight\"] {\n min-height: var(--dxr-tap);\n}\n.dxr-hl-swatch { display: inline-block; width: 12px; height: 12px; border-radius: 2px; vertical-align: -2px; margin-right: 4px; border: 1px solid rgba(15,23,42,.15); }\n\n/* \u2500\u2500 Find & replace bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.dxr-findbar {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 5px 10px;\n overflow-x: auto;\n border-top: 1px solid var(--dxr-rule);\n background: var(--dxr-chrome);\n scrollbar-width: none;\n}\n.dxr-findbar[hidden] { display: none; }\n.dxr-findbar > *, .dxr-findbar [data-dxr=\"replacegroup\"] { flex: 0 0 auto; white-space: nowrap; }\n.dxr-findbar [data-dxr=\"replacegroup\"] { display: inline-flex; align-items: center; gap: 6px; }\n.dxr-findbar input[type=\"search\"], .dxr-findbar input[type=\"text\"] { width: 180px; }\n.dxr-findbar .dxr-findcount { min-width: 5ch; color: var(--dxr-muted); font-family: var(--dxr-mono); font-size: 11.5px; }\n\n/* \u2500\u2500 Status bar (carries the anchor rail) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n The addressing spine made permanent chrome. Every block in this editor is\n addressable as kind:scope:unid, and the model of record is a live WASM session \u2014\n so the surface states both, live, instead of hiding them behind devtools. It also\n reports each command's real cost, which is what a smoke test needs to see. Word's\n own status-bar cells (page, words, zoom) sit on the same strip. */\n.dxr-rail {\n display: flex;\n align-items: center;\n flex: 0 0 auto;\n height: 26px;\n padding: 0 10px;\n overflow-x: auto;\n background: #fafafa;\n border-top: 1px solid var(--dxr-rule);\n color: var(--dxr-muted);\n font-family: var(--dxr-mono);\n font-size: 11.5px;\n scrollbar-width: none;\n}\n.dxr-rail::-webkit-scrollbar { display: none; }\n.dxr-rail .dxr-cell {\n display: flex;\n align-items: baseline;\n gap: 6px;\n padding: 0 12px;\n border-right: 1px solid var(--dxr-rule);\n white-space: nowrap;\n}\n.dxr-rail .dxr-cell:first-child { padding-left: 0; }\n.dxr-rail .dxr-cell.dxr-cell-end { margin-left: auto; border-right: none; padding-right: 0; }\n.dxr-rail .dxr-k {\n color: var(--dxr-faint);\n font-family: var(--dxr-ui);\n font-size: 9.5px;\n letter-spacing: .1em;\n text-transform: uppercase;\n}\n.dxr-rail .dxr-v { color: var(--dxr-data); }\n.dxr-rail .dxr-v.dxr-flash { animation: dxr-railflash .45s ease-out; }\n.dxr-rail .dxr-v.dxr-plain { color: var(--dxr-ink); font-family: var(--dxr-ui); font-size: 11.5px; }\n@keyframes dxr-railflash { from { background: #ccfbf1; } to { background: transparent; } }\n.dxr-zoom { display: inline-flex; align-items: center; gap: 2px; }\n.dxr-zoom button { min-height: 22px; min-width: 22px; padding: 0 5px; font-size: 13px; color: var(--dxr-muted); }\n.dxr-zoom select { min-height: 22px; padding: 0 4px; font-size: 11.5px; }\n\n/* \u2500\u2500 Hint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.dxr-hint {\n flex: 0 0 auto;\n max-width: 920px;\n margin: 0 auto;\n padding: 9px 16px 0;\n color: var(--dxr-muted);\n font-size: 12px;\n line-height: 1.5;\n}\n.dxr-hint kbd {\n padding: 0 4px;\n border: 1px solid var(--dxr-rule);\n border-radius: 4px;\n background: #f1f5f9;\n font-family: var(--dxr-mono);\n font-size: 11px;\n}\n\n/* \u2500\u2500 Document surface \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n The surface is also the element the converter's own stylesheet treats as the\n document body: in an embed, its \"body { margin: 20px }\" is rewritten to\n [data-docxodus-embed-root=\"dN\"] [data-dxr-surface] \u2014 (0,2,0), and inserted AFTER\n this sheet, so it wins a tie. Rules that own the SHEET BOX (centering, page\n padding, the paper itself) therefore qualify with the root's data-chrome to reach\n (0,3,0). Rules that only style CONTENT stay unqualified \u2014 there the converter\n SHOULD win.\n (No backticks in this file's comments: the stylesheet is a template literal.) */\n.dxr-scroll { flex: 1 1 auto; min-height: 0; overflow: auto; -webkit-overflow-scrolling: touch; }\n/* Soft scroll boundaries: content dissolves at the chrome and at the bottom edge\n instead of hard-clipping. Sticky gradient veils cost one paint layer each and\n never intercept input. */\n.dxr-scroll::before, .dxr-scroll::after {\n content: \"\";\n position: sticky;\n z-index: 3;\n display: block;\n height: 26px;\n pointer-events: none;\n}\n.dxr-scroll::before {\n top: 0;\n margin-bottom: -26px;\n background: linear-gradient(to bottom, var(--dxr-desk), transparent);\n}\n.dxr-scroll::after {\n bottom: 0;\n margin-top: -26px;\n background: linear-gradient(to top, var(--dxr-desk), transparent);\n}\n.dxr[data-chrome] .dxr-surface { position: relative; margin: 26px auto; padding: 0 16px 96px; }\n/* Reserve the markup area only while a visible comment or draft needs it. The gutter owns\n its empty/hidden state, so ordinary documents stay centered without disabling comments. */\n.dxr[data-chrome=\"full\"] .dxr-surface[data-comments=\"on\"]:has(> .docx-comment-gutter:not([data-empty]):not([hidden])) {\n padding-right: calc(var(--dxr-gutter) + 8px);\n}\n.dxr-surface [contenteditable=\"true\"]:focus {\n outline: 2px solid var(--dxr-accent);\n outline-offset: 2px;\n border-radius: 2px;\n}\n@media (hover: hover) { .dxr-surface [contenteditable=\"true\"]:hover { background: var(--dxr-wash); } }\n\n/* Header/footer bands (continuous view): the top and bottom margin of the sheet, drawn the way\n Word draws a header that is being edited \u2014 a dashed rule with a small tag in the margin. */\n.dxr-surface .docx-hf-band {\n /* Docked outside the zoomed sheet, so it takes the page's on-screen width from the\n custom property the viewport publishes, including when the page exceeds the surface. */\n position: relative;\n width: var(--docx-sheet-width, 100%);\n margin: 0 auto;\n padding: 34px 72px 12px;\n background: var(--dxr-sheet);\n border-radius: 3px 3px 0 0;\n box-shadow: 0 1px 3px rgba(15, 23, 42, .08), 0 12px 24px rgba(15, 23, 42, .06);\n}\n.dxr-surface .docx-hf-band[data-hf-band=\"footer\"] { padding: 12px 72px 34px; border-radius: 0 0 3px 3px; }\n/* The band and the sheet are one piece of paper: kill the sheet's own top/bottom corners and\n let the dashed rule separate the stories from the body. */\n.dxr-surface .docx-hf-band + .docx-body-flow { margin-top: 0; border-radius: 0; box-shadow: none; }\n.dxr-surface .docx-hf-band[data-hf-band=\"footer\"] { margin-top: 0; }\n.dxr[data-chrome] .dxr-surface[data-view=\"continuous\"] .docx-hf-band ~ .docx-body-flow { box-shadow: none; }\n.dxr[data-chrome] .dxr-surface[data-view=\"continuous\"]:has(.docx-hf-band) .docx-body-flow { padding: 18px 0; }\n.dxr-surface .docx-hf-band::after {\n content: \"\"; position: absolute; left: 0; right: 0; bottom: 0; border-bottom: 1px dashed var(--dxr-rule-strong);\n}\n.dxr-surface .docx-hf-band[data-hf-band=\"footer\"]::after { top: 0; bottom: auto; border-bottom: 0; border-top: 1px dashed var(--dxr-rule-strong); }\n.dxr-surface .docx-hf-band:hover::after, .dxr-surface .docx-hf-band[data-hf-active]::after { border-color: var(--dxr-accent); }\n.dxr-surface .docx-hf-tag {\n position: absolute; left: 72px; bottom: -9px; z-index: 2;\n display: flex; align-items: center; gap: 8px;\n padding: 1px 7px; border: 1px solid var(--dxr-rule-strong); border-radius: 4px;\n background: #fff; color: var(--dxr-muted);\n font-family: var(--dxr-ui); font-size: 9.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;\n}\n.dxr-surface .docx-hf-band[data-hf-band=\"footer\"] .docx-hf-tag { bottom: auto; top: -9px; }\n.dxr-surface .docx-hf-band[data-hf-active] .docx-hf-tag { border-color: var(--dxr-accent); color: var(--dxr-accent); }\n.dxr-surface .docx-hf-kinds { display: inline-flex; gap: 2px; }\n.dxr-surface .docx-hf-kinds button {\n min-height: 0; padding: 1px 6px; border-radius: 3px; font-family: var(--dxr-ui); font-size: 9.5px; font-weight: 600;\n letter-spacing: .06em; text-transform: uppercase; color: var(--dxr-muted); background: none;\n}\n.dxr-surface .docx-hf-kinds button[data-on] { background: var(--dxr-wash-on); color: var(--dxr-accent); }\n.dxr-surface .docx-hf-inherited { font-weight: 400; letter-spacing: normal; text-transform: none; font-style: italic; }\n.dxr-surface .docx-hf-placeholder { color: var(--dxr-faint); font-style: italic; cursor: text; }\n/* Bands only: a page host's height is the band the paginator reserved, and a floor here would\n read as \"the story grew\" and trigger a needless re-paginate. */\n.dxr-surface .docx-hf-band .docx-hf-body { min-height: 1.4em; }\n/* Page view: the page's own header/footer area is click-to-edit. */\n.dxr-surface .page-header[data-hf-page], .dxr-surface .page-footer[data-hf-page] { cursor: text; }\n.dxr-surface .page-header[data-hf-page]:hover, .dxr-surface .page-footer[data-hf-page]:hover {\n outline: 1px dashed var(--dxr-rule-strong); outline-offset: 2px;\n}\n.dxr-surface .page-header[data-hf-active], .dxr-surface .page-footer[data-hf-active] {\n outline: 1px dashed var(--dxr-accent); outline-offset: 2px; z-index: 5; background: #fff;\n}\n.dxr-surface [data-hf-active][data-hf-label]::before {\n content: attr(data-hf-label); position: absolute; left: -2px; top: -18px;\n padding: 1px 6px; border: 1px solid var(--dxr-accent); border-radius: 4px; background: #fff; color: var(--dxr-accent);\n font-family: var(--dxr-ui); font-size: 9px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; line-height: 1.4;\n}\n.dxr-surface .page-footer[data-hf-active][data-hf-label]::before { top: auto; bottom: -18px; }\n/* The sheet IS the page. The editor's viewport sizes .docx-body-flow to the section's page\n width and its section wrappers to the authored text column, so the horizontal gutters here\n are the document's own w:sectPr margins, not a padding this chrome invents; only the\n vertical breathing room is ours. Centering is left to margin:auto so a page the viewport\n has zoomed to fit stays centered at its scaled width. */\n.dxr[data-chrome] .dxr-surface[data-view=\"continuous\"] .docx-body-flow {\n /* CSS zoom scales the authored page width. A percentage cap would shrink only the\n paper to the host while its fixed-width section and content keep magnifying. */\n max-width: none;\n margin: 0 auto;\n padding: 56px 0;\n border-radius: 3px;\n background: var(--dxr-sheet);\n box-shadow: 0 1px 3px rgba(15, 23, 42, .08), 0 12px 24px rgba(15, 23, 42, .06);\n}\n\n/* \u2500\u2500 Table size picker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.dxr-pop {\n display: none;\n position: absolute;\n z-index: 30;\n padding: 9px;\n border: 1px solid var(--dxr-rule);\n border-radius: 12px;\n background: #fff;\n box-shadow: var(--dxr-shadow-xl);\n}\n.dxr-pop[data-open] { display: block; }\n.dxr-gridcells { display: grid; grid-template-columns: repeat(10, 16px); gap: 2px; }\n.dxr-gridcells div {\n width: 16px;\n height: 16px;\n border: 1px solid var(--dxr-rule);\n border-radius: 3px;\n background: var(--dxr-chrome-sunk);\n cursor: pointer;\n}\n.dxr-gridcells div[data-on] { background: #ccfbf1; border-color: var(--dxr-accent); }\n.dxr-popfoot {\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 10px;\n margin-top: 8px;\n font-size: 12px;\n}\n/* Small prompt popovers (link URL, page setup), anchored under their button. */\n.dxr-pop form { display: flex; flex-direction: column; gap: 8px; min-width: 260px; font-size: 12.5px; }\n.dxr-pop form label { display: flex; flex-direction: column; gap: 3px; color: var(--dxr-muted); font-size: 11.5px; }\n.dxr-pop form .dxr-row { justify-content: flex-end; }\n.dxr-pop form button[type=\"submit\"] { background: var(--dxr-accent); color: #fff; }\n.dxr-pop form button[type=\"submit\"]:hover { background: var(--dxr-accent-hover); }\n\n/* \u2500\u2500 Compact chrome (the mobile-first base) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n One scrolling strip per tab instead of a multi-row ribbon: group labels turn\n into inline dividers, the rail and hint step aside, and the picker becomes a\n bottom sheet because there is no room to hang a popover off a button. */\n/* A 320px phone cannot hold the product name AND the file actions, and the file\n actions are what a user came for. The strip also scrolls, so nothing is stranded. */\n/* Touch targets grow with the LAYOUT, not the pointer alone: a phone-width chrome is driven\n by a thumb whether or not the browser reports a coarse pointer (an emulated narrow viewport\n does not), so the compact strip adopts the same 40px control floor the coarse-pointer media\n query sets, keeping every icon button at a real tap size. */\n.dxr[data-chrome=\"compact\"] { --dxr-tap: 40px; }\n/* The floor buys tap SIZE; the rows must not spend it again on padding. A phone stacks three\n chrome rows \u2014 title, tabs, commands \u2014 above the page, so every pixel of row padding is paid\n three times before the document starts, and the arcade demo's card (which sizes itself to the\n game screen plus its controls) runs out of viewport when it is. */\n.dxr[data-chrome=\"compact\"] .dxr-titlebar {\n gap: 6px;\n padding: 0 8px;\n}\n.dxr[data-chrome=\"compact\"] .dxr-brandname { display: none; }\n.dxr[data-chrome=\"compact\"] .dxr-brand { flex: 0 1 auto; }\n/* A filename clipped to \"do...\" tells you less than no filename at all, so it keeps a\n readable floor and the strip scrolls instead. The tighter file-action padding is what\n buys that floor back on a 390px screen. */\n.dxr[data-chrome=\"compact\"] .dxr-brand .dxr-docname { min-width: 6ch; max-width: 14ch; }\n.dxr[data-chrome=\"compact\"] .dxr-quick button,\n.dxr[data-chrome=\"compact\"] .dxr-quick label.dxr-btn { padding: 4px 8px; }\n.dxr[data-chrome=\"compact\"] .dxr-status { display: none; }\n.dxr[data-chrome=\"compact\"] .dxr-tabs { padding: 0 8px; }\n/* A tab is a WIDE target \u2014 its label plus 11px of side padding already clears the tap floor\n horizontally \u2014 and it is navigation rather than a command, so it does not need the command\n row's full height. Word's own phone ribbon keeps its tab strip slim for the same reason: the\n page starts higher. The commands below keep the full 40px floor. */\n.dxr[data-chrome=\"compact\"] .dxr-tab { min-height: 34px; padding: 6px 11px 7px; font-size: 12px; }\n.dxr[data-chrome=\"compact\"] .dxr-panel {\n align-items: center;\n gap: 4px;\n padding: 2px 8px;\n scroll-snap-type: x proximity;\n}\n.dxr[data-chrome=\"compact\"] .dxr-group {\n flex-direction: row;\n align-items: center;\n gap: 4px;\n padding: 0 8px;\n scroll-snap-align: start;\n}\n.dxr[data-chrome=\"compact\"] .dxr-glabel { display: none; }\n.dxr[data-chrome=\"compact\"] .dxr-note { display: none; }\n.dxr[data-chrome=\"compact\"] .dxr-rail { display: none; }\n.dxr[data-chrome=\"compact\"] .dxr-hint { display: none; }\n.dxr[data-chrome=\"compact\"] .dxr-row + .dxr-row { margin-top: 0; }\n/* Compact trims the chrome around the page, never the page: the document's own column width\n is what the viewport's fit-to-width zoom scales, so a phone shows a whole smaller page\n instead of a narrower one that breaks its lines somewhere Word never would. */\n.dxr[data-chrome=\"compact\"] .dxr-surface { margin: 12px auto; padding: 0 10px 64px; }\n.dxr[data-chrome=\"compact\"] .dxr-surface[data-view=\"continuous\"] .docx-body-flow { padding: 22px 0; }\n.dxr[data-chrome=\"compact\"] .dxr-surface .docx-hf-band { padding: 26px 18px 10px; }\n.dxr[data-chrome=\"compact\"] .dxr-surface .docx-hf-band[data-hf-band=\"footer\"] { padding: 10px 18px 26px; }\n.dxr[data-chrome=\"compact\"] .dxr-surface .docx-hf-tag { left: 18px; }\n/* No room for a markup column on a phone: comments stay highlighted, bubbles step aside. */\n.dxr[data-chrome=\"compact\"] .docx-comment-gutter, .dxr[data-chrome=\"compact\"] .docx-comment-leaders { display: none; }\n/* A popover anchored to a button has nowhere to go on a narrow surface, so the\n picker docks to the bottom edge where a thumb already is. */\n.dxr[data-chrome=\"compact\"] .dxr-pop[data-open] {\n position: fixed;\n left: 50%;\n right: auto;\n bottom: 12px;\n top: auto !important;\n transform: translateX(-50%);\n max-width: calc(100vw - 20px);\n}\n\n/* \u2500\u2500 Loading overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Kept from the shipped demo: the wait is real (a .NET runtime is streaming), so\n the surface spends it explaining what is being built rather than showing a\n spinner. It covers the whole instrument so half-built chrome never flashes. */\n.dxr-loader {\n position: absolute;\n inset: 0;\n z-index: 40;\n display: grid;\n place-items: center;\n padding: 24px;\n color: #f8fafc;\n background:\n radial-gradient(circle at 20% 20%, rgba(13, 148, 136, .2), transparent 22rem),\n radial-gradient(circle at 82% 80%, rgba(45, 212, 191, .1), transparent 24rem),\n linear-gradient(150deg, #0b1220 0%, #0f172a 55%, #0f2723 100%);\n transition: opacity .55s ease, visibility .55s ease;\n}\n.dxr-loader[hidden] { display: none; }\n/* pointer-events drops the instant the fade starts: the surface underneath is already\n live, so a click during the half-second fade should reach it rather than be eaten. */\n.dxr-loader[data-done] { opacity: 0; visibility: hidden; pointer-events: none; }\n.dxr-loader-grid {\n width: min(850px, 100%);\n display: grid;\n grid-template-columns: 1fr;\n align-items: center;\n gap: 22px;\n text-align: center;\n}\n.dxr-visual { position: relative; width: min(170px, 52vw); aspect-ratio: 1; margin: 0 auto; }\n.dxr-orbit {\n position: absolute;\n inset: 7%;\n border: 1px solid rgba(45, 212, 191, .24);\n border-radius: 50%;\n animation: dxr-spin 9s linear infinite;\n}\n.dxr-orbit.dxr-two {\n inset: 20%;\n border-style: dashed;\n border-color: rgba(94, 234, 212, .3);\n animation-duration: 6s;\n animation-direction: reverse;\n}\n.dxr-orbit::before, .dxr-orbit::after {\n position: absolute;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n content: \"\";\n background: #2dd4bf;\n box-shadow: 0 0 18px rgba(45, 212, 191, .8);\n}\n.dxr-orbit::before { top: -5px; left: 50%; }\n.dxr-orbit::after { right: 7%; bottom: 12%; background: #5eead4; box-shadow: 0 0 18px rgba(94, 234, 212, .7); }\n.dxr-card {\n position: absolute;\n inset: 24% 28%;\n padding: 20px 15px;\n border: 1px solid rgba(255, 255, 255, .3);\n border-radius: 14px;\n background: linear-gradient(150deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, .05));\n box-shadow: 0 22px 50px rgba(0, 0, 0, .35), 0 0 45px rgba(13, 148, 136, .15);\n backdrop-filter: blur(10px);\n animation: dxr-float 3.6s ease-in-out infinite;\n}\n.dxr-card::before {\n position: absolute;\n top: -9px;\n right: -9px;\n padding: 4px 7px;\n border-radius: 6px;\n background: #2dd4bf;\n color: #042f2e;\n content: \"DOCX\";\n font-size: 8px;\n font-weight: 900;\n letter-spacing: .12em;\n}\n.dxr-card i {\n display: block;\n height: 4px;\n margin-bottom: 10px;\n border-radius: 4px;\n background: rgba(255, 255, 255, .56);\n transform-origin: left;\n animation: dxr-pulse 2.2s ease-in-out infinite;\n}\n.dxr-card i:nth-child(2) { width: 76%; animation-delay: -.45s; }\n.dxr-card i:nth-child(3) { width: 88%; animation-delay: -.85s; }\n.dxr-card i:nth-child(4) { width: 58%; background: rgba(248, 113, 113, .75); animation-delay: -1.2s; }\n.dxr-chip {\n position: absolute;\n display: grid;\n width: 34px;\n height: 34px;\n place-items: center;\n border: 1px solid rgba(255, 255, 255, .16);\n border-radius: 11px;\n background: rgba(15, 30, 46, .88);\n box-shadow: 0 12px 30px rgba(0, 0, 0, .28);\n font-size: 11px;\n font-weight: 850;\n}\n.dxr-chip.dxr-b { left: 2%; top: 30%; color: #5eead4; animation: dxr-chip 3s ease-in-out infinite; }\n.dxr-chip.dxr-r { right: -2%; bottom: 24%; color: #fca5a5; animation: dxr-chip 3s -1.4s ease-in-out infinite; }\n.dxr-chip.dxr-s { left: 20%; bottom: 0; color: #6ee7b7; animation: dxr-chip 3s -.7s ease-in-out infinite; }\n.dxr-eyebrow { color: #5eead4; font-size: 10px; font-weight: 850; letter-spacing: .16em; text-transform: uppercase; }\n/* Georgia headline \u2014 the house pairing of a serif headline over Inter UI copy. */\n.dxr-loader h2 {\n margin: 10px auto 10px;\n max-width: 520px;\n font-family: var(--dxr-serif);\n font-size: clamp(23px, 5vw, 38px);\n font-weight: 500;\n line-height: 1.08;\n letter-spacing: -.02em;\n}\n.dxr-loader-copy > p { margin: 0 auto; max-width: 46ch; color: #94a3b8; font-size: 13.5px; line-height: 1.6; }\n.dxr-ad {\n display: flex;\n gap: 12px;\n margin: 20px auto 0;\n max-width: 420px;\n padding: 13px;\n border: 1px solid rgba(148, 163, 184, .16);\n border-radius: 12px;\n background: rgba(255, 255, 255, .04);\n text-align: left;\n}\n.dxr-ad .dxr-num { color: #2dd4bf; font: 800 10px/1.4 var(--dxr-mono); }\n.dxr-ad strong { display: block; font-size: 12.5px; }\n.dxr-ad .dxr-adcopy { display: block; margin-top: 4px; color: #8ba0b9; font-size: 11.5px; line-height: 1.45; }\n.dxr-ad[data-swap] { animation: dxr-swap .4s ease; }\n.dxr-track {\n height: 3px;\n margin: 22px auto 0;\n max-width: 420px;\n overflow: hidden;\n border-radius: 999px;\n background: rgba(255, 255, 255, .09);\n}\n.dxr-bar {\n width: 12%;\n height: 100%;\n border-radius: inherit;\n background: linear-gradient(90deg, #14b8a6, #2dd4bf, #5eead4);\n box-shadow: 0 0 16px rgba(45, 212, 191, .5);\n transition: width .65s cubic-bezier(.22, .8, .28, 1);\n}\n.dxr-meta {\n display: flex;\n justify-content: space-between;\n gap: 14px;\n margin: 9px auto 0;\n max-width: 420px;\n color: #64748b;\n font: 700 9px/1 var(--dxr-mono);\n letter-spacing: .09em;\n text-transform: uppercase;\n}\n.dxr-retry {\n display: none;\n margin-top: 18px;\n padding: 9px 14px;\n border: 1px solid rgba(248, 113, 113, .4);\n border-radius: 9px;\n background: rgba(248, 113, 113, .12);\n color: #fff;\n cursor: pointer;\n}\n.dxr-loader[data-error] .dxr-retry { display: inline-flex; }\n.dxr-loader[data-error] .dxr-visual { opacity: .35; }\n\n/* Two columns once there is room \u2014 the visual earns its space beside the copy. */\n@media (min-width: 760px) {\n .dxr-loader-grid {\n grid-template-columns: minmax(220px, .8fr) minmax(300px, 1.2fr);\n gap: clamp(28px, 6vw, 72px);\n text-align: left;\n }\n .dxr-visual { width: min(280px, 30vw); }\n .dxr-loader h2 { margin-left: 0; }\n .dxr-loader-copy > p { margin-left: 0; min-height: 44px; }\n .dxr-ad, .dxr-track, .dxr-meta { margin-left: 0; }\n}\n\n@keyframes dxr-spin { to { transform: rotate(360deg); } }\n@keyframes dxr-float { 0%, 100% { transform: translateY(-5px) rotate(-2deg); } 50% { transform: translateY(7px) rotate(1deg); } }\n@keyframes dxr-chip { 0%, 100% { transform: translateY(-4px); } 50% { transform: translateY(5px); } }\n@keyframes dxr-pulse { 0%, 100% { transform: scaleX(.65); opacity: .45; } 50% { transform: scaleX(1); opacity: .95; } }\n@keyframes dxr-swap { from { opacity: .1; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }\n\n@media (prefers-reduced-motion: reduce) {\n .dxr *, .dxr *::before, .dxr *::after {\n animation-duration: .01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: .01ms !important;\n }\n}\n`;\n\nconst ICON_ALIGN = (bars: string) =>\n `<svg width=\"15\" height=\"13\" viewBox=\"0 0 15 13\" aria-hidden=\"true\">${bars}</svg>`;\n\n/** Word's highlighter palette (ST_HighlightColor) with its screen colours, in Word's order. */\nexport const HIGHLIGHT_COLORS: ReadonlyArray<{ value: string; label: string; css: string }> = [\n { value: \"yellow\", label: \"Yellow\", css: \"#ffff00\" },\n { value: \"green\", label: \"Bright green\", css: \"#00ff00\" },\n { value: \"cyan\", label: \"Turquoise\", css: \"#00ffff\" },\n { value: \"magenta\", label: \"Pink\", css: \"#ff00ff\" },\n { value: \"blue\", label: \"Blue\", css: \"#0000ff\" },\n { value: \"red\", label: \"Red\", css: \"#ff0000\" },\n { value: \"darkBlue\", label: \"Dark blue\", css: \"#000080\" },\n { value: \"darkCyan\", label: \"Teal\", css: \"#008080\" },\n { value: \"darkGreen\", label: \"Green\", css: \"#008000\" },\n { value: \"darkMagenta\", label: \"Violet\", css: \"#800080\" },\n { value: \"darkRed\", label: \"Dark red\", css: \"#800000\" },\n { value: \"darkYellow\", label: \"Dark yellow\", css: \"#808000\" },\n { value: \"darkGray\", label: \"Gray 50%\", css: \"#808080\" },\n { value: \"lightGray\", label: \"Gray 25%\", css: \"#c0c0c0\" },\n { value: \"black\", label: \"Black\", css: \"#000000\" },\n];\n\n/** The fonts every Word install has; the document's own fonts are added on top at open. */\nexport const COMMON_FONTS: readonly string[] = [\n \"Calibri\", \"Cambria\", \"Arial\", \"Times New Roman\", \"Georgia\", \"Garamond\", \"Verdana\",\n \"Tahoma\", \"Trebuchet MS\", \"Book Antiqua\", \"Century Gothic\", \"Courier New\", \"Consolas\",\n \"Segoe UI\", \"Helvetica\",\n];\n\n/**\n * The ribbon's DOM, as one template.\n *\n * `data-dxr` names are the addressing contract (see the module header); the\n * behavioural attributes (`data-cmd`, `data-align`, `data-indent`, `data-list`,\n * `data-tt`, `data-hf`, `data-rev`, `data-cmt`) are what `ribbon.ts` delegates on,\n * so adding a control here that follows an existing convention needs no wiring change.\n */\nexport const RIBBON_HTML = `\n<div class=\"dxr-chrome\">\n <div class=\"dxr-titlebar\">\n <span class=\"dxr-brand\"><span class=\"dxr-mark\"></span><span class=\"dxr-brandname\">Docxodus</span>\n <span class=\"dxr-docname\" data-dxr=\"docname\">no document</span></span>\n <div class=\"dxr-quick\" data-dxr-files>\n <button type=\"button\" data-dxr=\"new\" title=\"Start a new blank document\">New</button>\n <label class=\"dxr-btn\" tabindex=\"0\">Open<input data-dxr=\"file\" type=\"file\" accept=\".docx\" hidden /></label>\n <button type=\"button\" data-dxr=\"save\" disabled>Save</button>\n </div>\n <button type=\"button\" class=\"dxr-btn\" data-dxr=\"history\" title=\"Browse and save document versions\" aria-haspopup=\"dialog\">Version history</button>\n <div class=\"dxr-quick\">\n <button type=\"button\" class=\"dxr-icon\" data-dxr=\"undo\" title=\"Undo (Ctrl+Z)\" aria-label=\"Undo\">↶</button>\n <button type=\"button\" class=\"dxr-icon\" data-dxr=\"redo\" title=\"Redo (Ctrl+Shift+Z)\" aria-label=\"Redo\">↷</button>\n </div>\n <span class=\"dxr-spacer\"></span>\n <span class=\"dxr-status\" data-dxr=\"status\" role=\"status\" aria-live=\"polite\">Booting WASM…</span>\n </div>\n\n <div class=\"dxr-tabs\" role=\"tablist\">\n <button type=\"button\" class=\"dxr-tab\" role=\"tab\" data-tab=\"home\" aria-selected=\"true\">Home</button>\n <button type=\"button\" class=\"dxr-tab\" role=\"tab\" data-tab=\"insert\" aria-selected=\"false\">Insert</button>\n <button type=\"button\" class=\"dxr-tab\" role=\"tab\" data-tab=\"layout\" aria-selected=\"false\">Layout</button>\n <button type=\"button\" class=\"dxr-tab\" role=\"tab\" data-tab=\"references\" aria-selected=\"false\">References</button>\n <button type=\"button\" class=\"dxr-tab\" role=\"tab\" data-tab=\"review\" aria-selected=\"false\">Review</button>\n <button type=\"button\" class=\"dxr-tab\" role=\"tab\" data-tab=\"view\" aria-selected=\"false\">View</button>\n <button type=\"button\" class=\"dxr-tab\" role=\"tab\" data-tab=\"table\" data-contextual aria-selected=\"false\" hidden>Table</button>\n <button type=\"button\" class=\"dxr-tab\" role=\"tab\" data-tab=\"headerfooter\" data-contextual aria-selected=\"false\" hidden>Header & Footer</button>\n </div>\n\n <div class=\"dxr-ribbon\" data-dxr=\"ribbon\" aria-disabled=\"true\">\n <!-- HOME \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"dxr-panel\" data-panel=\"home\" data-active>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Font</span>\n <div class=\"dxr-row\">\n <select data-dxr=\"fontfamily\" title=\"Font family \u2014 applies to the selection\">\n <option value=\"\">Font…</option>\n </select>\n <input data-dxr=\"fontsize\" data-dxr-list=\"fontsizes\" type=\"number\" min=\"1\" max=\"1638\" step=\"0.5\"\n placeholder=\"pt\" title=\"Font size in points \u2014 type any value or pick a preset\" />\n <datalist data-dxr=\"fontsizes\">\n <option>8</option><option>9</option><option>10</option><option>11</option>\n <option>12</option><option>14</option><option>16</option><option>18</option>\n <option>20</option><option>24</option><option>28</option><option>36</option>\n <option>48</option><option>72</option><option>96</option>\n </datalist>\n <button type=\"button\" class=\"dxr-icon\" data-dxr=\"fontgrow\" title=\"Increase font size (Ctrl+])\">A<sup>▲</sup></button>\n <button type=\"button\" class=\"dxr-icon\" data-dxr=\"fontshrink\" title=\"Decrease font size (Ctrl+[)\">A<sub>▼</sub></button>\n <button type=\"button\" class=\"dxr-icon\" data-dxr=\"clearformat\" title=\"Clear all formatting\">A✘</button>\n </div>\n <div class=\"dxr-row\">\n <button type=\"button\" class=\"dxr-icon\" data-cmd=\"bold\" title=\"Bold (Ctrl+B)\"><b>B</b></button>\n <button type=\"button\" class=\"dxr-icon\" data-cmd=\"italic\" title=\"Italic (Ctrl+I)\"><i>I</i></button>\n <button type=\"button\" class=\"dxr-icon\" data-cmd=\"underline\" title=\"Underline (Ctrl+U)\"><u>U</u></button>\n <button type=\"button\" class=\"dxr-icon\" data-cmd=\"strike\" title=\"Strikethrough\"><s>S</s></button>\n <button type=\"button\" class=\"dxr-icon\" data-cmd=\"superscript\" title=\"Superscript\">x²</button>\n <button type=\"button\" class=\"dxr-icon\" data-cmd=\"subscript\" title=\"Subscript\">x₂</button>\n <button type=\"button\" class=\"dxr-icon\" data-dxr=\"smallcaps\" title=\"Small caps\" aria-pressed=\"false\"\n style=\"font-variant: small-caps;\">Aa</button>\n <button type=\"button\" class=\"dxr-icon\" data-cmd=\"code\" title=\"Inline code\"></></button>\n <span class=\"dxr-swatch\" title=\"Font color\">\n <button type=\"button\" class=\"dxr-icon\" data-dxr=\"fontcolorbtn\" aria-label=\"Font color\"><b>A</b></button>\n <span class=\"dxr-swatch-bar\" data-dxr=\"fontcolorbar\"></span>\n <input type=\"color\" data-dxr=\"fontcolor\" value=\"#1e293b\" aria-label=\"Pick a font color\" />\n </span>\n <span class=\"dxr-swatch\" title=\"Text highlight color\">\n <select data-dxr=\"highlight\" aria-label=\"Text highlight color\">\n <option value=\"\">✎ Highlight</option>\n <option value=\"none\">No color</option>\n </select>\n </span>\n </div>\n </div>\n\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Paragraph</span>\n <div class=\"dxr-row\">\n <button type=\"button\" class=\"dxr-icon\" data-list=\"bullet\" title=\"Bullets\">•≡</button>\n <button type=\"button\" class=\"dxr-icon\" data-list=\"decimal\" title=\"Numbering\">1.≡</button>\n <select data-dxr=\"listmenu\" title=\"Numbering format\">\n <option value=\"\">List style…</option>\n <option value=\"bullet\">• Bullet</option>\n <option value=\"decimal\">1. 2. 3.</option>\n <option value=\"decimalParenthesis\">(1) (2) (3)</option>\n <option value=\"lowerLetter\">a. b. c.</option>\n <option value=\"lowerLetterParenthesis\">(a) (b) (c)</option>\n <option value=\"upperLetter\">A. B. C.</option>\n <option value=\"lowerRoman\">i. ii. iii.</option>\n <option value=\"lowerRomanParenthesis\">(i) (ii) (iii)</option>\n <option value=\"upperRoman\">I. II. III.</option>\n <option value=\"none\">No list</option>\n </select>\n <button type=\"button\" class=\"dxr-icon\" data-indent=\"-720\" title=\"Decrease indent\">${ICON_ALIGN(\n '<rect x=\"0\" y=\"0\" width=\"15\" height=\"1.6\"/><rect x=\"6\" y=\"3.8\" width=\"9\" height=\"1.6\"/><rect x=\"6\" y=\"7.6\" width=\"9\" height=\"1.6\"/><rect x=\"0\" y=\"11.4\" width=\"15\" height=\"1.6\"/><path d=\"M4.6 4.2v4.6L0.6 6.5z\"/>',\n )}</button>\n <button type=\"button\" class=\"dxr-icon\" data-indent=\"720\" title=\"Increase indent\">${ICON_ALIGN(\n '<rect x=\"0\" y=\"0\" width=\"15\" height=\"1.6\"/><rect x=\"6\" y=\"3.8\" width=\"9\" height=\"1.6\"/><rect x=\"6\" y=\"7.6\" width=\"9\" height=\"1.6\"/><rect x=\"0\" y=\"11.4\" width=\"15\" height=\"1.6\"/><path d=\"M0.6 4.2v4.6l4-2.3z\"/>',\n )}</button>\n </div>\n <div class=\"dxr-row\">\n <button type=\"button\" class=\"dxr-icon\" data-align=\"left\" title=\"Align left (Ctrl+L)\">${ICON_ALIGN(\n '<rect x=\"0\" y=\"0\" width=\"15\" height=\"1.6\"/><rect x=\"0\" y=\"3.8\" width=\"9\" height=\"1.6\"/><rect x=\"0\" y=\"7.6\" width=\"15\" height=\"1.6\"/><rect x=\"0\" y=\"11.4\" width=\"9\" height=\"1.6\"/>',\n )}</button>\n <button type=\"button\" class=\"dxr-icon\" data-align=\"center\" title=\"Center (Ctrl+E)\">${ICON_ALIGN(\n '<rect x=\"0\" y=\"0\" width=\"15\" height=\"1.6\"/><rect x=\"3\" y=\"3.8\" width=\"9\" height=\"1.6\"/><rect x=\"0\" y=\"7.6\" width=\"15\" height=\"1.6\"/><rect x=\"3\" y=\"11.4\" width=\"9\" height=\"1.6\"/>',\n )}</button>\n <button type=\"button\" class=\"dxr-icon\" data-align=\"right\" title=\"Align right (Ctrl+R)\">${ICON_ALIGN(\n '<rect x=\"0\" y=\"0\" width=\"15\" height=\"1.6\"/><rect x=\"6\" y=\"3.8\" width=\"9\" height=\"1.6\"/><rect x=\"0\" y=\"7.6\" width=\"15\" height=\"1.6\"/><rect x=\"6\" y=\"11.4\" width=\"9\" height=\"1.6\"/>',\n )}</button>\n <button type=\"button\" class=\"dxr-icon\" data-align=\"justify\" title=\"Justify (Ctrl+J)\">${ICON_ALIGN(\n '<rect x=\"0\" y=\"0\" width=\"15\" height=\"1.6\"/><rect x=\"0\" y=\"3.8\" width=\"15\" height=\"1.6\"/><rect x=\"0\" y=\"7.6\" width=\"15\" height=\"1.6\"/><rect x=\"0\" y=\"11.4\" width=\"15\" height=\"1.6\"/>',\n )}</button>\n <select data-dxr=\"linespacing\" title=\"Line spacing\">\n <option value=\"\">↕ Spacing…</option>\n <option value=\"1\">1.0</option>\n <option value=\"1.15\">1.15</option>\n <option value=\"1.5\">1.5</option>\n <option value=\"2\">2.0</option>\n <option value=\"2.5\">2.5</option>\n <option value=\"3\">3.0</option>\n </select>\n </div>\n </div>\n\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Styles</span>\n <div class=\"dxr-row\">\n <select data-dxr=\"style\" title=\"Paragraph style\">\n <option value=\"\">Style…</option>\n <option value=\"Normal\">Normal</option>\n <option value=\"Heading1\">Heading 1</option>\n <option value=\"Heading2\">Heading 2</option>\n <option value=\"Heading3\">Heading 3</option>\n <option value=\"Title\">Title</option>\n </select>\n </div>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"delblock\" class=\"dxr-danger\" title=\"Delete the block the caret is in\">Delete block</button>\n </div>\n </div>\n\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Editing</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"findtoggle\" title=\"Find (Ctrl+F)\">🔍 Find</button>\n </div>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"replacetoggle\" title=\"Find and replace (Ctrl+H)\">Replace</button>\n </div>\n </div>\n </div>\n\n <!-- INSERT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"dxr-panel\" data-panel=\"insert\">\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Pages</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-pagebreak title=\"Start this block on a new page (Ctrl+Enter)\">Page break</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Tables</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"table\" title=\"Insert a table \u2014 pick its size on the grid\">▦ Table</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Illustrations</span>\n <div class=\"dxr-row\">\n <label class=\"dxr-btn\" tabindex=\"0\" title=\"Insert a picture from a file\">🖼 Picture<input data-dxr=\"picturefile\" type=\"file\" accept=\"image/png,image/jpeg,image/gif,image/bmp,image/webp,image/tiff\" hidden /></label>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Links</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"link\" title=\"Link the selected text to a URL (Ctrl+K)\">🔗 Link</button>\n <button type=\"button\" data-dxr=\"unlink\" title=\"Remove the link at the caret\">Unlink</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Comments</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"insertcomment\" title=\"Comment on the selection\">💬 Comment</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Header & Footer</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"gotoheader\" title=\"Edit the header\">Header</button>\n <button type=\"button\" data-dxr=\"gotofooter\" title=\"Edit the footer\">Footer</button>\n <select data-dxr=\"pagenummenu\" title=\"Add a page number to the footer\">\n <option value=\"\"># Page number…</option>\n <option value=\"currentPage\">Page number</option>\n <option value=\"totalPages\">Total pages</option>\n <option value=\"pageOf\">Page X of Y</option>\n </select>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Rules</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"hr\" class=\"dxr-wide\" title=\"Insert a single rule\"><svg width=\"22\" height=\"8\" viewBox=\"0 0 22 8\" aria-hidden=\"true\"><rect x=\"0\" y=\"3.2\" width=\"22\" height=\"1.4\"/></svg>Single</button>\n <button type=\"button\" data-dxr=\"hrThick\" class=\"dxr-wide\" title=\"Insert a thick rule\"><svg width=\"22\" height=\"8\" viewBox=\"0 0 22 8\" aria-hidden=\"true\"><rect x=\"0\" y=\"2.4\" width=\"22\" height=\"3.2\"/></svg>Thick</button>\n <button type=\"button\" data-dxr=\"hrDouble\" class=\"dxr-wide\" title=\"Insert a double rule\"><svg width=\"22\" height=\"8\" viewBox=\"0 0 22 8\" aria-hidden=\"true\"><rect x=\"0\" y=\"1.6\" width=\"22\" height=\"1.3\"/><rect x=\"0\" y=\"5\" width=\"22\" height=\"1.3\"/></svg>Double</button>\n </div>\n <div class=\"dxr-row\">\n <select data-dxr=\"rulepos\" title=\"Where the rule lands relative to the current block\">\n <option value=\"below\">Below block</option>\n <option value=\"above\">Above block</option>\n </select>\n <button type=\"button\" data-dxr=\"hrClear\" title=\"Remove the rule or paragraph border\">Clear</button>\n </div>\n </div>\n </div>\n\n <!-- LAYOUT \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"dxr-panel\" data-panel=\"layout\">\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Page setup</span>\n <div class=\"dxr-row\">\n <select data-dxr=\"margins\" title=\"Page margins for this section\">\n <option value=\"\">Margins…</option>\n <option value=\"1440,1440,1440,1440\">Normal \u2014 1" all round</option>\n <option value=\"720,720,720,720\">Narrow \u2014 0.5" all round</option>\n <option value=\"1440,1440,1080,1080\">Moderate \u2014 1" top/bottom, 0.75" sides</option>\n <option value=\"1440,1440,2880,2880\">Wide \u2014 1" top/bottom, 2" sides</option>\n </select>\n <select data-dxr=\"orientation\" title=\"Page orientation for this section\">\n <option value=\"\">Orientation…</option>\n <option value=\"portrait\">Portrait</option>\n <option value=\"landscape\">Landscape</option>\n </select>\n </div>\n <div class=\"dxr-row\">\n <select data-dxr=\"pagesize\" title=\"Paper size for this section\">\n <option value=\"\">Size…</option>\n <option value=\"12240,15840\">Letter \u2014 8.5 × 11"</option>\n <option value=\"12240,20160\">Legal \u2014 8.5 × 14"</option>\n <option value=\"11906,16838\">A4 \u2014 210 × 297 mm</option>\n <option value=\"15840,24480\">Tabloid \u2014 11 × 17"</option>\n </select>\n <span class=\"dxr-note\" data-dxr=\"pagesetupnote\"></span>\n </div>\n </div>\n\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Paragraph</span>\n <div class=\"dxr-row\">\n <label class=\"dxr-toggle\">Before <input data-dxr=\"spacebefore\" type=\"number\" min=\"0\" step=\"1\" placeholder=\"pt\" title=\"Space before the paragraph, in points\" /></label>\n <label class=\"dxr-toggle\">After <input data-dxr=\"spaceafter\" type=\"number\" min=\"0\" step=\"1\" placeholder=\"pt\" title=\"Space after the paragraph, in points\" /></label>\n </div>\n <div class=\"dxr-row\">\n <select data-dxr=\"specialindent\" title=\"First-line or hanging indent\">\n <option value=\"\">Special…</option>\n <option value=\"none\">(none)</option>\n <option value=\"firstLine\">First line</option>\n <option value=\"hanging\">Hanging</option>\n </select>\n <label class=\"dxr-toggle\">by <input data-dxr=\"specialindentval\" type=\"number\" min=\"0\" step=\"0.1\" value=\"0.5\" title=\"Indent amount, in inches\" /> in</label>\n </div>\n </div>\n\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Page numbers</span>\n <div class=\"dxr-row\">\n <select data-dxr=\"pgfmt\" title=\"Number format for this section\">\n <option value=\"\">Format…</option>\n <option value=\"decimal\">1, 2, 3</option>\n <option value=\"lowerLetter\">a, b, c</option>\n <option value=\"upperLetter\">A, B, C</option>\n <option value=\"lowerRoman\">i, ii, iii</option>\n <option value=\"upperRoman\">I, II, III</option>\n </select>\n <label class=\"dxr-toggle\">Start at\n <input data-dxr=\"pgstart\" type=\"number\" min=\"1\" step=\"1\"\n title=\"Restart this section's numbering at this value\" />\n </label>\n <button type=\"button\" data-dxr=\"pgclear\" title=\"Continue the previous section's numbering\">Clear</button>\n </div>\n <div class=\"dxr-row\">\n <span class=\"dxr-note\">Applies to the section holding the caret.</span>\n </div>\n </div>\n\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">View</span>\n <div class=\"dxr-row\">\n <label class=\"dxr-toggle\"><input data-dxr=\"paginated\" type=\"checkbox\" /> Page view</label>\n </div>\n <div class=\"dxr-row\">\n <label class=\"dxr-toggle\"><input data-dxr=\"headerfooter\" type=\"checkbox\" checked /> Headers & footers</label>\n </div>\n </div>\n </div>\n\n <!-- REFERENCES \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"dxr-panel\" data-panel=\"references\">\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Table of contents</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"toc\" title=\"Insert a table of contents built from the document's headings\">☰ Table of Contents</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Footnotes</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"footnote\" title=\"Cite a new footnote at the caret\">Insert Footnote</button>\n <button type=\"button\" data-dxr=\"endnote\" title=\"Cite a new endnote at the caret\">Insert Endnote</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Footer fields</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"pagenum\" title=\"Add a page-number field to the footer\">Page number</button>\n <button type=\"button\" data-dxr=\"totalpages\" title=\"Add a total-pages field to the footer\">Total pages</button>\n </div>\n </div>\n </div>\n\n <!-- REVIEW \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"dxr-panel\" data-panel=\"review\">\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Comments</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"comment\" title=\"Comment on the selection (Ctrl+Alt+M)\">💬 New Comment</button>\n <button type=\"button\" data-dxr=\"commentdelete\" class=\"dxr-danger\" title=\"Delete the active comment thread\">Delete</button>\n <button type=\"button\" data-dxr=\"commentprev\" class=\"dxr-icon\" title=\"Previous comment\">▲</button>\n <button type=\"button\" data-dxr=\"commentnext\" class=\"dxr-icon\" title=\"Next comment\">▼</button>\n </div>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"commentresolve\" title=\"Resolve or reopen the active thread\">Resolve</button>\n <label class=\"dxr-toggle\"><input data-dxr=\"showcomments\" type=\"checkbox\" checked /> Show comments</label>\n <span class=\"dxr-note\" data-dxr=\"commentcount\"></span>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Tracking</span>\n <div class=\"dxr-row\">\n <label class=\"dxr-toggle\"><input data-dxr=\"trackchanges\" type=\"checkbox\" /> Track changes</label>\n </div>\n <div class=\"dxr-row\">\n <select data-dxr=\"markup\" title=\"How revisions are shown\">\n <option value=\"all\">All markup</option>\n <option value=\"none\">No markup</option>\n </select>\n <input data-dxr=\"author\" type=\"text\" placeholder=\"Author\" title=\"Name stamped on your comments and revisions\" style=\"width: 110px;\" />\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Changes</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-rev=\"accept\" title=\"Accept the change at the caret\">✓ Accept</button>\n <button type=\"button\" data-rev=\"reject\" title=\"Reject the change at the caret\">✗ Reject</button>\n <button type=\"button\" data-rev=\"prev\" class=\"dxr-icon\" title=\"Previous change\">▲</button>\n <button type=\"button\" data-rev=\"next\" class=\"dxr-icon\" title=\"Next change\">▼</button>\n </div>\n <div class=\"dxr-row\">\n <button type=\"button\" data-rev=\"acceptall\" title=\"Accept every tracked change\">Accept all</button>\n <button type=\"button\" data-rev=\"rejectall\" title=\"Reject every tracked change\">Reject all</button>\n <span class=\"dxr-note\" data-dxr=\"revcount\"></span>\n </div>\n </div>\n </div>\n\n <!-- VIEW \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"dxr-panel\" data-panel=\"view\">\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Views</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"viewpage\" title=\"Page view \u2014 real page boxes, headers and footers in the margins\">🖹 Page view</button>\n <button type=\"button\" data-dxr=\"viewweb\" title=\"Continuous view \u2014 one sheet, no page breaks\">☰ Continuous</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Zoom</span>\n <div class=\"dxr-row\">\n <select data-dxr=\"zoom\" title=\"Zoom\">\n <option value=\"0.5\">50%</option>\n <option value=\"0.75\">75%</option>\n <option value=\"0.9\">90%</option>\n <option value=\"1\" selected>100%</option>\n <option value=\"1.25\">125%</option>\n <option value=\"1.5\">150%</option>\n <option value=\"2\">200%</option>\n </select>\n <button type=\"button\" data-dxr=\"zoomfit\" title=\"Fit the page to the window\">Fit width</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Show</span>\n <div class=\"dxr-row\">\n <label class=\"dxr-toggle\"><input data-dxr=\"showrail\" type=\"checkbox\" checked /> Status bar</label>\n <label class=\"dxr-toggle\"><input data-dxr=\"showhint\" type=\"checkbox\" checked /> Editing hint</label>\n </div>\n </div>\n </div>\n\n <!-- TABLE (contextual) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Row/column editing lives here rather than in a floating toolbar: a docked\n contextual tab cannot overlap the cell you are editing. -->\n <div class=\"dxr-panel\" data-panel=\"table\">\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Rows</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-tt=\"rowAbove\" title=\"Insert a row above this one\">Insert above</button>\n <button type=\"button\" data-tt=\"rowBelow\" title=\"Insert a row below this one\">Insert below</button>\n <button type=\"button\" data-tt=\"delRow\" class=\"dxr-danger\" title=\"Delete this row\">Delete row</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Columns</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-tt=\"colLeft\" title=\"Insert a column to the left\">Insert left</button>\n <button type=\"button\" data-tt=\"colRight\" title=\"Insert a column to the right\">Insert right</button>\n <button type=\"button\" data-tt=\"delCol\" class=\"dxr-danger\" title=\"Delete this column\">Delete column</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Merge</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-tt=\"mergeRight\" title=\"Merge this cell with the one to its right\">Merge right</button>\n <button type=\"button\" data-tt=\"mergeDown\" title=\"Merge this cell with the one below\">Merge down</button>\n <button type=\"button\" data-tt=\"unmerge\" title=\"Split a merged cell back into its cells\">Split</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Design</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-tt=\"borders\" title=\"Draw all borders\">Borders</button>\n <button type=\"button\" data-tt=\"noborders\" title=\"Remove all borders\">No borders</button>\n <span class=\"dxr-swatch\" title=\"Cell shading\">\n <button type=\"button\" class=\"dxr-icon\" data-dxr=\"shadebtn\" aria-label=\"Cell shading\">▦</button>\n <span class=\"dxr-swatch-bar\" data-dxr=\"shadebar\" style=\"--dxr-swatch: #fef08a;\"></span>\n <input type=\"color\" data-dxr=\"shade\" value=\"#fef08a\" aria-label=\"Pick a cell shading\" />\n </span>\n <button type=\"button\" data-tt=\"noshade\" title=\"Remove cell shading\">No shading</button>\n </div>\n <div class=\"dxr-row\">\n <label class=\"dxr-toggle\"><input data-dxr=\"repeatheader\" type=\"checkbox\" /> Repeat header row</label>\n <button type=\"button\" data-tt=\"delTable\" class=\"dxr-danger\" title=\"Delete the whole table\">Delete table</button>\n </div>\n </div>\n </div>\n\n <!-- HEADER & FOOTER (contextual) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Word's Header & Footer Tools: the two option checkboxes, page-number fields,\n navigation between the stories, and Close. -->\n <div class=\"dxr-panel\" data-panel=\"headerfooter\">\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Options</span>\n <div class=\"dxr-row\">\n <label class=\"dxr-toggle\"><input data-dxr=\"hfFirst\" type=\"checkbox\" /> Different first page</label>\n </div>\n <div class=\"dxr-row\">\n <label class=\"dxr-toggle\"><input data-dxr=\"hfEven\" type=\"checkbox\" /> Different odd & even pages</label>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Insert</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-hf=\"pagenum\" title=\"Insert the page number at the end of this line\">Page number</button>\n <button type=\"button\" data-hf=\"totalpages\" title=\"Insert the total page count\">Total pages</button>\n <button type=\"button\" data-hf=\"pageof\" title=\"Insert "Page X of Y"\">Page X of Y</button>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Navigation</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-hf=\"header\" title=\"Go to the header\">Go to Header</button>\n <button type=\"button\" data-hf=\"footer\" title=\"Go to the footer\">Go to Footer</button>\n </div>\n <div class=\"dxr-row\">\n <span class=\"dxr-note\" data-dxr=\"hfstory\">Header</span>\n </div>\n </div>\n <div class=\"dxr-group\">\n <span class=\"dxr-glabel\">Close</span>\n <div class=\"dxr-row\">\n <button type=\"button\" data-hf=\"close\" title=\"Return to the document body (Esc)\">✕ Close Header and Footer</button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Find & replace strip, under the ribbon. -->\n <div class=\"dxr-findbar\" data-dxr=\"findbar\" hidden>\n <input data-dxr=\"findtext\" type=\"search\" placeholder=\"Find\" aria-label=\"Find\" />\n <button type=\"button\" class=\"dxr-icon\" data-dxr=\"findprev\" title=\"Previous match (Shift+Enter)\">▲</button>\n <button type=\"button\" class=\"dxr-icon\" data-dxr=\"findnext\" title=\"Next match (Enter)\">▼</button>\n <span class=\"dxr-findcount\" data-dxr=\"findcount\"></span>\n <label class=\"dxr-toggle\"><input data-dxr=\"findcase\" type=\"checkbox\" /> Match case</label>\n <span data-dxr=\"replacegroup\">\n <input data-dxr=\"replacetext\" type=\"text\" placeholder=\"Replace with\" aria-label=\"Replace with\" />\n <button type=\"button\" data-dxr=\"replaceone\" title=\"Replace this match\">Replace</button>\n <button type=\"button\" data-dxr=\"replaceall\" title=\"Replace every match\">Replace all</button>\n </span>\n <span class=\"dxr-spacer\" style=\"flex:1\"></span>\n <button type=\"button\" class=\"dxr-icon\" data-dxr=\"findclose\" title=\"Close (Esc)\">✕</button>\n </div>\n</div>\n\n<div class=\"dxr-scroll\" data-dxr-scroll>\n <p class=\"dxr-hint\" data-dxr-hint></p>\n <div class=\"dxr-surface\" data-dxr=\"editor\" data-dxr-surface data-view=\"continuous\" data-comments=\"on\"></div>\n</div>\n\n<!-- Status bar \u2014 live engine state (the anchor rail), Word's page/word cells, and zoom. -->\n<div class=\"dxr-rail\" data-dxr-rail>\n <span class=\"dxr-cell\"><span class=\"dxr-k\">anchor</span><span class=\"dxr-v\" data-dxr=\"railAnchor\">—</span></span>\n <span class=\"dxr-cell\"><span class=\"dxr-k\">blocks</span><span class=\"dxr-v\" data-dxr=\"railBlocks\">—</span></span>\n <span class=\"dxr-cell\"><span class=\"dxr-k\">session</span><span class=\"dxr-v\" data-dxr=\"railSession\">—</span></span>\n <span class=\"dxr-cell\"><span class=\"dxr-k\">last op</span><span class=\"dxr-v\" data-dxr=\"railOp\">—</span></span>\n <span class=\"dxr-cell\"><span class=\"dxr-v dxr-plain\" data-dxr=\"pageinfo\">—</span></span>\n <span class=\"dxr-cell\"><span class=\"dxr-v dxr-plain\" data-dxr=\"wordcount\">—</span></span>\n <span class=\"dxr-cell dxr-cell-end\">\n <span class=\"dxr-zoom\">\n <button type=\"button\" data-dxr=\"zoomout\" title=\"Zoom out\" aria-label=\"Zoom out\">−</button>\n <select data-dxr=\"zoomlevel\" title=\"Zoom\" aria-label=\"Zoom level\">\n <option value=\"0.5\">50%</option>\n <option value=\"0.75\">75%</option>\n <option value=\"0.9\">90%</option>\n <option value=\"1\" selected>100%</option>\n <option value=\"1.25\">125%</option>\n <option value=\"1.5\">150%</option>\n <option value=\"2\">200%</option>\n </select>\n <button type=\"button\" data-dxr=\"zoomin\" title=\"Zoom in\" aria-label=\"Zoom in\">+</button>\n </span>\n </span>\n</div>\n\n<!-- Table size picker, anchored to the Insert tab's Table button. -->\n<div class=\"dxr-pop\" data-dxr=\"gridpicker\">\n <div class=\"dxr-gridcells\" data-dxr=\"gridcells\"></div>\n <div class=\"dxr-popfoot\">\n <span data-dxr=\"gridlabel\">0 × 0</span>\n <span style=\"display:inline-flex; align-items:center; gap:10px;\">\n <label class=\"dxr-toggle\">Align\n <select data-dxr=\"gridalign\">\n <option value=\"left\">Left</option>\n <option value=\"center\">Center</option>\n <option value=\"right\">Right</option>\n </select>\n </label>\n <label class=\"dxr-toggle\"><input data-dxr=\"gridborderless\" type=\"checkbox\" checked /> Borderless</label>\n </span>\n </div>\n</div>\n\n<!-- Link popover, anchored to the Insert tab's Link button. -->\n<div class=\"dxr-pop\" data-dxr=\"linkpop\">\n <form data-dxr=\"linkform\">\n <label>Address <input data-dxr=\"linkurl\" type=\"url\" placeholder=\"https://\" required /></label>\n <div class=\"dxr-row\">\n <button type=\"button\" data-dxr=\"linkcancel\">Cancel</button>\n <button type=\"submit\">Insert link</button>\n </div>\n </form>\n</div>\n\n<div class=\"dxr-loader\" data-dxr=\"loader\" aria-live=\"polite\" hidden>\n <div class=\"dxr-loader-grid\">\n <div class=\"dxr-visual\" aria-hidden=\"true\">\n <div class=\"dxr-orbit\"></div><div class=\"dxr-orbit dxr-two\"></div>\n <div class=\"dxr-card\"><i></i><i></i><i></i><i></i></div>\n <span class=\"dxr-chip dxr-b\">B</span><span class=\"dxr-chip dxr-r\">±</span><span class=\"dxr-chip dxr-s\">↓</span>\n </div>\n <div class=\"dxr-loader-copy\">\n <div class=\"dxr-eyebrow\" data-dxr=\"loaderEyebrow\">Running locally in this tab</div>\n <h2 data-dxr=\"loaderTitle\">Booting .NET inside your browser</h2>\n <p data-dxr=\"loaderCopy\">Streaming the trimmed WebAssembly runtime.</p>\n <div class=\"dxr-ad\" data-dxr=\"loaderAd\">\n <span class=\"dxr-num\" data-dxr=\"loaderNumber\">01</span>\n <div><strong data-dxr=\"loaderAdTitle\"></strong><span class=\"dxr-adcopy\" data-dxr=\"loaderAdCopy\"></span></div>\n </div>\n <div class=\"dxr-track\" aria-hidden=\"true\"><div class=\"dxr-bar\" data-dxr=\"loaderBar\"></div></div>\n <div class=\"dxr-meta\"><span data-dxr=\"loaderLabel\">Loading engine</span><span data-dxr=\"loaderMeta\">DOCX → WASM → DOCX</span></div>\n <button type=\"button\" class=\"dxr-retry\" data-dxr=\"loaderRetry\">Retry loading</button>\n </div>\n </div>\n</div>\n`;\n\n/** The default hint copy, shown above the document in full chrome. */\nexport const RIBBON_HINT_HTML =\n \"Click any paragraph, heading, table cell, footnote, header or footer to edit it. \" +\n \"<kbd>Enter</kbd> splits a block, <kbd>Backspace</kbd> at the start merges it into the previous one, \" +\n \"<kbd>Ctrl</kbd>+<kbd>Z</kbd> undoes. Select text and press <b>New Comment</b> to annotate it. Only the block you \" +\n \"changed re-renders \u2014 everything else keeps full fidelity, and <b>Save</b> writes a lossless .docx.\";\n", "/**\n * The ribbon surface \u2014 the full editor UI as a mountable module.\n *\n * `DocxEditor` (editor.ts) is the document engine: it owns the live `DocxSession`,\n * the block wiring and every command. It has deliberately no chrome. This module is\n * the chrome \u2014 the tabbed ribbon, the status bar (with the anchor rail), the table\n * picker, the find bar and the loading overlay \u2014 wired onto exactly that command\n * surface and nothing else.\n *\n * It exists because the same UI was hand-written three times (the standalone demo,\n * the GitHub Pages landing page, the compact iframe player) and drifted. Now the\n * surface has one owner, and the three hosts differ only in how they obtain the\n * WASM exports and how much of the chrome they turn on:\n *\n * ```ts\n * // Host that already booted the .NET runtime itself:\n * const ribbon = mountRibbon(document.querySelector(\"#app\")!, { exports });\n * ribbon.open(bytes, \"contract.docx\");\n *\n * // Host that wants one call and a CDN (see embed.ts):\n * await createRibbonEditor(\"#app\", \"./contract.docx\", { chrome: \"auto\" });\n * ```\n *\n * Chrome density is measured from the ROOT ELEMENT, not the viewport: a narrow\n * embed on a wide desktop page is narrow. See ribbon-chrome.ts for the layout.\n */\n\nimport { DocxEditor } from \"./editor.js\";\nimport type {\n DocxEditorExports,\n DocxEditorOptions,\n EditorAlignment,\n EditorMatch,\n FormatKey,\n} from \"./editor.js\";\nimport { threadMembers } from \"./editor-comments.js\";\nimport { RibbonHistory } from './ribbon-history.js';\nimport type { RibbonHistoryBinding } from './ribbon-history.js';\nexport type { RibbonHistoryBinding, RibbonHistoryOptions } from './ribbon-history.js';\nimport type { BandWhich } from \"./editor-headerfooter.js\";\nimport { TrackedChangeMode } from \"./types.js\";\nimport type { ListFormat, NumberFormat } from \"./types.js\";\nimport {\n COMMON_FONTS,\n HIGHLIGHT_COLORS,\n RIBBON_CSS,\n RIBBON_HINT_HTML,\n RIBBON_HTML,\n RIBBON_STYLE_ATTR,\n RIBBON_STYLE_VERSION,\n} from \"./ribbon-chrome.js\";\n\n// Re-exported so the IIFE bundle built from this module (window.DocxodusEditor)\n// carries both the shell and the engine it wraps.\nexport { DocxEditor } from \"./editor.js\";\nexport type { DocxEditorExports, DocxEditorOptions } from \"./editor.js\";\n\n/** Which layout the chrome uses. \"auto\" measures the root and switches at `compactBreakpoint`. */\nexport type RibbonChromeMode = \"full\" | \"compact\" | \"auto\";\n\n/** The lifecycle the surface reports on its root as `data-state`. */\nexport type RibbonState = \"idle\" | \"loading\" | \"ready\" | \"error\";\n\n/** One step of the loading narrative: what is happening, and how far along it is. */\nexport interface RibbonLoaderStage {\n title: string;\n copy: string;\n /** 0\u2013100. Drives the progress bar. */\n progress: number;\n /** The short machine-side label under the bar. */\n label: string;\n}\n\n/** A rotating capability card shown while the engine streams. */\nexport interface RibbonLoaderFeature {\n number: string;\n title: string;\n copy: string;\n}\n\nexport interface RibbonLoaderOptions {\n /** Replace the four default stages. */\n stages?: RibbonLoaderStage[];\n /** Replace the rotating cards. Pass `[]` to hide the card entirely. */\n features?: RibbonLoaderFeature[];\n /** Micro-caps line above the title. */\n eyebrow?: string;\n /** Right-hand label under the progress bar. */\n meta?: string;\n /** Milliseconds between card rotations. Default 1750. */\n rotateMs?: number;\n /** What the Retry button does. Default: reload the page. */\n onRetry?: () => void;\n}\n\nexport interface RibbonOptions extends DocxEditorOptions {\n /** Optional version-history services. createRibbonEditor accepts history: true to wire browser storage. */\n history?: RibbonHistoryBinding;\n /** WASM exports. Omit to mount chrome first (showing the loader) and call `setExports` later. */\n exports?: DocxEditorExports;\n /** Layout density. Default \"auto\". */\n chrome?: RibbonChromeMode;\n /**\n * Boundary treatment. \"flush\" (default) is edge-to-edge for full-bleed hosts\n * and hosts that frame the surface themselves; \"card\" makes the surface carry\n * its own boundary \u2014 rounded corners, hairline border, house shadow \u2014 for a\n * drop-in embed in the middle of a page. `createRibbonEditor` defaults to\n * \"card\", since that is the drop-in path.\n */\n frame?: \"card\" | \"flush\";\n /** Root width, in px, below which \"auto\" picks compact. Default 720. */\n compactBreakpoint?: number;\n /** Show the status bar with the anchor rail (full chrome only). Default true. */\n rail?: boolean;\n /** Show New / Open / Save. Default true. */\n fileActions?: boolean;\n /**\n * Editing hint above the document: false to hide, or a string to replace it.\n * Rendered as HTML (the default copy uses `<kbd>`), so pass author-controlled\n * markup only. Default true.\n */\n hint?: boolean | string;\n /** Loading overlay: false to suppress it, or an object to reword it. Default true. */\n loader?: boolean | RibbonLoaderOptions;\n /** Name shown in the title bar and used for the downloaded file. Default \"untitled.docx\". */\n documentName?: string;\n /**\n * Element-id prefix. Controls are addressable as `data-dxr=\"<name>\"` always, and\n * additionally get `id = idPrefix + name`. Omit and the surface uses bare ids when\n * they are free on the page, falling back to a generated prefix when they are not \u2014\n * so a second ribbon never collides with the first.\n */\n idPrefix?: string;\n /** Replace the default Save behaviour (download the bytes). */\n onSave?: (bytes: Uint8Array, name: string) => void;\n /** Called after any document opens, with the live editor. */\n onOpen?: (editor: DocxEditor) => void;\n /** Called whenever the status line changes. */\n onStatus?: (text: string) => void;\n /** Called after every ribbon command, with its label and measured duration. */\n onCommand?: (label: string, ms: number) => void;\n}\n\n/** Drives the loading overlay. Safe to call when the loader is disabled \u2014 every method no-ops. */\nexport interface RibbonLoader {\n /** Re-show the overlay (e.g. before loading a second document). */\n show(): void;\n /** Jump to a numbered stage, or set one inline. */\n stage(step: number | Partial<RibbonLoaderStage>): void;\n /** Move the bar without changing the copy. */\n progress(percent: number, label?: string): void;\n /** Fade the overlay out and stop the rotation. */\n done(): void;\n /** Show the failure state with a Retry button. */\n fail(error: unknown): void;\n}\n\nexport interface RibbonEditor {\n readonly history: RibbonHistory | null;\n /** The mounted root element (carries `data-state` and `data-chrome`). */\n readonly element: HTMLElement;\n /** The element the document renders into. */\n readonly surface: HTMLElement;\n /** The live editor, or null before a document is open. */\n readonly editor: DocxEditor | null;\n /** The density actually in effect right now. */\n readonly chrome: \"full\" | \"compact\";\n /** The loading overlay controller. */\n readonly loader: RibbonLoader;\n /** Supply (or replace) the WASM exports after mounting. */\n setExports(exports: DocxEditorExports): void;\n /** Open a document, replacing any open one. Throws if exports are not set yet. */\n open(bytes: Uint8Array, name?: string): DocxEditor;\n /** Open a fresh blank document. */\n openBlank(name?: string): DocxEditor;\n /** Lossless DOCX bytes, or null when nothing is open. */\n save(): Uint8Array | null;\n /** Save and hand the bytes to `onSave` (default: browser download). */\n download(name?: string): void;\n /** Set the status line. */\n setStatus(text: string): void;\n /** Activate a ribbon tab by name (\"home\" | \"insert\" | \"layout\" | \"references\" | \"review\" | \"view\" | \"table\" | \"headerfooter\"). */\n selectTab(name: string): void;\n /** Force a density, or hand control back to measurement with \"auto\". */\n setChrome(mode: RibbonChromeMode): void;\n /** Look up a control by its `data-dxr` name. */\n control<T extends HTMLElement = HTMLElement>(name: string): T | null;\n /** Close the session, drop listeners and empty the container. */\n destroy(): void;\n}\n\nconst DEFAULT_STAGES: RibbonLoaderStage[] = [\n {\n title: \"Booting .NET inside your browser\",\n copy: \"Streaming the trimmed WebAssembly runtime. No document bytes are sent to a server.\",\n progress: 16,\n label: \"Loading engine\",\n },\n {\n title: \"Opening the document\",\n copy: \"Parsing OOXML parts, styles, numbering, tables, notes, and tracked revisions locally.\",\n progress: 54,\n label: \"Reading document\",\n },\n {\n title: \"Wiring lossless editing\",\n copy: \"Connecting every editable block to its native WordprocessingML anchor.\",\n progress: 84,\n label: \"Mounting editor\",\n },\n {\n title: \"Your local editor is ready\",\n copy: \"Select text, use the ribbon, switch page view, and save a real DOCX.\",\n progress: 100,\n label: \"Ready\",\n },\n];\n\nconst DEFAULT_FEATURES: RibbonLoaderFeature[] = [\n { number: \"01\", title: \"Zero-upload architecture\", copy: \"Your source file and edits never leave this browser session.\" },\n { number: \"02\", title: \"Word-grade OOXML fidelity\", copy: \"Tables, numbering, footnotes, redlines, comments, and styles stay native.\" },\n { number: \"03\", title: \"Surgical editing\", copy: \"Formatting and text edits target real document anchors instead of flattening the file.\" },\n { number: \"04\", title: \"Lossless DOCX out\", copy: \"Undo, redo, edit, and save a Word document that remains a Word document.\" },\n];\n\n/** Every `data-dxr` name the template defines \u2014 the id-collision probe set. */\nconst CONTROL_NAMES = [\n \"docname\", \"new\", \"file\", \"save\", \"undo\", \"redo\", \"status\", \"ribbon\",\n \"fontsize\", \"fontsizes\", \"fontfamily\", \"fontgrow\", \"fontshrink\", \"clearformat\", \"smallcaps\",\n \"fontcolorbtn\", \"fontcolorbar\", \"fontcolor\", \"highlight\", \"listmenu\", \"linespacing\",\n \"style\", \"delblock\", \"findtoggle\", \"replacetoggle\",\n \"table\", \"picturefile\", \"link\", \"unlink\", \"insertcomment\", \"gotoheader\", \"gotofooter\", \"pagenummenu\",\n \"hr\", \"hrThick\", \"hrDouble\", \"rulepos\", \"hrClear\",\n \"margins\", \"orientation\", \"pagesize\", \"pagesetupnote\", \"spacebefore\", \"spaceafter\",\n \"specialindent\", \"specialindentval\", \"pgfmt\", \"pgstart\", \"pgclear\", \"paginated\", \"headerfooter\",\n \"toc\", \"footnote\", \"endnote\", \"pagenum\", \"totalpages\",\n \"comment\", \"commentdelete\", \"commentprev\", \"commentnext\", \"commentresolve\", \"showcomments\",\n \"commentcount\", \"trackchanges\", \"markup\", \"author\", \"revcount\",\n \"viewpage\", \"viewweb\", \"zoom\", \"zoomfit\", \"showrail\", \"showhint\",\n \"shadebtn\", \"shadebar\", \"shade\", \"repeatheader\",\n \"hfFirst\", \"hfEven\", \"hfstory\",\n \"findbar\", \"findtext\", \"findprev\", \"findnext\", \"findcount\", \"findcase\", \"replacegroup\",\n \"replacetext\", \"replaceone\", \"replaceall\", \"findclose\",\n \"railAnchor\", \"railBlocks\", \"railSession\", \"railOp\", \"pageinfo\", \"wordcount\",\n \"zoomout\", \"zoomlevel\", \"zoomin\",\n \"gridpicker\", \"gridcells\", \"gridlabel\", \"gridalign\", \"gridborderless\",\n \"linkpop\", \"linkform\", \"linkurl\", \"linkcancel\",\n \"editor\",\n \"loader\", \"loaderEyebrow\", \"loaderTitle\", \"loaderCopy\", \"loaderAd\", \"loaderNumber\",\n \"loaderAdTitle\", \"loaderAdCopy\", \"loaderBar\", \"loaderLabel\", \"loaderMeta\", \"loaderRetry\",\n];\n\nconst GRID_ROWS = 8;\nconst GRID_COLS = 10;\nconst ZOOM_STEPS = [0.5, 0.75, 0.9, 1, 1.25, 1.5, 2];\n\nlet nextIdPrefixSeed = 0;\n\n/** Inject the ribbon stylesheet once per document (replacing an older version). */\nfunction ensureStyles(doc: Document): void {\n const existing = doc.querySelector<HTMLStyleElement>(`style[${RIBBON_STYLE_ATTR}]`);\n if (existing?.getAttribute(RIBBON_STYLE_ATTR) === RIBBON_STYLE_VERSION) return;\n existing?.remove();\n const style = doc.createElement(\"style\");\n style.setAttribute(RIBBON_STYLE_ATTR, RIBBON_STYLE_VERSION);\n style.textContent = RIBBON_CSS;\n (doc.head ?? doc.documentElement).appendChild(style);\n}\n\n/**\n * Pick an id prefix. An explicit one always wins. Otherwise bare ids are used when\n * every name is free on the page \u2014 which keeps the historical ids of the standalone\n * demo intact \u2014 and a generated prefix is used the moment any of them is taken.\n */\nfunction resolveIdPrefix(explicit: string | undefined, doc: Document): string {\n if (explicit !== undefined) return explicit;\n if (!CONTROL_NAMES.some((name) => doc.getElementById(name))) return \"\";\n for (;;) {\n const candidate = `dxr${++nextIdPrefixSeed}-`;\n if (!CONTROL_NAMES.some((name) => doc.getElementById(candidate + name))) return candidate;\n }\n}\n\nfunction resolveContainer(container: string | HTMLElement): HTMLElement {\n if (typeof container !== \"string\") return container;\n const el = document.querySelector<HTMLElement>(container);\n if (!el) throw new Error(`Docxodus ribbon: no element matches \"${container}\"`);\n return el;\n}\n\n/** CSS colour \u2192 \"#rrggbb\" (for the colour inputs), or null when it cannot be expressed. */\nfunction toHex(color: string): string | null {\n const m = /^rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/.exec(color);\n if (m) {\n return \"#\" + [m[1], m[2], m[3]].map((n) => parseInt(n, 10).toString(16).padStart(2, \"0\")).join(\"\");\n }\n if (/^#[0-9a-f]{6}$/i.test(color)) return color.toLowerCase();\n return null;\n}\n\n/**\n * Mount the ribbon surface into `container`.\n *\n * The chrome paints synchronously \u2014 including the loading overlay \u2014 so a host can\n * mount before its WASM runtime exists, narrate the boot through `loader`, then call\n * `setExports` and `open`.\n */\nexport function mountRibbon(\n container: string | HTMLElement,\n options: RibbonOptions = {},\n): RibbonEditor {\n return new RibbonSurface(resolveContainer(container), options);\n}\n\nclass RibbonSurface implements RibbonEditor {\n readonly element: HTMLElement;\n readonly surface: HTMLElement;\n readonly loader: RibbonLoader;\n readonly history: RibbonHistory | null;\n\n private readonly options: RibbonOptions;\n private readonly idPrefix: string;\n private readonly loaderOptions: RibbonLoaderOptions | null;\n private readonly stages: RibbonLoaderStage[];\n private readonly features: RibbonLoaderFeature[];\n\n private exports: DocxEditorExports | null;\n private live: DocxEditor | null = null;\n private documentName: string;\n private chromeMode: RibbonChromeMode;\n private density: \"full\" | \"compact\" = \"full\";\n private headerFooter: boolean;\n private author: string;\n private destroyed = false;\n\n private featureTimer: ReturnType<typeof setInterval> | null = null;\n private featureIndex = 0;\n private resizeObserver: ResizeObserver | null = null;\n private strips: HTMLElement[] = [];\n private stripObserver: ResizeObserver | null = null;\n private lastAnchorText = \"\";\n private selectionFrame: number | null = null;\n private statsTimer: ReturnType<typeof setTimeout> | null = null;\n private findMatches: EditorMatch[] = [];\n private findIndex = -1;\n private readonly onSelectionChange: () => void;\n private readonly onDocumentMouseDown: (event: MouseEvent) => void;\n private readonly onKeydown: (event: KeyboardEvent) => void;\n\n constructor(container: HTMLElement, options: RibbonOptions) {\n this.options = options;\n this.exports = options.exports ?? null;\n this.documentName = options.documentName ?? \"untitled.docx\";\n this.chromeMode = options.chrome ?? \"auto\";\n // Headers and footers are document content, so the surface edits them by default; the\n // engine's own default stays off for consumers that mount `DocxEditor` bare.\n this.headerFooter = options.headerFooter ?? true;\n this.author = options.commentAuthor ?? options.revisionAuthor ?? \"Reviewer\";\n // false suppresses the overlay; true/omitted takes the defaults; an object rewords it.\n this.loaderOptions =\n options.loader === false\n ? null\n : typeof options.loader === \"object\"\n ? options.loader\n : {};\n this.stages = this.loaderOptions?.stages ?? DEFAULT_STAGES;\n this.features = this.loaderOptions?.features ?? DEFAULT_FEATURES;\n\n const doc = container.ownerDocument ?? document;\n ensureStyles(doc);\n this.idPrefix = resolveIdPrefix(options.idPrefix, doc);\n\n const root = doc.createElement(\"div\");\n root.className = \"dxr\";\n root.dataset.state = \"idle\";\n root.dataset.frame = this.options.frame ?? \"flush\";\n root.innerHTML = RIBBON_HTML;\n for (const el of Array.from(root.querySelectorAll<HTMLElement>(\"[data-dxr]\"))) {\n el.id = this.idPrefix + el.dataset.dxr;\n }\n for (const el of Array.from(root.querySelectorAll<HTMLElement>(\"[data-dxr-list]\"))) {\n el.setAttribute(\"list\", this.idPrefix + el.dataset.dxrList);\n }\n container.replaceChildren(root);\n this.element = root;\n this.surface = this.require(\"editor\");\n\n this.applyStaticOptions();\n this.buildGrid();\n this.populateStaticMenus();\n this.wire();\n this.wireScrollFades();\n this.applyChrome();\n\n this.loader = this.createLoaderController();\n if (this.loaderOptions) this.loader.show();\n\n // Coalesced to one frame: selectionchange fires per keystroke and continuously\n // during a drag, and the sync reads computed styles.\n this.onSelectionChange = () => {\n if (this.selectionFrame != null) cancelAnimationFrame(this.selectionFrame);\n this.selectionFrame = requestAnimationFrame(() => {\n this.selectionFrame = null;\n this.syncSelection();\n });\n };\n doc.addEventListener(\"selectionchange\", this.onSelectionChange);\n this.onDocumentMouseDown = (event) => this.maybeClosePopovers(event);\n doc.addEventListener(\"mousedown\", this.onDocumentMouseDown);\n this.onKeydown = (event) => this.handleShortcut(event);\n root.addEventListener(\"keydown\", this.onKeydown);\n\n if (this.chromeMode === \"auto\" && typeof ResizeObserver !== \"undefined\") {\n this.resizeObserver = new ResizeObserver(() => this.applyChrome());\n this.resizeObserver.observe(root);\n }\n this.history = options.history ? new RibbonHistory(this, options.history) : null;\n }\n\n // \u2500\u2500 element lookup \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n control<T extends HTMLElement = HTMLElement>(name: string): T | null {\n return this.element.querySelector<T>(`[data-dxr=\"${name}\"]`);\n }\n\n private require<T extends HTMLElement = HTMLElement>(name: string): T {\n const el = this.control<T>(name);\n if (!el) throw new Error(`Docxodus ribbon: template is missing \"${name}\"`);\n return el;\n }\n\n // \u2500\u2500 mount-time configuration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private applyStaticOptions(): void {\n const hintEl = this.element.querySelector<HTMLElement>(\"[data-dxr-hint]\");\n if (hintEl) {\n if (this.options.hint === false) hintEl.remove();\n else hintEl.innerHTML = typeof this.options.hint === \"string\" ? this.options.hint : RIBBON_HINT_HTML;\n }\n if (this.options.rail === false) {\n this.element.querySelector(\"[data-dxr-rail]\")?.remove();\n }\n if (this.options.fileActions === false) {\n this.element.querySelector(\"[data-dxr-files]\")?.remove();\n }\n if (!this.loaderOptions) this.control(\"loader\")?.remove();\n if (!this.options.history) this.control('history')?.remove();\n else {\n const file = this.control<HTMLInputElement>('file');\n if (file) { file.accept = '.docx,.docxhistory'; file.setAttribute('aria-label', 'Open a document or history file'); }\n }\n\n this.require(\"docname\").textContent = this.documentName;\n this.require<HTMLInputElement>(\"paginated\").checked = this.options.paginated ?? false;\n this.require<HTMLInputElement>(\"headerfooter\").checked = this.headerFooter;\n this.require<HTMLInputElement>(\"trackchanges\").checked =\n this.options.trackedChanges === TrackedChangeMode.RenderInline;\n this.require<HTMLInputElement>(\"author\").value = this.author;\n this.surface.dataset.view = this.options.paginated ? \"paginated\" : \"continuous\";\n this.surface.dataset.comments = this.options.comments === false ? \"off\" : \"on\";\n }\n\n private buildGrid(): void {\n const cells = this.require(\"gridcells\");\n const fragment = document.createDocumentFragment();\n for (let r = 0; r < GRID_ROWS; r++) {\n for (let c = 0; c < GRID_COLS; c++) {\n const cell = document.createElement(\"div\");\n cell.dataset.r = String(r);\n cell.dataset.c = String(c);\n fragment.appendChild(cell);\n }\n }\n cells.replaceChildren(fragment);\n }\n\n /** Menus whose entries do not depend on the document. */\n private populateStaticMenus(): void {\n const highlight = this.require<HTMLSelectElement>(\"highlight\");\n for (const color of HIGHLIGHT_COLORS) {\n const opt = document.createElement(\"option\");\n opt.value = color.value;\n opt.textContent = `\u25A0 ${color.label}`;\n opt.style.color = color.css;\n highlight.appendChild(opt);\n }\n this.populateFonts([]);\n }\n\n /** The font menu: the document's own fonts first, then the common list, no duplicates. */\n private populateFonts(documentFonts: string[]): void {\n const select = this.require<HTMLSelectElement>(\"fontfamily\");\n const seen = new Set<string>();\n select.replaceChildren();\n const placeholder = document.createElement(\"option\");\n placeholder.value = \"\";\n placeholder.textContent = \"Font\u2026\";\n select.appendChild(placeholder);\n const add = (name: string, group: HTMLElement | HTMLSelectElement) => {\n const key = name.toLowerCase();\n if (seen.has(key)) return;\n seen.add(key);\n const opt = document.createElement(\"option\");\n opt.value = name;\n opt.textContent = name;\n opt.style.fontFamily = `\"${name}\", sans-serif`;\n group.appendChild(opt);\n };\n if (documentFonts.length > 0) {\n const group = document.createElement(\"optgroup\");\n group.label = \"In this document\";\n for (const name of documentFonts) add(name, group);\n select.appendChild(group);\n }\n const common = document.createElement(\"optgroup\");\n common.label = \"Common fonts\";\n for (const name of COMMON_FONTS) add(name, common);\n select.appendChild(common);\n }\n\n /** The style gallery: every paragraph style the document defines, quick styles first, plus\n * the built-ins Word always offers (the engine creates a missing built-in on first use). */\n private populateStyles(): void {\n const select = this.require<HTMLSelectElement>(\"style\");\n const styles = this.live?.styles() ?? [];\n const paragraphStyles = styles.filter((s) => s.type === \"paragraph\" && !s.semiHidden);\n if (paragraphStyles.length === 0) return; // older bundle: keep the static five\n const have = new Set(paragraphStyles.map((s) => s.id.toLowerCase()));\n const builtIns: Array<[string, string, number]> = [\n [\"Normal\", \"Normal\", 0], [\"Heading1\", \"Heading 1\", 9], [\"Heading2\", \"Heading 2\", 9],\n [\"Heading3\", \"Heading 3\", 9], [\"Title\", \"Title\", 10], [\"Subtitle\", \"Subtitle\", 11],\n [\"Quote\", \"Quote\", 29], [\"ListParagraph\", \"List Paragraph\", 34],\n ];\n for (const [id, name, priority] of builtIns) {\n if (have.has(id.toLowerCase())) continue;\n paragraphStyles.push({\n id, name, type: \"paragraph\", isDefault: false, isCustom: false, hasLatentException: false,\n uiPriority: priority, quickFormat: true,\n });\n }\n paragraphStyles.sort((a, b) => {\n const qa = a.quickFormat ? 0 : 1;\n const qb = b.quickFormat ? 0 : 1;\n if (qa !== qb) return qa - qb;\n const pa = a.uiPriority ?? 99;\n const pb = b.uiPriority ?? 99;\n if (pa !== pb) return pa - pb;\n return a.name.localeCompare(b.name);\n });\n select.replaceChildren();\n const placeholder = document.createElement(\"option\");\n placeholder.value = \"\";\n placeholder.textContent = \"Style\u2026\";\n select.appendChild(placeholder);\n for (const style of paragraphStyles) {\n const opt = document.createElement(\"option\");\n opt.value = style.id;\n opt.textContent = style.name;\n select.appendChild(opt);\n }\n }\n\n // \u2500\u2500 chrome density \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n get chrome(): \"full\" | \"compact\" {\n return this.density;\n }\n\n setChrome(mode: RibbonChromeMode): void {\n this.chromeMode = mode;\n if (mode === \"auto\" && !this.resizeObserver && typeof ResizeObserver !== \"undefined\") {\n this.resizeObserver = new ResizeObserver(() => this.applyChrome());\n this.resizeObserver.observe(this.element);\n }\n this.applyChrome();\n }\n\n private applyChrome(): void {\n const breakpoint = this.options.compactBreakpoint ?? 720;\n const width = this.element.clientWidth || this.element.getBoundingClientRect().width;\n const next: \"full\" | \"compact\" =\n this.chromeMode === \"auto\"\n // Width 0 means the root is not laid out yet (display:none, or measured before\n // first paint). Assume the roomier layout and let the observer correct it.\n ? (width > 0 && width < breakpoint ? \"compact\" : \"full\")\n : this.chromeMode;\n if (next === this.density && this.element.dataset.chrome) return;\n this.density = next;\n this.element.dataset.chrome = next;\n // A popover's absolute position is meaningless after a density flip.\n this.closePopovers();\n // A density flip relays out every strip; re-measure without waiting for\n // the observer so the fades never lag a frame behind the new layout.\n this.syncAllStripFades();\n }\n\n // \u2500\u2500 scroll-edge affordances \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private syncStripFade(strip: HTMLElement): void {\n const max = strip.scrollWidth - strip.clientWidth;\n const tokens =\n max <= 1 ? \"\" : `${strip.scrollLeft > 1 ? \"l \" : \"\"}${strip.scrollLeft < max - 1 ? \"r\" : \"\"}`.trim();\n if (tokens) strip.setAttribute(\"data-fade\", tokens);\n else strip.removeAttribute(\"data-fade\");\n }\n\n private syncAllStripFades(): void {\n for (const strip of this.strips) this.syncStripFade(strip);\n }\n\n private wireScrollFades(): void {\n this.strips = Array.from(\n this.element.querySelectorAll<HTMLElement>(\".dxr-titlebar, .dxr-tabs, .dxr-panel, .dxr-rail, .dxr-findbar\"),\n );\n if (typeof ResizeObserver !== \"undefined\") {\n // One observer for all strips. It also fires when a panel becomes the\n // active one (display flips from none), which is what keeps a freshly\n // selected tab's fades honest without per-tab wiring.\n this.stripObserver = new ResizeObserver((entries) => {\n for (const entry of entries) this.syncStripFade(entry.target as HTMLElement);\n });\n }\n for (const strip of this.strips) {\n strip.addEventListener(\"scroll\", () => this.syncStripFade(strip), { passive: true });\n this.stripObserver?.observe(strip);\n this.syncStripFade(strip);\n }\n }\n\n // \u2500\u2500 status \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Publish the lifecycle on the root, where CSS and host pages can key off it. */\n private setState(state: RibbonState): void {\n this.element.dataset.state = state;\n }\n\n setStatus(text: string): void {\n const el = this.control(\"status\");\n if (el) el.textContent = text;\n this.options.onStatus?.(text);\n }\n\n // \u2500\u2500 document lifecycle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n get editor(): DocxEditor | null {\n return this.live;\n }\n\n setExports(exports: DocxEditorExports): void {\n this.exports = exports;\n }\n\n open(bytes: Uint8Array, name?: string): DocxEditor {\n if (!this.exports) throw new Error(\"Docxodus ribbon: WASM exports are not set yet\");\n this.history?.beforeOpen();\n const paginated = this.require<HTMLInputElement>(\"paginated\").checked;\n // Render the candidate before retiring the current session. Invalid uploads keep its\n // DOM, selection and undo stack intact. The viewport measures again after attachment.\n const candidateSurface = this.surface.cloneNode(false) as HTMLElement;\n candidateSurface.dataset.view = paginated ? \"paginated\" : \"continuous\";\n\n const started = performance.now();\n const tracked = this.require<HTMLInputElement>(\"trackchanges\").checked\n ? TrackedChangeMode.RenderInline\n : (this.options.trackedChanges ?? TrackedChangeMode.Accept);\n const candidate = DocxEditor.open(candidateSurface, bytes, this.exports, {\n cssPrefix: this.options.cssPrefix,\n fabricateClasses: this.options.fabricateClasses,\n editable: this.options.editable,\n scale: this.options.scale,\n columnWidth: this.options.columnWidth,\n fitToWidth: this.options.fitToWidth,\n onEdit: (info) => {\n this.history?.edited();\n this.options.onEdit?.(info);\n this.scheduleStats();\n },\n onMove: info => { this.history?.edited(); this.options.onMove?.(info); },\n onStoryChange: (which) => this.onStoryChange(which),\n onCommentsChange: (info) => this.onCommentsChange(info),\n paginated,\n headerFooter: this.headerFooter,\n blockDrag: this.options.blockDrag ?? true,\n trackedChanges: tracked,\n revisionAuthor: this.author,\n comments: this.options.comments,\n commentAuthor: this.author,\n });\n this.live?.close();\n candidate.adoptContainer(this.surface);\n this.surface.dataset.view = paginated ? \"paginated\" : \"continuous\";\n this.live = candidate;\n if (name) this.documentName = name;\n this.require('docname').textContent = this.documentName;\n this.closeFindBar();\n this.history?.documentOpened(this.documentName);\n const saveButton = this.control<HTMLButtonElement>(\"save\");\n if (saveButton) saveButton.disabled = false;\n this.require(\"ribbon\").setAttribute(\"aria-disabled\", \"false\");\n this.setState(\"ready\");\n this.setStatus(`Rendered in ${Math.round(performance.now() - started)} ms`);\n this.populateStyles();\n this.populateFonts(this.documentFonts());\n this.syncPageNumbering();\n this.syncLayoutState();\n this.syncReviewState();\n this.syncZoom();\n this.refreshRailCounts();\n this.refreshRailAnchor();\n this.scheduleStats();\n this.options.onOpen?.(this.live);\n return this.live;\n }\n\n openBlank(name = \"untitled.docx\"): DocxEditor {\n if (!this.exports) throw new Error(\"Docxodus ribbon: WASM exports are not set yet\");\n return this.open(this.exports.DocxSessionBridge.CreateBlankDocx(), name);\n }\n\n save(): Uint8Array | null {\n return this.live ? this.live.save() : null;\n }\n\n download(name?: string): void {\n const bytes = this.save();\n if (!bytes) return;\n const filename = name ?? this.documentName ?? \"edited.docx\";\n if (this.options.onSave) {\n this.options.onSave(bytes, filename);\n return;\n }\n const url = URL.createObjectURL(\n new Blob([bytes as BlobPart], {\n type: \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n }),\n );\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n link.click();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n this.setStatus(`Saved ${filename}`);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n void this.history?.destroy();\n const doc = this.element.ownerDocument ?? document;\n doc.removeEventListener(\"selectionchange\", this.onSelectionChange);\n doc.removeEventListener(\"mousedown\", this.onDocumentMouseDown);\n this.element.removeEventListener(\"keydown\", this.onKeydown);\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.stripObserver?.disconnect();\n this.stripObserver = null;\n if (this.selectionFrame != null) cancelAnimationFrame(this.selectionFrame);\n this.selectionFrame = null;\n if (this.statsTimer != null) clearTimeout(this.statsTimer);\n this.stopRotation();\n try {\n this.live?.close();\n } catch {\n /* already closed */\n }\n this.live = null;\n this.element.remove();\n }\n\n // \u2500\u2500 command plumbing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Run one ribbon command and report its real cost on the rail.\n *\n * Every control routes through here, which is what makes the rail's \"last op\"\n * an honest measurement rather than a label the surface makes up.\n */\n private run(label: string, fn: () => void): void {\n if (!this.live) return;\n const started = performance.now();\n try {\n fn();\n } finally {\n const ms = performance.now() - started;\n const el = this.control(\"railOp\");\n if (el) el.textContent = `${label} ${ms >= 1000 ? `${(ms / 1000).toFixed(2)} s` : `${Math.round(ms)} ms`}`;\n this.options.onCommand?.(label, ms);\n this.history?.edited();\n this.refreshRailCounts();\n this.refreshRailAnchor();\n this.scheduleStats();\n }\n }\n\n /** Format controls must not steal the document selection they are about to act on. */\n private keepSelection(el: HTMLElement): void {\n el.addEventListener(\"mousedown\", (event) => event.preventDefault());\n }\n\n private wire(): void {\n const ribbon = this.require(\"ribbon\");\n\n for (const tab of Array.from(this.element.querySelectorAll<HTMLElement>(\".dxr-tab\"))) {\n this.keepSelection(tab);\n tab.addEventListener(\"click\", () => this.selectTab(tab.dataset.tab ?? \"home\"));\n }\n\n const delegate = <T extends HTMLElement>(selector: string, label: (el: T) => string, fn: (el: T) => void) => {\n for (const el of Array.from(ribbon.querySelectorAll<T>(selector))) {\n this.keepSelection(el);\n el.addEventListener(\"click\", () => this.run(label(el), () => fn(el)));\n }\n };\n\n delegate<HTMLElement>(\"button[data-cmd]\", (b) => b.dataset.cmd!, (b) =>\n this.live!.format(b.dataset.cmd as FormatKey));\n delegate<HTMLElement>(\"button[data-align]\", (b) => `align ${b.dataset.align}`, (b) =>\n this.live!.setAlignment(b.dataset.align as EditorAlignment));\n delegate<HTMLElement>(\"button[data-indent]\", () => \"indent\", (b) =>\n this.live!.indent(parseInt(b.dataset.indent ?? \"720\", 10)));\n delegate<HTMLElement>(\"button[data-list]\", (b) => `list ${b.dataset.list}`, (b) =>\n this.live!.toggleList(b.dataset.list as \"bullet\" | \"decimal\"));\n delegate<HTMLElement>(\"button[data-pagebreak]\", () => \"page break\", () =>\n this.live!.pageBreakBefore(true));\n delegate<HTMLElement>('.dxr-panel[data-panel=\"table\"] button[data-tt]', (b) => b.dataset.tt!, (b) => {\n const ops: Record<string, () => void> = {\n rowAbove: () => this.live!.insertTableRow(\"above\"),\n rowBelow: () => this.live!.insertTableRow(\"below\"),\n colLeft: () => this.live!.insertTableColumn(\"left\"),\n colRight: () => this.live!.insertTableColumn(\"right\"),\n delRow: () => this.live!.deleteTableRow(),\n delCol: () => this.live!.deleteTableColumn(),\n mergeRight: () => this.live!.mergeCells(1, 2),\n mergeDown: () => this.live!.mergeCells(2, 1),\n unmerge: () => this.live!.unmergeCells(),\n borders: () => this.live!.setTableBorders({ scope: \"all\", style: \"single\", size: 4 }),\n noborders: () => this.live!.setTableBorders({ scope: \"all\", style: \"none\" }),\n noshade: () => this.live!.setCellShading(\"\", \"cell\"),\n delTable: () => this.live!.deleteTable(),\n };\n ops[b.dataset.tt ?? \"\"]?.();\n });\n delegate<HTMLElement>(\"button[data-rev]\", (b) => `revision ${b.dataset.rev}`, (b) =>\n this.runRevisionCommand(b.dataset.rev ?? \"\"));\n delegate<HTMLElement>(\"button[data-hf]\", (b) => `header/footer ${b.dataset.hf}`, (b) =>\n this.runHeaderFooterCommand(b.dataset.hf ?? \"\"));\n\n const rulepos = () => (this.require<HTMLSelectElement>(\"rulepos\").value === \"above\" ? \"above\" : \"below\");\n const simple: Array<[string, string, () => void]> = [\n [\"undo\", \"undo\", () => this.live!.undo()],\n [\"redo\", \"redo\", () => this.live!.redo()],\n [\"hr\", \"rule\", () => this.live!.insertHorizontalRule(12, \"single\", rulepos())],\n [\"hrThick\", \"thick rule\", () => this.live!.insertHorizontalRule(24, \"single\", rulepos())],\n [\"hrDouble\", \"double rule\", () => this.live!.insertHorizontalRule(12, \"double\", rulepos())],\n [\"hrClear\", \"clear border\", () => this.live!.clearParagraphBorders()],\n [\"delblock\", \"delete block\", () => this.live!.deleteBlock()],\n [\"footnote\", \"footnote\", () => this.live!.insertFootnote()],\n [\"endnote\", \"endnote\", () => this.live!.insertEndnote()],\n [\"pagenum\", \"page number\", () => this.live!.insertPageNumber(\"currentPage\")],\n [\"totalpages\", \"total pages\", () => this.live!.insertPageNumber(\"totalPages\")],\n [\"fontgrow\", \"grow font\", () => this.live!.adjustFontSize(1)],\n [\"fontshrink\", \"shrink font\", () => this.live!.adjustFontSize(-1)],\n [\"clearformat\", \"clear formatting\", () => this.live!.clearFormatting()],\n [\"toc\", \"table of contents\", () => this.live!.insertTableOfContents()],\n [\"unlink\", \"remove link\", () => this.live!.removeHyperlink()],\n [\"gotoheader\", \"go to header\", () => this.live!.goToHeaderFooter(\"header\")],\n [\"gotofooter\", \"go to footer\", () => this.live!.goToHeaderFooter(\"footer\")],\n [\"viewpage\", \"page view\", () => this.setPaginated(true)],\n [\"viewweb\", \"continuous view\", () => this.setPaginated(false)],\n [\"zoomfit\", \"fit width\", () => this.setZoom(1)],\n [\"zoomin\", \"zoom in\", () => this.stepZoom(1)],\n [\"zoomout\", \"zoom out\", () => this.stepZoom(-1)],\n ];\n for (const [name, label, fn] of simple) {\n const el = this.control(name);\n if (!el) continue;\n this.keepSelection(el);\n el.addEventListener(\"click\", () => this.run(label, fn));\n }\n\n const smallcaps = this.control(\"smallcaps\");\n if (smallcaps) {\n this.keepSelection(smallcaps);\n smallcaps.addEventListener(\"click\", () => {\n const on = smallcaps.getAttribute(\"aria-pressed\") !== \"true\";\n this.run(\"small caps\", () => this.live!.setSmallCaps(on));\n smallcaps.setAttribute(\"aria-pressed\", String(on));\n });\n }\n\n // Font size: `change` only (it fires on Enter and on blur). Binding keydown as\n // well fired twice and stacked two undo snapshots for one size change.\n const fontsize = this.require<HTMLInputElement>(\"fontsize\");\n fontsize.addEventListener(\"change\", () => {\n const pts = parseFloat(fontsize.value);\n if (this.live && pts > 0) this.run(\"font size\", () => this.live!.setFontSize(pts));\n });\n fontsize.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n fontsize.blur();\n }\n });\n\n this.wireSelect(\"fontfamily\", \"font family\", (v) => this.live!.setFontFamily(v));\n this.wireSelect(\"style\", \"style\", (v) => this.live!.setParagraphStyle(v));\n this.wireSelect(\"listmenu\", \"list style\", (v) => this.live!.setListFormat(v as ListFormat));\n this.wireSelect(\"linespacing\", \"line spacing\", (v) => this.live!.setLineSpacing(parseFloat(v)));\n this.wireSelect(\"highlight\", \"highlight\", (v) => this.live!.setHighlight(v === \"none\" ? \"\" : v));\n this.wireSelect(\"pagenummenu\", \"page number\", (v) =>\n this.live!.insertPageNumber(v === \"pageOf\" ? \"pageOfTotal\" : (v as \"currentPage\" | \"totalPages\")));\n\n // Colour pickers: the native input steals focus, so the engine's last-selection\n // bookmark is what the command applies to.\n const fontcolor = this.require<HTMLInputElement>(\"fontcolor\");\n fontcolor.addEventListener(\"input\", () => {\n this.require(\"fontcolorbar\").style.setProperty(\"--dxr-swatch\", fontcolor.value);\n });\n fontcolor.addEventListener(\"change\", () => {\n this.require(\"fontcolorbar\").style.setProperty(\"--dxr-swatch\", fontcolor.value);\n this.run(\"font color\", () => this.live!.setFontColor(fontcolor.value));\n });\n const fontcolorbtn = this.control(\"fontcolorbtn\");\n if (fontcolorbtn) {\n this.keepSelection(fontcolorbtn);\n fontcolorbtn.addEventListener(\"click\", () => this.run(\"font color\", () => this.live!.setFontColor(fontcolor.value)));\n }\n const shade = this.require<HTMLInputElement>(\"shade\");\n shade.addEventListener(\"input\", () => this.require(\"shadebar\").style.setProperty(\"--dxr-swatch\", shade.value));\n shade.addEventListener(\"change\", () => {\n this.require(\"shadebar\").style.setProperty(\"--dxr-swatch\", shade.value);\n this.run(\"cell shading\", () => this.live!.setCellShading(shade.value, \"cell\"));\n });\n const shadebtn = this.control(\"shadebtn\");\n if (shadebtn) {\n this.keepSelection(shadebtn);\n shadebtn.addEventListener(\"click\", () => this.run(\"cell shading\", () => this.live!.setCellShading(shade.value, \"cell\")));\n }\n const repeatheader = this.require<HTMLInputElement>(\"repeatheader\");\n repeatheader.addEventListener(\"change\", () =>\n this.run(\"repeat header row\", () => this.live!.setRepeatHeaderRow(repeatheader.checked)));\n\n // Comments: New/Insert open a draft bubble in the gutter (Word's flow); the rest act on the\n // active thread.\n for (const name of [\"comment\", \"insertcomment\"]) {\n const button = this.control(name);\n if (!button) continue;\n this.keepSelection(button);\n button.addEventListener(\"click\", () => this.beginComment());\n }\n this.control(\"commentdelete\")?.addEventListener(\"click\", () => {\n const active = this.live?.activeComment;\n if (!active) return;\n this.run(\"delete comment\", () => {\n for (const id of threadMembers(this.live!.listComments(), active)) this.live!.removeComment(id);\n this.live!.removeComment(active);\n });\n });\n this.control(\"commentresolve\")?.addEventListener(\"click\", () => {\n const active = this.live?.activeComment;\n if (!active) return;\n const entry = this.live!.listComments().find((c) => c.anchorId === active);\n if (!entry) return;\n this.run(entry.resolved ? \"reopen comment\" : \"resolve comment\", () =>\n this.live!.setCommentResolved(active, !entry.resolved));\n this.live!.activateComment(active);\n });\n this.control(\"commentprev\")?.addEventListener(\"click\", () => this.live?.stepComment(-1));\n this.control(\"commentnext\")?.addEventListener(\"click\", () => this.live?.stepComment(1));\n const showcomments = this.require<HTMLInputElement>(\"showcomments\");\n showcomments.addEventListener(\"change\", () => {\n this.live?.showComments(showcomments.checked);\n this.surface.dataset.comments = showcomments.checked && this.options.comments !== false ? \"on\" : \"off\";\n });\n\n // Tracking.\n const trackchanges = this.require<HTMLInputElement>(\"trackchanges\");\n trackchanges.addEventListener(\"change\", () => {\n if (!this.live) return;\n this.run(trackchanges.checked ? \"track changes on\" : \"track changes off\", () =>\n this.live!.setTrackedChanges(trackchanges.checked ? TrackedChangeMode.RenderInline : TrackedChangeMode.Accept));\n this.syncReviewState();\n });\n const markup = this.require<HTMLSelectElement>(\"markup\");\n markup.addEventListener(\"change\", () => {\n if (!this.live) return;\n // \"No markup\" shows the document as if every change were accepted; edits keep recording.\n this.run(`markup ${markup.value}`, () =>\n this.live!.setTrackedChanges(markup.value === \"none\" ? TrackedChangeMode.Accept : TrackedChangeMode.RenderInline));\n trackchanges.checked = markup.value !== \"none\";\n });\n const author = this.require<HTMLInputElement>(\"author\");\n author.addEventListener(\"change\", () => {\n this.author = author.value.trim() || \"Reviewer\";\n this.live?.setRevisionAuthor(this.author);\n });\n\n this.wireFileActions();\n this.wireLayout();\n this.wirePicker();\n this.wireLinkPopover();\n this.wireFindBar();\n this.wireHeaderFooterTab();\n this.wireZoom();\n this.wireViewToggles();\n }\n\n /** A `<select>` that acts on change and snaps back to its placeholder. */\n private wireSelect(name: string, label: string, apply: (value: string) => void): void {\n const select = this.require<HTMLSelectElement>(name);\n select.addEventListener(\"change\", () => {\n const value = select.value;\n if (this.live && value) this.run(label, () => apply(value));\n select.value = \"\";\n });\n }\n\n private wireFileActions(): void {\n const file = this.control<HTMLInputElement>(\"file\");\n file?.addEventListener(\"change\", async () => {\n const chosen = file.files?.[0];\n if (!chosen) return;\n file.value = '';\n if (this.history) { await this.history.openFile(chosen); return; }\n this.setStatus(`Loading ${chosen.name}\u2026`);\n try { this.open(new Uint8Array(await chosen.arrayBuffer()), chosen.name); }\n catch (error) { this.setStatus(`Could not open this document. ${String(error)}`); }\n // Reset so re-picking the same file fires `change` again.\n file.value = \"\";\n });\n this.control(\"new\")?.addEventListener(\"click\", () => {\n if (this.history) { void this.history.newDocument(); return; }\n if (this.exports) this.openBlank(\"untitled.docx\");\n });\n this.control(\"save\")?.addEventListener(\"click\", () => this.download());\n\n const picture = this.control<HTMLInputElement>(\"picturefile\");\n picture?.addEventListener(\"change\", async () => {\n const chosen = picture.files?.[0];\n picture.value = \"\";\n if (!chosen || !this.live) return;\n const started = performance.now();\n const ok = await this.live.insertImageFile(chosen, { altText: chosen.name });\n if (ok) this.history?.edited();\n const ms = performance.now() - started;\n const el = this.control(\"railOp\");\n if (el) el.textContent = `picture ${Math.round(ms)} ms`;\n this.setStatus(ok ? `Inserted ${chosen.name}` : \"Could not insert the picture here\");\n this.refreshRailCounts();\n });\n }\n\n private wireLayout(): void {\n // Pagination toggles re-render the LIVE session, so edits survive the switch.\n const paginated = this.require<HTMLInputElement>(\"paginated\");\n paginated.addEventListener(\"change\", () => this.setPaginated(paginated.checked));\n\n // The region is chosen at open time, so toggling it re-opens the LIVE\n // session's bytes rather than the originally loaded file \u2014 edits so far survive.\n const headerFooter = this.require<HTMLInputElement>(\"headerfooter\");\n headerFooter.addEventListener(\"change\", () => {\n this.headerFooter = headerFooter.checked;\n if (!this.live) return;\n this.open(this.live.save(), this.documentName);\n });\n\n const pgfmt = this.require<HTMLSelectElement>(\"pgfmt\");\n pgfmt.addEventListener(\"change\", () => {\n if (!this.live || !pgfmt.value) return;\n this.run(\"page format\", () => this.live!.setPageNumbering({ format: pgfmt.value as NumberFormat }));\n this.syncPageNumbering();\n });\n const pgstart = this.require<HTMLInputElement>(\"pgstart\");\n pgstart.addEventListener(\"change\", () => {\n const value = parseInt(pgstart.value, 10);\n if (!this.live || !(value > 0)) return;\n this.run(\"page start\", () => this.live!.setPageNumbering({ start: value }));\n this.syncPageNumbering();\n });\n this.control(\"pgclear\")?.addEventListener(\"click\", () => {\n this.run(\"clear numbering\", () => this.live!.clearPageNumbering());\n this.syncPageNumbering();\n });\n\n // Page setup (Word's Layout > Page Setup): margins presets, orientation, size.\n const pageSetup = (op: Parameters<DocxEditor[\"setPageSetup\"]>[0]) => {\n if (!this.live!.setPageSetup(op)) this.setStatus(\"This engine build cannot change the page setup\");\n this.syncLayoutState();\n };\n this.wireSelect(\"margins\", \"margins\", (v) => {\n const [top, bottom, left, right] = v.split(\",\").map((n) => parseInt(n, 10));\n pageSetup({ marginTopTwips: top, marginBottomTwips: bottom, marginLeftTwips: left, marginRightTwips: right });\n });\n this.wireSelect(\"orientation\", \"orientation\", (v) => pageSetup({ landscape: v === \"landscape\" }));\n this.wireSelect(\"pagesize\", \"page size\", (v) => {\n const [w, h] = v.split(\",\").map((n) => parseInt(n, 10));\n const landscape = !!this.live!.sectionInfo()?.landscape;\n pageSetup(landscape\n ? { pageWidthTwips: h, pageHeightTwips: w, landscape: true }\n : { pageWidthTwips: w, pageHeightTwips: h });\n });\n\n // Paragraph spacing / special indent.\n const before = this.require<HTMLInputElement>(\"spacebefore\");\n const after = this.require<HTMLInputElement>(\"spaceafter\");\n const spacing = (which: \"before\" | \"after\", input: HTMLInputElement) => {\n const pts = parseFloat(input.value);\n if (!this.live || !(pts >= 0)) return;\n this.run(`space ${which}`, () =>\n this.live!.setParagraphSpacing(which === \"before\" ? { beforePt: pts } : { afterPt: pts }));\n };\n before.addEventListener(\"change\", () => spacing(\"before\", before));\n after.addEventListener(\"change\", () => spacing(\"after\", after));\n const special = this.require<HTMLSelectElement>(\"specialindent\");\n const specialVal = this.require<HTMLInputElement>(\"specialindentval\");\n const applySpecial = () => {\n if (!this.live || !special.value) return;\n const inches = parseFloat(specialVal.value);\n const twips = Math.round((inches >= 0 ? inches : 0.5) * 1440);\n this.run(\"special indent\", () => {\n if (special.value === \"firstLine\") this.live!.setFirstLineIndent(twips);\n else if (special.value === \"hanging\") this.live!.setHangingIndent(twips);\n else this.live!.setFirstLineIndent(0);\n });\n };\n special.addEventListener(\"change\", applySpecial);\n specialVal.addEventListener(\"change\", applySpecial);\n }\n\n private setPaginated(on: boolean): void {\n const paginated = this.require<HTMLInputElement>(\"paginated\");\n paginated.checked = on;\n this.surface.dataset.view = on ? \"paginated\" : \"continuous\";\n if (!this.live) return;\n this.run(on ? \"page view\" : \"continuous view\", () => this.live!.setPaginated(on));\n this.syncViewButtons();\n }\n\n private syncViewButtons(): void {\n const on = this.require<HTMLInputElement>(\"paginated\").checked;\n this.control(\"viewpage\")?.classList.toggle(\"dxr-on\", on);\n this.control(\"viewweb\")?.classList.toggle(\"dxr-on\", !on);\n }\n\n private wireViewToggles(): void {\n const showrail = this.require<HTMLInputElement>(\"showrail\");\n showrail.addEventListener(\"change\", () => {\n const rail = this.element.querySelector<HTMLElement>(\"[data-dxr-rail]\");\n if (rail) rail.hidden = !showrail.checked;\n });\n const showhint = this.require<HTMLInputElement>(\"showhint\");\n showhint.addEventListener(\"change\", () => {\n const hint = this.element.querySelector<HTMLElement>(\"[data-dxr-hint]\");\n if (hint) hint.hidden = !showhint.checked;\n });\n this.syncViewButtons();\n }\n\n /** The bands own the same setting and read the live session, so both stay in step. */\n private syncPageNumbering(): void {\n if (!this.live) return;\n const numbering = this.live.pageNumbering() ?? {};\n this.require<HTMLSelectElement>(\"pgfmt\").value = numbering.format ?? \"\";\n this.require<HTMLInputElement>(\"pgstart\").value = numbering.start != null ? String(numbering.start) : \"\";\n }\n\n /** Layout tab: describe the section under the caret. */\n private syncLayoutState(): void {\n const note = this.control(\"pagesetupnote\");\n const info = this.live?.sectionInfo() ?? null;\n if (!note) return;\n if (!info) {\n note.textContent = \"\";\n return;\n }\n const inches = (twips: number) => (twips / 1440).toFixed(2).replace(/\\.?0+$/, \"\");\n note.textContent =\n `${inches(info.pageWidthTwips)}\u2033 \u00D7 ${inches(info.pageHeightTwips)}\u2033 ${info.landscape ? \"landscape\" : \"portrait\"}, ` +\n `margins ${inches(info.marginTopTwips)}\u2033 / ${inches(info.marginRightTwips)}\u2033 / ${inches(info.marginBottomTwips)}\u2033 / ${inches(info.marginLeftTwips)}\u2033`;\n }\n\n // \u2500\u2500 review \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private beginComment(): void {\n if (!this.live) return;\n if (this.density === \"compact\") {\n // No gutter on a phone: post directly on the selection with a prompt.\n const text = window.prompt(\"Comment\");\n if (!text?.trim()) return;\n this.run(\"comment\", () => this.live!.addComment(text.trim(), this.author));\n return;\n }\n if (!this.live.beginComment()) this.setStatus(\"Click into a paragraph (or select text) to comment on it\");\n }\n\n private onCommentsChange(info: { threads: number; open: number; active: string | null }): void {\n const count = this.control(\"commentcount\");\n if (count) count.textContent = info.threads === 0 ? \"No comments\" : `${info.open} open \u00B7 ${info.threads} total`;\n const resolve = this.control<HTMLButtonElement>(\"commentresolve\");\n const del = this.control<HTMLButtonElement>(\"commentdelete\");\n const entry = info.active ? this.live?.listComments().find((c) => c.anchorId === info.active) : null;\n if (resolve) {\n resolve.disabled = !entry;\n resolve.textContent = entry?.resolved ? \"Reopen\" : \"Resolve\";\n }\n if (del) del.disabled = !entry;\n }\n\n private syncReviewState(): void {\n if (!this.live) return;\n const tracked = this.live.trackedChanges === TrackedChangeMode.RenderInline;\n this.require<HTMLInputElement>(\"trackchanges\").checked = tracked;\n this.require<HTMLSelectElement>(\"markup\").value = tracked ? \"all\" : \"none\";\n const revs = this.live.listRevisions();\n const count = this.control(\"revcount\");\n if (count) count.textContent = revs.length === 0 ? \"No tracked changes\" : `${revs.length} change${revs.length === 1 ? \"\" : \"s\"}`;\n this.require<HTMLInputElement>(\"showcomments\").checked = this.live.commentsVisible || this.options.comments === false;\n }\n\n private runRevisionCommand(op: string): void {\n if (!this.live) return;\n const marks = this.live.revisionElements();\n const current = this.currentRevisionMark(marks);\n switch (op) {\n case \"accept\":\n case \"reject\": {\n const mark = current ?? marks[0];\n const entry = mark ? this.live.revisionAt(mark) : null;\n if (!entry) { this.setStatus(\"Put the caret in a tracked change first\"); return; }\n if (op === \"accept\") this.live.acceptRevision(entry.id);\n else this.live.rejectRevision(entry.id);\n break;\n }\n case \"acceptall\": this.live.acceptAllRevisions(); break;\n case \"rejectall\": this.live.rejectAllRevisions(); break;\n case \"next\":\n case \"prev\": {\n if (marks.length === 0) { this.setStatus(\"No tracked changes\"); return; }\n const index = current ? marks.indexOf(current) : -1;\n const target = marks[(index + (op === \"next\" ? 1 : -1) + marks.length) % marks.length];\n this.selectRevisionMark(target);\n return;\n }\n default: return;\n }\n this.syncReviewState();\n }\n\n private currentRevisionMark(marks: HTMLElement[]): HTMLElement | null {\n const sel = (this.element.ownerDocument ?? document).getSelection();\n const node = sel?.anchorNode ?? null;\n if (!node) return null;\n const el = node.nodeType === Node.ELEMENT_NODE ? (node as HTMLElement) : node.parentElement;\n const mark = el?.closest<HTMLElement>('ins, del, tr[class*=\"row-\"]') ?? null;\n return mark && marks.includes(mark) ? mark : null;\n }\n\n private selectRevisionMark(mark: HTMLElement): void {\n const doc = this.element.ownerDocument ?? document;\n const block = mark.closest<HTMLElement>('[data-anchor][contenteditable=\"true\"]');\n block?.focus({ preventScroll: true });\n const range = doc.createRange();\n range.selectNodeContents(mark);\n const sel = doc.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(range);\n mark.scrollIntoView({ block: \"center\", behavior: \"smooth\" });\n }\n\n // \u2500\u2500 header & footer tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private wireHeaderFooterTab(): void {\n for (const kind of [\"first\", \"even\"] as const) {\n const box = this.require<HTMLInputElement>(kind === \"first\" ? \"hfFirst\" : \"hfEven\");\n box.addEventListener(\"change\", () => {\n if (!this.live) return;\n const ok = this.live.setHeaderFooterKindEnabled(kind, box.checked);\n if (!ok) {\n box.checked = !box.checked;\n this.setStatus(\"This engine build cannot change that option\");\n }\n this.run(`${kind === \"first\" ? \"different first page\" : \"different odd & even\"} ${box.checked ? \"on\" : \"off\"}`, () => {});\n this.syncHeaderFooterState();\n });\n }\n }\n\n private runHeaderFooterCommand(op: string): void {\n if (!this.live) return;\n switch (op) {\n case \"pagenum\": this.live.insertPageNumber(\"currentPage\"); break;\n case \"totalpages\": this.live.insertPageNumber(\"totalPages\"); break;\n case \"pageof\": this.live.insertPageNumber(\"pageOfTotal\"); break;\n case \"header\": this.live.goToHeaderFooter(\"header\"); break;\n case \"footer\": this.live.goToHeaderFooter(\"footer\"); break;\n case \"close\": this.live.closeHeaderFooter(); break;\n }\n this.syncHeaderFooterState();\n }\n\n private onStoryChange(which: BandWhich | null): void {\n const tab = this.element.querySelector<HTMLElement>('.dxr-tab[data-tab=\"headerfooter\"]');\n if (!tab) return;\n tab.hidden = which === null;\n if (which) {\n this.selectTab(\"headerfooter\");\n } else if (tab.getAttribute(\"aria-selected\") === \"true\") {\n this.selectTab(\"home\");\n }\n this.syncHeaderFooterState();\n }\n\n private syncHeaderFooterState(): void {\n if (!this.live) return;\n this.require<HTMLInputElement>(\"hfFirst\").checked = this.live.headerFooterKindEnabled(\"first\");\n this.require<HTMLInputElement>(\"hfEven\").checked = this.live.headerFooterKindEnabled(\"even\");\n const story = this.control(\"hfstory\");\n if (story) {\n const which = this.live.activeStoryKind ?? \"header\";\n story.textContent = this.live.headerFooterStoryLabel(which);\n }\n }\n\n // \u2500\u2500 zoom \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private wireZoom(): void {\n for (const name of [\"zoom\", \"zoomlevel\"]) {\n const select = this.control<HTMLSelectElement>(name);\n select?.addEventListener(\"change\", () => this.setZoom(parseFloat(select.value)));\n }\n }\n\n private setZoom(scale: number): void {\n if (!this.live || !(scale > 0)) return;\n this.run(`zoom ${Math.round(scale * 100)}%`, () => this.live!.setZoom(scale));\n this.syncZoom();\n }\n\n private stepZoom(direction: 1 | -1): void {\n if (!this.live) return;\n const current = this.live.requestedZoom;\n const next = direction > 0\n ? ZOOM_STEPS.find((z) => z > current + 1e-6) ?? ZOOM_STEPS[ZOOM_STEPS.length - 1]\n : [...ZOOM_STEPS].reverse().find((z) => z < current - 1e-6) ?? ZOOM_STEPS[0];\n this.setZoom(next);\n }\n\n private syncZoom(): void {\n if (!this.live) return;\n const requested = this.live.requestedZoom;\n const value = String(ZOOM_STEPS.find((z) => Math.abs(z - requested) < 1e-6) ?? requested);\n for (const name of [\"zoom\", \"zoomlevel\"]) {\n const select = this.control<HTMLSelectElement>(name);\n if (!select) continue;\n if (!Array.from(select.options).some((o) => o.value === value)) {\n const opt = document.createElement(\"option\");\n opt.value = value;\n opt.textContent = `${Math.round(requested * 100)}%`;\n select.appendChild(opt);\n }\n select.value = value;\n }\n }\n\n // \u2500\u2500 find & replace \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private wireFindBar(): void {\n const bar = this.require(\"findbar\");\n const text = this.require<HTMLInputElement>(\"findtext\");\n const replace = this.require<HTMLInputElement>(\"replacetext\");\n const matchCase = this.require<HTMLInputElement>(\"findcase\");\n this.control(\"findtoggle\")?.addEventListener(\"click\", () => this.openFindBar(false));\n this.control(\"replacetoggle\")?.addEventListener(\"click\", () => this.openFindBar(true));\n this.control(\"findclose\")?.addEventListener(\"click\", () => this.closeFindBar());\n text.addEventListener(\"input\", () => this.refreshFind(true));\n matchCase.addEventListener(\"change\", () => this.refreshFind(true));\n text.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n this.stepFind(event.shiftKey ? -1 : 1);\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n this.closeFindBar();\n }\n });\n replace.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n this.replaceCurrent();\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n this.closeFindBar();\n }\n });\n this.control(\"findprev\")?.addEventListener(\"click\", () => this.stepFind(-1));\n this.control(\"findnext\")?.addEventListener(\"click\", () => this.stepFind(1));\n this.control(\"replaceone\")?.addEventListener(\"click\", () => this.replaceCurrent());\n this.control(\"replaceall\")?.addEventListener(\"click\", () => {\n if (!this.live || !text.value) return;\n let count = 0;\n this.run(\"replace all\", () => {\n count = this.live!.replaceAll(text.value, replace.value, {\n matchCase: matchCase.checked,\n focus: false,\n });\n });\n this.setStatus(`Replaced ${count} occurrence${count === 1 ? \"\" : \"s\"}`);\n this.refreshFind(true);\n });\n // Every find-bar button acts on the search, not on the caret: swallowing mousedown keeps the\n // keyboard in the field that was being typed into, so a click on Next does not end the query.\n for (const id of [\"findprev\", \"findnext\", \"replaceone\", \"replaceall\"]) {\n const button = this.control(id);\n if (button) this.keepSelection(button);\n }\n bar.hidden = true;\n }\n\n private openFindBar(withReplace: boolean): void {\n const bar = this.require(\"findbar\");\n bar.hidden = false;\n this.require(\"replacegroup\").hidden = !withReplace;\n this.syncStripFade(bar);\n const text = this.require<HTMLInputElement>(\"findtext\");\n text.focus();\n text.select();\n // Painting is focus-safe, so a reopened bar can show its hits without taking the keyboard.\n this.refreshFind(true);\n }\n\n /**\n * Close the bar and hand the current hit over to the caret: the document is where the user is\n * going next, and Word leaves the insertion point on the match it stopped at. Until this runs\n * the match is only PAINTED (see `showFindMatches`), so the search field keeps the keyboard for\n * as long as the bar is open.\n */\n private closeFindBar(): void {\n const bar = this.control(\"findbar\");\n if (bar) bar.hidden = true;\n const match = this.findMatches[this.findIndex];\n if (match) this.live?.selectMatch(match);\n else this.live?.clearFindMatches();\n this.findMatches = [];\n this.findIndex = -1;\n }\n\n /**\n * Re-scan for the current query. `show` paints the hits and rides to the first one \u2014 it never\n * focuses the document, so typing the second character of a query that already matched goes on\n * refining the search instead of being typed into the document.\n */\n private refreshFind(show: boolean): void {\n const text = this.require<HTMLInputElement>(\"findtext\");\n const matchCase = this.require<HTMLInputElement>(\"findcase\").checked;\n this.findMatches = this.live && text.value ? this.live.find(text.value, { matchCase }) : [];\n this.findIndex = this.findMatches.length > 0 ? 0 : -1;\n this.updateFindCount();\n if (!show) return;\n if (this.findIndex >= 0) this.live?.showFindMatches(this.findMatches, this.findIndex);\n else this.live?.clearFindMatches();\n }\n\n private stepFind(direction: 1 | -1): void {\n if (!this.live) return;\n if (this.findMatches.length === 0) this.refreshFind(false);\n if (this.findMatches.length === 0) return;\n this.findIndex = (this.findIndex + direction + this.findMatches.length) % this.findMatches.length;\n this.live.showFindMatches(this.findMatches, this.findIndex);\n this.updateFindCount();\n }\n\n private replaceCurrent(): void {\n if (!this.live) return;\n if (this.findMatches.length === 0 || this.findIndex < 0) this.refreshFind(true);\n const match = this.findMatches[this.findIndex];\n if (!match) return;\n const replacement = this.require<HTMLInputElement>(\"replacetext\").value;\n this.run(\"replace\", () => this.live!.replaceMatch(match, replacement, { focus: false }));\n // Offsets after the replacement shifted; re-scan and continue from the same slot.\n const keep = this.findIndex;\n this.refreshFind(false);\n if (this.findMatches.length > 0) {\n this.findIndex = Math.min(keep, this.findMatches.length - 1);\n this.live.showFindMatches(this.findMatches, this.findIndex);\n this.updateFindCount();\n }\n }\n\n private updateFindCount(): void {\n const el = this.control(\"findcount\");\n if (!el) return;\n el.textContent = this.findMatches.length === 0\n ? (this.require<HTMLInputElement>(\"findtext\").value ? \"0 of 0\" : \"\")\n : `${this.findIndex + 1} of ${this.findMatches.length}`;\n }\n\n // \u2500\u2500 keyboard shortcuts the engine does not own \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private handleShortcut(event: KeyboardEvent): void {\n if (!this.live || !(event.ctrlKey || event.metaKey)) return;\n const key = event.key.toLowerCase();\n const target = event.target instanceof Element ? event.target : null;\n const inDocument = this.surface.contains(event.target as Node);\n // Ctrl+Alt+M is Word's New Comment; every other chord here is plain Ctrl.\n if (event.altKey) {\n if (key === \"m\" && inDocument) { event.preventDefault(); this.beginComment(); }\n return;\n }\n if (key === \"f\") { event.preventDefault(); this.openFindBar(false); return; }\n if (key === \"h\") { event.preventDefault(); this.openFindBar(true); return; }\n if (!inDocument) return;\n // Below here every chord edits the focused BLOCK, so a text box inside the surface \u2014 the\n // comment gutter's reply and edit boxes \u2014 owns its keys: Ctrl+Enter posts a reply there and\n // must not also drop a page break on the commented paragraph, nor Ctrl+E/L/R/J re-align it\n // mid-reply. Find and replace stay reachable from a comment box, as they are in Word.\n if (target?.closest(\".docx-comment-gutter, textarea, input\")) return;\n const align = (alignment: EditorAlignment) => {\n event.preventDefault();\n this.run(`align ${alignment}`, () => this.live!.setAlignment(alignment));\n };\n switch (key) {\n case \"k\": event.preventDefault(); this.openLinkPopover(); return;\n case \"e\": align(\"center\"); return;\n case \"l\": align(\"left\"); return;\n case \"r\": align(\"right\"); return;\n case \"j\": align(\"justify\"); return;\n case \"]\": event.preventDefault(); this.run(\"grow font\", () => this.live!.adjustFontSize(1)); return;\n case \"[\": event.preventDefault(); this.run(\"shrink font\", () => this.live!.adjustFontSize(-1)); return;\n case \"enter\": event.preventDefault(); this.run(\"page break\", () => this.live!.pageBreakBefore(true)); return;\n default: return;\n }\n }\n\n // \u2500\u2500 popovers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private positionPopover(popover: HTMLElement, anchor: HTMLElement): void {\n if (this.density !== \"full\") return;\n const rect = anchor.getBoundingClientRect();\n const host = this.element.getBoundingClientRect();\n popover.style.left = `${rect.left - host.left}px`;\n popover.style.top = `${rect.bottom - host.top + 5}px`;\n }\n\n private wirePicker(): void {\n const button = this.require(\"table\");\n const picker = this.require(\"gridpicker\");\n const cells = this.require(\"gridcells\");\n\n const highlight = (rows: number, cols: number) => {\n for (const cell of Array.from(cells.children) as HTMLElement[]) {\n const on = Number(cell.dataset.r) < rows && Number(cell.dataset.c) < cols;\n if (on) cell.setAttribute(\"data-on\", \"\");\n else cell.removeAttribute(\"data-on\");\n }\n this.require(\"gridlabel\").textContent = `${rows} \u00D7 ${cols}`;\n };\n\n // `pointerover` covers mouse hover; touch users get the same feedback from the\n // press itself, since a tap fires pointerover immediately before pointerdown.\n cells.addEventListener(\"pointerover\", (event) => {\n const cell = (event.target as HTMLElement).closest<HTMLElement>(\"[data-r]\");\n if (cell) highlight(Number(cell.dataset.r) + 1, Number(cell.dataset.c) + 1);\n });\n cells.addEventListener(\"mousedown\", (event) => {\n const cell = (event.target as HTMLElement).closest<HTMLElement>(\"[data-r]\");\n if (!cell || !this.live) return;\n event.preventDefault();\n const rows = Number(cell.dataset.r) + 1;\n const cols = Number(cell.dataset.c) + 1;\n this.closePopovers();\n this.run(`table ${rows}\u00D7${cols}`, () =>\n this.live!.insertTable(rows, cols, {\n borderless: this.require<HTMLInputElement>(\"gridborderless\").checked,\n cellAlignment: this.require<HTMLSelectElement>(\"gridalign\").value as EditorAlignment,\n }));\n });\n\n this.keepSelection(button);\n button.addEventListener(\"click\", () => {\n if (!this.live) return;\n if (picker.hasAttribute(\"data-open\")) {\n this.closePopovers();\n return;\n }\n this.closePopovers();\n highlight(0, 0);\n picker.setAttribute(\"data-open\", \"\");\n this.positionPopover(picker, button);\n });\n }\n\n private wireLinkPopover(): void {\n const button = this.require(\"link\");\n const pop = this.require(\"linkpop\");\n const form = this.require<HTMLFormElement>(\"linkform\");\n const url = this.require<HTMLInputElement>(\"linkurl\");\n this.keepSelection(button);\n button.addEventListener(\"click\", () => {\n if (pop.hasAttribute(\"data-open\")) this.closePopovers();\n else this.openLinkPopover();\n });\n this.control(\"linkcancel\")?.addEventListener(\"click\", () => this.closePopovers());\n form.addEventListener(\"submit\", (event) => {\n event.preventDefault();\n const target = url.value.trim();\n if (!target || !this.live) return;\n this.closePopovers();\n let ok = false;\n this.run(\"link\", () => { ok = this.live!.insertHyperlink(target); });\n if (!ok) this.setStatus(\"Select the text to link first\");\n });\n url.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Escape\") { event.preventDefault(); this.closePopovers(); }\n });\n }\n\n private openLinkPopover(): void {\n if (!this.live) return;\n this.closePopovers();\n const pop = this.require(\"linkpop\");\n const url = this.require<HTMLInputElement>(\"linkurl\");\n const existing = this.live.hyperlinkAtCaret();\n url.value = existing?.target ?? \"\";\n pop.setAttribute(\"data-open\", \"\");\n this.positionPopover(pop, this.require(\"link\"));\n url.focus();\n url.select();\n }\n\n private closePopovers(): void {\n this.control(\"gridpicker\")?.removeAttribute(\"data-open\");\n this.control(\"linkpop\")?.removeAttribute(\"data-open\");\n }\n\n private maybeClosePopovers(event: MouseEvent): void {\n const target = event.target as Node;\n for (const [popName, buttonName] of [[\"gridpicker\", \"table\"], [\"linkpop\", \"link\"]] as const) {\n const pop = this.control(popName);\n if (!pop?.hasAttribute(\"data-open\")) continue;\n if (pop.contains(target) || this.control(buttonName)?.contains(target)) continue;\n pop.removeAttribute(\"data-open\");\n }\n }\n\n // \u2500\u2500 tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n selectTab(name: string): void {\n for (const tab of Array.from(this.element.querySelectorAll<HTMLElement>(\".dxr-tab\"))) {\n tab.setAttribute(\"aria-selected\", String(tab.dataset.tab === name));\n }\n for (const panel of Array.from(this.element.querySelectorAll<HTMLElement>(\".dxr-panel\"))) {\n if (panel.dataset.panel === name) panel.setAttribute(\"data-active\", \"\");\n else panel.removeAttribute(\"data-active\");\n }\n if (name === \"layout\") { this.syncPageNumbering(); this.syncLayoutState(); }\n if (name === \"review\") this.syncReviewState();\n if (name === \"headerfooter\") this.syncHeaderFooterState();\n if (name === \"view\") this.syncZoom();\n }\n\n // \u2500\u2500 selection-driven state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private selectionElement(): HTMLElement | null {\n const selection = (this.element.ownerDocument ?? document).getSelection();\n const node = selection?.anchorNode ?? null;\n if (!node) return null;\n const el = node.nodeType === Node.ELEMENT_NODE ? (node as HTMLElement) : node.parentElement;\n // Ignore selections belonging to another editor (or another ribbon) on the page.\n return el && this.surface.contains(el) ? el : null;\n }\n\n private syncSelection(): void {\n if (!this.live || this.destroyed) return;\n const el = this.selectionElement();\n\n const state = this.live.queryFormatState();\n for (const button of Array.from(this.element.querySelectorAll<HTMLElement>(\"button[data-cmd]\"))) {\n button.classList.toggle(\"dxr-on\", !!state[button.dataset.cmd as FormatKey]);\n }\n\n const doc = this.element.ownerDocument ?? document;\n if (el && typeof getComputedStyle === \"function\") {\n const cs = getComputedStyle(el);\n // Reflect the caret's font size, unless the field itself is being edited.\n const fontsize = this.control<HTMLInputElement>(\"fontsize\");\n if (fontsize && doc.activeElement !== fontsize) {\n const px = parseFloat(cs.fontSize);\n if (px) fontsize.value = String(Math.round(px * 0.75 * 2) / 2);\n }\n const hex = toHex(cs.color);\n if (hex) {\n this.control(\"fontcolorbar\")?.style.setProperty(\"--dxr-swatch\", hex);\n const input = this.control<HTMLInputElement>(\"fontcolor\");\n if (input && doc.activeElement !== input) input.value = hex;\n }\n this.control(\"smallcaps\")?.setAttribute(\"aria-pressed\", String(cs.fontVariant.includes(\"small-caps\")));\n const align = cs.textAlign === \"start\" ? \"left\" : cs.textAlign === \"end\" ? \"right\" : cs.textAlign;\n for (const button of Array.from(this.element.querySelectorAll<HTMLElement>(\"button[data-align]\"))) {\n button.classList.toggle(\"dxr-on\", button.dataset.align === align);\n }\n }\n const listFormat = this.live.listFormatAtCaret();\n for (const button of Array.from(this.element.querySelectorAll<HTMLElement>(\"button[data-list]\"))) {\n const kind = button.dataset.list;\n button.classList.toggle(\n \"dxr-on\",\n !!listFormat && (kind === \"bullet\" ? listFormat.startsWith(\"bullet\") : !listFormat.startsWith(\"bullet\")),\n );\n }\n\n // Reveal the contextual Table tab only while the caret is inside a table.\n const inTable = !!el?.closest(\"table\");\n const tableTab = this.element.querySelector<HTMLElement>('.dxr-tab[data-tab=\"table\"]');\n if (tableTab) {\n tableTab.hidden = !inTable;\n if (!inTable && tableTab.getAttribute(\"aria-selected\") === \"true\") this.selectTab(\"home\");\n if (inTable) {\n const row = el?.closest(\"tr\");\n this.require<HTMLInputElement>(\"repeatheader\").checked = !!row?.classList.toString().includes(\"header\");\n }\n }\n this.refreshRailAnchor();\n this.scheduleStats();\n }\n\n /** Scope is read from where the block lives, which is exactly what the anchor encodes. */\n private scopeOf(el: HTMLElement): string {\n const band = el.closest<HTMLElement>(\"[data-hf-band]\");\n if (band) return band.getAttribute(\"data-hf-band\") === \"header\" ? \"hdr\" : \"ftr\";\n if (el.closest(\".footnotes\")) return \"fn\";\n if (el.closest(\".endnotes\")) return \"en\";\n return \"body\";\n }\n\n private kindOf(el: HTMLElement): string {\n if (/^H[1-6]$/.test(el.tagName)) return \"h\";\n if (el.tagName === \"LI\" || el.hasAttribute(\"data-list-marker\") || el.querySelector(\"[data-list-marker]\")) {\n return \"li\";\n }\n return \"p\";\n }\n\n /**\n * Block count and session handle \u2014 an O(blocks) query, so it runs only when\n * something could have changed them (a command, or a document opening), never on\n * the selectionchange path that fires per keystroke.\n */\n private refreshRailCounts(): void {\n const blocks = this.control(\"railBlocks\");\n if (!blocks) return; // rail disabled\n blocks.textContent = this.live ? String(this.surface.querySelectorAll(\"[data-anchor]\").length) : \"\u2014\";\n const session = this.control(\"railSession\");\n if (session) session.textContent = this.live ? `#${this.live.sessionHandle}` : \"\u2014\";\n }\n\n /** The focused anchor \u2014 cheap, and the only part the caret can change. */\n private refreshRailAnchor(): void {\n const anchorEl = this.control(\"railAnchor\");\n if (!anchorEl) return;\n const block = this.selectionElement()?.closest<HTMLElement>(\"[data-anchor]\") ?? null;\n if (!block) {\n anchorEl.textContent = this.live ? \"none\" : \"\u2014\";\n this.lastAnchorText = \"\";\n return;\n }\n const unid = block.getAttribute(\"data-anchor\") ?? \"\";\n const text = `${this.kindOf(block)}:${this.scopeOf(block)}:${unid.slice(0, 10)}\u2026`;\n if (text === this.lastAnchorText) return;\n anchorEl.textContent = text;\n this.lastAnchorText = text;\n anchorEl.classList.remove(\"dxr-flash\");\n void anchorEl.offsetWidth;\n anchorEl.classList.add(\"dxr-flash\");\n }\n\n /** Page position and word count are O(document); debounced off the hot paths. */\n private scheduleStats(): void {\n if (this.statsTimer != null) clearTimeout(this.statsTimer);\n this.statsTimer = setTimeout(() => {\n this.statsTimer = null;\n this.refreshStats();\n }, 150);\n }\n\n private refreshStats(): void {\n if (!this.live || this.destroyed) return;\n const pageinfo = this.control(\"pageinfo\");\n if (pageinfo) {\n const info = this.live.pageInfo();\n pageinfo.textContent = info ? `Page ${info.page} of ${info.total}` : \"Continuous\";\n }\n const words = this.control(\"wordcount\");\n if (words) {\n const n = this.live.wordCount();\n words.textContent = `${n.toLocaleString()} word${n === 1 ? \"\" : \"s\"}`;\n }\n }\n\n /** Font families the document's rendered text actually uses, most common first. */\n private documentFonts(): string[] {\n const counts = new Map<string, number>();\n for (const el of Array.from(this.surface.querySelectorAll<HTMLElement>(\"[data-anchor] [style*='font-family'], [data-anchor][style*='font-family']\"))) {\n const family = el.style.fontFamily.split(\",\")[0]?.trim().replace(/^['\"]|['\"]$/g, \"\");\n if (!family || /^(serif|sans-serif|monospace)$/i.test(family)) continue;\n counts.set(family, (counts.get(family) ?? 0) + 1);\n }\n return Array.from(counts.entries()).sort((a, b) => b[1] - a[1]).map(([name]) => name).slice(0, 12);\n }\n\n // \u2500\u2500 loading overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private createLoaderController(): RibbonLoader {\n const overlay = this.control(\"loader\");\n if (!overlay) {\n const noop = () => {};\n return { show: noop, stage: noop, progress: noop, done: noop, fail: noop };\n }\n\n const options = this.loaderOptions ?? {};\n const eyebrow = this.control(\"loaderEyebrow\");\n if (eyebrow && options.eyebrow) eyebrow.textContent = options.eyebrow;\n const meta = this.control(\"loaderMeta\");\n if (meta && options.meta) meta.textContent = options.meta;\n this.control(\"loaderRetry\")?.addEventListener(\"click\", () => {\n if (options.onRetry) options.onRetry();\n else location.reload();\n });\n if (this.features.length === 0) this.control(\"loaderAd\")?.remove();\n\n const setProgress = (percent: number, label?: string) => {\n const bar = this.control(\"loaderBar\");\n if (bar) bar.style.width = `${Math.max(0, Math.min(100, percent))}%`;\n if (label) {\n const el = this.control(\"loaderLabel\");\n if (el) el.textContent = label;\n }\n };\n\n return {\n show: () => {\n overlay.hidden = false;\n overlay.removeAttribute(\"data-done\");\n overlay.removeAttribute(\"data-error\");\n this.setState(\"loading\");\n this.showFeature(0);\n this.startRotation();\n this.loaderStage(0);\n },\n stage: (step) => this.loaderStage(step),\n progress: setProgress,\n done: () => {\n this.stopRotation();\n this.setState(\"ready\");\n // Two-step so the fade actually plays before the overlay leaves the layout.\n setTimeout(() => overlay.setAttribute(\"data-done\", \"\"), 420);\n setTimeout(() => {\n overlay.hidden = true;\n }, 1050);\n },\n fail: (error) => {\n this.stopRotation();\n this.setState(\"error\");\n overlay.hidden = false;\n overlay.setAttribute(\"data-error\", \"\");\n overlay.removeAttribute(\"data-done\");\n const message = error instanceof Error ? error.message : String(error);\n const title = this.control(\"loaderTitle\");\n if (title) title.textContent = \"The local engine did not start\";\n const copy = this.control(\"loaderCopy\");\n if (copy) copy.textContent = message.slice(0, 220);\n setProgress(100, \"Load failed\");\n this.setStatus(message.slice(0, 180));\n },\n };\n }\n\n private loaderStage(step: number | Partial<RibbonLoaderStage>): void {\n const stage = typeof step === \"number\" ? this.stages[Math.max(0, Math.min(this.stages.length - 1, step))] : step;\n if (!stage) return;\n const title = this.control(\"loaderTitle\");\n if (title && stage.title) title.textContent = stage.title;\n const copy = this.control(\"loaderCopy\");\n if (copy && stage.copy) copy.textContent = stage.copy;\n const bar = this.control(\"loaderBar\");\n if (bar && stage.progress != null) bar.style.width = `${stage.progress}%`;\n const label = this.control(\"loaderLabel\");\n if (label && stage.label) label.textContent = stage.label;\n }\n\n private showFeature(index: number): void {\n const feature = this.features[index];\n if (!feature) return;\n const card = this.control(\"loaderAd\");\n const number = this.control(\"loaderNumber\");\n const title = this.control(\"loaderAdTitle\");\n const copy = this.control(\"loaderAdCopy\");\n if (number) number.textContent = feature.number;\n if (title) title.textContent = feature.title;\n if (copy) copy.textContent = feature.copy;\n if (card) {\n card.removeAttribute(\"data-swap\");\n void card.offsetWidth;\n card.setAttribute(\"data-swap\", \"\");\n }\n }\n\n private startRotation(): void {\n this.stopRotation();\n if (this.features.length < 2) return;\n const every = this.loaderOptions?.rotateMs ?? 1750;\n this.featureTimer = setInterval(() => {\n this.featureIndex = (this.featureIndex + 1) % this.features.length;\n this.showFeature(this.featureIndex);\n }, every);\n }\n\n private stopRotation(): void {\n if (this.featureTimer == null) return;\n clearInterval(this.featureTimer);\n this.featureTimer = null;\n }\n}\n"],
|
|
5
|
+
"mappings": "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IAAMyD,GAAoB,8BAW1B,IAAMC,GAAa;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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AA;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;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;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;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;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;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;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;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;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;AAAA;AAAA;AAAA;AAAA;AAAA;AA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",
|
|
6
|
+
"names": ["require_bind", "__commonJSMin", "exports", "bind", "target", "_a", "type", "listener", "options", "require_bind_all", "__commonJSMin", "exports", "__assign", "t", "s", "i", "p", "bind_1", "toOptions", "value", "getBinding", "original", "sharedOptions", "binding", "bindAll", "target", "bindings", "unbinds", "unbind", "require_dist", "__commonJSMin", "exports", "bind_1", "bind_all_1", "embed_exports", "__export", "AnchorIdRendering", "AnchorRenderMode", "AnnotationLabelMode", "CommentGutter", "CommentRenderMode", "ComparisonLogCodes", "ComparisonLogLevel", "ConflictResolution", "ContextBoundary", "DEFAULT_MARGIN", "DEFAULT_PAGE_HEIGHT", "DEFAULT_PAGE_WIDTH", "DiffFormat", "DocumentElementType", "DocumentViewport", "DocxDiffFormatComparison", "DocxDiffRevisionGranularity", "DocxEditor", "DocxHistoryArchive", "DocxHistoryClient", "DocxHistoryDocument", "DocxHistoryError", "DocxHistoryReader", "DocxSession", "EmptyParagraphMode", "HistoryCheckpoints", "MAX_HISTORY_ARCHIVE_BYTES", "PaginationEngine", "PaginationMode", "PlaceholderKinds", "ProjectionDepth", "ProjectionScopes", "RevisionPresentation", "RevisionType", "TableRenderMode", "TrackedChangeMode", "addAnnotation", "addAnnotationToHtml", "addAnnotationWithTarget", "clearPageCitationHighlight", "compareDocuments", "compareDocumentsToHtml", "computeDocumentHash", "convertDocxToHtml", "convertDocxToHtmlWithExternalAnnotations", "convertWmlToMarkdown", "createAnnotation", "createAnnotationFromSearch", "createBlankDocx", "createEditor", "createExternalAnnotationSet", "createHistoryViewer", "createMemoryHistoryStorage", "createRibbonEditor", "createUnavailablePageMap", "createViewer", "docxDiffAcceptRevisions", "docxDiffCompare", "docxDiffCompareBatch", "docxDiffCompareProducts", "docxDiffConsolidate", "docxDiffGetConflicts", "docxDiffGetConsolidatedEditScript", "docxDiffGetConsolidatedRevisions", "docxDiffGetEditScript", "docxDiffGetRevisions", "docxDiffGetSemanticChanges", "docxDiffRejectRevisions", "exportToOpenContract", "findElementById", "findElementsByType", "findTextOccurrences", "fitScale", "generateAnnotationCss", "generateAnnotationVisibilityCss", "generatePackageManifest", "getAnnotations", "getComments", "getDocumentMetadata", "getDocumentStructure", "getParagraphs", "getRevisions", "getTableColumns", "getTables", "getVersion", "getWasmExports", "hasAnnotations", "historyControlError", "initialize", "installHistoryStorageImports", "isDeletion", "isFormatChange", "isInitialized", "isInsertion", "isMove", "mountHistoryControls", "mountRibbon", "navigateToPageCitation", "openDocxHistory", "openDocxHistoryArchive", "openDocxSession", "openIndexedDbHistoryStore", "paginateHtml", "parseSectionDimensions", "projectAnnotationsOntoHtml", "proveRedlineReversibility", "ptToPx", "pxToPt", "removeAnnotation", "removeAnnotationFromHtml", "renderBlockHtml", "searchTextOffsets", "setWasmBasePath", "targetElement", "targetParagraph", "targetParagraphRange", "targetRun", "targetSearch", "targetSearchInElement", "targetTable", "targetTableCell", "targetTableColumn", "targetTableRow", "toDocumentBytes", "validateExternalAnnotations", "verifyDeliverable", "verifyDeliveryReceipt", "wasmBasePath", "serializeVerificationRequest", "request", "companionArtifacts", "rest", "wire", "encodeCompanion", "artifact", "bytes", "bytesToBase64", "binary", "i", "chunk", "ProjectionScopes", "AnchorRenderMode", "TableRenderMode", "TrackedChangeMode", "EmptyParagraphMode", "AnchorIdRendering", "ProjectionDepth", "RevisionType", "CommentRenderMode", "PaginationMode", "RevisionPresentation", "AnnotationLabelMode", "DocxDiffRevisionGranularity", "DocxDiffFormatComparison", "ConflictResolution", "isInsertion", "revision", "isDeletion", "isMove", "isFormatChange", "PlaceholderKinds", "DiffFormat", "ContextBoundary", "ComparisonLogLevel", "ComparisonLogCodes", "DocumentElementType", "findElementById", "structure", "elementId", "findElementsByType", "type", "el", "getParagraphs", "getTables", "getTableColumns", "tableId", "col", "a", "b", "targetElement", "targetParagraph", "paragraphIndex", "targetParagraphRange", "startIndex", "endIndex", "targetRun", "runIndex", "targetTable", "tableIndex", "targetTableRow", "rowIndex", "targetTableCell", "cellIndex", "targetTableColumn", "columnIndex", "targetSearch", "searchText", "occurrence", "targetSearchInElement", "mutationBatchChangeSet", "before", "after", "key", "beforeGroups", "afterGroups", "group", "items", "target", "item", "index", "identity", "indices", "beforeMatched", "afterMatched", "modified", "afterIndices", "beforeIndices", "afterIndex", "beforeIndex", "remainingBefore", "remainingAfter", "modifiedCount", "_", "BATCH_REPLAY_CAVEATS", "BATCH_REPLAY_CAVEAT_TEXTS", "RETAINED_PREVIEW_RECEIPTS", "DocxSession", "_DocxSession", "handle", "wasm", "anchorId", "position", "xml", "pageMap", "expectedRendererFingerprint", "request", "preconditions", "mutation", "checked", "steps", "mode", "transaction", "options", "wire", "decode", "base64", "c", "artifact", "bytes", "rest", "run", "step", "result", "previewId", "commit", "envelope", "receipt", "warning", "body", "decision", "completed", "baseVersion", "observationWarnings", "inspect", "label", "read", "fallback", "error", "beforeRevisions", "beforeComments", "beforeAnnotations", "complete", "revisionChanges", "revision", "commentChanges", "comment", "annotationChanges", "annotation", "resultVersion", "warnings", "edit", "packageHash", "internalFailure", "value", "results", "failureOf", "rolledBack", "preflightOne", "preflight", "failedPreflight", "source", "failed", "htmlMode", "shadow", "html", "unwrapRendered", "rendered", "legacyProfileWarning", "retention", "retained", "preview", "depth", "citation", "err", "markdown", "apply", "sourceAnchorId", "targetAnchorId", "fromAnchorId", "toAnchorIdExclusive", "headingAnchorId", "characterOffset", "firstAnchorId", "secondAnchorId", "rule", "ruleJson", "rows", "cols", "optionsJson", "tableAnchorId", "cellAnchorId", "rowIndex", "columnIndex", "rowSpan", "colSpan", "content", "widthsTwips", "spec", "fill", "scope", "repeat", "kind", "field", "format", "op", "pos", "enabled", "bookmarkName", "endnotes", "span", "author", "opts", "spanJson", "revisionId", "parentCommentAnchorId", "commentAnchorId", "resolved", "scopes", "hyperlinkId", "imageBytesToBase64", "imageId", "dimensions", "altText", "title", "layout", "text", "isChecked", "displayText", "timestamp", "sectionAnchorId", "afterItemAnchorId", "itemAnchorId", "name", "range", "newName", "filter", "v", "repairs", "substring", "match", "styleId", "levelDelta", "lastAnchorId", "pattern", "find", "replace", "fold", "l", "isSpace", "isClauseTerm", "isOpen", "isClose", "extendLeft", "extendRight", "newInner", "picker", "kinds", "PlaceholderKinds", "maxPasses", "preserveDollarPrefix", "contextChars", "boundary", "ContextBoundary", "coalesceEmpty", "filled", "workPasses", "errors", "unfilled", "seenSkipKeys", "pass", "placeholders", "a", "b", "cmp", "passChanges", "p", "pick", "replacement", "r", "stillPresent", "json", "raw", "DiffFormat", "serializeVerificationRequest", "annotationId", "labelId", "needle", "regexOptions", "anchorIds", "update", "newAnchorId", "newSpan", "binary", "offset", "openDocxSession", "wasmExports", "settings", "bridge", "COMPLETE_ONLY_CONVERSION_OPTIONS", "needsCompleteConversion", "options", "key", "readPawlsPage", "p", "t", "readAnnotationJson", "json", "result", "key", "value", "v", "readAnnotation", "a", "readRelationship", "r", "readLabel", "l", "readLabels", "raw", "labels", "readOpenContractExport", "parsed", "readExternalAnnotationSet", "readExternalAnnotationValidation", "i", "readProjectedHtml", "MAX_HISTORY_ARCHIVE_BYTES", "DocxHistoryError", "code", "message", "adapters", "nextAdapter", "adapter", "id", "store", "toBase64", "bytes", "binary", "offset", "fromBase64", "encoded", "c", "installHistoryStorageImports", "setModuleImports", "json", "reference", "documentId", "expected", "state", "head", "storage", "DocxHistoryClient", "bridge", "error", "DocxHistoryDocument", "operation", "fields", "checkArchiveSize", "after", "maxEntriesToScan", "operationId", "beforeVersionId", "afterVersionId", "expectedHead", "metadata", "requestId", "cursor", "limit", "versionId", "sequence", "cutoff", "parseResult", "DocxHistoryReader", "call", "#documentId", "requireRequestId", "DocxHistoryArchive", "_DocxHistoryArchive", "handle", "info", "result", "createMemoryHistoryStorage", "maxBlobBytes", "blobs", "heads", "copy", "value", "key", "equalReference", "b", "equalHead", "blobKey", "captured", "n", "current", "revision", "existing", "HistoryCheckpoints", "_HistoryCheckpoints", "document", "journal", "view", "controls", "DocxHistoryError", "bytes", "metadata", "target", "request", "intended", "error", "action", "openIndexedDbHistoryStore", "name", "db", "resolve", "reject", "blocked", "request", "store", "transaction", "mode", "action", "tx", "value", "result", "error", "reference", "key", "referenceKey", "event", "bytes", "captured", "DocxHistoryError", "byte", "documentId", "expected", "state", "validateHead", "revision", "current", "equalHead", "head", "existing", "requestId", "a", "b", "mountHistoryControls", "container", "options", "pageSize", "HistoryPanel", "doc", "style", "HISTORY_CSS", "title", "legend", "note", "versionTitle", "comparison", "compareNote", "before", "saveGroup", "attribution", "attributionTitle", "view", "version", "restoreNote", "request", "target", "sharing", "sharingNote", "portability", "time", "cutoff", "DocxHistoryError", "sequence", "activity", "decisions", "showOlderActivity", "operations", "resolved", "op", "shown", "page", "refresh", "cursor", "reset", "start", "index", "select", "option", "hasVersion", "pending", "stale", "key", "element", "item", "state", "label", "formatTime", "description", "decision", "kind", "metadata", "bytes", "suffix", "stem", "name", "url", "link", "action", "work", "error", "historyControlError", "parent", "button", "type", "value", "input", "details", "summary", "code", "ROMAN_ONES", "ROMAN_TENS", "ROMAN_HUNDREDS", "ROMAN_THOUSANDS", "toRoman", "value", "toLetter", "wrapped", "repeats", "RENDERERS", "v", "formatPageNumber", "format", "PARAGRAPH_SELECTOR", "baselineOffsets", "document", "offsets", "host", "paragraph", "child", "key", "offset", "probe", "property", "span", "marker", "alignExactLineBaselines", "root", "view", "offsetFor", "run", "movable", "style", "height", "runStyle", "top", "shift", "EXACT_INK_ATTRIBUTE", "preserveExactLineInk", "content", "topLimit", "bottomLimit", "paper", "band", "scale", "above", "below", "box", "element", "range", "rects", "rect", "bottom", "up", "down", "insetClipBounds", "value", "match", "parts", "right", "left", "movable", "element", "view", "position", "descendant", "DEFAULT_PAGE_WIDTH", "DEFAULT_PAGE_HEIGHT", "DEFAULT_MARGIN", "pxToPt", "px", "ptToPx", "pt", "finiteDataNumber", "value", "fallback", "parsed", "positiveDataNumber", "nonNegativeDataNumber", "positiveFinite", "parseSectionDimensions", "section", "pageWidth", "pageHeight", "marginTop", "marginRight", "marginBottom", "marginLeft", "derivedContentWidth", "derivedContentHeight", "contentWidth", "contentHeight", "headerDistance", "footerDistance", "MIN_BODY_BAND_PT", "resolvePageBands", "dims", "headerContentHeight", "footerContentHeight", "headerTop", "footerBottom", "headerReach", "footerReach", "bodyTop", "bodyBottom", "shortfall", "headerGrowth", "footerGrowth", "growth", "sectionWrappers", "root", "sections", "MIN_FIT_SCALE", "fitScale", "availablePx", "naturalPt", "max", "naturalPx", "applyZoom", "el", "scale", "samePageBox", "a", "b", "createUnavailablePageMap", "documentVersion", "rendererFingerprint", "mode", "activePageCitationHighlights", "clearPageCitationHighlight", "root", "active", "style", "navigateToPageCitation", "citation", "options", "byAttribute", "name", "value", "within", "node", "fragment", "target", "page", "addedClass", "inlineStyles", "MAX_FOOTNOTE_AREA_RATIO", "FOOTNOTE_MEASUREMENT_GUARD_PT", "FOOTNOTE_SOURCE_POSITION_ATTR", "collapsedBlockMarginsPx", "view", "element", "collapseMarginChain", "edge", "margins", "current", "collapsesThroughTo", "positive", "negative", "parent", "border", "padding", "nodes", "child", "childStyle", "DRAWING_HOST_ATTRIBUTE", "HOSTS_PROMOTED_DRAWING_ATTRIBUTE", "rendersOnlyItsLine", "createRenderedSourceMeasurer", "clipInset", "drawingHostAttribute", "hostsPromotedDrawingAttribute", "visibleWithinPage", "pageRect", "rect", "left", "top", "right", "bottom", "clips", "ancestor", "clipsX", "clipsY", "ancestorRect", "scale", "inset", "own", "ownResult", "ownMeasurable", "hostsPromotedDrawing", "hostAnchorId", "promoted", "drawing", "rendered", "childRect", "visible", "measureRenderedSource", "insetClipBounds", "PaginationEngine", "staging", "container", "options", "ownerDocument", "view", "pages", "pageNumber", "sections", "sectionsToProcess", "referencedFootnoteIds", "referencedCommentIds", "section", "reference", "id", "source", "commentId", "runs", "dims", "parseSectionDimensions", "previous", "samePageBox", "sectionIndex", "run", "precedingPage", "precedingPageInSection", "precedingDisplayedPageNumber", "filler", "blocks", "sectionDims", "columnCount", "gap", "sectionPages", "page", "pageInSection", "displayedPageNumber", "header", "footer", "result", "error", "documentVersion", "rendererFingerprint", "fragments", "requiredAnchorIds", "measuredAnchorIds", "emittedFragmentCounts", "pageRect", "pointPerRenderedX", "pointPerRenderedY", "nodes", "element", "anchorId", "style", "rect", "visibleRect", "measureRenderedSource", "left", "top", "right", "bottom", "fragmentIndex", "fragmentId", "missingAnchor", "visible", "first", "second", "scope", "destination", "excludeRegistries", "candidates", "next", "bounds", "sourceRoot", "current", "zeroHeightExplicitBreakCarrier", "fragmentCounts", "activeCanonicalIds", "activeBareAnchorIds", "makeInactive", "story", "mayOwnActiveEditorAnchor", "bareAnchorId", "activeStagingCanonicalIds", "visibleIds", "map", "index", "rawStart", "start", "totalPages", "boxes", "box", "markers", "numbering", "displayed", "marker", "kind", "format", "formatPageNumber", "children", "child", "nestedSectionIndex", "nestedBlocks", "endnoteBlocks", "marginTopPx", "marginBottomPx", "collapsedBlockMarginsPx", "heightPt", "pxToPt", "marginTopPt", "marginBottomPt", "isPageBreak", "sectionChildren", "list", "items", "item", "sectionStyle", "rule", "clonedRule", "ruleStyle", "property", "listStyle", "itemIndex", "ownerAnchorId", "paragraphs", "paragraphIndex", "paragraph", "clone", "node", "owner", "itemId", "value", "listStyleType", "columnGapPt", "sequential", "maxFragmentHeight", "isBreak", "makeContainer", "slice", "end", "measured", "candidate", "candidateMeasured", "host", "spaceBefore", "block", "availableHeightPt", "maximumHeight", "height", "make", "limit", "whole", "count", "measurementHost", "measuredElement", "margins", "startIndex", "firstBlock", "chain", "lastIndex", "nextBlock", "previousMarginBottomPt", "isFirstOnPage", "bodyHeight", "previousBlock", "existingFootnoteIds", "knownIds", "newIds", "wrapper", "table", "body", "rows", "retainAnchor", "wrapperClone", "tableClone", "bodyClone", "row", "tableElement", "minimumContentHeight", "maximumFragmentHeight", "groups", "isFirst", "isLast", "fragment", "emergencyGraphemeBreaks", "textNodes", "textStarts", "lastTextByField", "walker", "flattenedChunks", "flattenedLength", "textNode", "field", "flattenedText", "invisible", "firstVisibleOffset", "lastVisibleOffset", "graphemeBoundaries", "addCandidate", "textOffset", "atomic", "whitespace", "match", "matchesSinceCheckpoint", "offset", "last", "parent", "childIndex", "endpoints", "text", "SegmenterConstructor", "boundaries", "segmentCount", "part", "lastCodeUnit", "beforeOffset", "beforeCodePoint", "afterCodePoint", "before", "after", "eastAsian", "codePointBefore", "nonBreaking", "allowInlineRoot", "unsupportedDescendants", "paragraphStyle", "descendant", "range", "retainSourceIdentity", "isFinalFragment", "contents", "head", "tail", "elements", "root", "selector", "headIds", "headAnchors", "anchor", "fits", "largestFit", "lastEndpoint", "lastRange", "lastContents", "lastHead", "low", "high", "best", "middle", "endpoint", "headRange", "headContents", "tailRange", "tailContents", "effectiveMarginTopPt", "split", "headMeasured", "tailMeasured", "registry", "registryEl", "sectionWidths", "idx", "contentWidth", "defaultContentWidth", "entries", "entry", "hfType", "content", "measuredHeight", "footnoteId", "continuation", "fallback", "refs", "ids", "ref", "sourceIndex", "FOOTNOTE_SOURCE_POSITION_ATTR", "sourceContent", "sentinel", "footnote", "fittingElements", "number", "footnoteIds", "partialFootnotes", "hasContinuation", "measureContainer", "partialById", "partial", "fitting", "remaining", "sourcePosition", "canSplitCandidate", "footnoteElement", "forceProgress", "existingPayload", "layoutContext", "attachedFootnote", "measuredPartial", "measuredContent", "footnoteContent", "el", "overflow", "i", "measuredCandidate", "pageBox", "bands", "footnoteHeight", "maxFootnoteHeight", "MAX_FOOTNOTE_AREA_RATIO", "footnotesDiv", "sectionHf", "which", "even", "bodyHeightPt", "physicalPageNumber", "resolvePageBands", "startPageNumber", "sectionDimensions", "currentContent", "pageSectionIndex", "sectionStartPages", "physicalPage", "dimensionsFor", "markSectionPlaced", "previousBox", "ownerPageInSection", "ownerNumbering", "effectiveContentHeight", "remainingHeight", "prevMarginBottomPt", "currentFootnoteIds", "currentPageHasFootnoteReference", "currentFootnoteHeight", "currentContinuation", "nextPageContinuation", "currentContinuationPartitioned", "currentPageAdmitted", "deferredFootnoteIds", "currentPartialFootnotes", "adoptEmptyPageOwner", "admitCurrentPage", "prepareCurrentContinuation", "ownedDimensions", "pageBands", "partition", "finishPage", "nextPageSectionIndex", "forceEmptyPage", "hasCurrentContinuation", "pageContinuation", "ownedPageInSection", "ownedDisplayedPageNumber", "fittingIds", "candidateIds", "guardedCandidateHeight", "FOOTNOTE_MEASUREMENT_GUARD_PT", "hasPageContinuation", "newBands", "nextDimensions", "pageHasPayload", "allBlockFootnoteIds", "ownerDimensions", "ownerMaxFootnoteArea", "fittingHeight", "candidateHeight", "blockDimensions", "nextBlockPageInSection", "freshBlockPageBodyHeight", "startsKeepChain", "keepChain", "newChainFootnoteIds", "additionalChainFootnoteHeight", "totalChainFootnoteHeight", "currentChainHeight", "currentAvailableHeight", "nextPageBands", "freshChainBodyHeight", "freshChainFootnoteHeight", "newFootnoteIds", "combinedFootnoteHeight", "additionalFootnoteHeight", "combinedFootnoteIds", "effectiveMarginTop", "columnFragments", "blockSpace", "effectiveRemainingHeight", "bodyContentUsed", "maxFootnoteArea", "paragraphFragments", "blockSpaceWithoutFootnotes", "availableForFootnotes", "nextPageMaxFootnoteArea", "deferralCannotHelp", "noteIndex", "spaceLeftForFootnotes", "tableFragments", "contentArea", "anchors", "pixelsPerPoint", "staticRect", "paragraphRect", "toPageX", "x", "toPageY", "y", "context", "widthReference", "widthPercent", "heightReference", "heightPercent", "sizedRect", "width", "horizontal", "vertical", "hostElement", "hostAnchorId", "DRAWING_HOST_ATTRIBUTE", "rendersOnlyItsLine", "HOSTS_PROMOTED_DRAWING_ATTRIBUTE", "suffix", "raw", "relativeFrom", "leftMargin", "rightMargin", "topMargin", "bottomMargin", "objectSize", "alignment", "fraction", "prospectivePageCount", "isSectionFiller", "pageAlreadyAdmitted", "heightReductionPt", "widthReductionPt", "heightReductionPx", "ptToPx", "widthReductionPx", "headerSource", "headerDiv", "clonedheaderDiv", "contentAreaTop", "contentAreaHeight", "pageCommentIds", "marginColumn", "placedThreadRoots", "rootId", "footerSource", "footerDiv", "clonedfooterDiv", "pageNum", "notesEl", "notesHeightPt", "alignExactLineBaselines", "paper", "preserveExactLineInk", "paginateHtml", "html", "containerEl", "cssPrefix", "pageContainer", "DocumentViewport", "host", "options", "root", "applySectionGeometry", "scale", "applyZoom", "ptToPx", "fitScale", "style", "padding", "sections", "sectionWrappers", "section", "widest", "dims", "parseSectionDimensions", "box", "declared", "pxToPt", "import_meta", "openDocxHistory", "storage", "bridge", "ensureInitialized", "DocxHistoryClient", "openDocxHistoryArchive", "bytes", "DocxHistoryArchive", "openDocxSession", "settings", "wasm", "createBlankDocx", "wasmExports", "initPromise", "yieldToMain", "resolve", "getDefaultWasmBasePath", "moduleUrl", "import_meta", "wasmBasePath", "setWasmBasePath", "path", "initialize", "basePath", "loadWasm", "tryLoadFromPath", "dotnetPath", "dotnet", "getAssemblyExports", "getConfig", "setModuleImports", "installHistoryStorageImports", "config", "exports", "autoDetectedPath", "ensureInitialized", "isErrorResponse", "result", "parsed", "parseError", "toBytes", "input", "buffer", "generatePackageManifest", "document", "bytes", "verifyDeliverable", "baseline", "request", "baselineBytes", "requestJson", "serializeVerificationRequest", "converter", "verifyDeliveryReceipt", "receiptJson", "artifacts", "artifactsJson", "artifactId", "bytesToBase64", "proveRedlineReversibility", "intendedFinal", "redline", "intendedFinalBytes", "redlineBytes", "renderBlockHtml", "anchorId", "options", "convertDocxToHtml", "needsCompleteConversion", "error", "compareDocuments", "original", "modified", "originalBytes", "modifiedBytes", "compareDocumentsToHtml", "renderTrackedChanges", "getRevisions", "getComments", "docxDiffSettingsJson", "settings", "docxDiffCompare", "left", "right", "leftBytes", "rightBytes", "docxDiffGetRevisions", "mapDocxDiffRevision", "docxDiffCompareProducts", "products", "docxDiffCompareBatch", "candidates", "payload", "i", "entry", "c", "docxDiffGetEditScript", "docxDiffGetSemanticChanges", "docxDiffAcceptRevisions", "docxDiffRejectRevisions", "binary", "chunk", "reviewersJson", "reviewers", "arr", "r", "docxDiffConsolidateSettingsJson", "docxDiffConsolidate", "base", "baseBytes", "reviewersJsonStr", "docxDiffGetConflicts", "comp", "docxDiffGetConsolidatedRevisions", "docxDiffGetConsolidatedEditScript", "getVersion", "isInitialized", "getWasmExports", "getAnnotations", "a", "addAnnotation", "annotation", "removeAnnotation", "annotationId", "hasAnnotations", "getDocumentStructure", "convertElement", "el", "convertTableColumn", "col", "root", "elementsById", "rawElementsById", "key", "tableColumns", "rawTableColumns", "getDocumentMetadata", "convertSection", "exportToOpenContract", "readOpenContractExport", "convertWmlToMarkdown", "settingsJson", "rawIndex", "anchorIndex", "value", "v", "addAnnotationWithTarget", "computeDocumentHash", "createExternalAnnotationSet", "documentId", "readExternalAnnotationSet", "validateExternalAnnotations", "annotationSet", "annotationSetJson", "readExternalAnnotationValidation", "convertDocxToHtmlWithExternalAnnotations", "conversionOptions", "projectionOptions", "readProjectedHtml", "searchTextOffsets", "searchText", "maxResults", "createAnnotation", "id", "labelId", "documentText", "startOffset", "endOffset", "rawText", "createAnnotationFromSearch", "occurrence", "offsets", "findTextOccurrences", "start", "end", "results", "index", "projectAnnotationsOntoHtml", "html", "addAnnotationToHtml", "label", "annotationJson", "labelJson", "removeAnnotationFromHtml", "cssClassPrefix", "generateAnnotationVisibilityCss", "hiddenLabelIds", "generateAnnotationCss", "labels", "STORY_BLOCK_KINDS", "KIND_LABELS", "LIVE_BLOCK_ATTRS", "HeaderFooterRegion", "bridge", "handle", "callbacks", "bodyAnchorId", "cached", "info", "changed", "which", "kind", "r", "enabled", "parseResult", "kinds", "anchorId", "field", "near", "target", "op", "node", "band", "el", "host", "previous", "pages", "page", "area", "pageIndex", "bodyAnchor", "block", "placeCaretAtEnd", "pageRoot", "listener", "event", "hadActive", "caret", "blocks", "hit", "doc", "point", "caretFromPoint", "sel", "range", "box", "unid", "id", "body", "partUri", "sourceBody", "sectionParts", "sectionIndex", "part", "anchor", "child", "inertClone", "total", "displayed", "format", "marker", "formatPageNumber", "parsed", "index", "raw", "t", "set", "tag", "label", "note", "focused", "available", "k", "button", "e", "inherited", "hadFocus", "anchors", "last", "sib", "clone", "attr", "x", "y", "d", "position", "json", "HIGHLIGHT_SELECTOR", "MARKER_SELECTOR", "idsOf", "el", "s", "formatDate", "iso", "d", "initialsOf", "author", "initials", "parts", "p", "authorHue", "h", "i", "threadMembers", "comments", "rootAnchorId", "children", "c", "list", "out", "seen", "walk", "id", "child", "CommentGutter", "host", "options", "doc", "event", "target", "hit", "records", "record", "node", "view", "byId", "entry", "roots", "repliesOf", "root", "existing", "containerRect", "gutterRect", "views", "anchor", "replies", "bubble", "key", "fresh", "rect", "desiredTop", "desiredLeft", "stale", "a", "b", "gap", "cursor", "placed", "draftPlaced", "placeDraft", "top", "orphan", "wanted", "scrollW", "scrollH", "paths", "offX", "offY", "gutterX", "active", "source", "x1", "y1", "y2", "x2", "xm", "v", "visible", "wasVisible", "opts", "x", "direction", "order", "index", "next", "sel", "r", "input", "post", "text", "created", "candidates", "marker", "ids", "hue", "collapsed", "reply", "actions", "cancel", "submit", "bar", "resolve", "isRoot", "head", "avatar", "date", "badge", "menu", "edit", "del", "save", "body", "COMMENT_GUTTER_CSS", "_arrayWithHoles", "r", "_iterableToArrayLimit", "r", "l", "e", "n", "u", "f", "o", "_arrayLikeToArray", "r", "a", "e", "_unsupportedIterableToArray", "r", "a", "_arrayLikeToArray", "_nonIterableRest", "_slicedToArray", "r", "_arrayWithHoles", "_iterableToArrayLimit", "_unsupportedIterableToArray", "_nonIterableRest", "import_bind_event_listener", "honeyPotDataAttribute", "isHoneyPotElement", "target", "honeyPotDataAttribute", "getElementFromPointWithoutHoneypot", "client", "_document$elementsFro", "_document$elementsFro2", "_slicedToArray", "top", "second", "isHoneyPotElement", "_typeof", "o", "toPrimitive", "t", "r", "_typeof", "e", "i", "toPropertyKey", "t", "i", "toPrimitive", "_typeof", "_defineProperty", "e", "r", "toPropertyKey", "import_bind_event_listener", "maxZIndex", "popoverResetUserAgentStyles", "once", "fn", "cache", "_len", "args", "_key", "result", "supportsPopover", "once", "ownKeys", "e", "r", "o", "_objectSpread", "_defineProperty", "honeyPotSize", "halfHoneyPotSize", "floorToClosestPixel", "point", "pullBackByHalfHoneyPotSize", "preventGoingBackwardsOffScreen", "preventGoingForwardsOffScreen", "getHoneyPotRectFor", "_ref", "client", "getRectStyles", "_ref2", "clientRect", "isWithin", "_ref3", "mountHoneyPot", "_ref4", "initial", "element", "honeyPotDataAttribute", "supportsPopover", "popoverResetUserAgentStyles", "maxZIndex", "unbindPointerMove", "event", "_ref5", "current", "cleanup", "unbindPostDragEvents", "makeHoneyPotFix", "latestPointerMove", "bindEvents", "getOnPostDispatch", "finish", "_ref6", "eventName", "payload", "input", "_finish", "_input", "_arrayWithoutHoles", "r", "_arrayLikeToArray", "_iterableToArray", "r", "_nonIterableSpread", "_toConsumableArray", "r", "_arrayWithoutHoles", "_iterableToArray", "_unsupportedIterableToArray", "_nonIterableSpread", "import_bind_event_listener", "isFirefox", "once", "isSafari", "once", "_navigator", "userAgent", "import_bind_event_listener", "symbols", "isLeavingWindowInSafari", "_ref2", "dragLeave", "isSafari", "symbols", "getInitialState", "state", "resetState", "event", "isNodeLike", "target", "isFromAnotherWindow", "eventTarget", "isLeavingWindow", "_ref", "dragLeave", "type", "relatedTarget", "isSafari", "isLeavingWindowInSafari", "isFirefox", "isFromAnotherWindow", "getBindingsForBrokenDrags", "_ref", "onDragEnd", "callCount", "getInput", "event", "rafSchd", "fn", "lastArgs", "frameId", "wrapperFn", "_len", "args", "_key", "raf_schd_esm_default", "scheduleOnDrag", "raf_schd_esm_default", "fn", "dragStart", "scheduled", "schedule", "frameId", "flush", "makeDispatch", "_ref", "source", "initial", "dispatchEvent", "previous", "safeDispatch", "args", "dispatch", "_ref2", "nativeSetDragImage", "location", "_ref3", "current", "_ref4", "_ref5", "updatedSourcePayload", "globalState", "canStart", "getNativeSetDragImage", "event", "hasHierarchyChanged", "_ref", "current", "next", "i", "start", "_ref2", "dragType", "getDropTargetsOver", "dispatchEvent", "initial", "getStartLocation", "state", "setDropEffectOnEvent", "dispatch", "makeDispatch", "updateState", "hasChanged", "onUpdateEvent", "input", "getInput", "target", "isHoneyPotElement", "getElementFromPointWithoutHoneypot", "nextDropTargets", "cancel", "finish", "unbindEvents", "isLeavingWindow", "_toConsumableArray", "getBindingsForBrokenDrags", "_ref3", "_current$", "innerMost", "_ref4", "dropTargets", "lifecycle", "ledger", "registerUsage", "_ref", "typeKey", "mount", "entry", "initial", "register", "args", "combine", "_len", "fns", "_key", "fn", "addAttribute", "element", "_ref", "attribute", "value", "ownKeys", "e", "r", "o", "_objectSpread", "_defineProperty", "_createForOfIteratorHelper", "_unsupportedIterableToArray", "_n", "F", "a", "u", "_arrayLikeToArray", "copyReverse", "array", "makeDropTarget", "_ref", "typeKey", "defaultDropEffect", "registry", "dropTargetDataAtt", "dropTargetSelector", "addToRegistry", "args", "dropTargetForConsumers", "existing", "cleanup", "combine", "addAttribute", "once", "getActualDropTargets", "_ref2", "_args$getData", "_args$getData2", "_args$getDropEffect", "_args$getDropEffect2", "source", "target", "input", "_ref2$result", "result", "closest", "feedback", "data", "dropEffect", "record", "_toConsumableArray", "notifyCurrent", "_ref3", "eventName", "payload", "_iterator", "_step", "_entry$eventName", "entry", "err", "actions", "_ref4", "isCurrent", "visited", "_iterator2", "_step2", "_entry$onDropTargetCh", "isOver", "_entry$onDragLeave", "_iterator3", "_step3", "_entry$onDropTargetCh2", "_entry$onDragEnter", "_record", "_args", "_entry", "dispatchEvent", "getIsOver", "_ref5", "current", "actual", "lastCaptureOrdered", "actualCaptureOrdered", "resultCaptureOrdered", "index", "_argsForLast$getIsSti", "last", "fresh", "parent", "lastParent", "argsForLast", "_createForOfIteratorHelper", "r", "_unsupportedIterableToArray", "_n", "F", "o", "a", "u", "_arrayLikeToArray", "e", "ownKeys", "_objectSpread", "_defineProperty", "makeMonitor", "registry", "dragging", "tryAddToActive", "monitor", "monitorForConsumers", "args", "entry", "cleanup", "once", "dispatchEvent", "_ref", "eventName", "payload", "_iterator", "_step", "err", "active", "_i", "_active", "_monitor", "_monitor$eventName", "makeAdapter", "_ref", "typeKey", "mount", "dispatchEventToSource", "onPostDispatch", "defaultDropEffect", "monitorAPI", "makeMonitor", "dropTargetAPI", "makeDropTarget", "dispatchEvent", "args", "start", "_ref2", "event", "dragType", "lifecycle", "registerUsage", "mountAdapter", "api", "register", "isAndroid", "once", "androidFallbackText", "textMediaType", "URLMediaType", "elementAdapterNativeDataKey", "draggableRegistry", "addToRegistry", "args", "honeyPotFix", "makeHoneyPotFix", "adapter", "makeAdapter", "api", "combine", "event", "_entry$dragHandle", "_entry$getInitialData", "_entry$getInitialData2", "_entry$dragHandle2", "_entry$getInitialData3", "_entry$getInitialData4", "target", "entry", "input", "getInput", "feedback", "over", "getElementFromPointWithoutHoneypot", "nativeData", "_i", "_Object$entries", "_Object$entries$_i", "_slicedToArray", "key", "data", "isAndroid", "textMediaType", "URLMediaType", "androidFallbackText", "elementAdapterNativeDataKey", "payload", "dragType", "_ref", "_draggableRegistry$ge", "_draggableRegistry$ge2", "eventName", "dropTargetForElements", "monitorForElements", "draggable", "existing", "cleanup", "addAttribute", "once", "ownKeys", "e", "r", "o", "_objectSpread", "_defineProperty", "defaultOffset", "setCustomNativeDragPreview", "_ref", "render", "nativeSetDragImage", "_ref$getOffset", "getOffset", "container", "supportsPopover", "popoverResetUserAgentStyles", "maxZIndex", "unmount", "previewOffset", "isSafari", "rect", "cleanup", "unbindMonitor", "monitorForElements", "isSafariOnIOS", "once", "isSafari", "centerUnderPointer", "_ref", "container", "rect", "pointerOutsideOfPreview", "point", "_ref", "container", "isSafariOnIOS", "isAndroid", "centerUnderPointer", "computed", "box", "ledger", "requested", "markAndGetEngagement", "element", "markEngagement", "entry", "fresh", "clearUnusedEngagements", "fn", "_", "clearEngagementHistory", "schedulers", "getScheduler", "monitor", "scheduler", "created", "makeScheduler", "state", "callbacks", "loop", "timeLastFrameFinished", "timeSinceLastFrame", "_state", "latestArgs", "underUsersPointer", "getElementFromPointWithoutHoneypot", "clearUnusedEngagements", "onFrame", "reset", "clearEngagementHistory", "start", "args", "update", "api", "fn", "dataAttribute", "selector", "addScrollableAttribute", "element", "ownKeys", "e", "r", "o", "_objectSpread", "_defineProperty", "baseConfig", "maxPixelScrollPerSecond", "getInternalConfig", "provided", "_provided$maxScrollSp", "canScrollOnEdge", "element", "edges", "edgeAxisLookup", "vertical", "horizontal", "axisLookup", "mainAxisSideLookup", "makeGetHitbox", "_ref", "edge", "axis", "_ref2", "clientRect", "config", "_axisLookup$axis", "axisLookup", "mainAxis", "crossAxis", "side", "mainAxisSideLookup", "mainAxisHitboxSize", "_defineProperty", "getOverElementHitbox", "getPercentageInRange", "_ref", "startOfRange", "endOfRange", "value", "isValid", "range", "getMaxScrollChange", "_ref", "timeSinceLastFrame", "config", "targetScrollPerMs", "proposed", "maximum", "getDistanceDampening", "_ref2", "client", "axis", "edge", "hitbox", "mainAxis", "axisLookup", "side", "mainAxisSideLookup", "maxSpeedBuffer", "getPercentageInRange", "raw", "getScrollChange", "_ref3", "engagement", "isDistanceDampeningEnabled", "maxScroll", "percentageDistanceDampening", "percentageThroughTimeDampening", "percentageOfMaxScroll", "scroll", "isAxisAllowed", "axis", "allowedAxis", "isWithin", "_ref", "client", "clientRect", "getRectDefault", "element", "getScrollBy", "_ref", "input", "timeSinceLastFrame", "engagement", "config", "allowedAxis", "_ref$getRect", "getRect", "client", "clientRect", "scrollableEdges", "edges", "map", "edge", "hitbox", "getOverElementHitbox", "axis", "edgeAxisLookup", "isAxisAllowed", "isWithin", "canScrollOnEdge", "left", "leftEdge", "getScrollChange", "rightEdge", "top", "bottomEdge", "topEdge", "_createForOfIteratorHelper", "r", "_unsupportedIterableToArray", "_n", "F", "o", "a", "u", "_arrayLikeToArray", "e", "isScrollingAvailable", "value", "tryScrollElements", "_ref", "_container$getConfigu", "_container$getAllowed", "_container$getAllowed2", "target", "input", "source", "findEntry", "timeSinceLastFrame", "_ref$available", "available", "element", "selector", "container", "continueSearchUp", "_element$parentElemen", "feedback", "engagement", "markAndGetEngagement", "config", "getInternalConfig", "allowedAxis", "scrollBy", "getScrollBy", "scroll", "tryScrollWindow", "_ref2", "entries", "_iterator", "_step", "_entry$getConfigurati", "_entry$getAllowedAxis", "_entry$getAllowedAxis2", "entry", "err", "tryScroll", "_ref3", "getWindowScrollEntries", "underUsersPointer", "remainder", "ownKeys", "e", "r", "o", "_objectSpread", "_defineProperty", "makeApi", "_ref", "monitor", "elementRegistry", "windowRegistry", "autoScroll", "args", "_window$getComputedSt", "overflowX", "overflowY", "isScrollable", "existing", "cleanup", "combine", "addScrollableAttribute", "once", "autoScrollWindow", "unique", "findEntry", "element", "_elementRegistry$get", "getWindowScrollEntries", "onFrame", "_ref2", "latestArgs", "underUsersPointer", "timeSinceLastFrame", "tryScroll", "getScheduler", "api", "makeApi", "monitorForElements", "autoScrollForElements", "autoScrollWindowForElements", "tokenOf", "unit", "unidOf", "id", "diffUnits", "oldUnids", "newUnits", "n", "m", "newUnids", "lcs", "i", "j", "keep", "removed", "added", "bareUnid", "token", "bar", "moved", "usedRemoved", "usedAdded", "removedByToken", "oi", "nj", "substituted", "removedByUnid", "u", "unmatchedAdded", "keptBeforeOld", "c", "v", "keptBeforeNew", "k", "target", "needsRemount", "diff", "oldKinds", "threshold", "subNew", "subOld", "imageOnlyDelta", "live", "fresh", "ignoredAttributes", "ignored", "pairs", "attributeNames", "el", "a", "n", "sameAttributes", "b", "na", "nb", "i", "liveChildren", "walk", "ea", "eb", "ca", "cb", "patchImageAttributes", "attr", "src", "EDITABLE_TAGS", "BLOCK_DRAG_TYPE", "blockDragStyledDocuments", "blockPreviewText", "unit", "text", "BLOCK_HANDLE_WIDTH", "BLOCK_HANDLE_HEIGHT", "BLOCK_HANDLE_GAP", "clampToRange", "value", "low", "high", "ensureBlockDragStyles", "doc", "style", "CHROME_CARRIER_ANCHOR", "yieldToEventLoop", "resolve", "settle", "trackedChangeWireName", "mode", "fontWeightIsBold", "w", "n", "escapeInlineMarkdown", "escapeLeadingBlockMarkers", "md", "line", "collectInlineSegments", "node", "out", "child", "isGeneratedChrome", "isField", "fieldText", "parent", "bold", "italic", "href", "cs", "a", "el", "segToMarkdown", "seg", "serializeInlineMarkdown", "block", "segs", "merged", "s", "prev", "keepsTrailingSpace", "blockContentText", "noteTypedSpace", "event", "input", "caretOffsetIn", "isListBlock", "ensureListMarkerSeparator", "marker", "separator", "GENERATED_CHROME_SELECTOR", "isField", "node", "fieldText", "field", "adoptFields", "block", "isInMarker", "el", "isGeneratedChrome", "BIDI_MARK_CLASS", "BIDI_MARKS_RE_G", "BIDI_MARK_RE", "stripBidi", "s", "domOffsetForContentOffset", "n", "content", "i", "contentOffsetOf", "container", "offset", "count", "done", "walk", "inside", "kids", "caretOffsetIn", "sel", "range", "blockContentText", "out", "trimmedSplitOffset", "domOffset", "leading", "trimmedLen", "trimBounds", "keepsTrailingSpace", "trimmedSpan", "span", "start", "end", "contentPositionIn", "remaining", "result", "lastText", "len", "parent", "index", "raw", "caretPointFromClient", "doc", "clientX", "clientY", "caretDoc", "position", "setSelectionBetween", "anchor", "focus", "probe", "focusIsBefore", "placeCaretAtOffset", "pos", "selectionSpanIn", "contentRangeIn", "length", "from", "to", "selectRange", "FIND_HIGHLIGHT", "FIND_HIGHLIGHT_ACTIVE", "FIND_PAINT_LIMIT", "findHighlightStyledDocuments", "findPaintOwner", "ensureFindHighlightStyles", "style", "highlightRegistry", "registry", "ctor", "makeHighlight", "ranges", "inBorderWrapper", "selectionHasFormat", "key", "fallback", "cs", "fontWeightIsBold", "completeArgs", "bytes", "cssPrefix", "fabricate", "paginated", "scale", "renderTrackedChanges", "comments", "DocxEditor", "_DocxEditor", "exports", "handle", "options", "startBlock", "endBlock", "startUnid", "endUnid", "unid", "event", "target", "origin", "drag", "focusBlock", "DocumentViewport", "view", "focusIndex", "caretAtEnd", "forceRemount", "band", "opts", "editor", "fullHtml", "error", "bridge", "trackedChangeWireName", "windowSize", "onProgress", "profile", "chrome", "parsed", "CHROME_CARRIER_ANCHOR", "styles", "flow", "hosts", "attachNow", "wireNow", "plan", "units", "sectionOf", "u", "unidOf", "mounted", "place", "sameHostAs", "unit", "host", "window", "rendered", "html", "yieldToEventLoop", "value", "previous", "sourceAnchorId", "targetAnchorId", "res", "destination", "moved", "focusTarget", "EDITABLE_TAGS", "candidate", "fromActive", "clip", "box", "changed", "known", "rect", "top", "BLOCK_HANDLE_HEIGHT", "clampToRange", "BLOCK_HANDLE_WIDTH", "BLOCK_HANDLE_GAP", "preview", "blockPreviewText", "source", "data", "indicator", "zone", "y", "neighbour", "message", "live", "sourceId", "targets", "t", "run", "idle", "id", "sides", "boxes", "anchorId", "ends", "best", "bestGap", "gap", "preferred", "other", "restoreFocus", "menu", "button", "action", "candidates", "targetId", "overflowY", "ensureBlockDragStyles", "onPointerMove", "onFocusIn", "onPointerLeave", "next", "onViewportChange", "onHandleClick", "onHandlePointerDown", "onPointerUp", "onHandleKeydown", "onMenuClick", "onMenuKeydown", "draggable", "BLOCK_DRAG_TYPE", "nativeSetDragImage", "setCustomNativeDragPreview", "pointerOutsideOfPreview", "chip", "dropTargetForElements", "input", "hit", "self", "monitorForElements", "location", "drop", "scroller", "autoScrollForElements", "autoScrollWindowForElements", "cleanup", "proj", "bodyOwned", "fullId", "isBody", "stamped", "HeaderFooterRegion", "_host", "which", "ensureCommentGutterStyles", "CommentGutter", "markdown", "author", "resolved", "info", "fromBlock", "bodyRoot", "paginateHtml", "pageRoot", "root", "ensureListMarkerSeparator", "GENERATED_CHROME_SELECTOR", "m", "ev", "noteTypedSpace", "oldEl", "newNodes", "prev", "newAnchor", "newUnid", "fresh", "inBand", "k", "fmt", "inTableCell", "isListBlock", "cell", "table", "cells", "backwards", "state", "adjacent", "rawOffset", "idx", "wrappedInBorder", "first", "second", "firstEl", "secondEl", "prevUnid", "thisUnid", "prevId", "thisId", "prevIdx", "caret", "merged", "mergedEl", "old", "serializeInlineMarkdown", "minLen", "p", "middle", "inserted", "idsJson", "a", "b", "json", "map", "parse", "h", "fa", "fb", "all", "active", "failure", "bookmark", "last", "startsAfterEnd", "endsBeforeStart", "hasStart", "hasEnd", "contentLen", "blocks", "op", "synced", "edited", "swapped", "startOff", "endOff", "startPos", "endPos", "on0", "multiOp", "on", "pts", "name", "alignment", "weight", "rows", "cols", "emptyHere", "paragraphId", "cellId", "where", "deltaTwips", "delta", "kind", "membership", "isThisKind", "call", "created", "c", "parentAnchorId", "commentAnchorId", "direction", "visible", "styleId", "hex", "px", "size", "multiple", "payload", "twips", "r", "l", "link", "imageBase64", "file", "binary", "chunk", "rowSpan", "colSpan", "spec", "fill", "scope", "repeat", "tableId", "mode", "revisionId", "fn", "inBlock", "text", "query", "needle", "hay", "at", "match", "matches", "activeIndex", "activeRange", "rest", "replacement", "byBlock", "list", "current", "before", "words", "total", "enabled", "body", "oldUnid", "ref", "ancestor", "sig", "err", "oldNodes", "oldTokens", "oldKinds", "bodyDiff", "diffUnits", "needsRemount", "fnState", "enState", "movedBodyNew", "addedBodyIds", "j", "addedNoteIds", "allIds", "renderedJson", "freshBody", "oldIndex", "newIndex", "freshRoot", "oldMarker", "newMarker", "bodyApply", "freshHasMarker", "reason", "diff", "subOldByNew", "nj", "oi", "oldWrapper", "leaf", "imagePairs", "imageOnlyDelta", "patchImageAttributes", "movedOldByNew", "movedNew", "movedOld", "pureAdded", "pureRemoved", "appliedFresh", "nodeAt", "movedOi", "f", "prevW", "nextW", "moving", "movingW", "anchorEl", "sectionClass", "ol", "lis", "tokens", "li", "section", "following", "prefix", "nodes", "paras", "backref", "notes", "sup", "byUnid", "stampNotes", "commentGutterStyledDocuments", "COMMENT_GUTTER_CSS", "RibbonHistory", "ribbon", "options", "doc", "style", "HISTORY_DRAWER_CSS", "header", "close", "recentLabel", "selectedId", "selected", "dialog", "event", "rect", "DocxHistoryError", "name", "version", "previous", "error", "file", "bytes", "reader", "store", "openIndexedDbHistoryStore", "document", "HistoryCheckpoints", "identity", "checkpoints", "pending", "view", "current", "writable", "holder", "panel", "mountHistoryControls", "title", "action", "request", "sameBytes", "preview", "heading", "actions", "download", "imported", "archive", "value", "i", "key", "message", "historyControlError", "busy", "chrome", "create", "work", "label", "parent", "button", "url", "link", "left", "right", "index", "RIBBON_STYLE_ATTR", "RIBBON_CSS", "ICON_ALIGN", "bars", "HIGHLIGHT_COLORS", "COMMON_FONTS", "RIBBON_HTML", "RIBBON_HINT_HTML", "DEFAULT_STAGES", "DEFAULT_FEATURES", "CONTROL_NAMES", "GRID_ROWS", "GRID_COLS", "ZOOM_STEPS", "nextIdPrefixSeed", "ensureStyles", "doc", "existing", "RIBBON_STYLE_ATTR", "style", "RIBBON_CSS", "resolveIdPrefix", "explicit", "name", "candidate", "resolveContainer", "container", "el", "toHex", "color", "m", "n", "mountRibbon", "options", "RibbonSurface", "root", "RIBBON_HTML", "event", "RibbonHistory", "hintEl", "RIBBON_HINT_HTML", "file", "cells", "fragment", "r", "c", "cell", "highlight", "HIGHLIGHT_COLORS", "opt", "documentFonts", "select", "seen", "placeholder", "add", "group", "key", "common", "COMMON_FONTS", "paragraphStyles", "s", "have", "builtIns", "id", "priority", "b", "qa", "qb", "pa", "pb", "mode", "breakpoint", "width", "next", "strip", "max", "tokens", "entries", "entry", "state", "text", "exports", "bytes", "paginated", "candidateSurface", "started", "tracked", "DocxEditor", "info", "which", "saveButton", "filename", "url", "link", "label", "fn", "ms", "ribbon", "tab", "delegate", "selector", "rulepos", "simple", "smallcaps", "on", "fontsize", "pts", "v", "fontcolor", "fontcolorbtn", "shade", "shadebtn", "repeatheader", "button", "active", "threadMembers", "showcomments", "trackchanges", "markup", "author", "apply", "value", "chosen", "error", "picture", "ok", "headerFooter", "pgfmt", "pgstart", "pageSetup", "op", "top", "bottom", "left", "right", "w", "h", "landscape", "before", "after", "spacing", "input", "special", "specialVal", "applySpecial", "inches", "twips", "showrail", "rail", "showhint", "hint", "numbering", "note", "count", "resolve", "del", "revs", "marks", "current", "mark", "index", "target", "node", "range", "sel", "kind", "box", "story", "scale", "direction", "z", "requested", "o", "bar", "replace", "matchCase", "withReplace", "match", "show", "replacement", "keep", "inDocument", "align", "alignment", "popover", "anchor", "rect", "host", "picker", "rows", "cols", "pop", "form", "popName", "buttonName", "panel", "cs", "px", "hex", "listFormat", "inTable", "tableTab", "row", "band", "blocks", "session", "anchorEl", "block", "unid", "pageinfo", "words", "counts", "family", "a", "overlay", "noop", "eyebrow", "meta", "setProgress", "percent", "step", "message", "title", "copy", "stage", "feature", "card", "number", "every", "import_meta", "scriptBase", "el", "moduleBaseDir", "url", "ensureWasm", "wasmBasePath", "initialize", "dir", "resolveContainer", "container", "EMBED_ROOT_ATTR", "SCOPED_STYLE_ATTR", "nextEmbedRootId", "createScopedMount", "id", "root", "splitSelectorList", "selectorText", "selectors", "start", "parentheses", "brackets", "quote", "escaped", "i", "ch", "scopeSelector", "selector", "rootSelector", "remaining", "consumedRoot", "separated", "match", "whitespace", "scopeCssRules", "rule", "styleRule", "grouping", "scopeStyleElement", "style", "parser", "sheet", "error", "scopeDocumentStyles", "fullHtml", "parsed", "createScopedEditorExports", "exports", "convert", "bridge", "renderHtml", "args", "renderHtmlForReview", "renderEditorHtml", "toDocumentBytes", "source", "response", "scopedDocumentFragment", "mount", "html", "fragment", "sourceStyle", "body", "createViewer", "options", "conversion", "lastHtml", "render", "src", "opts", "bytes", "convertDocxToHtml", "createHistoryViewer", "history", "documentId", "maxEntriesToScan", "accepted", "acceptedBytes", "displayedBytes", "shownSequence", "following", "closed", "queue", "clone", "value", "assertOpen", "DocxHistoryError", "enqueue", "action", "result", "sameHead", "a", "b", "paint", "sequence", "nextHtml", "refresh", "resume", "update", "wantLive", "changedContent", "showSequence", "viewer", "cutoff", "createEditor", "editorOptions", "getWasmExports", "DocxEditor", "nameFromSource", "path", "createRibbonEditor", "ribbonOptions", "ribbon", "mountRibbon", "openDocxHistory", "openDocxHistoryArchive"]
|
|
7
|
+
}
|