docxodus 9.8.0 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/README.md +178 -0
  2. package/dist/canonical.d.ts +7 -0
  3. package/dist/canonical.d.ts.map +1 -0
  4. package/dist/canonical.js +56 -0
  5. package/dist/canonical.js.map +1 -0
  6. package/dist/docxodus.worker.d.ts +2 -1
  7. package/dist/docxodus.worker.d.ts.map +1 -1
  8. package/dist/docxodus.worker.js +244 -3
  9. package/dist/docxodus.worker.js.map +1 -1
  10. package/dist/editor.bundle.js +2024 -388
  11. package/dist/editor.d.ts +22 -2
  12. package/dist/editor.d.ts.map +1 -1
  13. package/dist/editor.js +94 -9
  14. package/dist/editor.js.map +1 -1
  15. package/dist/embed.bundle.js +2912 -437
  16. package/dist/embed.iife.js +2911 -436
  17. package/dist/export-assets.json +283 -0
  18. package/dist/export-browser.bundle.js +7990 -0
  19. package/dist/export-browser.d.ts +266 -0
  20. package/dist/export-browser.d.ts.map +1 -0
  21. package/dist/export-browser.js +2915 -0
  22. package/dist/export-browser.js.map +1 -0
  23. package/dist/export-resource-limits-v1.json +57 -0
  24. package/dist/font-contract.d.ts +150 -0
  25. package/dist/font-contract.d.ts.map +1 -0
  26. package/dist/font-contract.js +59 -0
  27. package/dist/font-contract.js.map +1 -0
  28. package/dist/font-runtime.d.ts +33 -0
  29. package/dist/font-runtime.d.ts.map +1 -0
  30. package/dist/font-runtime.js +1100 -0
  31. package/dist/font-runtime.js.map +1 -0
  32. package/dist/index.d.ts +62 -5
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +130 -16
  35. package/dist/index.js.map +1 -1
  36. package/dist/page-geometry.d.ts +8 -1
  37. package/dist/page-geometry.d.ts.map +1 -1
  38. package/dist/page-geometry.js +37 -11
  39. package/dist/page-geometry.js.map +1 -1
  40. package/dist/pagination.bundle.js +1937 -380
  41. package/dist/pagination.d.ts +277 -15
  42. package/dist/pagination.d.ts.map +1 -1
  43. package/dist/pagination.js +2055 -438
  44. package/dist/pagination.js.map +1 -1
  45. package/dist/react.d.ts +11 -4
  46. package/dist/react.d.ts.map +1 -1
  47. package/dist/react.js +38 -5
  48. package/dist/react.js.map +1 -1
  49. package/dist/render-report-v2.schema.json +1581 -0
  50. package/dist/ribbon-chrome.d.ts +1 -1
  51. package/dist/ribbon-chrome.d.ts.map +1 -1
  52. package/dist/ribbon-chrome.js +46 -0
  53. package/dist/ribbon-chrome.js.map +1 -1
  54. package/dist/ribbon.js +70 -0
  55. package/dist/ribbon.js.map +1 -1
  56. package/dist/session.bundle.js +695 -29
  57. package/dist/session.d.ts +134 -19
  58. package/dist/session.d.ts.map +1 -1
  59. package/dist/session.js +562 -25
  60. package/dist/session.js.map +1 -1
  61. package/dist/types.d.ts +1207 -16
  62. package/dist/types.d.ts.map +1 -1
  63. package/dist/types.js.map +1 -1
  64. package/dist/wasm/_framework/DocumentFormat.OpenXml.Framework.wasm +0 -0
  65. package/dist/wasm/_framework/DocumentFormat.OpenXml.Framework.wasm.br +0 -0
  66. package/dist/wasm/_framework/DocumentFormat.OpenXml.wasm +0 -0
  67. package/dist/wasm/_framework/DocumentFormat.OpenXml.wasm.br +0 -0
  68. package/dist/wasm/_framework/Docxodus.wasm +0 -0
  69. package/dist/wasm/_framework/Docxodus.wasm.br +0 -0
  70. package/dist/wasm/_framework/DocxodusWasm.wasm +0 -0
  71. package/dist/wasm/_framework/DocxodusWasm.wasm.br +0 -0
  72. package/dist/wasm/_framework/System.Collections.Concurrent.wasm +0 -0
  73. package/dist/wasm/_framework/System.Collections.Concurrent.wasm.br +0 -0
  74. package/dist/wasm/_framework/System.Collections.Immutable.wasm +0 -0
  75. package/dist/wasm/_framework/System.Collections.Immutable.wasm.br +0 -0
  76. package/dist/wasm/_framework/System.Collections.NonGeneric.wasm +0 -0
  77. package/dist/wasm/_framework/System.Collections.NonGeneric.wasm.br +0 -0
  78. package/dist/wasm/_framework/System.Collections.Specialized.wasm +0 -0
  79. package/dist/wasm/_framework/System.Collections.Specialized.wasm.br +0 -0
  80. package/dist/wasm/_framework/System.Collections.wasm +0 -0
  81. package/dist/wasm/_framework/System.Collections.wasm.br +0 -0
  82. package/dist/wasm/_framework/System.ComponentModel.Primitives.wasm +0 -0
  83. package/dist/wasm/_framework/System.ComponentModel.Primitives.wasm.br +0 -0
  84. package/dist/wasm/_framework/System.ComponentModel.TypeConverter.wasm +0 -0
  85. package/dist/wasm/_framework/System.ComponentModel.TypeConverter.wasm.br +0 -0
  86. package/dist/wasm/_framework/System.ComponentModel.wasm +0 -0
  87. package/dist/wasm/_framework/System.ComponentModel.wasm.br +0 -0
  88. package/dist/wasm/_framework/System.Console.wasm +0 -0
  89. package/dist/wasm/_framework/System.Console.wasm.br +0 -0
  90. package/dist/wasm/_framework/System.Diagnostics.Process.wasm +0 -0
  91. package/dist/wasm/_framework/System.Diagnostics.Process.wasm.br +0 -0
  92. package/dist/wasm/_framework/System.IO.Compression.wasm +0 -0
  93. package/dist/wasm/_framework/System.IO.Compression.wasm.br +0 -0
  94. package/dist/wasm/_framework/System.IO.Packaging.wasm +0 -0
  95. package/dist/wasm/_framework/System.IO.Packaging.wasm.br +0 -0
  96. package/dist/wasm/_framework/System.IO.Pipelines.wasm +0 -0
  97. package/dist/wasm/_framework/System.IO.Pipelines.wasm.br +0 -0
  98. package/dist/wasm/_framework/System.Linq.Expressions.wasm +0 -0
  99. package/dist/wasm/_framework/System.Linq.Expressions.wasm.br +0 -0
  100. package/dist/wasm/_framework/System.Linq.wasm +0 -0
  101. package/dist/wasm/_framework/System.Linq.wasm.br +0 -0
  102. package/dist/wasm/_framework/System.Memory.wasm +0 -0
  103. package/dist/wasm/_framework/System.Memory.wasm.br +0 -0
  104. package/dist/wasm/_framework/System.Net.Http.wasm +0 -0
  105. package/dist/wasm/_framework/System.Net.Http.wasm.br +0 -0
  106. package/dist/wasm/_framework/System.Net.Primitives.wasm +0 -0
  107. package/dist/wasm/_framework/System.Net.Primitives.wasm.br +0 -0
  108. package/dist/wasm/_framework/System.ObjectModel.wasm +0 -0
  109. package/dist/wasm/_framework/System.ObjectModel.wasm.br +0 -0
  110. package/dist/wasm/_framework/System.Private.CoreLib.wasm +0 -0
  111. package/dist/wasm/_framework/System.Private.CoreLib.wasm.br +0 -0
  112. package/dist/wasm/_framework/System.Private.Uri.wasm +0 -0
  113. package/dist/wasm/_framework/System.Private.Uri.wasm.br +0 -0
  114. package/dist/wasm/_framework/System.Private.Xml.Linq.wasm +0 -0
  115. package/dist/wasm/_framework/System.Private.Xml.Linq.wasm.br +0 -0
  116. package/dist/wasm/_framework/System.Private.Xml.wasm +0 -0
  117. package/dist/wasm/_framework/System.Private.Xml.wasm.br +0 -0
  118. package/dist/wasm/_framework/System.Runtime.InteropServices.JavaScript.wasm +0 -0
  119. package/dist/wasm/_framework/System.Runtime.InteropServices.JavaScript.wasm.br +0 -0
  120. package/dist/wasm/_framework/System.Runtime.wasm +0 -0
  121. package/dist/wasm/_framework/System.Runtime.wasm.br +0 -0
  122. package/dist/wasm/_framework/System.Security.Cryptography.wasm +0 -0
  123. package/dist/wasm/_framework/System.Security.Cryptography.wasm.br +0 -0
  124. package/dist/wasm/_framework/System.Text.Encodings.Web.wasm +0 -0
  125. package/dist/wasm/_framework/System.Text.Encodings.Web.wasm.br +0 -0
  126. package/dist/wasm/_framework/System.Text.Json.wasm +0 -0
  127. package/dist/wasm/_framework/System.Text.Json.wasm.br +0 -0
  128. package/dist/wasm/_framework/System.Text.RegularExpressions.wasm +0 -0
  129. package/dist/wasm/_framework/System.Text.RegularExpressions.wasm.br +0 -0
  130. package/dist/wasm/_framework/System.Xml.Linq.wasm +0 -0
  131. package/dist/wasm/_framework/System.Xml.Linq.wasm.br +0 -0
  132. package/dist/wasm/_framework/System.Xml.XDocument.wasm +0 -0
  133. package/dist/wasm/_framework/System.Xml.XDocument.wasm.br +0 -0
  134. package/dist/wasm/_framework/System.wasm +0 -0
  135. package/dist/wasm/_framework/System.wasm.br +0 -0
  136. package/dist/wasm/_framework/dotnet.boot.js +38 -38
  137. package/dist/wasm/_framework/dotnet.boot.js.br +0 -0
  138. package/dist/wasm/_framework/dotnet.js +1 -1
  139. package/dist/wasm/_framework/dotnet.js.br +0 -0
  140. package/dist/wasm/_framework/dotnet.native.js +3 -3
  141. package/dist/wasm/_framework/dotnet.native.js.br +0 -0
  142. package/dist/wasm/_framework/dotnet.native.wasm +0 -0
  143. package/dist/wasm/_framework/dotnet.native.wasm.br +0 -0
  144. package/dist/wasm/_framework/dotnet.runtime.js +1 -1
  145. package/dist/wasm/_framework/dotnet.runtime.js.br +0 -0
  146. package/dist/worker-proxy.bundle.js +196 -29
  147. package/dist/worker-proxy.d.ts +36 -3
  148. package/dist/worker-proxy.d.ts.map +1 -1
  149. package/dist/worker-proxy.js +186 -33
  150. package/dist/worker-proxy.js.map +1 -1
  151. package/package.json +24 -7
