@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.
- package/AGENTS.md +15 -10
- package/ARCHITECTURE.md +30 -10
- package/CHANGELOG.md +539 -431
- package/README.md +331 -309
- package/adapters/xml-adapter.js +84 -56
- package/core/sha256.js +120 -0
- package/dist/docx-redline-js.esm.js +8982 -693
- package/dist/docx-redline-js.esm.js.map +4 -4
- package/dist/docx-redline-js.esm.min.js +102 -89
- package/dist/docx-redline-js.esm.min.js.map +4 -4
- package/dist/docx-redline.bundle.cjs +28305 -0
- package/dist/docx-redline.bundle.cjs.map +7 -0
- package/dist/docx-redline.bundle.js +28296 -0
- package/dist/docx-redline.bundle.js.map +7 -0
- package/docs/AGENT_FAST_START.md +2 -1
- package/docs/AGENT_KNOWLEDGE_BASE.md +480 -393
- package/docs/SKILL_AUTHORING.md +5 -2
- package/docs/TESTING.md +2 -1
- package/docs/schemas/document-operations.schema.json +29 -0
- package/document/docx-document.d.ts +39 -0
- package/document/docx-document.js +1010 -0
- package/document/zip-archive.js +258 -0
- package/engine/reconstruction-writer.js +18 -0
- package/index.d.ts +598 -531
- package/index.js +349 -340
- package/node/cli-help.js +5 -5
- package/node/cli.js +760 -754
- package/node/docx-document.js +11 -355
- package/node/index.d.ts +1 -1
- package/node/zip-archive.js +28 -38
- package/package.json +14 -11
- package/scripts/build.mjs +40 -5
- package/scripts/generate-word-comment-edge-case-fixture.ps1 +58 -0
- package/scripts/generate-word-comment-thread-fixture.ps1 +36 -0
- package/scripts/generate-word-header-footer-fixture.ps1 +32 -0
- package/scripts/generate-word-multi-section-fixture.ps1 +27 -0
- package/scripts/generate-word-package-integrity-cases.mjs +141 -0
- package/scripts/generate-word-thread-state-fixtures.ps1 +50 -0
- package/scripts/word-com-package-integrity.ps1 +98 -0
- package/services/batch-operation-orchestrator.js +262 -259
- package/services/comment-replies.js +96 -95
- package/services/comment-thread-parts.js +280 -0
- package/services/document-inspection.js +366 -365
- package/services/document-operation-applier.js +230 -202
- package/services/document-operation-contract.js +17 -2
- package/services/error-recovery.js +6 -0
- package/services/headers-footers.js +206 -0
- package/services/operation-batch-compiler.js +1 -0
- package/services/operation-preflight.js +231 -218
- package/services/package-parts.js +80 -0
- package/services/revision-token.js +11 -7
- package/services/standalone-docx-plumbing.js +631 -569
- package/services/standalone-operation-runner.d.ts +19 -3
package/adapters/xml-adapter.js
CHANGED
|
@@ -1,64 +1,92 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* XML adapter for parser/serializer portability.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
1
|
+
/**
|
|
2
|
+
* XML adapter for parser/serializer portability.
|
|
3
|
+
*
|
|
4
|
+
* Transparently uses browser-provided DOMParser/XMLSerializer when available in
|
|
5
|
+
* standard web runtimes, automatically falling back to pure-JS @xmldom/xmldom in
|
|
6
|
+
* Node.js and sandbox environments. Consumers can also explicitly override these
|
|
7
|
+
* constructors via configureXmlProvider.
|
|
6
8
|
*/
|
|
7
9
|
|
|
10
|
+
import { DOMParser as XmlDomParser, XMLSerializer as XmlDomSerializer } from '@xmldom/xmldom';
|
|
8
11
|
import { warn as logWarning, error as logError } from './logger.js';
|
|
9
12
|
|
|
10
|
-
let _DOMParser =
|
|
11
|
-
let _XMLSerializer =
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Configures XML provider constructors.
|
|
15
|
-
*
|
|
16
|
-
* @param {Object} [options={}] - Provider overrides
|
|
17
|
-
* @param {typeof DOMParser} [options.DOMParser] - DOMParser constructor
|
|
18
|
-
* @param {typeof XMLSerializer} [options.XMLSerializer] - XMLSerializer constructor
|
|
19
|
-
*/
|
|
20
|
-
export function configureXmlProvider(options = {}) {
|
|
21
|
-
if (options
|
|
22
|
-
if (options
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
|
|
13
|
+
let _DOMParser = null;
|
|
14
|
+
let _XMLSerializer = null;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Configures XML provider constructors.
|
|
18
|
+
*
|
|
19
|
+
* @param {Object} [options={}] - Provider overrides
|
|
20
|
+
* @param {typeof DOMParser} [options.DOMParser] - DOMParser constructor
|
|
21
|
+
* @param {typeof XMLSerializer} [options.XMLSerializer] - XMLSerializer constructor
|
|
22
|
+
*/
|
|
23
|
+
export function configureXmlProvider(options = {}) {
|
|
24
|
+
if ('DOMParser' in options) _DOMParser = options.DOMParser;
|
|
25
|
+
if ('XMLSerializer' in options) _XMLSerializer = options.XMLSerializer;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Resolves the active DOMParser constructor.
|
|
30
|
+
*
|
|
31
|
+
* Priority order:
|
|
32
|
+
* 1. Explicitly configured constructor (via configureXmlProvider)
|
|
33
|
+
* 2. Host environment native DOMParser (globalThis.DOMParser)
|
|
34
|
+
* 3. Pure-JS @xmldom/xmldom fallback
|
|
35
|
+
*
|
|
36
|
+
* @returns {typeof DOMParser}
|
|
37
|
+
*/
|
|
38
|
+
export function resolveDomParserConstructor() {
|
|
39
|
+
return _DOMParser || globalThis.DOMParser || XmlDomParser;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Resolves the active XMLSerializer constructor.
|
|
44
|
+
*
|
|
45
|
+
* Priority order:
|
|
46
|
+
* 1. Explicitly configured constructor (via configureXmlProvider)
|
|
47
|
+
* 2. Host environment native XMLSerializer (globalThis.XMLSerializer)
|
|
48
|
+
* 3. Pure-JS @xmldom/xmldom fallback
|
|
49
|
+
*
|
|
50
|
+
* @returns {typeof XMLSerializer}
|
|
51
|
+
*/
|
|
52
|
+
export function resolveXmlSerializerConstructor() {
|
|
53
|
+
return _XMLSerializer || globalThis.XMLSerializer || XmlDomSerializer;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Creates a parser instance.
|
|
58
|
+
*
|
|
59
|
+
* @param {Object} [options={}] - Parser options (e.g. { onError } for xmldom)
|
|
60
|
+
* @returns {DOMParser}
|
|
61
|
+
*/
|
|
30
62
|
export function createParser(options = {}) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*
|
|
57
|
-
|
|
58
|
-
* @param {string} xmlString - XML string
|
|
59
|
-
* @param {string} [contentType='text/xml'] - MIME type
|
|
60
|
-
* @returns {Document}
|
|
61
|
-
*/
|
|
63
|
+
const ParserCtor = resolveDomParserConstructor();
|
|
64
|
+
if (!ParserCtor) {
|
|
65
|
+
throw new Error('DOMParser is not configured and no fallback XML parser is available.');
|
|
66
|
+
}
|
|
67
|
+
return new ParserCtor(options);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Creates a serializer instance.
|
|
72
|
+
*
|
|
73
|
+
* @returns {XMLSerializer}
|
|
74
|
+
*/
|
|
75
|
+
export function createSerializer() {
|
|
76
|
+
const SerializerCtor = resolveXmlSerializerConstructor();
|
|
77
|
+
if (!SerializerCtor) {
|
|
78
|
+
throw new Error('XMLSerializer is not configured and no fallback XML serializer is available.');
|
|
79
|
+
}
|
|
80
|
+
return new SerializerCtor();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Parses XML text into a DOM document.
|
|
85
|
+
*
|
|
86
|
+
* @param {string} xmlString - XML string
|
|
87
|
+
* @param {string} [contentType='text/xml'] - MIME type
|
|
88
|
+
* @returns {Document}
|
|
89
|
+
*/
|
|
62
90
|
export function parseXml(xmlString, contentType = 'text/xml') {
|
|
63
91
|
const result = parseOoxmlSafe(xmlString, contentType);
|
|
64
92
|
if (result.error) {
|
package/core/sha256.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure-JS synchronous SHA-256 (FIPS 180-4) implementation.
|
|
3
|
+
*
|
|
4
|
+
* Self-contained, deterministic, and free from Node.js or browser crypto built-ins.
|
|
5
|
+
* Accepts string, Uint8Array, Buffer, or ArrayBuffer and returns a 64-character hex string.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const K = new Uint32Array([
|
|
9
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
10
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
11
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
12
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
13
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
14
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
15
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
16
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
const textEncoder = new TextEncoder();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Computes the SHA-256 digest of binary or text data.
|
|
23
|
+
*
|
|
24
|
+
* @param {Uint8Array|ArrayBuffer|ArrayBufferView|string} input - Input data to hash
|
|
25
|
+
* @returns {string} 64-character lowercase hex string
|
|
26
|
+
*/
|
|
27
|
+
export function sha256(input) {
|
|
28
|
+
let bytes;
|
|
29
|
+
if (typeof input === 'string') {
|
|
30
|
+
bytes = textEncoder.encode(input);
|
|
31
|
+
} else if (input instanceof Uint8Array) {
|
|
32
|
+
bytes = input;
|
|
33
|
+
} else if (input instanceof ArrayBuffer) {
|
|
34
|
+
bytes = new Uint8Array(input);
|
|
35
|
+
} else if (ArrayBuffer.isView(input)) {
|
|
36
|
+
bytes = new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
37
|
+
} else {
|
|
38
|
+
throw new TypeError('sha256 input must be a string, Uint8Array, Buffer, or ArrayBuffer.');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const byteLen = bytes.length;
|
|
42
|
+
const bitLen = byteLen * 8;
|
|
43
|
+
|
|
44
|
+
// Pad length: input + 1 (0x80) + zeros + 8 bytes (64-bit length) to multiple of 64 bytes
|
|
45
|
+
const paddedLen = Math.ceil((byteLen + 9) / 64) * 64;
|
|
46
|
+
const padded = new Uint8Array(paddedLen);
|
|
47
|
+
padded.set(bytes, 0);
|
|
48
|
+
padded[byteLen] = 0x80;
|
|
49
|
+
|
|
50
|
+
const dataView = new DataView(padded.buffer, padded.byteOffset, padded.byteLength);
|
|
51
|
+
// Write 64-bit big-endian length in bits
|
|
52
|
+
const highBits = Math.floor(bitLen / 0x100000000);
|
|
53
|
+
const lowBits = (bitLen >>> 0);
|
|
54
|
+
dataView.setUint32(paddedLen - 8, highBits, false);
|
|
55
|
+
dataView.setUint32(paddedLen - 4, lowBits, false);
|
|
56
|
+
|
|
57
|
+
// Initial hash values
|
|
58
|
+
let h0 = 0x6a09e667;
|
|
59
|
+
let h1 = 0xbb67ae85;
|
|
60
|
+
let h2 = 0x3c6ef372;
|
|
61
|
+
let h3 = 0xa54ff53a;
|
|
62
|
+
let h4 = 0x510e527f;
|
|
63
|
+
let h5 = 0x9b05688c;
|
|
64
|
+
let h6 = 0x1f83d9ab;
|
|
65
|
+
let h7 = 0x5be0cd19;
|
|
66
|
+
|
|
67
|
+
const W = new Uint32Array(64);
|
|
68
|
+
|
|
69
|
+
for (let offset = 0; offset < paddedLen; offset += 64) {
|
|
70
|
+
for (let t = 0; t < 16; t++) {
|
|
71
|
+
W[t] = dataView.getUint32(offset + t * 4, false);
|
|
72
|
+
}
|
|
73
|
+
for (let t = 16; t < 64; t++) {
|
|
74
|
+
const w15 = W[t - 15];
|
|
75
|
+
const s0 = ((w15 >>> 7) | (w15 << 25)) ^ ((w15 >>> 18) | (w15 << 14)) ^ (w15 >>> 3);
|
|
76
|
+
const w2 = W[t - 2];
|
|
77
|
+
const s1 = ((w2 >>> 17) | (w2 << 15)) ^ ((w2 >>> 19) | (w2 << 13)) ^ (w2 >>> 10);
|
|
78
|
+
W[t] = (W[t - 16] + s0 + W[t - 7] + s1) | 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let a = h0;
|
|
82
|
+
let b = h1;
|
|
83
|
+
let c = h2;
|
|
84
|
+
let d = h3;
|
|
85
|
+
let e = h4;
|
|
86
|
+
let f = h5;
|
|
87
|
+
let g = h6;
|
|
88
|
+
let h = h7;
|
|
89
|
+
|
|
90
|
+
for (let t = 0; t < 64; t++) {
|
|
91
|
+
const S1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));
|
|
92
|
+
const ch = (e & f) ^ (~e & g);
|
|
93
|
+
const temp1 = (h + S1 + ch + K[t] + W[t]) | 0;
|
|
94
|
+
const S0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));
|
|
95
|
+
const maj = (a & b) ^ (a & c) ^ (b & c);
|
|
96
|
+
const temp2 = (S0 + maj) | 0;
|
|
97
|
+
|
|
98
|
+
h = g;
|
|
99
|
+
g = f;
|
|
100
|
+
f = e;
|
|
101
|
+
e = (d + temp1) | 0;
|
|
102
|
+
d = c;
|
|
103
|
+
c = b;
|
|
104
|
+
b = a;
|
|
105
|
+
a = (temp1 + temp2) | 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
h0 = (h0 + a) | 0;
|
|
109
|
+
h1 = (h1 + b) | 0;
|
|
110
|
+
h2 = (h2 + c) | 0;
|
|
111
|
+
h3 = (h3 + d) | 0;
|
|
112
|
+
h4 = (h4 + e) | 0;
|
|
113
|
+
h5 = (h5 + f) | 0;
|
|
114
|
+
h6 = (h6 + g) | 0;
|
|
115
|
+
h7 = (h7 + h) | 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const hex = n => (n >>> 0).toString(16).padStart(8, '0');
|
|
119
|
+
return hex(h0) + hex(h1) + hex(h2) + hex(h3) + hex(h4) + hex(h5) + hex(h6) + hex(h7);
|
|
120
|
+
}
|