@ansonlai/docx-redline-js 0.8.2 → 0.8.4

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 (33) hide show
  1. package/CHANGELOG.md +75 -1
  2. package/README.md +28 -13
  3. package/core/list-targeting.js +12 -10
  4. package/dist/docx-redline-js.esm.js +837 -549
  5. package/dist/docx-redline-js.esm.js.map +4 -4
  6. package/dist/docx-redline-js.esm.min.js +93 -90
  7. package/dist/docx-redline-js.esm.min.js.map +4 -4
  8. package/dist/docx-redline.bundle.cjs +837 -549
  9. package/dist/docx-redline.bundle.cjs.map +4 -4
  10. package/dist/docx-redline.bundle.js +837 -549
  11. package/dist/docx-redline.bundle.js.map +4 -4
  12. package/docs/AGENT_KNOWLEDGE_BASE.md +4 -1
  13. package/docs/schemas/document-operations.schema.json +168 -168
  14. package/engine/oxml-engine.js +215 -195
  15. package/engine/reconstruction-mode.js +183 -183
  16. package/index.d.ts +4 -0
  17. package/index.js +36 -1
  18. package/node/cli.js +2 -1
  19. package/orchestration/list-structural-fallback.js +530 -518
  20. package/package.json +1 -1
  21. package/pipeline/list-generation.js +203 -168
  22. package/pipeline/serialization.js +111 -94
  23. package/services/batch-operation-orchestrator.js +6 -0
  24. package/services/document-inspection.js +10 -7
  25. package/services/document-operation-applier.js +2 -0
  26. package/services/document-operation-contract.js +553 -537
  27. package/services/document-operation-mutations.js +1140 -1011
  28. package/services/numbering-helpers.js +108 -0
  29. package/services/operation-batch-compiler.js +440 -436
  30. package/services/operation-heuristics.js +197 -173
  31. package/services/revision-comment-management.js +601 -594
  32. package/services/standalone-operation-runner.d.ts +429 -427
  33. package/services/table-reconciliation.js +48 -46