@@ -47,7 +47,46 @@ var DocxodusSession = (() => {
47
47
  };
48
48
 
49
49
  // src/session.ts
50
- var DocxSession = class {
50
+ function mutationBatchChangeSet(before, after, key) {
51
+ const beforeGroups = /* @__PURE__ */ new Map();
52
+ const afterGroups = /* @__PURE__ */ new Map();
53
+ const group = (items, target) => {
54
+ items.forEach((item, index) => {
55
+ const identity = key(item);
56
+ const indices = target.get(identity) ?? [];
57
+ indices.push(index);
58
+ target.set(identity, indices);
59
+ });
60
+ };
61
+ group(before, beforeGroups);
62
+ group(after, afterGroups);
63
+ const beforeMatched = before.map(() => false);
64
+ const afterMatched = after.map(() => false);
65
+ const modified = after.map(() => false);
66
+ for (const [identity, afterIndices] of afterGroups) {
67
+ const beforeIndices = beforeGroups.get(identity) ?? [];
68
+ for (const afterIndex of afterIndices) {
69
+ const beforeIndex = beforeIndices.find((index) => !beforeMatched[index] && JSON.stringify(before[index]) === JSON.stringify(after[afterIndex]));
70
+ if (beforeIndex === void 0) continue;
71
+ beforeMatched[beforeIndex] = true;
72
+ afterMatched[afterIndex] = true;
73
+ }
74
+ const remainingBefore = beforeIndices.filter((index) => !beforeMatched[index]);
75
+ const remainingAfter = afterIndices.filter((index) => !afterMatched[index]);
76
+ const modifiedCount = Math.min(remainingBefore.length, remainingAfter.length);
77
+ for (let index = 0; index < modifiedCount; index++) {
78
+ beforeMatched[remainingBefore[index]] = true;
79
+ afterMatched[remainingAfter[index]] = true;
80
+ modified[remainingAfter[index]] = true;
81
+ }
82
+ }
83
+ return {
84
+ added: after.filter((_, index) => !afterMatched[index]),
85
+ removed: before.filter((_, index) => !beforeMatched[index]),
86
+ modified: after.filter((_, index) => modified[index])
87
+ };
88
+ }
89
+ var DocxSession = class _DocxSession {
51
90
  /** @internal */
52
91
  constructor(handle, wasm) {
53
92
  // ─── Raw escape hatch ────────────────────────────────────────────────
@@ -63,6 +102,336 @@ var DocxodusSession = (() => {
63
102
  project() {
64
103
  return JSON.parse(this.wasm.Project(this.handle));
65
104
  }
105
+ /** Monotonic document version (0 at open; +1 per committed mutation/undo/redo). */
106
+ getVersion() {
107
+ return JSON.parse(this.wasm.GetVersion(this.handle)).version;
108
+ }
109
+ /**
110
+ * Verification manifest for the current logical checkpoint. Unsaved edits are included and
111
+ * the read does not mutate package bytes, caches, history, or the document version.
112
+ */
113
+ getPackageManifest() {
114
+ return JSON.parse(this.wasm.GetPackageManifest(this.handle));
115
+ }
116
+ /** Register a browser-materialized PageMap without changing the document version. */
117
+ registerPageMap(pageMap, expectedRendererFingerprint) {
118
+ return JSON.parse(this.wasm.RegisterPageMap(
119
+ this.handle,
120
+ JSON.stringify(pageMap),
121
+ expectedRendererFingerprint ?? ""
122
+ ));
123
+ }
124
+ getPageMapStatus(request) {
125
+ return JSON.parse(this.wasm.GetPageMapStatus(
126
+ this.handle,
127
+ request ? JSON.stringify(request) : ""
128
+ ));
129
+ }
130
+ getPageCitation(anchorId, request) {
131
+ return JSON.parse(this.wasm.GetPageCitation(
132
+ this.handle,
133
+ anchorId,
134
+ JSON.stringify(request)
135
+ ));
136
+ }
137
+ /** Evaluate optimistic guards without mutating or advancing the version. */
138
+ checkPreconditions(preconditions) {
139
+ return JSON.parse(
140
+ this.wasm.CheckPreconditions(this.handle, JSON.stringify(preconditions))
141
+ );
142
+ }
143
+ /**
144
+ * Guard any synchronous mutation. WASM calls are synchronous and single-threaded, so the
145
+ * check and callback form one uninterrupted client-side operation. Prefer a method's native
146
+ * `preconditions` option where it has one (notably replaceTextRange's match-count guard).
147
+ */
148
+ runWithPreconditions(preconditions, mutation) {
149
+ const checked = this.checkPreconditions(preconditions);
150
+ return checked.success ? mutation() : checked;
151
+ }
152
+ /**
153
+ * Execute synchronous mutations atomically by default. Atomic success is one undo/version
154
+ * unit; any failed or thrown step restores the exact package and history checkpoint.
155
+ */
156
+ executeBatch(steps, mode = "atomic") {
157
+ if (mode !== "atomic" && mode !== "best_effort") {
158
+ throw new RangeError(`unknown mutation batch mode: ${String(mode)}`);
159
+ }
160
+ const baseVersion = this.getVersion();
161
+ const observationWarnings = [];
162
+ const inspect = (label, read, fallback) => {
163
+ try {
164
+ return read();
165
+ } catch (error) {
166
+ observationWarnings.push(`${label} unavailable: ${error instanceof Error ? error.message : String(error)}`);
167
+ return fallback;
168
+ }
169
+ };
170
+ const beforeRevisions = inspect("Revision delta inspection", () => this.listRevisions(), []);
171
+ const beforeComments = inspect("Comment delta inspection", () => this.listComments(), []);
172
+ const beforeAnnotations = inspect("Annotation delta inspection", () => this.listAnnotations(), []);
173
+ const complete = (result) => {
174
+ try {
175
+ const revisionChanges = mutationBatchChangeSet(
176
+ beforeRevisions,
177
+ inspect("Revision delta inspection", () => this.listRevisions(), beforeRevisions),
178
+ (revision) => revision.id
179
+ );
180
+ const commentChanges = mutationBatchChangeSet(
181
+ beforeComments,
182
+ inspect("Comment delta inspection", () => this.listComments(), beforeComments),
183
+ (comment) => comment.anchorId
184
+ );
185
+ const annotationChanges = mutationBatchChangeSet(
186
+ beforeAnnotations,
187
+ inspect("Annotation delta inspection", () => this.listAnnotations(), beforeAnnotations),
188
+ (annotation) => annotation.id ?? ""
189
+ );
190
+ const resultVersion = inspect(
191
+ "Result version inspection",
192
+ () => this.getVersion(),
193
+ baseVersion
194
+ );
195
+ const warnings = [...observationWarnings];
196
+ if ([...revisionChanges.added, ...revisionChanges.modified].some((revision) => revision.date !== void 0 && revision.date !== null)) {
197
+ warnings.push("Tracked-revision date attributes may use the execution clock; compare revision ids, authors, types, text, and anchors across separate executions.");
198
+ }
199
+ if ([...commentChanges.added, ...commentChanges.modified].some((comment) => comment.date !== void 0 && comment.date !== null)) {
200
+ warnings.push("Comment date attributes may be generated from the execution clock; supply dates explicitly when byte-identical replay is required.");
201
+ }
202
+ if (annotationChanges.added.some((annotation) => annotation.created !== void 0 && annotation.created !== null)) {
203
+ warnings.push("Auto-generated annotation ids or creation timestamps are execution metadata; supply id and created explicitly when byte-identical replay is required.");
204
+ }
205
+ if (result.steps.some((step) => step.results.some((edit) => edit.created.length > 0))) {
206
+ warnings.push("Created anchors and related OOXML ids may be generated independently on replay; preview/apply equivalence is semantic and packageHash or anchor ids may differ.");
207
+ }
208
+ if (mode === "best_effort" && !result.success) {
209
+ warnings.push("Best-effort execution retains every successful step despite later failures.");
210
+ }
211
+ let packageHash = null;
212
+ if (!this.wasm.GetPackageContentHash) {
213
+ warnings.push("This WASM bundle predates package equivalence hashes; packageHash is unavailable.");
214
+ } else {
215
+ try {
216
+ packageHash = this.wasm.GetPackageContentHash(this.handle);
217
+ } catch (error) {
218
+ warnings.push(`Package equivalence hash unavailable: ${error instanceof Error ? error.message : String(error)}`);
219
+ }
220
+ }
221
+ return {
222
+ ...result,
223
+ preview: false,
224
+ baseVersion,
225
+ resultVersion,
226
+ packageHash,
227
+ revisionChanges,
228
+ commentChanges,
229
+ annotationChanges,
230
+ warnings,
231
+ html: null
232
+ };
233
+ } catch (error) {
234
+ return {
235
+ ...result,
236
+ preview: false,
237
+ baseVersion,
238
+ resultVersion: inspect("Result version inspection", () => this.getVersion(), baseVersion),
239
+ packageHash: null,
240
+ revisionChanges: { added: [], removed: [], modified: [] },
241
+ commentChanges: { added: [], removed: [], modified: [] },
242
+ annotationChanges: { added: [], removed: [], modified: [] },
243
+ warnings: [
244
+ ...observationWarnings,
245
+ `Batch receipt enrichment unavailable: ${error instanceof Error ? error.message : String(error)}`
246
+ ],
247
+ html: null
248
+ };
249
+ }
250
+ };
251
+ const internalFailure = (value) => ({
252
+ success: false,
253
+ error: { code: "internal_error", message: value instanceof Error ? value.message : String(value) },
254
+ created: [],
255
+ removed: [],
256
+ modified: []
257
+ });
258
+ const run = (step) => {
259
+ try {
260
+ const value = step.mutation();
261
+ const results = Array.isArray(value) ? value : [value];
262
+ if (results.some((result) => result === null || typeof result !== "object" || typeof result.success !== "boolean")) {
263
+ return [internalFailure("batch mutation returned invalid edit results")];
264
+ }
265
+ return results;
266
+ } catch (error) {
267
+ return [internalFailure(error)];
268
+ }
269
+ };
270
+ const failureOf = (step, rolledBack) => ({
271
+ index: step.index,
272
+ tool: step.tool,
273
+ action: step.action,
274
+ error: step.results.find((result) => !result.success)?.error ?? { code: "internal_error", message: "batch step failed without an error" },
275
+ rolledBack
276
+ });
277
+ const preflightOne = (step) => {
278
+ try {
279
+ return step.preflight?.();
280
+ } catch (error) {
281
+ return internalFailure(error).error;
282
+ }
283
+ };
284
+ if (mode === "atomic") {
285
+ const preflight = steps.map(preflightOne);
286
+ const failedPreflight = preflight.findIndex((error) => error !== void 0);
287
+ if (failedPreflight >= 0) {
288
+ const source = steps[failedPreflight];
289
+ const failed2 = {
290
+ index: failedPreflight,
291
+ tool: source.tool,
292
+ action: source.action,
293
+ success: false,
294
+ rolledBack: true,
295
+ results: [{ success: false, error: preflight[failedPreflight], created: [], removed: [], modified: [] }]
296
+ };
297
+ return complete({
298
+ mode,
299
+ status: "failed",
300
+ success: false,
301
+ rolledBack: true,
302
+ steps: [failed2],
303
+ failure: failureOf(failed2, true)
304
+ });
305
+ }
306
+ const transaction = this.wasm.BeginTransaction(this.handle);
307
+ const completed2 = [];
308
+ try {
309
+ for (let index = 0; index < steps.length; index++) {
310
+ const source = steps[index];
311
+ const results = run(source);
312
+ const step = {
313
+ index,
314
+ tool: source.tool,
315
+ action: source.action,
316
+ success: results.every((result) => result.success),
317
+ rolledBack: false,
318
+ results
319
+ };
320
+ completed2.push(step);
321
+ if (!step.success) {
322
+ this.wasm.RollbackTransaction(transaction);
323
+ const rolledBack = completed2.map((value) => ({ ...value, rolledBack: true }));
324
+ const failed2 = rolledBack[rolledBack.length - 1];
325
+ return complete({
326
+ mode,
327
+ status: "failed",
328
+ success: false,
329
+ rolledBack: true,
330
+ steps: rolledBack,
331
+ failure: failureOf(failed2, true)
332
+ });
333
+ }
334
+ }
335
+ this.wasm.CommitTransaction(transaction);
336
+ return complete({ mode, status: "ok", success: true, rolledBack: false, steps: completed2 });
337
+ } catch (error) {
338
+ try {
339
+ this.wasm.RollbackTransaction(transaction);
340
+ } catch {
341
+ }
342
+ throw error;
343
+ }
344
+ }
345
+ const completed = steps.map((source, index) => {
346
+ const preflight = preflightOne(source);
347
+ const results = preflight ? [{ success: false, error: preflight, created: [], removed: [], modified: [] }] : run(source);
348
+ return {
349
+ index,
350
+ tool: source.tool,
351
+ action: source.action,
352
+ success: results.every((result) => result.success),
353
+ rolledBack: false,
354
+ results
355
+ };
356
+ });
357
+ const failed = completed.find((step) => !step.success);
358
+ return complete({
359
+ mode,
360
+ status: failed ? completed.some((step) => step.success) ? "partial" : "failed" : "ok",
361
+ success: failed === void 0,
362
+ rolledBack: false,
363
+ steps: completed,
364
+ failure: failed ? failureOf(failed, false) : void 0
365
+ });
366
+ }
367
+ /**
368
+ * Execute the same callback batch algorithm against a complete isolated package clone.
369
+ * Callbacks receive the shadow session explicitly; mutate that argument. The live session's
370
+ * package, caches, version, configuration, and undo/redo history are never execution targets.
371
+ */
372
+ previewBatch(steps, mode = "atomic", options) {
373
+ if (mode !== "atomic" && mode !== "best_effort") {
374
+ throw new RangeError(`unknown mutation batch mode: ${String(mode)}`);
375
+ }
376
+ const htmlMode = options?.html ?? "none";
377
+ if (htmlMode !== "none" && htmlMode !== "scoped" && htmlMode !== "full") {
378
+ throw new RangeError(`unknown preview HTML mode: ${String(htmlMode)}`);
379
+ }
380
+ if (!this.wasm.OpenPreviewSession) {
381
+ throw new Error("This WASM bundle does not support isolated mutation previews.");
382
+ }
383
+ const shadow = new _DocxSession(this.wasm.OpenPreviewSession(this.handle), this.wasm);
384
+ try {
385
+ const result = shadow.executeBatch(
386
+ steps.map((step) => ({
387
+ tool: step.tool,
388
+ action: step.action,
389
+ mutation: () => step.mutation(shadow),
390
+ preflight: step.preflight ? () => step.preflight(shadow) : void 0
391
+ })),
392
+ mode
393
+ );
394
+ const warnings = [...result.warnings];
395
+ let html = null;
396
+ const unwrapRendered = (rendered) => {
397
+ if (rendered.trimStart().startsWith("{")) {
398
+ const envelope = JSON.parse(rendered);
399
+ if (envelope.error) {
400
+ warnings.push(`Preview HTML could not be generated: ${envelope.error}`);
401
+ return null;
402
+ }
403
+ }
404
+ return rendered;
405
+ };
406
+ const legacyProfileWarning = "This WASM bundle predates the shared preview HTML profile; preview HTML omits comments, annotations and headers/footers and may differ from other surfaces.";
407
+ try {
408
+ if (htmlMode === "scoped") {
409
+ if (!options?.htmlAnchorId) {
410
+ warnings.push("Scoped HTML was requested without htmlAnchorId; no HTML was generated.");
411
+ } else if (this.wasm.RenderPreviewBlockHtml) {
412
+ html = unwrapRendered(
413
+ this.wasm.RenderPreviewBlockHtml(shadow.handle, options.htmlAnchorId)
414
+ );
415
+ } else {
416
+ warnings.push(legacyProfileWarning);
417
+ html = shadow.renderBlock(options.htmlAnchorId);
418
+ }
419
+ } else if (htmlMode === "full") {
420
+ if (this.wasm.RenderPreviewHtml) {
421
+ html = unwrapRendered(this.wasm.RenderPreviewHtml(shadow.handle));
422
+ } else {
423
+ warnings.push(legacyProfileWarning);
424
+ html = unwrapRendered(this.wasm.RenderHtmlForReview ? this.wasm.RenderHtmlForReview(shadow.handle, "docx-", false, false, 1, true) : this.wasm.RenderHtml(shadow.handle, "docx-", false, false, 1));
425
+ }
426
+ }
427
+ } catch (error) {
428
+ warnings.push(`Preview HTML could not be generated: ${error instanceof Error ? error.message : String(error)}`);
429
+ }
430
+ return { ...result, preview: true, warnings, html };
431
+ } finally {
432
+ shadow.close();
433
+ }
434
+ }
66
435
  /**
67
436
  * Project a slice of the document keyed off an anchor — useful for showing
68
437
  * one section to an LLM at a time without paying the cost of projecting the
@@ -78,9 +447,9 @@ var DocxodusSession = (() => {
78
447
  *
79
448
  * @see docs/architecture/docx_mutation_api.md
80
449
  */
81
- projectAnchor(anchorId, depth = 2 /* SubtreeAndFollowingSiblings */) {
450
+ projectAnchor(anchorId, depth = 2 /* SubtreeAndFollowingSiblings */, citation) {
82
451
  return JSON.parse(
83
- this.wasm.ProjectAnchor(this.handle, anchorId, depth)
452
+ citation ? this.wasm.ProjectAnchorWithCitations(this.handle, anchorId, depth, JSON.stringify(citation)) : this.wasm.ProjectAnchor(this.handle, anchorId, depth)
84
453
  );
85
454
  }
86
455
  /**
@@ -104,11 +473,21 @@ var DocxodusSession = (() => {
104
473
  return html;
105
474
  }
106
475
  // ─── Tier A: text CRUD ───────────────────────────────────────────────
107
- replaceText(anchorId, markdown) {
108
- return JSON.parse(this.wasm.ReplaceText(this.handle, anchorId, markdown));
109
- }
110
- deleteBlock(anchorId) {
111
- return JSON.parse(this.wasm.DeleteBlock(this.handle, anchorId));
476
+ replaceText(anchorId, markdown, preconditions) {
477
+ const apply = () => JSON.parse(
478
+ this.wasm.ReplaceText(this.handle, anchorId, markdown)
479
+ );
480
+ return preconditions ? this.runWithPreconditions(
481
+ { ...preconditions, anchorId: preconditions.anchorId ?? anchorId },
482
+ apply
483
+ ) : apply();
484
+ }
485
+ deleteBlock(anchorId, preconditions) {
486
+ const apply = () => JSON.parse(this.wasm.DeleteBlock(this.handle, anchorId));
487
+ return preconditions ? this.runWithPreconditions(
488
+ { ...preconditions, anchorId: preconditions.anchorId ?? anchorId },
489
+ apply
490
+ ) : apply();
112
491
  }
113
492
  /** Reorder one top-level paragraph/heading/list/table block relative to another. */
114
493
  moveBlock(sourceAnchorId, targetAnchorId, position) {
@@ -163,7 +542,7 @@ var DocxodusSession = (() => {
163
542
  }
164
543
  /**
165
544
  * Insert a `rows`×`cols` table before/after the block. `options` controls borders, row-major
166
- * cell markdown, and cell alignment. The returned `EditResult.created` lists the cell-paragraph
545
+ * cell markdown, and cell alignment. The returned `EditResult.created` lists canonical `tc`
167
546
  * anchors (row-major), so each cell can then be addressed to fill/format.
168
547
  */
169
548
  insertTable(anchorId, position, rows, cols, options) {
@@ -172,10 +551,26 @@ var DocxodusSession = (() => {
172
551
  this.wasm.InsertTable(this.handle, anchorId, position, rows, cols, optionsJson)
173
552
  );
174
553
  }
554
+ /** Resolve a canonical `tbl` anchor to explicit table/row/column/cell identities. */
555
+ getTableMetadata(tableAnchorId) {
556
+ return JSON.parse(this.wasm.GetTableMetadata(this.handle, tableAnchorId));
557
+ }
558
+ /** Resolve a canonical `tc` anchor to its zero-based table-grid coordinate and spans. */
559
+ resolveTableCellAnchor(cellAnchorId) {
560
+ return JSON.parse(
561
+ this.wasm.ResolveTableCellAnchor(this.handle, cellAnchorId)
562
+ );
563
+ }
564
+ /** Resolve a zero-based table-grid coordinate to the physical `tc` covering it. */
565
+ resolveTableCellCoordinate(tableAnchorId, rowIndex, columnIndex) {
566
+ return JSON.parse(
567
+ this.wasm.ResolveTableCellCoordinate(this.handle, tableAnchorId, rowIndex, columnIndex)
568
+ );
569
+ }
175
570
  /**
176
- * Table row/column editing, addressed by a cell-paragraph anchor (e.g. one returned from
177
- * {@link insertTable}'s `created`). Insert clones the reference row/column's widths and starts
178
- * empty (`created` lists the new cell-paragraph anchors); delete of the last row/column removes
571
+ * Table row/column editing, addressed by the canonical `tc` anchor returned from
572
+ * {@link insertTable}'s `created` or table metadata. Insert clones the reference row/column's
573
+ * widths and starts empty (`created` lists new `tc` anchors); delete of the last row/column removes
179
574
  * the whole table. All four are grid-aware: inserting across a merge extends it, deleting
180
575
  * through one narrows it, and deleting a vertical merge's lead row promotes the next row to
181
576
  * carry it — the grid is never left ragged.
@@ -215,7 +610,7 @@ var DocxodusSession = (() => {
215
610
  return JSON.parse(this.wasm.UnmergeCells(this.handle, cellAnchorId));
216
611
  }
217
612
  /**
218
- * Table styling, addressed by a cell-paragraph anchor — the post-insert counterpart of
613
+ * Table styling, addressed by a canonical `tc` anchor — the post-insert counterpart of
219
614
  * {@link insertTable}'s options (issue #315 Stage A). `setColumnWidths` retunes `w:tblGrid` +
220
615
  * every row's cell width (one positive twip value per column) and pins the table to fixed
221
616
  * layout, exactly as inserting with explicit `columnWidths` would.
@@ -255,6 +650,19 @@ var DocxodusSession = (() => {
255
650
  this.wasm.SetRepeatHeaderRow(this.handle, cellAnchorId, repeat)
256
651
  );
257
652
  }
653
+ /** Apply row layout options to the row containing the canonical cell anchor. */
654
+ setTableRowOptions(cellAnchorId, options) {
655
+ return JSON.parse(
656
+ this.wasm.SetTableRowOptions(
657
+ this.handle,
658
+ cellAnchorId,
659
+ options.repeatHeader ?? null,
660
+ options.allowBreakAcrossPages ?? null,
661
+ options.heightTwips ?? null,
662
+ options.heightRule ?? "atLeast"
663
+ )
664
+ );
665
+ }
258
666
  // ─── Headers / footers / page numbers ────────────────────────────────
259
667
  /**
260
668
  * Set the running header story for the section that owns `anchorId` (any body block in that
@@ -349,6 +757,25 @@ var DocxodusSession = (() => {
349
757
  this.wasm.InsertFootnote(this.handle, anchorId, characterOffset, markdown)
350
758
  );
351
759
  }
760
+ /**
761
+ * Insert a Word-faithful internal cross-reference — a `REF` field targeting an existing
762
+ * bookmark — at a character offset (issue #545). The field carries a cached result run
763
+ * (the bookmarked text, or the target's auto-number under `referenceNumber`), so
764
+ * renderers that do not recompute fields show a faithful snapshot and Word updates it
765
+ * like a hand-authored cross-reference. A missing or incoherent bookmark fails with
766
+ * `missing_bookmark_target`.
767
+ */
768
+ insertCrossReference(anchorId, characterOffset, bookmarkName, options) {
769
+ return JSON.parse(
770
+ this.wasm.InsertCrossReference(
771
+ this.handle,
772
+ anchorId,
773
+ characterOffset,
774
+ bookmarkName,
775
+ options ? JSON.stringify(options) : ""
776
+ )
777
+ );
778
+ }
352
779
  /** Create an endnote — see {@link insertFootnote}; writes the endnotes part and a
353
780
  * `w:endnoteReference`, and the created definition anchor has kind `en`. */
354
781
  insertEndnote(anchorId, characterOffset, markdown) {
@@ -440,6 +867,170 @@ var DocxodusSession = (() => {
440
867
  listComments() {
441
868
  return JSON.parse(this.wasm.ListComments(this.handle));
442
869
  }
870
+ listHyperlinks(scopes = 63 /* All */) {
871
+ return JSON.parse(this.wasm.ListHyperlinks(this.handle, scopes));
872
+ }
873
+ addHyperlink(anchorId, span, kind, target) {
874
+ return JSON.parse(this.wasm.AddHyperlink(
875
+ this.handle,
876
+ anchorId,
877
+ span.start,
878
+ span.length,
879
+ kind,
880
+ target
881
+ ));
882
+ }
883
+ updateHyperlink(hyperlinkId, kind, target) {
884
+ return JSON.parse(this.wasm.UpdateHyperlink(this.handle, hyperlinkId, kind, target));
885
+ }
886
+ removeHyperlink(hyperlinkId) {
887
+ return JSON.parse(this.wasm.RemoveHyperlink(this.handle, hyperlinkId));
888
+ }
889
+ /** Versioned operational facts for native image inspection/mutation in this runtime. */
890
+ getImageCapabilities() {
891
+ return JSON.parse(this.wasm.GetImageCapabilities());
892
+ }
893
+ listImages(scopes = 63 /* All */) {
894
+ return JSON.parse(this.wasm.ListImages(this.handle, scopes));
895
+ }
896
+ insertImage(anchorId, characterOffset, bytes, options = {}) {
897
+ return JSON.parse(this.wasm.InsertImage(
898
+ this.handle,
899
+ anchorId,
900
+ characterOffset,
901
+ imageBytesToBase64(bytes),
902
+ JSON.stringify(options)
903
+ ));
904
+ }
905
+ replaceImage(imageId, bytes) {
906
+ return JSON.parse(this.wasm.ReplaceImage(
907
+ this.handle,
908
+ imageId,
909
+ imageBytesToBase64(bytes)
910
+ ));
911
+ }
912
+ setImageDimensions(imageId, dimensions) {
913
+ return JSON.parse(this.wasm.SetImageDimensions(
914
+ this.handle,
915
+ imageId,
916
+ JSON.stringify(dimensions)
917
+ ));
918
+ }
919
+ setImageMetadata(imageId, altText, title) {
920
+ return JSON.parse(this.wasm.SetImageMetadata(
921
+ this.handle,
922
+ imageId,
923
+ altText,
924
+ title
925
+ ));
926
+ }
927
+ setImageFloatingLayout(imageId, layout) {
928
+ return JSON.parse(this.wasm.SetImageFloatingLayout(
929
+ this.handle,
930
+ imageId,
931
+ JSON.stringify(layout)
932
+ ));
933
+ }
934
+ removeImage(imageId) {
935
+ return JSON.parse(this.wasm.RemoveImage(this.handle, imageId));
936
+ }
937
+ /** Native Word structured-document tags, in outer-before-inner story order. */
938
+ listContentControls(scopes = 63 /* All */) {
939
+ return JSON.parse(this.wasm.ListContentControls(this.handle, scopes));
940
+ }
941
+ fillContentControlText(anchorId, text, options = {}) {
942
+ return JSON.parse(this.wasm.FillContentControlText(
943
+ this.handle,
944
+ anchorId,
945
+ text,
946
+ JSON.stringify(options)
947
+ ));
948
+ }
949
+ fillContentControlRichText(anchorId, markdown, options = {}) {
950
+ return JSON.parse(this.wasm.FillContentControlRichText(
951
+ this.handle,
952
+ anchorId,
953
+ markdown,
954
+ JSON.stringify(options)
955
+ ));
956
+ }
957
+ setContentControlChecked(anchorId, isChecked, options = {}) {
958
+ return JSON.parse(this.wasm.SetContentControlChecked(
959
+ this.handle,
960
+ anchorId,
961
+ isChecked,
962
+ JSON.stringify(options)
963
+ ));
964
+ }
965
+ setContentControlDate(anchorId, value, displayText, options = {}) {
966
+ const timestamp = value instanceof Date ? value.toISOString() : value;
967
+ return JSON.parse(this.wasm.SetContentControlDate(
968
+ this.handle,
969
+ anchorId,
970
+ timestamp,
971
+ displayText ?? null,
972
+ JSON.stringify(options)
973
+ ));
974
+ }
975
+ selectContentControlItem(anchorId, value, options = {}) {
976
+ return JSON.parse(this.wasm.SelectContentControlItem(
977
+ this.handle,
978
+ anchorId,
979
+ value,
980
+ JSON.stringify(options)
981
+ ));
982
+ }
983
+ fillContentControlPicture(anchorId, bytes, options = {}) {
984
+ return JSON.parse(this.wasm.FillContentControlPicture(
985
+ this.handle,
986
+ anchorId,
987
+ imageBytesToBase64(bytes),
988
+ JSON.stringify(options)
989
+ ));
990
+ }
991
+ addRepeatingSectionItem(sectionAnchorId, afterItemAnchorId, options = {}) {
992
+ return JSON.parse(this.wasm.AddRepeatingSectionItem(
993
+ this.handle,
994
+ sectionAnchorId,
995
+ afterItemAnchorId ?? "",
996
+ JSON.stringify(options)
997
+ ));
998
+ }
999
+ removeRepeatingSectionItem(itemAnchorId) {
1000
+ return JSON.parse(this.wasm.RemoveRepeatingSectionItem(
1001
+ this.handle,
1002
+ itemAnchorId
1003
+ ));
1004
+ }
1005
+ listBookmarks(scopes = 63 /* All */) {
1006
+ return JSON.parse(this.wasm.ListBookmarks(this.handle, scopes));
1007
+ }
1008
+ addBookmark(name, range) {
1009
+ return JSON.parse(this.wasm.AddBookmark(
1010
+ this.handle,
1011
+ name,
1012
+ range.startAnchorId,
1013
+ range.startOffset,
1014
+ range.endAnchorId,
1015
+ range.endOffset
1016
+ ));
1017
+ }
1018
+ renameBookmark(name, newName) {
1019
+ return JSON.parse(this.wasm.RenameBookmark(this.handle, name, newName));
1020
+ }
1021
+ moveBookmark(name, range) {
1022
+ return JSON.parse(this.wasm.MoveBookmark(
1023
+ this.handle,
1024
+ name,
1025
+ range.startAnchorId,
1026
+ range.startOffset,
1027
+ range.endAnchorId,
1028
+ range.endOffset
1029
+ ));
1030
+ }
1031
+ removeBookmark(name) {
1032
+ return JSON.parse(this.wasm.RemoveBookmark(this.handle, name));
1033
+ }
443
1034
  // ─── Tracked revisions (issue #318) ──────────────────────────────────
444
1035
  /** Markup-native tracked-revision listing, in document order across body, headers,
445
1036
  * footers, footnotes, and endnotes. Ids are stable while the underlying markup
@@ -460,6 +1051,22 @@ var DocxodusSession = (() => {
460
1051
  rejectRevision(revisionId) {
461
1052
  return JSON.parse(this.wasm.RejectRevision(this.handle, revisionId));
462
1053
  }
1054
+ /**
1055
+ * Accept every live revision as one undoable session mutation.
1056
+ *
1057
+ * Fails closed: an unsupported, malformed, or ambiguous registry entry aborts the whole
1058
+ * operation (`revisionUnsupported`/`revisionMalformed`/`revisionAmbiguous`) and nothing is
1059
+ * mutated. There is no force mode — call {@link listRevisions} and read each entry's
1060
+ * `diagnostic` to see what blocks it.
1061
+ */
1062
+ acceptAllRevisions() {
1063
+ return JSON.parse(this.wasm.AcceptAllRevisions(this.handle));
1064
+ }
1065
+ /** Reject every live revision as one undoable session mutation. Fails closed exactly like
1066
+ * {@link acceptAllRevisions}. */
1067
+ rejectAllRevisions() {
1068
+ return JSON.parse(this.wasm.RejectAllRevisions(this.handle));
1069
+ }
463
1070
  // ─── Tier C: formatting ──────────────────────────────────────────────
464
1071
  applyFormat(anchorId, span, op) {
465
1072
  const spanJson = span ? JSON.stringify(span) : "";
@@ -565,6 +1172,10 @@ var DocxodusSession = (() => {
565
1172
  * replaces it with `replace`, preserving the surrounding run formatting that
566
1173
  * the match didn't touch. Returns one `EditResult` per attempted match.
567
1174
  *
1175
+ * A `find` that matches nothing fails with a single `text_not_found` result
1176
+ * naming the anchor and the needle — never an empty array. Pass
1177
+ * `expectedMatchCount: 0` to assert absence as a successful no-op instead.
1178
+ *
568
1179
  * Run-formatting contract: the replacement text inherits the formatting of
569
1180
  * the FIRST run the match spanned. Middle/trailing runs keep their `w:rPr`
570
1181
  * but lose the slice of text the match consumed.
@@ -741,10 +1352,16 @@ var DocxodusSession = (() => {
741
1352
  *
742
1353
  * @see docs/architecture/docx_mutation_api.md#findplaceholders
743
1354
  */
744
- findPlaceholders(kinds = PlaceholderKinds.All, scope = 1, contextChars = 80, boundary = ContextBoundary.Char) {
745
- return JSON.parse(
746
- this.wasm.FindPlaceholders(this.handle, kinds, scope, contextChars, boundary)
747
- );
1355
+ findPlaceholders(kinds = PlaceholderKinds.All, scope = 1, contextChars = 80, boundary = ContextBoundary.Char, citation) {
1356
+ const json = citation ? this.wasm.FindPlaceholdersWithCitations(
1357
+ this.handle,
1358
+ kinds,
1359
+ scope,
1360
+ contextChars,
1361
+ boundary,
1362
+ JSON.stringify(citation)
1363
+ ) : this.wasm.FindPlaceholders(this.handle, kinds, scope, contextChars, boundary);
1364
+ return JSON.parse(json);
748
1365
  }
749
1366
  /**
750
1367
  * Returns a snapshot of edit-state introspection signals — placeholder counts,
@@ -767,6 +1384,23 @@ var DocxodusSession = (() => {
767
1384
  }
768
1385
  return raw;
769
1386
  }
1387
+ /**
1388
+ * Return stable semantic changes from the package opened for this session to
1389
+ * its current state. Requires `captureInitialProjection` (enabled by default).
1390
+ */
1391
+ getSemanticChanges() {
1392
+ return JSON.parse(this.wasm.GetSemanticChanges(this.handle));
1393
+ }
1394
+ /**
1395
+ * Run the default deliverable gate on this session's normal clean-save checkpoint.
1396
+ * With initial projection capture enabled (the default), exact opening bytes are the
1397
+ * baseline used for dispositions and semantic/package deltas.
1398
+ */
1399
+ verifyDeliverable() {
1400
+ return JSON.parse(
1401
+ this.wasm.VerifyDeliverable(this.handle)
1402
+ );
1403
+ }
770
1404
  // ─── Annotation-based anchor discovery (#132) ────────────────────────
771
1405
  /**
772
1406
  * Resolves an annotation's range to the block-level markdown anchors covering
@@ -782,8 +1416,9 @@ var DocxodusSession = (() => {
782
1416
  *
783
1417
  * @see docs/architecture/docx_mutation_api.md#findbyannotation
784
1418
  */
785
- findByAnnotation(annotationId) {
786
- return JSON.parse(this.wasm.FindByAnnotation(this.handle, annotationId));
1419
+ findByAnnotation(annotationId, citation) {
1420
+ const json = citation ? this.wasm.FindByAnnotationWithCitations(this.handle, annotationId, JSON.stringify(citation)) : this.wasm.FindByAnnotation(this.handle, annotationId);
1421
+ return JSON.parse(json);
787
1422
  }
788
1423
  /**
789
1424
  * Finds every annotation whose `labelId` matches and resolves each of their
@@ -792,8 +1427,9 @@ var DocxodusSession = (() => {
792
1427
  * annotations on different paragraphs become three entries). Annotations
793
1428
  * whose bookmark resolves to no anchors are omitted from the result.
794
1429
  */
795
- findByLabel(labelId) {
796
- return JSON.parse(this.wasm.FindByLabel(this.handle, labelId));
1430
+ findByLabel(labelId, citation) {
1431
+ const json = citation ? this.wasm.FindByLabelWithCitations(this.handle, labelId, JSON.stringify(citation)) : this.wasm.FindByLabel(this.handle, labelId);
1432
+ return JSON.parse(json);
797
1433
  }
798
1434
  /**
799
1435
  * Resolves any bookmark in the main document part (Docxodus-managed or
@@ -801,8 +1437,9 @@ var DocxodusSession = (() => {
801
1437
  * order. Empty when the bookmark name is unknown. Use this for raw bookmark
802
1438
  * names that didn't come from the annotation system.
803
1439
  */
804
- findByBookmark(bookmarkName) {
805
- return JSON.parse(this.wasm.FindByBookmark(this.handle, bookmarkName));
1440
+ findByBookmark(bookmarkName, citation) {
1441
+ const json = citation ? this.wasm.FindByBookmarkWithCitations(this.handle, bookmarkName, JSON.stringify(citation)) : this.wasm.FindByBookmark(this.handle, bookmarkName);
1442
+ return JSON.parse(json);
806
1443
  }
807
1444
  // ─── Text/kind-based anchor discovery (#171) ─────────────────────────
808
1445
  /**
@@ -847,15 +1484,25 @@ var DocxodusSession = (() => {
847
1484
  );
848
1485
  }
849
1486
  /**
850
- * Return every anchor of the given `kind` (`"p"`, `"h"`, `"li"`, `"tbl"`,
851
- * `"row"`, `"cell"`, …), in document order. Reads the projection's anchor
1487
+ * Return every anchor of the given `kind` — one of `"p"`, `"h"`, `"li"`,
1488
+ * `"tbl"`, `"tr"`, `"tc"`, `"col"`, `"sdt"`, `"sec"`, `"fn"`, `"en"`,
1489
+ * `"cmt"`, `"unk"` — in document order. Matching is an exact string comparison;
1490
+ * in particular the row and cell tokens are `"tr"` and `"tc"`, never
1491
+ * `"row"`/`"cell"`. Unknown strings are not parsed or rejected: they simply
1492
+ * return an empty array. `"img"` and `"drw"` likewise return empty because the
1493
+ * projection never assigns those reserved kinds; address images through the
1494
+ * image surface instead. Reads the projection's anchor
852
1495
  * index directly — no text scan. Pass `scope` (e.g. `"body"`) to restrict to
853
1496
  * a single part; omit it to span all scopes.
854
1497
  */
855
- findByKind(kind, scope) {
856
- return JSON.parse(
857
- this.wasm.FindByKind(this.handle, kind, scope ?? "")
858
- );
1498
+ findByKind(kind, scope, citation) {
1499
+ const json = citation ? this.wasm.FindByKindWithCitations(
1500
+ this.handle,
1501
+ kind,
1502
+ scope ?? "",
1503
+ JSON.stringify(citation)
1504
+ ) : this.wasm.FindByKind(this.handle, kind, scope ?? "");
1505
+ return JSON.parse(json);
859
1506
  }
860
1507
  /**
861
1508
  * Look up a single anchor's preview info — `{ id, kind, scope, textPreview }`.
@@ -909,6 +1556,18 @@ var DocxodusSession = (() => {
909
1556
  const raw = this.wasm.GetSectionInfo(this.handle, anchorId);
910
1557
  return JSON.parse(raw);
911
1558
  }
1559
+ /** Enumerate the document's explicit style catalog with resolved high-signal properties. */
1560
+ listStyles() {
1561
+ return JSON.parse(this.wasm.ListStyles(this.handle));
1562
+ }
1563
+ /** Inspect direct and effective paragraph/run formatting for one paragraph anchor. */
1564
+ getFormatting(anchorId) {
1565
+ return JSON.parse(this.wasm.GetFormatting(this.handle, anchorId));
1566
+ }
1567
+ /** Enumerate text-bearing runs as mutation-compatible anchor/span pairs. */
1568
+ listInlineSpans(anchorId) {
1569
+ return JSON.parse(this.wasm.ListInlineSpans(this.handle, anchorId));
1570
+ }
912
1571
  /**
913
1572
  * Enumerates every annotation persisted in the document. Lets an agent prime
914
1573
  * itself with "here are the labeled regions you can target" before committing
@@ -973,6 +1632,13 @@ var DocxodusSession = (() => {
973
1632
  this.close();
974
1633
  }
975
1634
  };
1635
+ function imageBytesToBase64(bytes) {
1636
+ let binary = "";
1637
+ for (let offset = 0; offset < bytes.length; offset += 32768) {
1638
+ binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
1639
+ }
1640
+ return globalThis.btoa(binary);
1641
+ }
976
1642
  function openDocxSession(bytes, wasmExports, settings) {
977
1643
  const bridge = wasmExports.DocxSessionBridge;
978
1644
  const handle = bridge.OpenSession(bytes, settings ? JSON.stringify(settings) : "");