@docx-editor.dev/core 0.0.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +92 -2
  3. package/THIRD_PARTY_NOTICES.md +18 -0
  4. package/dist/automation.cjs +1 -0
  5. package/dist/automation.d.cts +74 -0
  6. package/dist/automation.d.ts +74 -0
  7. package/dist/automation.js +1 -0
  8. package/dist/binding.cjs +1 -0
  9. package/dist/binding.d.cts +82 -0
  10. package/dist/binding.d.ts +82 -0
  11. package/dist/binding.js +1 -0
  12. package/dist/chunk-5KSCB2OZ.js +2 -0
  13. package/dist/chunk-BSC44TIT.js +5 -0
  14. package/dist/chunk-DLPL5DAG.js +12 -0
  15. package/dist/chunk-DOEIARE2.js +2 -0
  16. package/dist/chunk-G7YCQBZE.cjs +5 -0
  17. package/dist/chunk-HBL3NNH5.cjs +1 -0
  18. package/dist/chunk-HR7K3W6A.js +1 -0
  19. package/dist/chunk-HVAV2JSN.js +11 -0
  20. package/dist/chunk-MYH2HCUJ.cjs +2 -0
  21. package/dist/chunk-NSM75TN6.cjs +1 -0
  22. package/dist/chunk-PHDVKUWZ.js +1 -0
  23. package/dist/chunk-QADYGK5L.cjs +12 -0
  24. package/dist/chunk-REZUWYB7.js +1 -0
  25. package/dist/chunk-RNBHTPW7.js +10 -0
  26. package/dist/chunk-UD2ZXLFI.cjs +2 -0
  27. package/dist/chunk-VYAVK2AH.cjs +1 -0
  28. package/dist/chunk-YUK46A2N.cjs +11 -0
  29. package/dist/chunk-ZMIX42J7.cjs +10 -0
  30. package/dist/chunk-ZT55Q52J.cjs +2 -0
  31. package/dist/chunk-ZUALAR4M.js +2 -0
  32. package/dist/content-control-walk-CbTqHq6O.d.cts +56 -0
  33. package/dist/content-control-walk-D06GijR0.d.ts +56 -0
  34. package/dist/contracts/document.cjs +1 -0
  35. package/dist/contracts/document.d.cts +246 -0
  36. package/dist/contracts/document.d.ts +246 -0
  37. package/dist/contracts/document.js +0 -0
  38. package/dist/contracts/editor.cjs +1 -0
  39. package/dist/contracts/editor.d.cts +11 -0
  40. package/dist/contracts/editor.d.ts +11 -0
  41. package/dist/contracts/editor.js +1 -0
  42. package/dist/contracts/interaction.cjs +1 -0
  43. package/dist/contracts/interaction.d.cts +11 -0
  44. package/dist/contracts/interaction.d.ts +11 -0
  45. package/dist/contracts/interaction.js +0 -0
  46. package/dist/contracts/modules.cjs +1 -0
  47. package/dist/contracts/modules.d.cts +90 -0
  48. package/dist/contracts/modules.d.ts +90 -0
  49. package/dist/contracts/modules.js +1 -0
  50. package/dist/contracts/types.cjs +1 -0
  51. package/dist/contracts/types.d.cts +452 -0
  52. package/dist/contracts/types.d.ts +452 -0
  53. package/dist/contracts/types.js +0 -0
  54. package/dist/editor-C1QRi1v4.d.ts +1671 -0
  55. package/dist/editor-D0UDock4.d.cts +1671 -0
  56. package/dist/editor.cjs +1 -0
  57. package/dist/editor.css +6017 -0
  58. package/dist/editor.d.cts +271 -0
  59. package/dist/editor.d.ts +271 -0
  60. package/dist/editor.js +1 -0
  61. package/dist/hf-references-BdjsQNE_.d.ts +71 -0
  62. package/dist/hf-references-CgEOSw3i.d.cts +71 -0
  63. package/dist/image-resources-BJnTpG66.d.ts +195 -0
  64. package/dist/image-resources-BpIydXtU.d.cts +195 -0
  65. package/dist/index-CrW-IxXt.d.cts +2515 -0
  66. package/dist/index-ZqBEOrTV.d.ts +2515 -0
  67. package/dist/index.cjs +1 -0
  68. package/dist/index.d.cts +22 -0
  69. package/dist/index.d.ts +22 -0
  70. package/dist/index.js +1 -0
  71. package/dist/layout.cjs +1 -0
  72. package/dist/layout.d.cts +2316 -0
  73. package/dist/layout.d.ts +2316 -0
  74. package/dist/layout.js +1 -0
  75. package/dist/note-nodes-BPSTVDMr.d.ts +108 -0
  76. package/dist/note-nodes-C6DLxlvj.d.cts +108 -0
  77. package/dist/note-properties-CnmCoory.d.cts +68 -0
  78. package/dist/note-properties-m75hmP70.d.ts +68 -0
  79. package/dist/ooxml-package-CR5us6ad.d.cts +354 -0
  80. package/dist/ooxml-package-D_CtywTW.d.ts +354 -0
  81. package/dist/ooxml-tree-BU0e3DVi.d.cts +871 -0
  82. package/dist/ooxml-tree-BU0e3DVi.d.ts +871 -0
  83. package/dist/output.cjs +1 -0
  84. package/dist/output.d.cts +158 -0
  85. package/dist/output.d.ts +158 -0
  86. package/dist/output.js +1 -0
  87. package/dist/protocol-CAkOBBGE.d.cts +1201 -0
  88. package/dist/protocol-oxHaWmt4.d.ts +1201 -0
  89. package/dist/review-support-DS8DYX2a.d.cts +326 -0
  90. package/dist/review-support-Fy3vdIea.d.ts +326 -0
  91. package/dist/revision-projection-72ZApe-g.d.cts +84 -0
  92. package/dist/revision-projection-DHAkcD_L.d.ts +84 -0
  93. package/dist/semantic-cell-selection-CZjBSmMv.d.cts +427 -0
  94. package/dist/semantic-cell-selection-DsmHmLJ5.d.ts +427 -0
  95. package/dist/semantic-interaction-D-Dszxrn.d.cts +187 -0
  96. package/dist/semantic-interaction-Dy-dCUFF.d.ts +187 -0
  97. package/dist/semantic-paint-drawings-BA3z9jl8.d.ts +21 -0
  98. package/dist/semantic-paint-drawings-D7qbB0E2.d.cts +21 -0
  99. package/dist/semantic-records-CJR3BvHs.d.cts +1432 -0
  100. package/dist/semantic-records-CWodBJsz.d.ts +1432 -0
  101. package/dist/shaped-measurer-B-TAtcQU.d.ts +613 -0
  102. package/dist/shaped-measurer-CNIT_svZ.d.cts +613 -0
  103. package/dist/store.cjs +1 -0
  104. package/dist/store.d.cts +2247 -0
  105. package/dist/store.d.ts +2247 -0
  106. package/dist/store.js +1 -0
  107. package/dist/tree-op-types-CwOeiaQ8.d.ts +1431 -0
  108. package/dist/tree-op-types-DMiW6nIH.d.cts +1431 -0
  109. package/dist/tree-package-store-D5S7VKs5.d.ts +708 -0
  110. package/dist/tree-package-store-DOKMtCnh.d.cts +708 -0
  111. package/dist/tree-session-CiUel5Kz.d.ts +542 -0
  112. package/dist/tree-session-D47_imvR.d.cts +542 -0
  113. package/dist/tree-store-CxifqwIv.d.cts +273 -0
  114. package/dist/tree-store-hLtjeyWE.d.ts +273 -0
  115. package/package.json +105 -8
  116. package/index.js +0 -1
