@ansonlai/docx-redline-js 0.7.2 → 0.8.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 (53) hide show
  1. package/AGENTS.md +15 -10
  2. package/ARCHITECTURE.md +30 -10
  3. package/CHANGELOG.md +539 -431
  4. package/README.md +331 -309
  5. package/adapters/xml-adapter.js +84 -56
  6. package/core/sha256.js +120 -0
  7. package/dist/docx-redline-js.esm.js +8982 -693
  8. package/dist/docx-redline-js.esm.js.map +4 -4
  9. package/dist/docx-redline-js.esm.min.js +102 -89
  10. package/dist/docx-redline-js.esm.min.js.map +4 -4
  11. package/dist/docx-redline.bundle.cjs +28305 -0
  12. package/dist/docx-redline.bundle.cjs.map +7 -0
  13. package/dist/docx-redline.bundle.js +28296 -0
  14. package/dist/docx-redline.bundle.js.map +7 -0
  15. package/docs/AGENT_FAST_START.md +2 -1
  16. package/docs/AGENT_KNOWLEDGE_BASE.md +480 -393
  17. package/docs/SKILL_AUTHORING.md +5 -2
  18. package/docs/TESTING.md +2 -1
  19. package/docs/schemas/document-operations.schema.json +29 -0
  20. package/document/docx-document.d.ts +39 -0
  21. package/document/docx-document.js +1010 -0
  22. package/document/zip-archive.js +258 -0
  23. package/engine/reconstruction-writer.js +18 -0
  24. package/index.d.ts +598 -531
  25. package/index.js +349 -340
  26. package/node/cli-help.js +5 -5
  27. package/node/cli.js +760 -754
  28. package/node/docx-document.js +11 -355
  29. package/node/index.d.ts +1 -1
  30. package/node/zip-archive.js +28 -38
  31. package/package.json +14 -11
  32. package/scripts/build.mjs +40 -5
  33. package/scripts/generate-word-comment-edge-case-fixture.ps1 +58 -0
  34. package/scripts/generate-word-comment-thread-fixture.ps1 +36 -0
  35. package/scripts/generate-word-header-footer-fixture.ps1 +32 -0
  36. package/scripts/generate-word-multi-section-fixture.ps1 +27 -0
  37. package/scripts/generate-word-package-integrity-cases.mjs +141 -0
  38. package/scripts/generate-word-thread-state-fixtures.ps1 +50 -0
  39. package/scripts/word-com-package-integrity.ps1 +98 -0
  40. package/services/batch-operation-orchestrator.js +262 -259
  41. package/services/comment-replies.js +96 -95
  42. package/services/comment-thread-parts.js +280 -0
  43. package/services/document-inspection.js +366 -365
  44. package/services/document-operation-applier.js +230 -202
  45. package/services/document-operation-contract.js +17 -2
  46. package/services/error-recovery.js +6 -0
  47. package/services/headers-footers.js +206 -0
  48. package/services/operation-batch-compiler.js +1 -0
  49. package/services/operation-preflight.js +231 -218
  50. package/services/package-parts.js +80 -0
  51. package/services/revision-token.js +11 -7
  52. package/services/standalone-docx-plumbing.js +631 -569
  53. package/services/standalone-operation-runner.d.ts +19 -3
