@ansonlai/docx-redline-js 0.4.0 → 0.5.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 (100) hide show
  1. package/AGENTS.md +589 -287
  2. package/ARCHITECTURE.md +215 -9
  3. package/CHANGELOG.md +319 -0
  4. package/README.md +604 -360
  5. package/adapters/config.js +45 -43
  6. package/bin/docx-redline.js +3 -0
  7. package/core/list-targeting.js +101 -110
  8. package/core/paragraph-targeting.js +501 -61
  9. package/core/paragraph-text.js +209 -0
  10. package/core/revision-cloning.js +38 -0
  11. package/core/types.js +64 -10
  12. package/core/word-xml.js +43 -15
  13. package/dist/docx-redline-js.esm.js +2849 -466
  14. package/dist/docx-redline-js.esm.js.map +4 -4
  15. package/dist/docx-redline-js.esm.min.js +87 -76
  16. package/dist/docx-redline-js.esm.min.js.map +4 -4
  17. package/docs/TESTING.md +342 -23
  18. package/docs/plans/2026-09-05-structural-revisions-and-fidelity-oracles.md +1669 -0
  19. package/docs/plans/completed/2026-09-01-performance-and-complexity-reduction.md +669 -0
  20. package/docs/plans/completed/2026-09-03-agent-friendly-document-workflows.md +427 -0
  21. package/docs/plans/completed/2026-09-04-comment-anchor-and-cli-reliability.md +519 -0
  22. package/docs/plans/completed/PERFORMANCE-CONSOLIDATION.md +69 -0
  23. package/docs/plans/completed/structural-revision-capability-matrix.md +115 -0
  24. package/docs/schemas/document-operations.schema.json +109 -0
  25. package/docs/test-comparison-dashboard.html +4250 -7
  26. package/engine/formatting-removal.js +11 -2
  27. package/engine/oxml-engine.js +491 -336
  28. package/engine/reconstruction-mode.js +15 -14
  29. package/engine/reconstruction-writer.js +247 -142
  30. package/engine/route-selection.js +35 -0
  31. package/engine/rpr-helpers.js +334 -35
  32. package/engine/run-builders.js +239 -196
  33. package/engine/surgical-diff-application.js +222 -37
  34. package/engine/surgical-mode.js +134 -6
  35. package/engine/surgical-spans.js +52 -1
  36. package/engine/table-cell-context.js +3 -6
  37. package/engine/table-mode.js +1 -1
  38. package/index.d.ts +234 -6
  39. package/index.js +24 -1
  40. package/node/cli.js +317 -0
  41. package/node/docx-document.js +302 -0
  42. package/node/index.d.ts +31 -0
  43. package/node/index.js +2 -0
  44. package/node/zip-archive.js +52 -0
  45. package/orchestration/list-markdown.js +10 -16
  46. package/orchestration/list-parsing.js +7 -12
  47. package/orchestration/list-structural-fallback.js +21 -10
  48. package/package.json +24 -3
  49. package/pipeline/content-analysis.js +12 -17
  50. package/pipeline/ingestion-export.js +3 -31
  51. package/pipeline/ingestion-paragraph.js +10 -5
  52. package/pipeline/list-generation.js +150 -55
  53. package/pipeline/list-markers.js +70 -3
  54. package/pipeline/serialization.js +4 -2
  55. package/pipeline/structured-content.js +160 -0
  56. package/scripts/apply_changes.mjs +27 -0
  57. package/scripts/benchmark-operation-session.mjs +137 -0
  58. package/scripts/benchmark-targeting-browser.html +74 -0
  59. package/scripts/benchmark-targeting-hot-paths.mjs +67 -0
  60. package/scripts/benchmark-test-runner.mjs +59 -0
  61. package/scripts/build-test-dashboard.mjs +23 -0
  62. package/scripts/export-lane1-fixtures.mjs +380 -0
  63. package/scripts/export-reredline-stress-fixtures.mjs +317 -0
  64. package/scripts/export-validation-fixtures.mjs +1 -1
  65. package/scripts/extract_text.mjs +7 -0
  66. package/scripts/generate-paragraph-boundary-fixtures.ps1 +215 -0
  67. package/scripts/generate-test-dashboard.mjs +362 -11
  68. package/scripts/lib/word-coverage-catalogue.mjs +6 -2
  69. package/scripts/profile-route-selection.mjs +19 -0
  70. package/scripts/render-agenda-multilevel.mjs +0 -5
  71. package/scripts/render-multilevel-cases.mjs +0 -1
  72. package/scripts/run-tests.mjs +107 -35
  73. package/scripts/word-com-corpus-suite.ps1 +3 -0
  74. package/scripts/word-com-differential.ps1 +64 -4
  75. package/scripts/word-com-suite.ps1 +3 -0
  76. package/services/batch-operation-orchestrator.js +494 -0
  77. package/services/capture-engine.js +226 -0
  78. package/services/comment-builders.js +23 -6
  79. package/services/comment-engine.js +108 -47
  80. package/services/comment-locator.js +187 -82
  81. package/services/comment-replies.js +95 -0
  82. package/services/document-inspection.js +258 -0
  83. package/services/document-operation-applier.js +372 -0
  84. package/services/document-operation-contract.js +323 -0
  85. package/services/document-operation-mutations.js +1733 -0
  86. package/services/document-operation-session.js +258 -0
  87. package/services/numbering-service.js +14 -5
  88. package/services/operation-heuristics.js +173 -0
  89. package/services/operation-preflight.js +366 -0
  90. package/services/receipt-collector.js +288 -0
  91. package/services/revision-comment-management.js +37 -5
  92. package/services/revision-token.js +290 -0
  93. package/services/standalone-docx-plumbing.js +123 -8
  94. package/services/standalone-operation-runner.d.ts +296 -0
  95. package/services/standalone-operation-runner.js +10 -1455
  96. package/services/table-reconciliation.js +15 -6
  97. package/docs/VALIDATION.md +0 -183
  98. package/docs/WORD-MANUAL-REVIEW.md +0 -138
  99. package/docs/plans/2026-09-01-performance-and-complexity-reduction.md +0 -210
  100. /package/docs/plans/{2026-08-30-reliability-testing-improvements.md → completed/2026-08-30-reliability-testing-improvements.md} +0 -0