@@ -0,0 +1,542 @@
1
+ import { S as SupportedImageMime, b as ImageDecodePort } from './image-resources-BJnTpG66.js';
2
+ import { S as StoryScope, a as StoryTargetRejection, D as DocumentTrackingSettings, E as EmbeddedFont, B as BookmarkIndex, L as ListKind, I as InsertImageInput, b as ImageIntentResult, R as ReplaceImageOptions, A as ApplyImagePropertiesInput } from './tree-package-store-D5S7VKs5.js';
3
+ import { Node } from 'prosemirror-model';
4
+ import { a as ReviewItem } from './review-support-Fy3vdIea.js';
5
+ import { ReviewModuleContribution } from './contracts/modules.js';
6
+ import { e as OoxmlPart, O as OoxmlNode, a as OoxmlElement } from './ooxml-tree-BU0e3DVi.js';
7
+ import { O as OoxmlPackage, b as OoxmlPackageRejection } from './ooxml-package-D_CtywTW.js';
8
+ import { a as HeaderFooterParts, b as HeaderFooterSectionResolution } from './hf-references-BdjsQNE_.js';
9
+ import { T as TreeDocOp } from './tree-op-types-CwOeiaQ8.js';
10
+ import { S as SelectionMark, T as TreeModelChange } from './tree-store-hLtjeyWE.js';
11
+
12
+ /**
13
+ * The scheme slots the picker shows, in Word's column order.
14
+ *
15
+ * Assumes the default `w:clrSchemeMapping` (bg1→lt1, t1→dk1, ...); a settings part
16
+ * that remaps them is rare and a follow-up.
17
+ */
18
+ declare const PICKER_SLOTS: readonly ["lt1", "dk1", "lt2", "dk2", "accent1", "accent2", "accent3", "accent4", "accent5", "accent6"];
19
+ type ThemeColorSlot = (typeof PICKER_SLOTS)[number];
20
+ /** One theme colour: the scheme slot and its resolved six-digit hex (no '#'). */
21
+ interface DocumentThemeColorEntry {
22
+ readonly slot: ThemeColorSlot;
23
+ readonly hex: string;
24
+ }
25
+ /** The theme's two font slots, for resolving `w:rFonts` theme attributes. */
26
+ interface DocumentThemeFonts {
27
+ /** `a:majorFont` latin typeface — headings. */
28
+ readonly major: string | null;
29
+ /** `a:minorFont` latin typeface — body text. */
30
+ readonly minor: string | null;
31
+ }
32
+
33
+ /**
34
+ * Why an edited projection could not be mapped back into tree ops.
35
+ *
36
+ * A refusal, not a fallback. The reverse direction never RECONSTRUCTS the tree from the
37
+ * projection — it explains a difference — so a shape it cannot explain is rejected outright.
38
+ * A silently-dropped edit is worse than a refused one, because only the refusal can be
39
+ * reconciled.
40
+ */
41
+ type TreeBindingRejection = 'paragraph-count-unexplained' | 'paragraph-reordered' | 'unknown-paragraph-id' | 'unknown-content-moved' | 'unsupported-node' | 'split-not-clean' | 'join-not-clean';
42
+ /**
43
+ * The ops explaining one edit, or the reason it could not be explained.
44
+ *
45
+ * `ops` is the SMALLEST set that accounts for the difference, so anything the projection does not
46
+ * model — unknown nodes, lexical form, node identities — stays carried by the tree rather than
47
+ * round-tripping through the editor.
48
+ */
49
+ type MapResult = {
50
+ readonly ok: true;
51
+ readonly ops: readonly TreeDocOp[];
52
+ } | {
53
+ readonly ok: false;
54
+ readonly reason: TreeBindingRejection;
55
+ readonly detail?: string;
56
+ };
57
+ /** Body paragraphs of a part, in document order. */
58
+ declare function bodyParagraphs(part: OoxmlPart): OoxmlNode[];
59
+ /** Project one tree revision into a ProseMirror doc (task 6.1). */
60
+ declare function treeToDoc(part: OoxmlPart): Node;
61
+ /**
62
+ * Map an edited ProseMirror doc back into typed tree ops (task 6.2), or refuse (6.3).
63
+ *
64
+ * Handles a paragraph count delta of 0 (in-place edits), +1 (a clean split) and -1 (a clean
65
+ * join). Anything else — a reorder, a multi-paragraph paste, a structural change combined
66
+ * with an edit elsewhere — is refused rather than approximated, because the approximation
67
+ * is what silently loses content.
68
+ */
69
+ declare function docToTreeOps(part: OoxmlPart, doc: Node): MapResult;
70
+ /** Whether a tree node id is still present, for reconciliation checks. */
71
+ declare function partHasNode(part: OoxmlPart, nodeId: string): boolean;
72
+ /**
73
+ * Rebuild a projected doc from a new tree revision, reusing untouched paragraphs (task 6.4).
74
+ *
75
+ * A full reprojection is always CORRECT, so this only ever narrows the work: paragraphs the
76
+ * change did not name are carried over by reference, which lets ProseMirror keep their node
77
+ * identity and redraw nothing. When the change is structural — a paragraph created, deleted,
78
+ * split or joined — positions shift in ways a per-paragraph patch cannot express, so it
79
+ * falls back to a full projection rather than guessing.
80
+ *
81
+ * Passing `null` means "no evidence available", which also takes the full path. Reconciling
82
+ * on partial evidence is how a projection silently diverges from the model.
83
+ */
84
+ declare function reconcileDoc(previousDoc: Node, part: OoxmlPart, change: {
85
+ readonly dirty: readonly string[];
86
+ readonly created: readonly string[];
87
+ readonly deleted: readonly string[];
88
+ readonly splitJoin: readonly unknown[];
89
+ } | null): Node;
90
+
91
+ /**
92
+ * How a style LOOKS, for a picker to preview it in its own face — Word shows the gallery
93
+ * that way, and a list of identical rows makes the user apply a style to find out what it
94
+ * is. PRESENTATION ONLY: these are the few properties a one-line preview can show, not the
95
+ * cascade layout resolves. Every value is already bounded here (the family against the same
96
+ * shape the CSS sink enforces, the colour against six hex digits), because a picker renders
97
+ * them into a style attribute and they come from an attacker-controlled `styles.xml`.
98
+ */
99
+ interface DocumentStylePreview {
100
+ readonly fontFamily: string | null;
101
+ /** Points, already halved from `w:sz`. Null when the style states no size. */
102
+ readonly fontSizePt: number | null;
103
+ readonly bold: boolean;
104
+ readonly italic: boolean;
105
+ /** RRGGBB, or null for inherited/automatic — theme colours are not resolved here. */
106
+ readonly color: string | null;
107
+ }
108
+ /** One `w:style` definition, projected for a style picker. */
109
+ interface DocumentStyleEntry {
110
+ readonly styleId: string;
111
+ readonly name: string;
112
+ readonly type: string;
113
+ readonly preview: DocumentStylePreview;
114
+ }
115
+
116
+ /** One heading of the outline, in document order. `level` is 0-based (Heading 1 = 0). */
117
+ interface DocumentOutlineEntry {
118
+ /** The paragraph's text, control characters flattened, bounded to 200 characters. */
119
+ readonly text: string;
120
+ /** 0-based outline level: `heading 1` / `outlineLvl 0` → 0. */
121
+ readonly level: number;
122
+ /** The paragraph's canonical node id — the address `setSelection` navigates to. */
123
+ readonly blockId: string;
124
+ }
125
+
126
+ /** How a search is narrowed. Both flags default to off, matching Word's initial state. */
127
+ interface DocumentSearchOptions {
128
+ readonly matchCase?: boolean;
129
+ readonly wholeWord?: boolean;
130
+ /** Override the default {@link SEARCH_MATCH_LIMIT}. Clamped to it; never raised past it. */
131
+ readonly limit?: number;
132
+ }
133
+ /**
134
+ * One occurrence of a query in the body story.
135
+ *
136
+ * Carries the engine's own address (`blockId` + `start`) and the positional one a find UI
137
+ * needs (`paragraphIndex` / `runIndex` / `runOffset`), both derived from the SAME walk —
138
+ * a caller reconstructing run boundaries itself is where an off-by-one would come from.
139
+ * A match can span runs when formatting changes mid-word; the run address is where it
140
+ * STARTS.
141
+ */
142
+ interface DocumentSearchMatch {
143
+ readonly blockId: string;
144
+ readonly start: number;
145
+ readonly length: number;
146
+ readonly paragraphIndex: number;
147
+ readonly runIndex: number;
148
+ readonly runOffset: number;
149
+ /** The matched text as it appears in the document, control characters flattened. */
150
+ readonly text: string;
151
+ /** Paragraph text immediately before the match, bounded and flattened. */
152
+ readonly contextBefore: string;
153
+ /** Paragraph text immediately after the match, bounded and flattened. */
154
+ readonly contextAfter: string;
155
+ }
156
+ /**
157
+ * What one search answers with.
158
+ *
159
+ * `truncated` says the scan stopped at the cap with matches still ahead of it, so a caller
160
+ * can show "2000+" honestly instead of claiming an exact total it does not have.
161
+ */
162
+ interface DocumentSearchResult {
163
+ readonly matches: readonly DocumentSearchMatch[];
164
+ readonly truncated: boolean;
165
+ }
166
+
167
+ /** What a run inherits at one point of the chain — null means "nothing authored". */
168
+ interface StyleRunDefaults {
169
+ readonly fontFamily: string | null;
170
+ readonly fontSizeHalfPoints: number | null;
171
+ }
172
+ /** One run property as the layout records carry it (structurally SurfaceProperty). */
173
+ interface RunPropertyLike {
174
+ readonly localName: string;
175
+ readonly attributes?: Record<string, string>;
176
+ }
177
+
178
+ interface ParagraphAnchorIndex {
179
+ /** nodeId → `w14:paraId`, verbatim as authored/minted. Paragraphs without one are absent. */
180
+ readonly paraIdByNode: ReadonlyMap<string, string>;
181
+ /** UPPERCASED paraId → nodeId (matching is case-insensitive). First occurrence wins on the impossible-by-invariant duplicate. */
182
+ readonly nodeByParaId: ReadonlyMap<string, string>;
183
+ /** nodeId → reading-order ordinal, for document-ordering DocRange endpoints. */
184
+ readonly ordinalByNode: ReadonlyMap<string, number>;
185
+ }
186
+
187
+ /**
188
+ * What applying ops produced: whether it committed, and why not when it did not.
189
+ *
190
+ * `committed` and `rejected` are separate flags because they are not opposites — a batch of zero
191
+ * ops neither commits nor is rejected.
192
+ */
193
+ interface TreeApplyResult {
194
+ readonly committed: boolean;
195
+ readonly rejected: boolean;
196
+ readonly opCount: number;
197
+ /** Present when the edit was refused, so a host can report WHY rather than a silent no-op. */
198
+ readonly reason?: TreeBindingRejection | StoryTargetRejection | string;
199
+ }
200
+ /**
201
+ * One open document: the canonical tree, and the only write path into it.
202
+ *
203
+ * `applyTreeOps` is that path. Every mutation is a `TreeDocOp` addressed by node id plus UTF-16
204
+ * offset, applied in one transaction, which is what makes cell and nested paragraphs ordinary
205
+ * rather than special cases.
206
+ *
207
+ * Holds the whole package, not just the body — headers, footers, notes, comments and styles are
208
+ * all reachable through it, and parts the engine does not model are preserved verbatim.
209
+ */
210
+ interface TreeDocxSession {
211
+ /** Whether the body holds at least one editable paragraph. */
212
+ readonly editable: boolean;
213
+ /** Canonical node ids of the body paragraphs, in order. */
214
+ paragraphIds(): string[];
215
+ /**
216
+ * Canonical node ids of paragraphs in a story scope. Defaults to the body.
217
+ * Header/footer scopes address the part `EditorScope { kind: 'headerFooter'; rId }` names.
218
+ */
219
+ paragraphIdsIn(scope?: StoryScope): string[];
220
+ /** The current canonical BODY part — what layout reads for the main story. */
221
+ part(): OoxmlPart;
222
+ /** The current part for a story scope, or null when the target is refused. */
223
+ partFor(scope: StoryScope): OoxmlPart | null;
224
+ /**
225
+ * The current package with every opened story store merged in. Authority for layout
226
+ * resolution and save — never a swapped single-part view.
227
+ */
228
+ currentPackage(): OoxmlPackage;
229
+ /**
230
+ * Commit typed tree ops directly, as ONE transaction.
231
+ *
232
+ * The paginated surface has no ProseMirror doc to diff, so it addresses the model the way
233
+ * the ops already do — by node id and offset — rather than round-tripping an edit through
234
+ * a projection just to have it diffed back out.
235
+ *
236
+ * `scope` defaults to the body. Pass `{ kind: 'headerFooter', rId }` to target an existing
237
+ * header/footer part; the transaction publishes one ModelChange (HF → `global` impact)
238
+ * and one undo unit without swapping the body store.
239
+ */
240
+ applyTreeOps(ops: readonly TreeDocOp[], selectionBefore?: SelectionMark | null, selectionAfter?: SelectionMark | null, scope?: StoryScope): TreeApplyResult;
241
+ /** Project the current BODY revision into a ProseMirror doc. */
242
+ projectDoc(): Node;
243
+ /** Re-project incrementally from the last committed change, reusing untouched paragraphs. */
244
+ reconcile(previousDoc: Node): Node;
245
+ /**
246
+ * Whether the last commit changed the BLOCK SEQUENCE (a split, join, insert or delete).
247
+ *
248
+ * A host needs this to decide whether the view must be re-projected at all: after a pure
249
+ * text edit the view already holds what the model holds, and re-projecting anyway both
250
+ * wastes work and races the next keystroke.
251
+ */
252
+ lastCommitWasStructural(): boolean;
253
+ /** Map an edited BODY doc to tree ops and commit them as ONE transaction. */
254
+ applyPmDoc(doc: Node): TreeApplyResult;
255
+ /** Body text, paragraphs joined by newlines, read from the CANONICAL tree. */
256
+ bodyText(): string;
257
+ /** Text of a story scope, paragraphs joined by newlines. */
258
+ storyText(scope: StoryScope): string | null;
259
+ /** Body-store revision (independent of header/footer store revisions). */
260
+ revision(): number;
261
+ /** Per-story revision, or null when the target is refused. */
262
+ revisionFor(scope: StoryScope): number | null;
263
+ /** Package-wide revision — bumps on any story commit (body or HF). */
264
+ packageRevision(): number;
265
+ canUndo(): boolean;
266
+ canRedo(): boolean;
267
+ /**
268
+ * Undo the last entry, returning the selection to restore.
269
+ *
270
+ * The selection is part of the entry, not something a host can recompute: after undoing a
271
+ * split the caret belongs where the user was typing, and offsets in the reverted tree do
272
+ * not correspond to offsets in the one that replaced it. `null` means nothing was undone
273
+ * or the entry recorded no selection.
274
+ */
275
+ undo(): SelectionMark | null;
276
+ redo(): SelectionMark | null;
277
+ beginComposition(scope?: StoryScope): void;
278
+ endComposition(): void;
279
+ subscribe(onChange: (change: TreeModelChange) => void): () => void;
280
+ /** Serialize the whole package back to DOCX bytes. */
281
+ save(): Uint8Array;
282
+ /**
283
+ * The resolved header/footer parts of the section, by variant (phase 2).
284
+ *
285
+ * Returns the FINAL section's effective parts after OOXML inheritance. Prefer
286
+ * `headerFooterPartsBySection` for multi-section pagination.
287
+ *
288
+ * Re-resolved after any package revision so an edited shared part is visible everywhere
289
+ * it is attached.
290
+ */
291
+ headerFooterParts(): HeaderFooterParts;
292
+ /**
293
+ * Per-section header/footer parts after OOXML inheritance, index-aligned with
294
+ * `enumerateDocumentSections`.
295
+ */
296
+ headerFooterPartsBySection(): readonly HeaderFooterParts[];
297
+ /**
298
+ * Per-section resolution with declared-vs-inherited metadata for "Same as previous"
299
+ * chrome. Index-aligned with `headerFooterPartsBySection`.
300
+ */
301
+ headerFooterResolutionBySection(): readonly HeaderFooterSectionResolution[];
302
+ /**
303
+ * Font family names the document uses, from every `w:rFonts` in the CURRENT main
304
+ * part plus the styles and header/footer parts — validated, deduplicated, sorted.
305
+ * Memoized per package revision.
306
+ */
307
+ documentFonts(): readonly string[];
308
+ /**
309
+ * The `w:style` definitions of the styles part, validated and projected for a style
310
+ * picker. Memoized once: the styles part is immutable for the session's lifetime.
311
+ * A document without a styles part answers `[]`.
312
+ */
313
+ documentStyles(): readonly DocumentStyleEntry[];
314
+ /**
315
+ * Root of the styles part tree, for layout's style cascade. Memoized once; `null` when
316
+ * the package has no styles part. Styles editing is a later slice, so this is immutable
317
+ * for the session.
318
+ */
319
+ stylesRoot(): OoxmlElement | null;
320
+ /**
321
+ * The theme part's Latin typefaces, for resolving `w:rFonts` theme references in layout.
322
+ *
323
+ * Memoized once: theme editing is a later slice. A document with no theme part answers
324
+ * `{ major: null, minor: null }`, which leaves every theme reference on the explicit
325
+ * font name beside it.
326
+ */
327
+ documentThemeFonts(): DocumentThemeFonts;
328
+ /**
329
+ * Root of the numbering part tree (`w:numbering`), for list layout. Memoized once;
330
+ * `null` when the package has no numbering part. Numbering editing is a later slice.
331
+ */
332
+ numberingRoot(): OoxmlElement | null;
333
+ /**
334
+ * Root of the settings part tree (`w:settings`), for document-wide layout constants such
335
+ * as `w:defaultTabStop`. Memoized once; `null` when the package has no settings part.
336
+ * Settings editing is a later slice, so this is immutable for the session.
337
+ */
338
+ settingsRoot(): OoxmlElement | null;
339
+ /**
340
+ * What `settings.xml` says about tracking — `w:trackRevisions`, the tracked-changes
341
+ * protection, and the two do-not-track switches.
342
+ *
343
+ * Read from the document rather than assumed, because Word records the tracking state on
344
+ * the FILE: a package that asks to be edited as tracked changes, presented as an ordinary
345
+ * editable one, takes its first keystroke as an untracked edit.
346
+ */
347
+ trackingSettings(): DocumentTrackingSettings;
348
+ /**
349
+ * The theme's ten picker colours (`a:clrScheme`), in Word's column order, or `[]`
350
+ * when the package has no complete scheme. Memoized once: the theme part is
351
+ * immutable for the session's lifetime.
352
+ */
353
+ documentThemeColors(): readonly DocumentThemeColorEntry[];
354
+ /**
355
+ * The run formatting a paragraph's content INHERITS when it authors none: the
356
+ * paragraph style's `basedOn` chain, then `w:docDefaults`, with theme `rFonts`
357
+ * attributes resolved through the font scheme. `runProperties` (the span's own
358
+ * authored properties) lets a theme-only run-level `w:rFonts` resolve too. This is
359
+ * what lets a toolbar always show the effective font, the way Word does.
360
+ */
361
+ effectiveRunDefaults(paragraphId: string, runProperties?: readonly RunPropertyLike[]): StyleRunDefaults;
362
+ /**
363
+ * The heading outline of the BODY story, in document order: paragraphs whose
364
+ * `w:pStyle` resolves to a heading through the styles part (built-in `heading N`
365
+ * name, or the style's own `w:outlineLvl` 0..8). Memoized per main-part revision —
366
+ * an edit can retitle, add or remove a heading, but the styles part cannot change
367
+ * in-session.
368
+ */
369
+ documentOutline(): readonly DocumentOutlineEntry[];
370
+ /**
371
+ * Every pending review decision in the document, memoized per revision.
372
+ *
373
+ * Derived from the canonical TREE — the queue is a property of the document, and one derived
374
+ * from laid-out spans empties by half whenever the reader switches to a resolved view.
375
+ */
376
+ reviewItems(): readonly ReviewItem[];
377
+ /**
378
+ * Whether the document carries review content — tracked changes or comment
379
+ * anchors — regardless of any review module. Derived from store vocabulary
380
+ * only (never the review model), memoized per revision: it is the free
381
+ * tier's honest "this document has more than you are seeing" signal.
382
+ */
383
+ hasReviewContent(): boolean;
384
+ /** Reply to a comment, or add one over a revision's range. Returns the new comment's id. */
385
+ replyToComment(parentCommentId: string | null, anchor: {
386
+ paragraphId: string;
387
+ start: number;
388
+ end: number;
389
+ endParagraphId?: string;
390
+ }, text: string, author: string,
391
+ /** ISO-8601. Omitted writes no `@w:date`, because inventing one is a content change. */
392
+ date?: string): string | null;
393
+ /**
394
+ * Resolve a comment thread, or reopen it. False when the document holds no such comment.
395
+ *
396
+ * The same package transaction shape as a reply, and for the same reason: `@w15:done` lives in
397
+ * `commentsExtended.xml`, a part a document with no thread does not have, so the state and the
398
+ * part that records it commit together.
399
+ */
400
+ setCommentResolved(commentId: string, resolved: boolean): boolean;
401
+ /**
402
+ * Delete a comment thread outright — body, thread state and story markers.
403
+ *
404
+ * A THREAD, like resolving one: a reply whose parent is gone has nothing left to answer.
405
+ * False when the document holds no such comment, or when the removal was refused.
406
+ */
407
+ deleteComment(commentId: string): boolean;
408
+ /**
409
+ * Every occurrence of `query` in the BODY story, in document order, addressed in the
410
+ * same offset vocabulary the tree ops and the surface selection use — so a match can be
411
+ * handed straight to `setSelection` without re-deriving anything.
412
+ *
413
+ * Memoized one deep, keyed on the revision AND the question asked: a find panel asks the
414
+ * same question on every tick, and a different query replaces the entry rather than
415
+ * growing a cache the session would have to bound.
416
+ */
417
+ findText(query: string, options?: DocumentSearchOptions): DocumentSearchResult;
418
+ /**
419
+ * The faces the package EMBEDS (`word/fontTable.xml` embed relationships),
420
+ * deobfuscated — the only font source that needs neither a substitute nor a network.
421
+ * Extraction asserts nothing about validity; admitting a face is the font resource
422
+ * lane's job. Memoized once: the font table and font parts are immutable in-session.
423
+ */
424
+ embeddedFonts(): readonly EmbeddedFont[];
425
+ /**
426
+ * The `w:numId` of a bullet or numbered list definition, creating one where the document
427
+ * has none — including `numbering.xml` itself, its relationship and its content type.
428
+ *
429
+ * A document Word has never numbered carries no numbering part at all, so the first
430
+ * bullet a user asks for has to bring the whole definition with it. An existing
431
+ * definition of the same kind is reused rather than duplicated.
432
+ */
433
+ /**
434
+ * What the owning part's relationships answer for one `r:id` under `scope` (default:
435
+ * body): the authored target and whether it is external. `null` for an id the part does
436
+ * not declare, or when the scoped part is not open.
437
+ *
438
+ * Live rather than memoized: inserting a link mints a relationship mid-session, and a
439
+ * cached resolver would report the link this session just created as dangling.
440
+ */
441
+ relationshipTarget(relationshipId: string, scope?: StoryScope): {
442
+ readonly target: string;
443
+ readonly external: boolean;
444
+ } | null;
445
+ /**
446
+ * `bookmarkName -> { paragraphId, offset }` over the main part, memoized per revision.
447
+ *
448
+ * What an internal hyperlink's `w:anchor` resolves through. Keyed on the store revision
449
+ * because an edit can move, split or delete the paragraph a bookmark sits in.
450
+ */
451
+ bookmarks(): BookmarkIndex;
452
+ /**
453
+ * The relationship id for an external hyperlink target on the part owning `scope`
454
+ * (default: body), minting one if that part has none, or `null` when the URL is refused
455
+ * or the scoped part cannot be resolved.
456
+ *
457
+ * Lives on the PACKAGE, outside `store.transact`, like the numbering definitions: the
458
+ * undoable half is the tree op that names the id. An unreferenced relationship left
459
+ * behind by an undo is inert and is what Word writes anyway. Scoped inserts mint onto
460
+ * the story's own `.rels` so a header/footer or note link never creates a stray body
461
+ * relationship.
462
+ */
463
+ ensureHyperlinkRelationship(url: string, scope?: StoryScope): string | null;
464
+ ensureListDefinition(kind: ListKind): string | null;
465
+ /**
466
+ * Declare `level` in the list definition `numId` names, with Word's default format for
467
+ * that depth, or answer false.
468
+ *
469
+ * Word never greys Increase Indent out on a list item: demoting past the deepest level
470
+ * a definition declares makes Word define the level, cycling its stock bullets and
471
+ * number formats. An already-declared level answers true without changing anything.
472
+ *
473
+ * The declaration lives on the PACKAGE, outside the store's history — undoing the edit
474
+ * that needed it restores the paragraph but leaves the level declared, which is
475
+ * harmless: an unreferenced level renders nothing and Word writes files full of them.
476
+ */
477
+ ensureNumberingLevel(numId: string, level: number, kind: ListKind): boolean;
478
+ /**
479
+ * The `w14:paraId` ↔ node-id index over the full editable set of the MAIN part,
480
+ * memoized per revision. Every editable paragraph carries a valid, part-unique id
481
+ * (established at open, maintained by the split appliers), so every paragraph is
482
+ * mapped. Header/footer paragraphs become addressable through `partFor` once their
483
+ * story store is open.
484
+ */
485
+ paragraphAnchors(): ParagraphAnchorIndex;
486
+ /** `w14:paraId` of a canonical paragraph node id, verbatim, or null. */
487
+ paraIdOf(nodeId: string): string | null;
488
+ /** Canonical node id for a `w14:paraId`, matched case-insensitively, or null. */
489
+ nodeIdOf(paraId: string): string | null;
490
+ /** Insert a validated raster image as one package undo unit (task 12). */
491
+ insertImage(scope: StoryScope, input: InsertImageInput): Promise<ImageIntentResult>;
492
+ /** Replace a picture drawing's embedded media in one package undo unit. */
493
+ replaceImage(scope: StoryScope, drawingNodeId: string, bytes: Uint8Array, mime: SupportedImageMime, decodePort: ImageDecodePort, options: ReplaceImageOptions): Promise<ImageIntentResult>;
494
+ /** Delete a picture drawing and collect orphaned media in one package undo unit. */
495
+ deleteImage(scope: StoryScope, drawingNodeId: string): ImageIntentResult;
496
+ /** Apply image property tree ops plus hyperlink relationship wiring atomically. */
497
+ applyImageProperties(scope: StoryScope, input: ApplyImagePropertiesInput): ImageIntentResult;
498
+ }
499
+
500
+ /**
501
+ * Why bytes could not be opened: any bounded-reader rejection, plus the package that parsed but
502
+ * carried no main document tree.
503
+ */
504
+ type TreeSessionRejection = OoxmlPackageRejection | 'no-main-document-tree';
505
+ /**
506
+ * An open session, or a typed refusal.
507
+ *
508
+ * A result rather than a throw: every failure here is a property of the FILE, and a host needs to
509
+ * tell "this is not a package" from "this package is malicious" from "this document has no body".
510
+ */
511
+ type OpenTreeSessionResult = {
512
+ readonly ok: true;
513
+ readonly session: TreeDocxSession;
514
+ } | {
515
+ readonly ok: false;
516
+ readonly reason: TreeSessionRejection;
517
+ readonly detail?: string;
518
+ };
519
+ interface OpenTreeSessionOptions {
520
+ /**
521
+ * The review module's derivation hooks, contributed through the editor's
522
+ * `EditorModule` seam. Absent — the free engine — the session's
523
+ * `reviewItems()` reports the typed empty queue; parse, preservation, and
524
+ * `hasReviewContent` are unaffected.
525
+ */
526
+ readonly reviewModel?: ReviewModuleContribution;
527
+ }
528
+ /**
529
+ * Open DOCX bytes into a tree-backed session.
530
+ *
531
+ * Returns a typed rejection rather than throwing: every failure here is a property of the FILE,
532
+ * and a host needs to tell "this is not a package" from "this package is malicious" from "this
533
+ * document has no body".
534
+ *
535
+ * The read is BOUNDED — decompression ratio, part count, XML depth and element counts are all
536
+ * capped — because the bytes are untrusted by definition.
537
+ */
538
+ declare function openTreeSession(bytes: Uint8Array, options?: OpenTreeSessionOptions): OpenTreeSessionResult;
539
+ /** The origin a host should use when committing a reconciliation rather than a user edit. */
540
+ declare const PROJECTION_ORIGIN: "dev.docx-editor.core.origin.projection";
541
+
542
+ export { type DocumentStyleEntry as D, type MapResult as M, type OpenTreeSessionResult as O, PROJECTION_ORIGIN as P, type TreeDocxSession as T, type TreeApplyResult as a, type TreeBindingRejection as b, type TreeSessionRejection as c, bodyParagraphs as d, docToTreeOps as e, type DocumentThemeColorEntry as f, openTreeSession as o, partHasNode as p, reconcileDoc as r, treeToDoc as t };