@@ -1,427 +1,429 @@
1
- import type { ExistingRevisionsPolicy, RedlineError, RedlineStatus, RevisionToken } from '../index.js';
2
-
3
- export interface ParagraphTargetDescriptor {
4
- text?: string;
5
- exactText?: string;
6
- index?: number | string;
7
- paragraphIndex?: number | string;
8
- paragraphId?: string;
9
- occurrence?: number;
10
- inTable?: boolean;
11
- fingerprint?: string;
12
- sourceFingerprint?: string;
13
- /** Defaults to rejected for restore operations and accepted for all other operations. */
14
- revisionView?: 'accepted' | 'rejected';
15
- captureRef?: string;
16
- select?: string;
17
- createdByOperation?: number;
18
- }
19
-
20
- export interface InsertionAffinity {
21
- formatting?: 'left' | 'right' | 'none';
22
- hyperlink?: 'inside' | 'outside' | 'preserve';
23
- revision?: 'coalesce_same_author' | 'separate';
24
- bookmark?: 'inside' | 'outside';
25
- comment?: 'inside' | 'outside';
26
- }
27
-
28
- export interface RejectedTextInsertionAnchor {
29
- exactText: string;
30
- occurrence?: number;
31
- offset: number;
32
- }
33
-
34
- export interface LocalizedReplacement {
35
- find: string;
36
- replace: string;
37
- occurrence?: number;
38
- }
39
-
40
- /** A header/footer part path from `inspect().headersFooters`, or a selector. */
41
- export type HeaderFooterPartSelector =
42
- | string
43
- | { kind: 'header' | 'footer'; type?: 'default' | 'first' | 'even'; section?: number };
44
-
45
- export interface DocumentOperationBase {
46
- operationId?: string;
47
- /** Target a header or footer instead of the body. Comments are not supported there. */
48
- part?: HeaderFooterPartSelector;
49
- captureKey?: string;
50
- target?: string | ParagraphTargetDescriptor;
51
- targetRef?: number | string | null;
52
- author?: string;
53
- generateRedlines?: boolean;
54
- existingRevisions?: ExistingRevisionsPolicy;
55
- pairReplacements?: boolean;
56
- insertionAffinity?: InsertionAffinity;
57
- }
58
-
59
- interface RedlineDocumentOperationCommon extends DocumentOperationBase {
60
- structuredContent?: boolean;
61
- targetEnd?: ParagraphTargetDescriptor;
62
- targetEndRef?: number | string | null;
63
- /** Required when type is insert and target.revisionView is rejected. */
64
- anchor?: RejectedTextInsertionAnchor;
65
- }
66
-
67
- export type RedlineDocumentOperation =
68
- | (RedlineDocumentOperationCommon & {
69
- type: 'redline' | 'replace';
70
- modified: string;
71
- replacements?: never;
72
- })
73
- | (RedlineDocumentOperationCommon & {
74
- type: 'redline' | 'replace';
75
- modified?: never;
76
- /** Exact, case-sensitive replacements in one batch-start accepted-view paragraph. */
77
- replacements: LocalizedReplacement[];
78
- })
79
- | (RedlineDocumentOperationCommon & {
80
- type: 'format' | 'list-change' | 'table-reconciliation' | 'insert';
81
- modified: string;
82
- replacements?: never;
83
- });
84
-
85
- interface RestoreDocumentOperationCommon extends DocumentOperationBase {
86
- type: 'restore';
87
- }
88
-
89
- export type RestoreDocumentOperation =
90
- | (RestoreDocumentOperationCommon & {
91
- modified: string | string[];
92
- replacements?: never;
93
- targetEnd?: ParagraphTargetDescriptor;
94
- targetEndRef?: number | string | null;
95
- })
96
- | (RestoreDocumentOperationCommon & {
97
- modified?: never;
98
- /** Exact, case-sensitive replacements in one strong rejected-view paragraph. */
99
- replacements: LocalizedReplacement[];
100
- targetEnd?: never;
101
- targetEndRef?: never;
102
- })
103
- | (RestoreDocumentOperationCommon & {
104
- /** Omit modified to restore one strong rejected-view paragraph verbatim. */
105
- modified?: never;
106
- replacements?: never;
107
- targetEnd?: never;
108
- targetEndRef?: never;
109
- });
110
-
111
- export interface DeleteDocumentOperation extends DocumentOperationBase {
112
- type: 'delete';
113
- modified?: '';
114
- }
115
-
116
- export interface CommentDocumentOperation extends DocumentOperationBase {
117
- type: 'comment';
118
- textToComment?: string;
119
- commentContent: string;
120
- }
121
-
122
- export interface CommentReplyDocumentOperation {
123
- type: 'comment_reply';
124
- operationId?: string;
125
- parentCommentId: number | string;
126
- commentContent: string;
127
- author?: string;
128
- date?: string;
129
- }
130
-
131
- /** Resolves (or with `resolved: false`, reopens) the whole thread containing `commentId`. Body-only. */
132
- export interface CommentResolveDocumentOperation {
133
- type: 'comment_resolve';
134
- operationId?: string;
135
- commentId: number | string;
136
- resolved?: boolean;
137
- }
138
-
139
- export interface CharacterFormatProperties {
140
- bold?: boolean;
141
- italic?: boolean;
142
- underline?: boolean;
143
- strike?: boolean;
144
- strikethrough?: boolean;
145
- highlight?: string | null;
146
- color?: string | null;
147
- fontSize?: number | string | null;
148
- fontFamily?: string | null;
149
- }
150
-
151
- export interface ParagraphFormatProperties {
152
- alignment?: 'left' | 'center' | 'right' | 'both';
153
- keepNext?: boolean;
154
- keepLines?: boolean;
155
- pageBreakBefore?: boolean;
156
- style?: string | null;
157
- }
158
-
159
- export interface HighlightDocumentOperation extends DocumentOperationBase {
160
- type: 'highlight';
161
- textToHighlight: string;
162
- color?: string;
163
- }
164
-
165
- export interface CharacterFormatDocumentOperation extends DocumentOperationBase {
166
- type: 'format' | 'character-format';
167
- textToFormat: string;
168
- properties: CharacterFormatProperties;
169
- formattingRevisionPolicy?: 'always' | 'coalesce-own-insertion';
170
- }
171
-
172
- export interface ParagraphFormatDocumentOperation extends DocumentOperationBase {
173
- type: 'paragraph-format';
174
- properties: ParagraphFormatProperties;
175
- }
176
-
177
- export type DocumentOperation =
178
- | RedlineDocumentOperation
179
- | RestoreDocumentOperation
180
- | DeleteDocumentOperation
181
- | CommentDocumentOperation
182
- | CommentReplyDocumentOperation
183
- | CommentResolveDocumentOperation
184
- | HighlightDocumentOperation
185
- | CharacterFormatDocumentOperation
186
- | ParagraphFormatDocumentOperation;
187
-
188
- export interface ResolvedDocumentTarget {
189
- index: number;
190
- paragraphId: string | null;
191
- text: string;
192
- fingerprint?: string;
193
- revisionView?: 'accepted' | 'rejected';
194
- inTable?: boolean;
195
- targetTextMatch?: {
196
- mode: 'exact' | 'space_equivalent' | 'normalized';
197
- differences?: Array<{
198
- offset: number;
199
- sourceCodePoint: string;
200
- requestedCodePoint: string;
201
- }>;
202
- sourceExcerpt?: string;
203
- requestedExcerpt?: string;
204
- };
205
- }
206
-
207
- export interface ResolvedCommentAnchor {
208
- requestIndex: number;
209
- paragraphIndex: number;
210
- text: string;
211
- resolvedBy: 'exact_anchor' | 'space_equivalent_anchor';
212
- start: number;
213
- end: number;
214
- }
215
-
216
- export interface StandaloneRunnerOptions {
217
- atomic?: boolean;
218
- continueOnError?: boolean;
219
- generateRedlines?: boolean;
220
- existingRevisions?: ExistingRevisionsPolicy;
221
- strictTargets?: boolean;
222
- expectedRevision?: RevisionToken;
223
- pairReplacements?: boolean;
224
- insertionAffinity?: InsertionAffinity;
225
- onInfo?: (message: string) => void;
226
- onWarn?: (message: string) => void;
227
- [key: string]: unknown;
228
- }
229
-
230
- export interface MutationReceiptRevisionItem {
231
- id: string;
232
- kind: 'ins' | 'del' | 'move_from' | 'move_to' | 'rPrChange' | 'pPrChange' | 'structural';
233
- partName: string;
234
- }
235
-
236
- export interface MutationReceipt {
237
- operationIndex: number;
238
- operationId?: string;
239
- attemptedDisposition: 'applied' | 'no_change' | 'refused' | 'not_attempted';
240
- finalDisposition: 'applied' | 'no_change' | 'refused' | 'rolled_back' | 'not_attempted';
241
- committed: boolean;
242
- authorUsed?: string;
243
- revisionItems: MutationReceiptRevisionItem[];
244
- commentIds: string[];
245
- numberingIds: string[];
246
- relationshipIds: string[];
247
- affectedTargets: ResolvedDocumentTarget[];
248
- warnings: string[];
249
- }
250
-
251
- export interface LocalizedReplacementChange {
252
- kind: 'localized_replacement';
253
- committed: boolean;
254
- finalDisposition: 'applied' | 'rolled_back';
255
- target: {
256
- paragraphId?: string;
257
- index?: number;
258
- fingerprint?: string;
259
- humanReference?: string;
260
- };
261
- context?: {
262
- search?: string;
263
- range?: string;
264
- anchorMatchCount?: number;
265
- humanReference?: string;
266
- };
267
- replacements: Array<{
268
- find: string;
269
- replace: string;
270
- occurrence?: number;
271
- matchMode?: 'space_equivalent';
272
- beforeExcerpt: string;
273
- afterExcerpt: string;
274
- }>;
275
- verification: {
276
- acceptedViewMatchesCompiledText: boolean;
277
- };
278
- }
279
-
280
- export interface DocumentOperationResult {
281
- documentXml: string;
282
- hasChanges: boolean;
283
- numberingXml?: string | null;
284
- commentsXml?: string | null;
285
- commentsExtendedXml?: string | null;
286
- commentsXmlMode?: 'merge' | 'replace';
287
- commentsExtendedXmlMode?: 'merge' | 'replace';
288
- warnings?: string[];
289
- status?: RedlineStatus;
290
- error?: RedlineError;
291
- operationType: 'redline' | 'comment' | 'comment_reply' | 'comment_resolve' | 'highlight' | 'format' | 'paragraph-format';
292
- authorUsed: string;
293
- resolvedBy?: string;
294
- resolvedTarget?: ResolvedDocumentTarget;
295
- resolvedAnchor?: ResolvedCommentAnchor;
296
- receipt?: MutationReceipt;
297
- change?: LocalizedReplacementChange;
298
- }
299
-
300
- export interface BatchOperationItemResult {
301
- index: number;
302
- type: string;
303
- operationType: 'redline' | 'comment' | 'comment_reply' | 'comment_resolve' | 'highlight' | 'format' | 'paragraph-format';
304
- status: 'applied' | 'no_change' | 'error';
305
- authorUsed: string;
306
- resolvedBy?: string;
307
- resolvedTarget?: ResolvedDocumentTarget;
308
- resolvedAnchor?: ResolvedCommentAnchor;
309
- warnings?: string[];
310
- error?: RedlineError;
311
- receipt?: MutationReceipt;
312
- change?: LocalizedReplacementChange;
313
- }
314
-
315
- export interface DocumentOperationBatchResult {
316
- documentXml: string;
317
- hasChanges: boolean;
318
- commentsXml: string | null;
319
- commentsExtendedXml?: string | null;
320
- commentsXmlMode?: 'merge' | 'replace';
321
- commentsExtendedXmlMode?: 'merge' | 'replace';
322
- numberingXmlParts: string[];
323
- results: BatchOperationItemResult[];
324
- receipts?: MutationReceipt[];
325
- executionOrder: number[];
326
- /** Authors attached to committed changes. Empty when an atomic batch rolls back. */
327
- authorsUsed: string[];
328
- rolledBack?: boolean;
329
- status?: RedlineStatus;
330
- error?: RedlineError;
331
- warnings?: string[];
332
- conflicts?: OperationConflict[];
333
- retryPlan?: MutationRetryPlan;
334
- }
335
-
336
- export interface MutationRetryPlan {
337
- base: 'original' | 'output';
338
- committedIndexes: number[];
339
- failedIndexes: number[];
340
- unattemptedIndexes: number[];
341
- replayWholeBatch: boolean;
342
- sameArgumentsSafe: false;
343
- }
344
-
345
- export interface OperationPreflightItemResult {
346
- index: number;
347
- type: string;
348
- operationType: 'redline' | 'comment' | 'comment_reply' | 'comment_resolve' | 'highlight' | 'format' | 'paragraph-format';
349
- status: 'ready' | 'deferred' | 'error';
350
- authorUsed: string;
351
- resolvedBy?: string;
352
- captureRef?: string;
353
- select?: string;
354
- resolvedTarget?: ResolvedDocumentTarget;
355
- matchDiagnostics?: {
356
- exactTextMatch: boolean;
357
- normalizedTextMatch: boolean;
358
- suppliedText: string;
359
- actualText: string;
360
- };
361
- anchor?: {
362
- text: string;
363
- found: boolean;
364
- resolvedBy?: 'exact_anchor' | 'space_equivalent_anchor';
365
- start?: number;
366
- end?: number;
367
- candidates?: Array<{ start: number; end: number }>;
368
- } | null;
369
- hasRevisions?: boolean;
370
- existingRevisions?: ExistingRevisionsPolicy;
371
- warnings?: string[];
372
- error?: RedlineError & { candidates?: ResolvedDocumentTarget[] };
373
- }
374
-
375
- export interface OperationConflict {
376
- code: 'OVERLAPPING_SOURCE_TARGETS' | 'OVERLAPPING_TEXT_EDITS' | 'REVISION_ORDER_CONFLICT' | 'CAPTURE_FANOUT_CONFLICT' | string;
377
- message: string;
378
- operationIndexes: number[];
379
- target: ResolvedDocumentTarget;
380
- recoveryVersion?: number;
381
- category?: string;
382
- recovery?: RedlineError['recovery'];
383
- }
384
-
385
- export interface OperationPreflightResult {
386
- valid: boolean;
387
- status: 'ok' | 'error';
388
- results: OperationPreflightItemResult[];
389
- conflicts: OperationConflict[];
390
- authorsUsed: string[];
391
- requiredArtifacts: { comments: boolean; numbering: boolean };
392
- error?: RedlineError;
393
- }
394
-
395
- export interface OperationDependencyPlan {
396
- valid: boolean;
397
- scheduled?: Array<{ operation: DocumentOperation; index: number }>;
398
- captureProducers?: Map<string, number>;
399
- error?: RedlineError;
400
- }
401
-
402
- export function buildOperationDependencyPlan(operations?: DocumentOperation[]): OperationDependencyPlan;
403
-
404
- export function orderOperationsForStableTargets(operations?: DocumentOperation[]): DocumentOperation[];
405
-
406
- export function preflightOperations(
407
- documentXml: string,
408
- operations: DocumentOperation[],
409
- author?: string,
410
- options?: StandaloneRunnerOptions
411
- ): OperationPreflightResult;
412
-
413
- export function applyOperationToDocumentXml(
414
- documentXml: string,
415
- operation: DocumentOperation,
416
- author?: string,
417
- runtimeContext?: Record<string, unknown> | null,
418
- options?: StandaloneRunnerOptions
419
- ): Promise<DocumentOperationResult>;
420
-
421
- export function applyOperationsToDocumentXml(
422
- documentXml: string,
423
- operations: DocumentOperation[],
424
- author?: string,
425
- runtimeContext?: Record<string, unknown> | null,
426
- options?: StandaloneRunnerOptions
427
- ): Promise<DocumentOperationBatchResult>;
1
+ import type { ExistingRevisionsPolicy, RedlineError, RedlineStatus, RevisionToken } from '../index.js';
2
+
3
+ export interface ParagraphTargetDescriptor {
4
+ text?: string;
5
+ exactText?: string;
6
+ index?: number | string;
7
+ paragraphIndex?: number | string;
8
+ paragraphId?: string;
9
+ occurrence?: number;
10
+ inTable?: boolean;
11
+ fingerprint?: string;
12
+ sourceFingerprint?: string;
13
+ /** Defaults to rejected for restore operations and accepted for all other operations. */
14
+ revisionView?: 'accepted' | 'rejected';
15
+ captureRef?: string;
16
+ select?: string;
17
+ createdByOperation?: number;
18
+ }
19
+
20
+ export interface InsertionAffinity {
21
+ formatting?: 'left' | 'right' | 'none';
22
+ hyperlink?: 'inside' | 'outside' | 'preserve';
23
+ revision?: 'coalesce_same_author' | 'separate';
24
+ bookmark?: 'inside' | 'outside';
25
+ comment?: 'inside' | 'outside';
26
+ }
27
+
28
+ export interface RejectedTextInsertionAnchor {
29
+ exactText: string;
30
+ occurrence?: number;
31
+ offset: number;
32
+ }
33
+
34
+ export interface LocalizedReplacement {
35
+ find: string;
36
+ replace: string;
37
+ occurrence?: number;
38
+ }
39
+
40
+ /** A header/footer part path from `inspect().headersFooters`, or a selector. */
41
+ export type HeaderFooterPartSelector =
42
+ | string
43
+ | { kind: 'header' | 'footer'; type?: 'default' | 'first' | 'even'; section?: number };
44
+
45
+ export interface DocumentOperationBase {
46
+ operationId?: string;
47
+ /** Target a header or footer instead of the body. Comments are not supported there. */
48
+ part?: HeaderFooterPartSelector;
49
+ captureKey?: string;
50
+ target?: string | ParagraphTargetDescriptor;
51
+ targetRef?: number | string | null;
52
+ author?: string;
53
+ generateRedlines?: boolean;
54
+ existingRevisions?: ExistingRevisionsPolicy;
55
+ pairReplacements?: boolean;
56
+ insertionAffinity?: InsertionAffinity;
57
+ }
58
+
59
+ interface RedlineDocumentOperationCommon extends DocumentOperationBase {
60
+ structuredContent?: boolean;
61
+ targetEnd?: ParagraphTargetDescriptor;
62
+ targetEndRef?: number | string | null;
63
+ /** Required when type is insert and target.revisionView is rejected. */
64
+ anchor?: RejectedTextInsertionAnchor;
65
+ }
66
+
67
+ export type RedlineDocumentOperation =
68
+ | (RedlineDocumentOperationCommon & {
69
+ type: 'redline' | 'replace';
70
+ modified: string;
71
+ replacements?: never;
72
+ })
73
+ | (RedlineDocumentOperationCommon & {
74
+ type: 'redline' | 'replace';
75
+ modified?: never;
76
+ /** Exact, case-sensitive replacements in one batch-start accepted-view paragraph. */
77
+ replacements: LocalizedReplacement[];
78
+ })
79
+ | (RedlineDocumentOperationCommon & {
80
+ type: 'format' | 'list-change' | 'table-reconciliation' | 'insert';
81
+ modified: string;
82
+ replacements?: never;
83
+ });
84
+
85
+ interface RestoreDocumentOperationCommon extends DocumentOperationBase {
86
+ type: 'restore';
87
+ }
88
+
89
+ export type RestoreDocumentOperation =
90
+ | (RestoreDocumentOperationCommon & {
91
+ modified: string | string[];
92
+ replacements?: never;
93
+ targetEnd?: ParagraphTargetDescriptor;
94
+ targetEndRef?: number | string | null;
95
+ })
96
+ | (RestoreDocumentOperationCommon & {
97
+ modified?: never;
98
+ /** Exact, case-sensitive replacements in one strong rejected-view paragraph. */
99
+ replacements: LocalizedReplacement[];
100
+ targetEnd?: never;
101
+ targetEndRef?: never;
102
+ })
103
+ | (RestoreDocumentOperationCommon & {
104
+ /** Omit modified to restore one strong rejected-view paragraph verbatim. */
105
+ modified?: never;
106
+ replacements?: never;
107
+ targetEnd?: never;
108
+ targetEndRef?: never;
109
+ });
110
+
111
+ export interface DeleteDocumentOperation extends DocumentOperationBase {
112
+ type: 'delete';
113
+ modified?: '';
114
+ }
115
+
116
+ export interface CommentDocumentOperation extends DocumentOperationBase {
117
+ type: 'comment';
118
+ textToComment?: string;
119
+ commentContent: string;
120
+ }
121
+
122
+ export interface CommentReplyDocumentOperation {
123
+ type: 'comment_reply';
124
+ operationId?: string;
125
+ parentCommentId: number | string;
126
+ commentContent: string;
127
+ author?: string;
128
+ date?: string;
129
+ }
130
+
131
+ /** Resolves (or with `resolved: false`, reopens) the whole thread containing `commentId`. Body-only. */
132
+ export interface CommentResolveDocumentOperation {
133
+ type: 'comment_resolve';
134
+ operationId?: string;
135
+ commentId: number | string;
136
+ resolved?: boolean;
137
+ }
138
+
139
+ export interface CharacterFormatProperties {
140
+ bold?: boolean;
141
+ italic?: boolean;
142
+ underline?: boolean;
143
+ strike?: boolean;
144
+ strikethrough?: boolean;
145
+ highlight?: string | null;
146
+ color?: string | null;
147
+ fontSize?: number | string | null;
148
+ fontFamily?: string | null;
149
+ }
150
+
151
+ export interface ParagraphFormatProperties {
152
+ alignment?: 'left' | 'center' | 'right' | 'both';
153
+ keepNext?: boolean;
154
+ keepLines?: boolean;
155
+ pageBreakBefore?: boolean;
156
+ style?: string | null;
157
+ }
158
+
159
+ export interface HighlightDocumentOperation extends DocumentOperationBase {
160
+ type: 'highlight';
161
+ textToHighlight: string;
162
+ color?: string;
163
+ }
164
+
165
+ export interface CharacterFormatDocumentOperation extends DocumentOperationBase {
166
+ type: 'format' | 'character-format';
167
+ textToFormat: string;
168
+ /** 1-based match of `textToFormat` inside the resolved paragraph (default 1). Independent of `target.occurrence`. */
169
+ textOccurrence?: number;
170
+ properties: CharacterFormatProperties;
171
+ formattingRevisionPolicy?: 'always' | 'coalesce-own-insertion';
172
+ }
173
+
174
+ export interface ParagraphFormatDocumentOperation extends DocumentOperationBase {
175
+ type: 'paragraph-format';
176
+ properties: ParagraphFormatProperties;
177
+ }
178
+
179
+ export type DocumentOperation =
180
+ | RedlineDocumentOperation
181
+ | RestoreDocumentOperation
182
+ | DeleteDocumentOperation
183
+ | CommentDocumentOperation
184
+ | CommentReplyDocumentOperation
185
+ | CommentResolveDocumentOperation
186
+ | HighlightDocumentOperation
187
+ | CharacterFormatDocumentOperation
188
+ | ParagraphFormatDocumentOperation;
189
+
190
+ export interface ResolvedDocumentTarget {
191
+ index: number;
192
+ paragraphId: string | null;
193
+ text: string;
194
+ fingerprint?: string;
195
+ revisionView?: 'accepted' | 'rejected';
196
+ inTable?: boolean;
197
+ targetTextMatch?: {
198
+ mode: 'exact' | 'space_equivalent' | 'normalized';
199
+ differences?: Array<{
200
+ offset: number;
201
+ sourceCodePoint: string;
202
+ requestedCodePoint: string;
203
+ }>;
204
+ sourceExcerpt?: string;
205
+ requestedExcerpt?: string;
206
+ };
207
+ }
208
+
209
+ export interface ResolvedCommentAnchor {
210
+ requestIndex: number;
211
+ paragraphIndex: number;
212
+ text: string;
213
+ resolvedBy: 'exact_anchor' | 'space_equivalent_anchor';
214
+ start: number;
215
+ end: number;
216
+ }
217
+
218
+ export interface StandaloneRunnerOptions {
219
+ atomic?: boolean;
220
+ continueOnError?: boolean;
221
+ generateRedlines?: boolean;
222
+ existingRevisions?: ExistingRevisionsPolicy;
223
+ strictTargets?: boolean;
224
+ expectedRevision?: RevisionToken;
225
+ pairReplacements?: boolean;
226
+ insertionAffinity?: InsertionAffinity;
227
+ onInfo?: (message: string) => void;
228
+ onWarn?: (message: string) => void;
229
+ [key: string]: unknown;
230
+ }
231
+
232
+ export interface MutationReceiptRevisionItem {
233
+ id: string;
234
+ kind: 'ins' | 'del' | 'move_from' | 'move_to' | 'rPrChange' | 'pPrChange' | 'structural';
235
+ partName: string;
236
+ }
237
+
238
+ export interface MutationReceipt {
239
+ operationIndex: number;
240
+ operationId?: string;
241
+ attemptedDisposition: 'applied' | 'no_change' | 'refused' | 'not_attempted';
242
+ finalDisposition: 'applied' | 'no_change' | 'refused' | 'rolled_back' | 'not_attempted';
243
+ committed: boolean;
244
+ authorUsed?: string;
245
+ revisionItems: MutationReceiptRevisionItem[];
246
+ commentIds: string[];
247
+ numberingIds: string[];
248
+ relationshipIds: string[];
249
+ affectedTargets: ResolvedDocumentTarget[];
250
+ warnings: string[];
251
+ }
252
+
253
+ export interface LocalizedReplacementChange {
254
+ kind: 'localized_replacement';
255
+ committed: boolean;
256
+ finalDisposition: 'applied' | 'rolled_back';
257
+ target: {
258
+ paragraphId?: string;
259
+ index?: number;
260
+ fingerprint?: string;
261
+ humanReference?: string;
262
+ };
263
+ context?: {
264
+ search?: string;
265
+ range?: string;
266
+ anchorMatchCount?: number;
267
+ humanReference?: string;
268
+ };
269
+ replacements: Array<{
270
+ find: string;
271
+ replace: string;
272
+ occurrence?: number;
273
+ matchMode?: 'space_equivalent';
274
+ beforeExcerpt: string;
275
+ afterExcerpt: string;
276
+ }>;
277
+ verification: {
278
+ acceptedViewMatchesCompiledText: boolean;
279
+ };
280
+ }
281
+
282
+ export interface DocumentOperationResult {
283
+ documentXml: string;
284
+ hasChanges: boolean;
285
+ numberingXml?: string | null;
286
+ commentsXml?: string | null;
287
+ commentsExtendedXml?: string | null;
288
+ commentsXmlMode?: 'merge' | 'replace';
289
+ commentsExtendedXmlMode?: 'merge' | 'replace';
290
+ warnings?: string[];
291
+ status?: RedlineStatus;
292
+ error?: RedlineError;
293
+ operationType: 'redline' | 'comment' | 'comment_reply' | 'comment_resolve' | 'highlight' | 'format' | 'paragraph-format';
294
+ authorUsed: string;
295
+ resolvedBy?: string;
296
+ resolvedTarget?: ResolvedDocumentTarget;
297
+ resolvedAnchor?: ResolvedCommentAnchor;
298
+ receipt?: MutationReceipt;
299
+ change?: LocalizedReplacementChange;
300
+ }
301
+
302
+ export interface BatchOperationItemResult {
303
+ index: number;
304
+ type: string;
305
+ operationType: 'redline' | 'comment' | 'comment_reply' | 'comment_resolve' | 'highlight' | 'format' | 'paragraph-format';
306
+ status: 'applied' | 'no_change' | 'error';
307
+ authorUsed: string;
308
+ resolvedBy?: string;
309
+ resolvedTarget?: ResolvedDocumentTarget;
310
+ resolvedAnchor?: ResolvedCommentAnchor;
311
+ warnings?: string[];
312
+ error?: RedlineError;
313
+ receipt?: MutationReceipt;
314
+ change?: LocalizedReplacementChange;
315
+ }
316
+
317
+ export interface DocumentOperationBatchResult {
318
+ documentXml: string;
319
+ hasChanges: boolean;
320
+ commentsXml: string | null;
321
+ commentsExtendedXml?: string | null;
322
+ commentsXmlMode?: 'merge' | 'replace';
323
+ commentsExtendedXmlMode?: 'merge' | 'replace';
324
+ numberingXmlParts: string[];
325
+ results: BatchOperationItemResult[];
326
+ receipts?: MutationReceipt[];
327
+ executionOrder: number[];
328
+ /** Authors attached to committed changes. Empty when an atomic batch rolls back. */
329
+ authorsUsed: string[];
330
+ rolledBack?: boolean;
331
+ status?: RedlineStatus;
332
+ error?: RedlineError;
333
+ warnings?: string[];
334
+ conflicts?: OperationConflict[];
335
+ retryPlan?: MutationRetryPlan;
336
+ }
337
+
338
+ export interface MutationRetryPlan {
339
+ base: 'original' | 'output';
340
+ committedIndexes: number[];
341
+ failedIndexes: number[];
342
+ unattemptedIndexes: number[];
343
+ replayWholeBatch: boolean;
344
+ sameArgumentsSafe: false;
345
+ }
346
+
347
+ export interface OperationPreflightItemResult {
348
+ index: number;
349
+ type: string;
350
+ operationType: 'redline' | 'comment' | 'comment_reply' | 'comment_resolve' | 'highlight' | 'format' | 'paragraph-format';
351
+ status: 'ready' | 'deferred' | 'error';
352
+ authorUsed: string;
353
+ resolvedBy?: string;
354
+ captureRef?: string;
355
+ select?: string;
356
+ resolvedTarget?: ResolvedDocumentTarget;
357
+ matchDiagnostics?: {
358
+ exactTextMatch: boolean;
359
+ normalizedTextMatch: boolean;
360
+ suppliedText: string;
361
+ actualText: string;
362
+ };
363
+ anchor?: {
364
+ text: string;
365
+ found: boolean;
366
+ resolvedBy?: 'exact_anchor' | 'space_equivalent_anchor';
367
+ start?: number;
368
+ end?: number;
369
+ candidates?: Array<{ start: number; end: number }>;
370
+ } | null;
371
+ hasRevisions?: boolean;
372
+ existingRevisions?: ExistingRevisionsPolicy;
373
+ warnings?: string[];
374
+ error?: RedlineError & { candidates?: ResolvedDocumentTarget[] };
375
+ }
376
+
377
+ export interface OperationConflict {
378
+ code: 'OVERLAPPING_SOURCE_TARGETS' | 'OVERLAPPING_TEXT_EDITS' | 'REVISION_ORDER_CONFLICT' | 'CAPTURE_FANOUT_CONFLICT' | string;
379
+ message: string;
380
+ operationIndexes: number[];
381
+ target: ResolvedDocumentTarget;
382
+ recoveryVersion?: number;
383
+ category?: string;
384
+ recovery?: RedlineError['recovery'];
385
+ }
386
+
387
+ export interface OperationPreflightResult {
388
+ valid: boolean;
389
+ status: 'ok' | 'error';
390
+ results: OperationPreflightItemResult[];
391
+ conflicts: OperationConflict[];
392
+ authorsUsed: string[];
393
+ requiredArtifacts: { comments: boolean; numbering: boolean };
394
+ error?: RedlineError;
395
+ }
396
+
397
+ export interface OperationDependencyPlan {
398
+ valid: boolean;
399
+ scheduled?: Array<{ operation: DocumentOperation; index: number }>;
400
+ captureProducers?: Map<string, number>;
401
+ error?: RedlineError;
402
+ }
403
+
404
+ export function buildOperationDependencyPlan(operations?: DocumentOperation[]): OperationDependencyPlan;
405
+
406
+ export function orderOperationsForStableTargets(operations?: DocumentOperation[]): DocumentOperation[];
407
+
408
+ export function preflightOperations(
409
+ documentXml: string,
410
+ operations: DocumentOperation[],
411
+ author?: string,
412
+ options?: StandaloneRunnerOptions
413
+ ): OperationPreflightResult;
414
+
415
+ export function applyOperationToDocumentXml(
416
+ documentXml: string,
417
+ operation: DocumentOperation,
418
+ author?: string,
419
+ runtimeContext?: Record<string, unknown> | null,
420
+ options?: StandaloneRunnerOptions
421
+ ): Promise<DocumentOperationResult>;
422
+
423
+ export function applyOperationsToDocumentXml(
424
+ documentXml: string,
425
+ operations: DocumentOperation[],
426
+ author?: string,
427
+ runtimeContext?: Record<string, unknown> | null,
428
+ options?: StandaloneRunnerOptions
429
+ ): Promise<DocumentOperationBatchResult>;