@@ -0,0 +1,296 @@
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
+ revisionView?: 'accepted' | 'rejected';
14
+ captureRef?: string;
15
+ select?: string;
16
+ }
17
+
18
+ export interface InsertionAffinity {
19
+ formatting?: 'left' | 'right' | 'none';
20
+ hyperlink?: 'inside' | 'outside' | 'preserve';
21
+ revision?: 'coalesce_same_author' | 'separate';
22
+ bookmark?: 'inside' | 'outside';
23
+ comment?: 'inside' | 'outside';
24
+ }
25
+
26
+ export interface DocumentOperationBase {
27
+ operationId?: string;
28
+ captureKey?: string;
29
+ target?: string | ParagraphTargetDescriptor;
30
+ targetRef?: number | string | null;
31
+ author?: string;
32
+ generateRedlines?: boolean;
33
+ existingRevisions?: ExistingRevisionsPolicy;
34
+ pairReplacements?: boolean;
35
+ insertionAffinity?: InsertionAffinity;
36
+ }
37
+
38
+ export interface RedlineDocumentOperation extends DocumentOperationBase {
39
+ type: 'redline' | 'replace' | 'format' | 'list-change' | 'table-reconciliation' | 'insert';
40
+ modified: string;
41
+ structuredContent?: boolean;
42
+ targetEnd?: ParagraphTargetDescriptor;
43
+ targetEndRef?: number | string | null;
44
+ }
45
+
46
+ export interface DeleteDocumentOperation extends DocumentOperationBase {
47
+ type: 'delete';
48
+ modified?: '';
49
+ }
50
+
51
+ export interface CommentDocumentOperation extends DocumentOperationBase {
52
+ type: 'comment';
53
+ textToComment?: string;
54
+ commentContent: string;
55
+ }
56
+
57
+ export interface CommentReplyDocumentOperation {
58
+ type: 'comment_reply';
59
+ operationId?: string;
60
+ parentCommentId: number | string;
61
+ commentContent: string;
62
+ author?: string;
63
+ date?: string;
64
+ }
65
+
66
+ export interface CharacterFormatProperties {
67
+ bold?: boolean;
68
+ italic?: boolean;
69
+ underline?: boolean;
70
+ strike?: boolean;
71
+ strikethrough?: boolean;
72
+ highlight?: string | null;
73
+ color?: string | null;
74
+ fontSize?: number | string | null;
75
+ fontFamily?: string | null;
76
+ }
77
+
78
+ export interface ParagraphFormatProperties {
79
+ alignment?: 'left' | 'center' | 'right' | 'both';
80
+ keepNext?: boolean;
81
+ keepLines?: boolean;
82
+ pageBreakBefore?: boolean;
83
+ style?: string | null;
84
+ }
85
+
86
+ export interface HighlightDocumentOperation extends DocumentOperationBase {
87
+ type: 'highlight';
88
+ textToHighlight: string;
89
+ color?: string;
90
+ }
91
+
92
+ export interface CharacterFormatDocumentOperation extends DocumentOperationBase {
93
+ type: 'format' | 'character-format';
94
+ textToFormat: string;
95
+ properties: CharacterFormatProperties;
96
+ formattingRevisionPolicy?: 'always' | 'coalesce-own-insertion';
97
+ }
98
+
99
+ export interface ParagraphFormatDocumentOperation extends DocumentOperationBase {
100
+ type: 'paragraph-format';
101
+ properties: ParagraphFormatProperties;
102
+ }
103
+
104
+ export type DocumentOperation =
105
+ | RedlineDocumentOperation
106
+ | DeleteDocumentOperation
107
+ | CommentDocumentOperation
108
+ | CommentReplyDocumentOperation
109
+ | HighlightDocumentOperation
110
+ | CharacterFormatDocumentOperation
111
+ | ParagraphFormatDocumentOperation;
112
+
113
+ export interface ResolvedDocumentTarget {
114
+ index: number;
115
+ paragraphId: string | null;
116
+ text: string;
117
+ fingerprint?: string;
118
+ inTable?: boolean;
119
+ }
120
+
121
+ export interface ResolvedCommentAnchor {
122
+ requestIndex: number;
123
+ paragraphIndex: number;
124
+ text: string;
125
+ resolvedBy: 'exact_anchor' | 'space_equivalent_anchor';
126
+ start: number;
127
+ end: number;
128
+ }
129
+
130
+ export interface StandaloneRunnerOptions {
131
+ atomic?: boolean;
132
+ continueOnError?: boolean;
133
+ generateRedlines?: boolean;
134
+ existingRevisions?: ExistingRevisionsPolicy;
135
+ strictTargets?: boolean;
136
+ expectedRevision?: RevisionToken;
137
+ pairReplacements?: boolean;
138
+ insertionAffinity?: InsertionAffinity;
139
+ onInfo?: (message: string) => void;
140
+ onWarn?: (message: string) => void;
141
+ [key: string]: unknown;
142
+ }
143
+
144
+ export interface MutationReceiptRevisionItem {
145
+ id: string;
146
+ kind: 'ins' | 'del' | 'move_from' | 'move_to' | 'rPrChange' | 'pPrChange' | 'structural';
147
+ partName: string;
148
+ }
149
+
150
+ export interface MutationReceipt {
151
+ operationIndex: number;
152
+ operationId?: string;
153
+ attemptedDisposition: 'applied' | 'no_change' | 'refused' | 'not_attempted';
154
+ finalDisposition: 'applied' | 'no_change' | 'refused' | 'rolled_back' | 'not_attempted';
155
+ committed: boolean;
156
+ authorUsed?: string;
157
+ revisionItems: MutationReceiptRevisionItem[];
158
+ commentIds: string[];
159
+ numberingIds: string[];
160
+ relationshipIds: string[];
161
+ affectedTargets: ResolvedDocumentTarget[];
162
+ warnings: string[];
163
+ }
164
+
165
+ export interface DocumentOperationResult {
166
+ documentXml: string;
167
+ hasChanges: boolean;
168
+ numberingXml?: string | null;
169
+ commentsXml?: string | null;
170
+ commentsExtendedXml?: string | null;
171
+ commentsXmlMode?: 'merge' | 'replace';
172
+ commentsExtendedXmlMode?: 'merge' | 'replace';
173
+ warnings?: string[];
174
+ status?: RedlineStatus;
175
+ error?: RedlineError;
176
+ operationType: 'redline' | 'comment' | 'comment_reply' | 'highlight' | 'format' | 'paragraph-format';
177
+ authorUsed: string;
178
+ resolvedBy?: string;
179
+ resolvedTarget?: ResolvedDocumentTarget;
180
+ resolvedAnchor?: ResolvedCommentAnchor;
181
+ receipt?: MutationReceipt;
182
+ }
183
+
184
+ export interface BatchOperationItemResult {
185
+ index: number;
186
+ type: string;
187
+ operationType: 'redline' | 'comment' | 'comment_reply' | 'highlight' | 'format' | 'paragraph-format';
188
+ status: 'applied' | 'no_change' | 'error';
189
+ authorUsed: string;
190
+ resolvedBy?: string;
191
+ resolvedTarget?: ResolvedDocumentTarget;
192
+ resolvedAnchor?: ResolvedCommentAnchor;
193
+ warnings?: string[];
194
+ error?: RedlineError;
195
+ receipt?: MutationReceipt;
196
+ }
197
+
198
+ export interface DocumentOperationBatchResult {
199
+ documentXml: string;
200
+ hasChanges: boolean;
201
+ commentsXml: string | null;
202
+ commentsExtendedXml?: string | null;
203
+ commentsXmlMode?: 'merge' | 'replace';
204
+ commentsExtendedXmlMode?: 'merge' | 'replace';
205
+ numberingXmlParts: string[];
206
+ results: BatchOperationItemResult[];
207
+ receipts?: MutationReceipt[];
208
+ executionOrder: number[];
209
+ /** Authors attached to committed changes. Empty when an atomic batch rolls back. */
210
+ authorsUsed: string[];
211
+ rolledBack?: boolean;
212
+ status?: RedlineStatus;
213
+ error?: RedlineError;
214
+ warnings?: string[];
215
+ }
216
+
217
+ export interface OperationPreflightItemResult {
218
+ index: number;
219
+ type: string;
220
+ operationType: 'redline' | 'comment' | 'comment_reply' | 'highlight' | 'format' | 'paragraph-format';
221
+ status: 'ready' | 'deferred' | 'error';
222
+ authorUsed: string;
223
+ resolvedBy?: string;
224
+ captureRef?: string;
225
+ select?: string;
226
+ resolvedTarget?: ResolvedDocumentTarget;
227
+ matchDiagnostics?: {
228
+ exactTextMatch: boolean;
229
+ normalizedTextMatch: boolean;
230
+ suppliedText: string;
231
+ actualText: string;
232
+ };
233
+ anchor?: {
234
+ text: string;
235
+ found: boolean;
236
+ resolvedBy?: 'exact_anchor' | 'space_equivalent_anchor';
237
+ start?: number;
238
+ end?: number;
239
+ candidates?: Array<{ start: number; end: number }>;
240
+ } | null;
241
+ hasRevisions?: boolean;
242
+ existingRevisions?: ExistingRevisionsPolicy;
243
+ warnings?: string[];
244
+ error?: RedlineError & { candidates?: ResolvedDocumentTarget[] };
245
+ }
246
+
247
+ export interface OperationConflict {
248
+ code: 'OVERLAPPING_TEXT_EDITS' | 'REVISION_ORDER_CONFLICT' | string;
249
+ message: string;
250
+ operationIndexes: number[];
251
+ target: ResolvedDocumentTarget;
252
+ }
253
+
254
+ export interface OperationPreflightResult {
255
+ valid: boolean;
256
+ status: 'ok' | 'error';
257
+ results: OperationPreflightItemResult[];
258
+ conflicts: OperationConflict[];
259
+ authorsUsed: string[];
260
+ requiredArtifacts: { comments: boolean; numbering: boolean };
261
+ error?: RedlineError;
262
+ }
263
+
264
+ export interface OperationDependencyPlan {
265
+ valid: boolean;
266
+ scheduled?: Array<{ operation: DocumentOperation; index: number }>;
267
+ captureProducers?: Map<string, number>;
268
+ error?: RedlineError;
269
+ }
270
+
271
+ export function buildOperationDependencyPlan(operations?: DocumentOperation[]): OperationDependencyPlan;
272
+
273
+ export function orderOperationsForStableTargets(operations?: DocumentOperation[]): DocumentOperation[];
274
+
275
+ export function preflightOperations(
276
+ documentXml: string,
277
+ operations: DocumentOperation[],
278
+ author?: string,
279
+ options?: StandaloneRunnerOptions
280
+ ): OperationPreflightResult;
281
+
282
+ export function applyOperationToDocumentXml(
283
+ documentXml: string,
284
+ operation: DocumentOperation,
285
+ author?: string,
286
+ runtimeContext?: Record<string, unknown> | null,
287
+ options?: StandaloneRunnerOptions
288
+ ): Promise<DocumentOperationResult>;
289
+
290
+ export function applyOperationsToDocumentXml(
291
+ documentXml: string,
292
+ operations: DocumentOperation[],
293
+ author?: string,
294
+ runtimeContext?: Record<string, unknown> | null,
295
+ options?: StandaloneRunnerOptions
296
+ ): Promise<DocumentOperationBatchResult>;