@@ -78,8 +78,11 @@ node emit-operations.mjs | docx-redline apply input.docx --operations - --profil
78
78
  ```
79
79
 
80
80
  Use `JSON.stringify` or a structured tool API. Never demonstrate `echo`, a
81
- heredoc, or shell-interpolated document text. A Node byte-oriented wrapper should
82
- call `openDocx` and return the structured result instead of recreating CLI
81
+ heredoc, or shell-interpolated document text. In JavaScript/TypeScript runtimes
82
+ (Node.js, browsers, Cloudflare Workers, Deno, Bun, or sandboxed environments like
83
+ n8n), an in-process wrapper should call `openDocx(uint8Array)` directly from
84
+ `@ansonlai/docx-redline-js` (or `@ansonlai/docx-redline-js/bundle` for zero-dependency
85
+ standalone sandboxes) and return the structured result instead of recreating CLI
83
86
  serialization, ZIP handling, targeting, validation, or rollback.
84
87
 
85
88
  ## Ordinary generated workflow
package/docs/TESTING.md CHANGED
@@ -31,7 +31,8 @@ fixtures rarely contain.
31
31
  | Live-session accuracy and instrumentation | `node tests/performance_phase1_session_tests.mjs` | One full parse/serialization, sequential semantic equivalence, exact accepted/rejected text, valid revisions, list/table/comment/highlight preservation, savepoint no-ops, and zero-serialization rollback | Desktop Word rendering |
32
32
  | Target hot-path parity | `node tests/performance_phase3_target_hot_paths_tests.mjs` | Cached and uncached resolution metadata parity, duplicate safety, snapshots, session invalidation, and pointer-based revision-ID seeding | Machine-independent latency thresholds |
33
33
  | List and text-walker parity | `node tests/performance_phase4_list_and_text_parity_tests.mjs` | One shared marker vocabulary and canonical/specialized visible-text agreement across structural characters and revision views | That all specialized mappings are interchangeable |
34
- | Route compatibility | `node tests/performance_phase5_route_consolidation_tests.mjs` | Direct/legacy list accepted-rejected parity, numbering artifacts, route selection, capability records, and stable public exports | Permission to migrate the retained multi-paragraph compatibility route |
34
+ | Universal document facade & ZIP | `node tests/universal_docx_document_tests.mjs`, `node tests/universal_zip_archive_tests.mjs`, `node tests/universal_facade_edge_cases_tests.mjs` | Universal `Uint8Array` binary handling, `fflate` compression/decompression, optimistic concurrency, and complete-DOCX operations without Node built-ins | Desktop Word rendering |
35
+ | Sandbox bundle isolation | `node tests/sandbox_bundle_isolation_tests.mjs` | Zero-dependency standalone ESM/CJS bundles execute in restricted VM sandboxes without `process`, `Buffer`, or `require`, with zero Node built-in imports | Web Worker latency |
35
36
  | Cross-author revision slicing | `node tests/cross_author_slicing_fixtures_tests.mjs`, `node tests/cross_author_carrier_splitting_tests.mjs`, `node tests/cross_author_slicing_synthetic_tests.mjs`, `node tests/cross_author_slicing_real_tests.mjs`, `node tests/cross_author_slicing_hyperlink_roundtrip_tests.mjs`, `node tests/cross_author_slicing_insertion_stress_tests.mjs` | Word-native `<w:ins>` splitting, `<w:del>` nesting, multi-author stacking, straddle boundaries, synthetic matrix (SYN-01..12d), strict package differential replay (PKG-01..06), exact hyperlink/NBSP round trips, and 76 insertion stress scenarios | Non-Word consumers beyond OpenXML XSD validation |
36
37
 
37
38
  The package-facade regression opens a real ZIP buffer, adds a comment beside an
@@ -71,6 +71,22 @@
71
71
  }
72
72
  ]
73
73
  },
74
+ "headerFooterPart": {
75
+ "description": "Targets a header or footer instead of the body. Use a part path from inspect().headersFooters, or a selector. Comments are not supported in headers or footers.",
76
+ "oneOf": [
77
+ { "type": "string", "minLength": 1, "examples": ["word/footer2.xml"] },
78
+ {
79
+ "type": "object",
80
+ "required": ["kind"],
81
+ "properties": {
82
+ "kind": { "enum": ["header", "footer"] },
83
+ "type": { "enum": ["default", "first", "even"], "description": "Defaults to default." },
84
+ "section": { "type": "integer", "minimum": 0, "description": "Zero-based section; required when several sections have their own part." }
85
+ },
86
+ "additionalProperties": false
87
+ }
88
+ ]
89
+ },
74
90
  "base": {
75
91
  "type": "object",
76
92
  "required": ["type", "target"],
@@ -78,6 +94,7 @@
78
94
  "operationId": { "type": "string", "minLength": 1, "maxLength": 256 },
79
95
  "captureKey": { "type": "string", "minLength": 1, "maxLength": 256 },
80
96
  "target": { "$ref": "#/$defs/target" }, "targetRef": { "type": ["integer", "string", "null"] },
97
+ "part": { "$ref": "#/$defs/headerFooterPart" },
81
98
  "author": { "type": "string", "minLength": 1 }, "generateRedlines": { "type": "boolean" },
82
99
  "existingRevisions": { "enum": ["merge-same-author", "slice-cross-author", "reject-input", "accept-all-first", "accept-all-first-keep-normalized"] },
83
100
  "pairReplacements": { "type": "boolean" },
@@ -109,6 +126,18 @@
109
126
  },
110
127
  "additionalProperties": false
111
128
  },
129
+ {
130
+ "type": "object",
131
+ "description": "Resolve or reopen the comment thread containing commentId. Resolved is thread-level in Word, so the root and every reply change together. Body-only; not allowed with part.",
132
+ "required": ["type", "commentId"],
133
+ "properties": {
134
+ "type": { "const": "comment_resolve" },
135
+ "operationId": { "type": "string", "minLength": 1, "maxLength": 256 },
136
+ "commentId": { "type": ["integer", "string"] },
137
+ "resolved": { "type": "boolean", "default": true }
138
+ },
139
+ "additionalProperties": false
140
+ },
112
141
  {
113
142
  "allOf": [ { "$ref": "#/$defs/base" }, { "type": "object", "required": ["replacements"], "properties": { "type": { "enum": ["redline", "replace"] }, "replacements": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/localizedReplacement" } } } } ]
114
143
  },
@@ -0,0 +1,39 @@
1
+ import type { DocumentOperation, DocumentOperationBatchResult, OperationPreflightResult, StandaloneRunnerOptions } from '../services/standalone-operation-runner.js';
2
+ import type { DocumentInspectionOptions, DocumentInspectionResult, RevisionToken } from '../index.js';
3
+
4
+ export interface DocxApplyOptions extends StandaloneRunnerOptions {
5
+ author?: string;
6
+ validate?: boolean;
7
+ }
8
+
9
+ export interface DocxApplyResult extends DocumentOperationBatchResult {
10
+ written: boolean;
11
+ uint8Array: Uint8Array;
12
+ buffer: Uint8Array;
13
+ inspection?: DocumentInspectionResult;
14
+ artifactsChanged?: string[];
15
+ validation?: { originalIssues: unknown[]; generatedIssues: unknown[] };
16
+ issues?: unknown[];
17
+ toUint8Array(): Uint8Array;
18
+ toBuffer(): Uint8Array;
19
+ }
20
+
21
+ export class DocxDocument {
22
+ constructor(input: Uint8Array | ArrayBuffer | string);
23
+ readonly originalBytes: Uint8Array;
24
+ readonly originalBuffer: Uint8Array;
25
+ readonly entries: Map<string, Uint8Array>;
26
+ inspect(options?: DocumentInspectionOptions): DocumentInspectionResult;
27
+ getRevisionToken(): RevisionToken;
28
+ readonly revisionToken: RevisionToken;
29
+ preflight(operations: DocumentOperation[], author?: string, options?: StandaloneRunnerOptions): OperationPreflightResult;
30
+ applyOperations(operations: DocumentOperation[], options?: DocxApplyOptions): Promise<DocxApplyResult>;
31
+ resolveRevisions(action: 'accept' | 'reject', options?: { author?: string; allAuthors?: boolean; validate?: boolean }): Promise<DocxApplyResult>;
32
+ deleteComments(options?: { author?: string; allAuthors?: boolean; validate?: boolean }): Promise<DocxApplyResult>;
33
+ toUint8Array(): Uint8Array;
34
+ toBuffer(): Uint8Array;
35
+ }
36
+
37
+ export function computePackageRevisionToken(input: unknown): RevisionToken;
38
+
39
+ export function openDocx(input: Uint8Array | ArrayBuffer | string): DocxDocument;