wpd-codec 3.2.2 → 3.4.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 (44) hide show
  1. package/README.md +8 -3
  2. package/dist/bytes/base64.cjs +21 -0
  3. package/dist/bytes/base64.d.cts +4 -0
  4. package/dist/bytes/base64.d.ts +4 -0
  5. package/dist/bytes/base64.js +20 -0
  6. package/dist/container/container.cjs +6 -3
  7. package/dist/container/container.d.cts +2 -2
  8. package/dist/container/container.d.ts +2 -2
  9. package/dist/container/container.js +6 -3
  10. package/dist/container/encryption.cjs +59 -0
  11. package/dist/container/encryption.d.cts +9 -0
  12. package/dist/container/encryption.d.ts +9 -0
  13. package/dist/container/encryption.js +54 -0
  14. package/dist/container/header.cjs +5 -3
  15. package/dist/container/header.d.cts +6 -2
  16. package/dist/container/header.d.ts +6 -2
  17. package/dist/container/header.js +5 -3
  18. package/dist/{diagnostics-Dtb2uPw4.d.cts → diagnostics-DhO7mgqJ.d.cts} +1 -0
  19. package/dist/{diagnostics-Dtb2uPw4.d.ts → diagnostics-DhO7mgqJ.d.ts} +1 -0
  20. package/dist/diagnostics.cjs +1 -0
  21. package/dist/diagnostics.d.cts +1 -1
  22. package/dist/diagnostics.d.ts +1 -1
  23. package/dist/diagnostics.js +1 -0
  24. package/dist/errors.cjs +11 -0
  25. package/dist/errors.d.cts +6 -1
  26. package/dist/errors.d.ts +6 -1
  27. package/dist/errors.js +11 -1
  28. package/dist/index.cjs +1 -0
  29. package/dist/index.d.cts +3 -3
  30. package/dist/index.d.ts +3 -3
  31. package/dist/index.js +2 -2
  32. package/dist/read.cjs +177 -7
  33. package/dist/read.d.cts +9 -3
  34. package/dist/read.d.ts +9 -3
  35. package/dist/read.js +177 -7
  36. package/dist/stream/furniture.cjs +33 -0
  37. package/dist/stream/furniture.d.cts +15 -0
  38. package/dist/stream/furniture.d.ts +15 -0
  39. package/dist/stream/furniture.js +25 -0
  40. package/dist/stream/image.cjs +72 -0
  41. package/dist/stream/image.d.cts +8 -0
  42. package/dist/stream/image.d.ts +8 -0
  43. package/dist/stream/image.js +71 -0
  44. package/package.json +3 -3
package/README.md CHANGED
@@ -71,7 +71,7 @@ readWpdContent(bytes, {
71
71
  });
72
72
  ```
73
73
 
74
- Structural nonconformance is not a diagnostic — it throws. `WpdNotAWordPerfectFileError`, `WpdEncryptedDocumentError`, `WpdUnsupportedVersionError`, and the general `WpdFormatError` are all exported, and all extend the last.
74
+ Structural nonconformance is not a diagnostic — it throws. `WpdNotAWordPerfectFileError`, `WpdEncryptedDocumentError`, `WpdWrongPasswordError`, `WpdUnsupportedVersionError`, and the general `WpdFormatError` are all exported, and all extend the last.
75
75
 
76
76
  ## What it provides
77
77
 
@@ -174,12 +174,17 @@ This is a bet against libwpd's _code_, not against citing its _data_: the charac
174
174
 
175
175
  Everything below is recognised by the tokeniser and skipped by the fold, so a document containing it still reads — losing that construct's own structure, never the surrounding text. Each is reported through the diagnostic sink rather than passed over in silence.
176
176
 
177
- - **Headers, footers, footnotes, and endnotes** (the 0xD6 and 0xD7 groups). Reported through `wpd/header-footer-dropped` and `wpd/note-dropped`. The text is genuinely recoverable each function names a General WP Text packet (type 0x08) holding its own function-code stream, which this package's tokeniser and fold would read (the same packet type boxes now resolve their own text content through) but the flat `ContentDocument` has no page-furniture position for a header or footer and no note position for a footnote body. That body's real home is `document-schema.js`'s tree-only `definitions` table, which a codec producing the flat form cannot reach; it is the same gap `rtf-codec` documents for its own equivalent constructs, and it closes at the schema boundary rather than here the one gap in this list that stays blocked pending a DocumentTree-producing wpd-codec, distinct from every other entry, which is a parsing-effort gap rather than a schema-shape one.
177
+ - **A box whose content is a presentation, video, macro, sound, or external payload**, and a box relying on its own template's inherited geometry rather than an explicit function-level position/size override. Reported through `wpd/box-content-unresolved` and `wpd/box-frame-unresolved` respectively. An image box IS lifted when its content packet carries a whole PNG or JPEG payload: the packet's raw bytes are scanned by signature and structural walk (`src/stream/image.ts` the chunk chain to IEND for PNG, the marker segments to EOI for JPEG), never by guessing at a container header, and the span lifts as a `ContentImageBlock` sized by the box's own frame, with an absolute-from-page-edge position carried as the image's `floatPosition`. What stays unresolved: a WPG vector graphic (a distinct binary graphics format `ContentImageBlock`'s `png`/`jpeg`/`svg`/`gif` set cannot hold as recovered, and which this package does not decode a project on the scale of this package's own WordPerfect reader, not a wiring job) and a native OLE object (see the next bullet). A box with no function-level content override at all relying entirely on its template's own rendering defaults is reported through `wpd/box-dropped`, unchanged from before.
178
+ - **Watermarks** (the 0xD6 group's two watermark subfunctions). Reported through `wpd/header-footer-dropped`: a watermark is neither a header nor a footer and owns no parity, so the shared page-furniture vocabulary has no slot for one.
179
+ - **A second header or footer claiming a slot a first already filled.** WordPerfect's own A/B two-slot-per-kind mechanism is a shape the shared one-flow-per-slot vocabulary does not carry; the first function to claim a slot is the one lifted, and the collision is reported through `wpd/header-footer-dropped`.
180
+
181
+ Headers and footers themselves are LIFTED (ExaDev/documents.js#1128): a D6 function's occurrence bits narrow onto the shared furniture vocabulary's slots (`ContentSection.headers`/`footers`, `default`/`even` — odd-only and both-parities are the default slot, even-only the even slot), its body folded from the General WP Text packet its first prefix ID names. Footnotes and endnotes are anchored in the flat form (a footnote/endnote anchor construct around the reference site, `definition` naming `note-1`, `note-2`, ... in document order) and their bodies are carried by `readWpd` as definitions-table entries in the tree form — the flat `readWpdContent` reports each still-borne body through `wpd/note-dropped`, since the flat `ContentDocument` genuinely has no home for one (`rtf-codec` documents the same split for its own equivalent constructs).
182
+
178
183
  - **A box whose content is an image, presentation, video, macro, sound, or external payload**, and a box relying on its own template's inherited geometry rather than an explicit function-level position/size override. Reported through `wpd/box-content-unresolved` and `wpd/box-frame-unresolved` respectively. An image box's own content resolves to a Graphics Filename prefix packet (type 0x40) whose children carry either WPG vector graphics (a distinct binary graphics format `ContentImageBlock`'s `png`/`jpeg`/`svg`/`gif` set cannot hold as recovered, and which this package does not decode — a project on the scale of this package's own WordPerfect reader, not a wiring job) or a native OLE object (see the next bullet). A box with no function-level content override at all — relying entirely on its template's own rendering defaults — is reported through `wpd/box-dropped`, unchanged from before.
179
184
  - **Embedded OLE objects**, stored under the compound file's `PerfectOffice_OBJECTS` storage and named by an image box's Graphics Filename packet's own `0x70`/`0x71` (OLE Object Descriptor / OLE Object Data) children. `archive-codec`'s compound-file reader already reaches that storage, which is how `ooxml.js` recovers a ZIP-payload embedded object — but a WordPerfect OLE object's payload is a native OLE server's own stream rather than a nested document package (`ooxml.js`'s own equivalent case, a classic OLE1 `.bin` payload with no `Package` stream, stays opaque by the identical scope boundary), so recovering one generically is a project in its own right, not a wiring job.
180
185
  - **The counter groups** (0xD8, 0xD9, 0xDB, 0xDC): setting, numbering-method, increment and decrement carry no text and change no structure this reader models, so only the Display Number group's own paragraph-number pair is read.
181
186
  - **Every merge subfunction other than FIELD** (ASSIGN, CALL, IF, FOR, CASE, and the rest of WordPerfect's own merge scripting language) and **cross-references** (0xD5). A cross-reference's displayed text survives as ordinary text; its target binding does not. Reported through `wpd/merge-code-dropped` and `wpd/cross-reference-flattened`. Unlike FIELD, these can legitimately wrap whole paragraphs of body text as control flow, which the run-scoped field construct's own one-paragraph extent cannot express regardless — a schema gap for a scripting language's control flow, not a parsing gap.
182
- - **Encrypted documents**, which throw: the specification states that nothing beyond the file header is intelligible without the password, so there is no partial read to offer.
187
+ - **WordPerfect 9-and-later "enhanced encryption"**, which throws: a different, unpublished cipher whose header word is not the standard mode's password checksum, so a `password` read option either verifies against that checksum and decrypts the standard ("original") mode or throws `WpdWrongPasswordError` naming both possible readings of the mismatch. The standard mode itself is decrypted for real (see `src/container/encryption.ts` for the cipher's two independent sources, and for the honest limit that no open-source reference implementation of the 6.x wiring exists to cross-check against a WordPerfect-produced encrypted file).
183
188
 
184
189
  ## Evidence
185
190
 
@@ -0,0 +1,21 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_bytes_view = require("./view.cjs");
3
+ //#region src/bytes/base64.ts
4
+ const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5
+ function bytesToBase64(bytes) {
6
+ let out = "";
7
+ for (let i = 0; i < bytes.length; i += 3) {
8
+ const b0 = require_bytes_view.byteAt(bytes, i);
9
+ const b1 = bytes[i + 1];
10
+ const b2 = bytes[i + 2];
11
+ out += ALPHABET.charAt(b0 >>> 2);
12
+ out += ALPHABET.charAt((b0 & 3) << 4 | (b1 ?? 0) >>> 4);
13
+ if (b1 === void 0) return out + "==";
14
+ out += ALPHABET.charAt((b1 & 15) << 2 | (b2 ?? 0) >>> 6);
15
+ if (b2 === void 0) return out + "=";
16
+ out += ALPHABET.charAt(b2 & 63);
17
+ }
18
+ return out;
19
+ }
20
+ //#endregion
21
+ exports.bytesToBase64 = bytesToBase64;
@@ -0,0 +1,4 @@
1
+ //#region src/bytes/base64.d.ts
2
+ declare function bytesToBase64(bytes: Uint8Array): string;
3
+ //#endregion
4
+ export { bytesToBase64 };
@@ -0,0 +1,4 @@
1
+ //#region src/bytes/base64.d.ts
2
+ declare function bytesToBase64(bytes: Uint8Array): string;
3
+ //#endregion
4
+ export { bytesToBase64 };
@@ -0,0 +1,20 @@
1
+ import { byteAt } from "./view.js";
2
+ //#region src/bytes/base64.ts
3
+ const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4
+ function bytesToBase64(bytes) {
5
+ let out = "";
6
+ for (let i = 0; i < bytes.length; i += 3) {
7
+ const b0 = byteAt(bytes, i);
8
+ const b1 = bytes[i + 1];
9
+ const b2 = bytes[i + 2];
10
+ out += ALPHABET.charAt(b0 >>> 2);
11
+ out += ALPHABET.charAt((b0 & 3) << 4 | (b1 ?? 0) >>> 4);
12
+ if (b1 === void 0) return out + "==";
13
+ out += ALPHABET.charAt((b1 & 15) << 2 | (b2 ?? 0) >>> 6);
14
+ if (b2 === void 0) return out + "=";
15
+ out += ALPHABET.charAt(b2 & 63);
16
+ }
17
+ return out;
18
+ }
19
+ //#endregion
20
+ export { bytesToBase64 };
@@ -1,6 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_errors = require("../errors.cjs");
3
3
  const require_container_header = require("./header.cjs");
4
+ const require_container_encryption = require("./encryption.cjs");
4
5
  const require_container_prefix = require("./prefix.cjs");
5
6
  let archive_codec = require("archive-codec");
6
7
  //#region src/container/container.ts
@@ -35,9 +36,11 @@ function documentAreaEnd(bytes, header) {
35
36
  if (fileSize > documentAreaOffset && fileSize <= bytes.length) return fileSize;
36
37
  return bytes.length;
37
38
  }
38
- function openWpdDocument(input) {
39
- const { bytes, compound } = unwrapContainer(toArrayBufferBacked(input));
40
- const header = require_container_header.readFileHeader(bytes);
39
+ function openWpdDocument(input, options = {}) {
40
+ const { bytes: wrapped, compound } = unwrapContainer(toArrayBufferBacked(input));
41
+ const header = require_container_header.readFileHeader(wrapped, options);
42
+ const suppliedPassword = options.password === "" ? void 0 : options.password;
43
+ const bytes = header.encryption !== 0 && suppliedPassword !== void 0 ? require_container_encryption.decryptWpdDocument(wrapped, header, suppliedPassword) : wrapped;
41
44
  return {
42
45
  header,
43
46
  packets: require_container_prefix.readPrefixPackets(bytes, header),
@@ -1,4 +1,4 @@
1
- import { WpdFileHeader } from "./header.cjs";
1
+ import { ReadWpdHeaderOptions, WpdFileHeader } from "./header.cjs";
2
2
  import { WpdPrefixPacket } from "./prefix.cjs";
3
3
  //#region src/container/container.d.ts
4
4
  declare const PERFECT_OFFICE_MAIN_STREAM = "PerfectOffice_MAIN";
@@ -11,6 +11,6 @@ interface WpdDocumentContainer {
11
11
  readonly documentAreaEnd: number;
12
12
  readonly compound: boolean;
13
13
  }
14
- declare function openWpdDocument(input: Uint8Array): WpdDocumentContainer;
14
+ declare function openWpdDocument(input: Uint8Array, options?: ReadWpdHeaderOptions): WpdDocumentContainer;
15
15
  //#endregion
16
16
  export { PERFECT_OFFICE_MAIN_STREAM, PERFECT_OFFICE_OBJECTS_STORAGE, WpdDocumentContainer, openWpdDocument };
@@ -1,4 +1,4 @@
1
- import { WpdFileHeader } from "./header.js";
1
+ import { ReadWpdHeaderOptions, WpdFileHeader } from "./header.js";
2
2
  import { WpdPrefixPacket } from "./prefix.js";
3
3
  //#region src/container/container.d.ts
4
4
  declare const PERFECT_OFFICE_MAIN_STREAM = "PerfectOffice_MAIN";
@@ -11,6 +11,6 @@ interface WpdDocumentContainer {
11
11
  readonly documentAreaEnd: number;
12
12
  readonly compound: boolean;
13
13
  }
14
- declare function openWpdDocument(input: Uint8Array): WpdDocumentContainer;
14
+ declare function openWpdDocument(input: Uint8Array, options?: ReadWpdHeaderOptions): WpdDocumentContainer;
15
15
  //#endregion
16
16
  export { PERFECT_OFFICE_MAIN_STREAM, PERFECT_OFFICE_OBJECTS_STORAGE, WpdDocumentContainer, openWpdDocument };
@@ -1,5 +1,6 @@
1
1
  import { WpdNotAWordPerfectFileError } from "../errors.js";
2
2
  import { hasWordPerfectFileId, readFileHeader } from "./header.js";
3
+ import { decryptWpdDocument } from "./encryption.js";
3
4
  import { readPrefixPackets } from "./prefix.js";
4
5
  import { isCompoundFile, readCompoundFile } from "archive-codec";
5
6
  //#region src/container/container.ts
@@ -34,9 +35,11 @@ function documentAreaEnd(bytes, header) {
34
35
  if (fileSize > documentAreaOffset && fileSize <= bytes.length) return fileSize;
35
36
  return bytes.length;
36
37
  }
37
- function openWpdDocument(input) {
38
- const { bytes, compound } = unwrapContainer(toArrayBufferBacked(input));
39
- const header = readFileHeader(bytes);
38
+ function openWpdDocument(input, options = {}) {
39
+ const { bytes: wrapped, compound } = unwrapContainer(toArrayBufferBacked(input));
40
+ const header = readFileHeader(wrapped, options);
41
+ const suppliedPassword = options.password === "" ? void 0 : options.password;
42
+ const bytes = header.encryption !== 0 && suppliedPassword !== void 0 ? decryptWpdDocument(wrapped, header, suppliedPassword) : wrapped;
40
43
  return {
41
44
  header,
42
45
  packets: readPrefixPackets(bytes, header),
@@ -0,0 +1,59 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_errors = require("../errors.cjs");
3
+ const require_bytes_view = require("../bytes/view.cjs");
4
+ require("./header.cjs");
5
+ //#region src/container/encryption.ts
6
+ function normaliseWpdPassword(password) {
7
+ const normalised = [];
8
+ for (let i = 0; i < password.length; i++) {
9
+ const unit = password.charCodeAt(i);
10
+ if (unit > 255) throw new require_errors.WpdFormatError(`A password with characters outside Latin-1 cannot be encoded into the byte-keyed WordPerfect cipher (code unit U+${unit.toString(16).toUpperCase().padStart(4, "0")} at position ${i}).`);
11
+ normalised.push(unit >= 97 && unit <= 122 ? unit - 97 + 65 : unit);
12
+ }
13
+ return normalised;
14
+ }
15
+ function wpdPasswordChecksum16(normalised) {
16
+ let checksum = 0;
17
+ for (const unit of normalised) {
18
+ checksum = (checksum >>> 1 | checksum << 15) ^ unit << 8;
19
+ checksum &= 65535;
20
+ }
21
+ return checksum;
22
+ }
23
+ function applyWpdStandardEncryption(bytes, normalised, startOffset) {
24
+ if (normalised.length === 0) throw new require_errors.WpdFormatError("The WordPerfect cipher is keyed by the password's own bytes, so an empty password decrypts nothing.");
25
+ const maskBase = normalised.length + 1 & 255;
26
+ const output = new Uint8Array(bytes.length);
27
+ output.set(bytes.subarray(0, startOffset));
28
+ for (let pos = startOffset; pos < bytes.length; pos++) {
29
+ const relative = pos - startOffset;
30
+ const passwordByte = normalised[relative % normalised.length];
31
+ if (passwordByte === void 0) throw new require_errors.WpdFormatError("The password normalised to no bytes, which the cipher cannot key with.");
32
+ const mask = maskBase + relative & 255;
33
+ output[pos] = require_bytes_view.byteAt(bytes, pos) ^ passwordByte ^ mask;
34
+ }
35
+ return output;
36
+ }
37
+ function decryptWpdDocument(bytes, header, password) {
38
+ const normalised = normaliseWpdPassword(password);
39
+ if (normalised.length === 0) throw new require_errors.WpdWrongPasswordError(header.encryption, 0);
40
+ const checksum = wpdPasswordChecksum16(normalised);
41
+ if (checksum !== header.encryption) throw new require_errors.WpdWrongPasswordError(header.encryption, checksum);
42
+ return applyWpdStandardEncryption(bytes, normalised, 512);
43
+ }
44
+ function encryptWpdDocumentForTests(bytes, password) {
45
+ const normalised = normaliseWpdPassword(password);
46
+ const checksum = wpdPasswordChecksum16(normalised);
47
+ const encrypted = applyWpdStandardEncryption(bytes, normalised, 512);
48
+ const output = new Uint8Array(encrypted.length);
49
+ output.set(encrypted);
50
+ output[12] = checksum & 255;
51
+ output[13] = checksum >>> 8 & 255;
52
+ return output;
53
+ }
54
+ //#endregion
55
+ exports.applyWpdStandardEncryption = applyWpdStandardEncryption;
56
+ exports.decryptWpdDocument = decryptWpdDocument;
57
+ exports.encryptWpdDocumentForTests = encryptWpdDocumentForTests;
58
+ exports.normaliseWpdPassword = normaliseWpdPassword;
59
+ exports.wpdPasswordChecksum16 = wpdPasswordChecksum16;
@@ -0,0 +1,9 @@
1
+ import { WpdFileHeader } from "./header.cjs";
2
+ //#region src/container/encryption.d.ts
3
+ declare function normaliseWpdPassword(password: string): number[];
4
+ declare function wpdPasswordChecksum16(normalised: readonly number[]): number;
5
+ declare function applyWpdStandardEncryption(bytes: Uint8Array, normalised: readonly number[], startOffset: number): Uint8Array<ArrayBuffer>;
6
+ declare function decryptWpdDocument(bytes: Uint8Array<ArrayBuffer>, header: WpdFileHeader, password: string): Uint8Array<ArrayBuffer>;
7
+ declare function encryptWpdDocumentForTests(bytes: Uint8Array, password: string): Uint8Array<ArrayBuffer>;
8
+ //#endregion
9
+ export { applyWpdStandardEncryption, decryptWpdDocument, encryptWpdDocumentForTests, normaliseWpdPassword, wpdPasswordChecksum16 };
@@ -0,0 +1,9 @@
1
+ import { WpdFileHeader } from "./header.js";
2
+ //#region src/container/encryption.d.ts
3
+ declare function normaliseWpdPassword(password: string): number[];
4
+ declare function wpdPasswordChecksum16(normalised: readonly number[]): number;
5
+ declare function applyWpdStandardEncryption(bytes: Uint8Array, normalised: readonly number[], startOffset: number): Uint8Array<ArrayBuffer>;
6
+ declare function decryptWpdDocument(bytes: Uint8Array<ArrayBuffer>, header: WpdFileHeader, password: string): Uint8Array<ArrayBuffer>;
7
+ declare function encryptWpdDocumentForTests(bytes: Uint8Array, password: string): Uint8Array<ArrayBuffer>;
8
+ //#endregion
9
+ export { applyWpdStandardEncryption, decryptWpdDocument, encryptWpdDocumentForTests, normaliseWpdPassword, wpdPasswordChecksum16 };
@@ -0,0 +1,54 @@
1
+ import { WpdFormatError, WpdWrongPasswordError } from "../errors.js";
2
+ import { byteAt } from "../bytes/view.js";
3
+ import "./header.js";
4
+ //#region src/container/encryption.ts
5
+ function normaliseWpdPassword(password) {
6
+ const normalised = [];
7
+ for (let i = 0; i < password.length; i++) {
8
+ const unit = password.charCodeAt(i);
9
+ if (unit > 255) throw new WpdFormatError(`A password with characters outside Latin-1 cannot be encoded into the byte-keyed WordPerfect cipher (code unit U+${unit.toString(16).toUpperCase().padStart(4, "0")} at position ${i}).`);
10
+ normalised.push(unit >= 97 && unit <= 122 ? unit - 97 + 65 : unit);
11
+ }
12
+ return normalised;
13
+ }
14
+ function wpdPasswordChecksum16(normalised) {
15
+ let checksum = 0;
16
+ for (const unit of normalised) {
17
+ checksum = (checksum >>> 1 | checksum << 15) ^ unit << 8;
18
+ checksum &= 65535;
19
+ }
20
+ return checksum;
21
+ }
22
+ function applyWpdStandardEncryption(bytes, normalised, startOffset) {
23
+ if (normalised.length === 0) throw new WpdFormatError("The WordPerfect cipher is keyed by the password's own bytes, so an empty password decrypts nothing.");
24
+ const maskBase = normalised.length + 1 & 255;
25
+ const output = new Uint8Array(bytes.length);
26
+ output.set(bytes.subarray(0, startOffset));
27
+ for (let pos = startOffset; pos < bytes.length; pos++) {
28
+ const relative = pos - startOffset;
29
+ const passwordByte = normalised[relative % normalised.length];
30
+ if (passwordByte === void 0) throw new WpdFormatError("The password normalised to no bytes, which the cipher cannot key with.");
31
+ const mask = maskBase + relative & 255;
32
+ output[pos] = byteAt(bytes, pos) ^ passwordByte ^ mask;
33
+ }
34
+ return output;
35
+ }
36
+ function decryptWpdDocument(bytes, header, password) {
37
+ const normalised = normaliseWpdPassword(password);
38
+ if (normalised.length === 0) throw new WpdWrongPasswordError(header.encryption, 0);
39
+ const checksum = wpdPasswordChecksum16(normalised);
40
+ if (checksum !== header.encryption) throw new WpdWrongPasswordError(header.encryption, checksum);
41
+ return applyWpdStandardEncryption(bytes, normalised, 512);
42
+ }
43
+ function encryptWpdDocumentForTests(bytes, password) {
44
+ const normalised = normaliseWpdPassword(password);
45
+ const checksum = wpdPasswordChecksum16(normalised);
46
+ const encrypted = applyWpdStandardEncryption(bytes, normalised, 512);
47
+ const output = new Uint8Array(encrypted.length);
48
+ output.set(encrypted);
49
+ output[12] = checksum & 255;
50
+ output[13] = checksum >>> 8 & 255;
51
+ return output;
52
+ }
53
+ //#endregion
54
+ export { applyWpdStandardEncryption, decryptWpdDocument, encryptWpdDocumentForTests, normaliseWpdPassword, wpdPasswordChecksum16 };
@@ -16,7 +16,7 @@ function hasWordPerfectFileId(bytes) {
16
16
  if (bytes.length < WPD_FILE_ID.length) return false;
17
17
  return WPD_FILE_ID.every((expected, index) => bytes[index] === expected);
18
18
  }
19
- function readFileHeader(bytes) {
19
+ function readFileHeader(bytes, options = {}) {
20
20
  if (!hasWordPerfectFileId(bytes)) {
21
21
  const actual = Array.from(require_bytes_view.sliceAt(bytes, 0, Math.min(4, bytes.length))).map((byte) => byte.toString(16).padStart(2, "0")).join(" ");
22
22
  throw new require_errors.WpdNotAWordPerfectFileError(`Expected the WordPerfect file ID FF 57 50 43 (-1,"WPC") at offset 0, found ${actual}.`);
@@ -28,7 +28,8 @@ function readFileHeader(bytes) {
28
28
  const minorVersion = require_bytes_view.byteAt(bytes, 11);
29
29
  const encryption = require_bytes_view.uint16At(bytes, 12);
30
30
  const indexAreaOffset = require_bytes_view.uint16At(bytes, 14);
31
- if (encryption !== 0) throw new require_errors.WpdEncryptedDocumentError(`This document is encrypted (encryption word ${encryption}); nothing beyond the file header is intelligible without the password, which this reader does not support.`);
31
+ const suppliedPassword = options.password === "" ? void 0 : options.password;
32
+ if (encryption !== 0 && suppliedPassword === void 0) throw new require_errors.WpdEncryptedDocumentError(`This document is encrypted (encryption word ${encryption}); nothing beyond the file header is intelligible without the password. Pass { password } to read it -- the standard ("original") encryption mode is supported, and a non-matching password throws WpdWrongPasswordError.`);
32
33
  if (productType !== PRODUCT_TYPE_WORDPERFECT) throw new require_errors.WpdUnsupportedVersionError(`Product type ${productType} is not WordPerfect (${PRODUCT_TYPE_WORDPERFECT}); this file was produced by a different Corel product.`);
33
34
  if (!DOCUMENT_FILE_TYPES.includes(fileType)) throw new require_errors.WpdUnsupportedVersionError(`File type ${fileType} is not a WordPerfect document (expected ${DOCUMENT_FILE_TYPES.join(" or ")}).`);
34
35
  if (majorVersion !== MAJOR_VERSION_WP6_THROUGH_X6) throw new require_errors.WpdUnsupportedVersionError(`Major version ${majorVersion} is outside the WordPerfect 6.x-X6 lineage (major version ${MAJOR_VERSION_WP6_THROUGH_X6}), the one generation this reader covers.`);
@@ -39,7 +40,8 @@ function readFileHeader(bytes) {
39
40
  majorVersion,
40
41
  minorVersion,
41
42
  indexAreaOffset,
42
- fileSize: require_bytes_view.uint32At(bytes, 20)
43
+ fileSize: require_bytes_view.uint32At(bytes, 20),
44
+ encryption
43
45
  };
44
46
  }
45
47
  //#endregion
@@ -1,6 +1,9 @@
1
1
  //#region src/container/header.d.ts
2
2
  declare const WPD_FILE_ID: readonly number[];
3
3
  declare const WPD_PREFIX_HEADER_SIZE = 512;
4
+ interface ReadWpdHeaderOptions {
5
+ readonly password?: string;
6
+ }
4
7
  interface WpdFileHeader {
5
8
  readonly documentAreaOffset: number;
6
9
  readonly productType: number;
@@ -9,8 +12,9 @@ interface WpdFileHeader {
9
12
  readonly minorVersion: number;
10
13
  readonly indexAreaOffset: number;
11
14
  readonly fileSize: number;
15
+ readonly encryption: number;
12
16
  }
13
17
  declare function hasWordPerfectFileId(bytes: Uint8Array): boolean;
14
- declare function readFileHeader(bytes: Uint8Array): WpdFileHeader;
18
+ declare function readFileHeader(bytes: Uint8Array, options?: ReadWpdHeaderOptions): WpdFileHeader;
15
19
  //#endregion
16
- export { WPD_FILE_ID, WPD_PREFIX_HEADER_SIZE, WpdFileHeader, hasWordPerfectFileId, readFileHeader };
20
+ export { ReadWpdHeaderOptions, WPD_FILE_ID, WPD_PREFIX_HEADER_SIZE, WpdFileHeader, hasWordPerfectFileId, readFileHeader };
@@ -1,6 +1,9 @@
1
1
  //#region src/container/header.d.ts
2
2
  declare const WPD_FILE_ID: readonly number[];
3
3
  declare const WPD_PREFIX_HEADER_SIZE = 512;
4
+ interface ReadWpdHeaderOptions {
5
+ readonly password?: string;
6
+ }
4
7
  interface WpdFileHeader {
5
8
  readonly documentAreaOffset: number;
6
9
  readonly productType: number;
@@ -9,8 +12,9 @@ interface WpdFileHeader {
9
12
  readonly minorVersion: number;
10
13
  readonly indexAreaOffset: number;
11
14
  readonly fileSize: number;
15
+ readonly encryption: number;
12
16
  }
13
17
  declare function hasWordPerfectFileId(bytes: Uint8Array): boolean;
14
- declare function readFileHeader(bytes: Uint8Array): WpdFileHeader;
18
+ declare function readFileHeader(bytes: Uint8Array, options?: ReadWpdHeaderOptions): WpdFileHeader;
15
19
  //#endregion
16
- export { WPD_FILE_ID, WPD_PREFIX_HEADER_SIZE, WpdFileHeader, hasWordPerfectFileId, readFileHeader };
20
+ export { ReadWpdHeaderOptions, WPD_FILE_ID, WPD_PREFIX_HEADER_SIZE, WpdFileHeader, hasWordPerfectFileId, readFileHeader };
@@ -15,7 +15,7 @@ function hasWordPerfectFileId(bytes) {
15
15
  if (bytes.length < WPD_FILE_ID.length) return false;
16
16
  return WPD_FILE_ID.every((expected, index) => bytes[index] === expected);
17
17
  }
18
- function readFileHeader(bytes) {
18
+ function readFileHeader(bytes, options = {}) {
19
19
  if (!hasWordPerfectFileId(bytes)) {
20
20
  const actual = Array.from(sliceAt(bytes, 0, Math.min(4, bytes.length))).map((byte) => byte.toString(16).padStart(2, "0")).join(" ");
21
21
  throw new WpdNotAWordPerfectFileError(`Expected the WordPerfect file ID FF 57 50 43 (-1,"WPC") at offset 0, found ${actual}.`);
@@ -27,7 +27,8 @@ function readFileHeader(bytes) {
27
27
  const minorVersion = byteAt(bytes, 11);
28
28
  const encryption = uint16At(bytes, 12);
29
29
  const indexAreaOffset = uint16At(bytes, 14);
30
- if (encryption !== 0) throw new WpdEncryptedDocumentError(`This document is encrypted (encryption word ${encryption}); nothing beyond the file header is intelligible without the password, which this reader does not support.`);
30
+ const suppliedPassword = options.password === "" ? void 0 : options.password;
31
+ if (encryption !== 0 && suppliedPassword === void 0) throw new WpdEncryptedDocumentError(`This document is encrypted (encryption word ${encryption}); nothing beyond the file header is intelligible without the password. Pass { password } to read it -- the standard ("original") encryption mode is supported, and a non-matching password throws WpdWrongPasswordError.`);
31
32
  if (productType !== PRODUCT_TYPE_WORDPERFECT) throw new WpdUnsupportedVersionError(`Product type ${productType} is not WordPerfect (${PRODUCT_TYPE_WORDPERFECT}); this file was produced by a different Corel product.`);
32
33
  if (!DOCUMENT_FILE_TYPES.includes(fileType)) throw new WpdUnsupportedVersionError(`File type ${fileType} is not a WordPerfect document (expected ${DOCUMENT_FILE_TYPES.join(" or ")}).`);
33
34
  if (majorVersion !== MAJOR_VERSION_WP6_THROUGH_X6) throw new WpdUnsupportedVersionError(`Major version ${majorVersion} is outside the WordPerfect 6.x-X6 lineage (major version ${MAJOR_VERSION_WP6_THROUGH_X6}), the one generation this reader covers.`);
@@ -38,7 +39,8 @@ function readFileHeader(bytes) {
38
39
  majorVersion,
39
40
  minorVersion,
40
41
  indexAreaOffset,
41
- fileSize: uint32At(bytes, 20)
42
+ fileSize: uint32At(bytes, 20),
43
+ encryption
42
44
  };
43
45
  }
44
46
  //#endregion
@@ -16,6 +16,7 @@ declare const WpdDiagnosticCodes: {
16
16
  readonly OutlineNumberRegenerated: "wpd/outline-number-regenerated";
17
17
  readonly BoxDropped: "wpd/box-dropped";
18
18
  readonly NoteDropped: "wpd/note-dropped";
19
+ readonly NoteSpansParagraphs: "wpd/note-spans-paragraphs";
19
20
  readonly HeaderFooterDropped: "wpd/header-footer-dropped";
20
21
  readonly CrossReferenceFlattened: "wpd/cross-reference-flattened";
21
22
  readonly MergeCodeDropped: "wpd/merge-code-dropped";
@@ -16,6 +16,7 @@ declare const WpdDiagnosticCodes: {
16
16
  readonly OutlineNumberRegenerated: "wpd/outline-number-regenerated";
17
17
  readonly BoxDropped: "wpd/box-dropped";
18
18
  readonly NoteDropped: "wpd/note-dropped";
19
+ readonly NoteSpansParagraphs: "wpd/note-spans-paragraphs";
19
20
  readonly HeaderFooterDropped: "wpd/header-footer-dropped";
20
21
  readonly CrossReferenceFlattened: "wpd/cross-reference-flattened";
21
22
  readonly MergeCodeDropped: "wpd/merge-code-dropped";
@@ -12,6 +12,7 @@ const WpdDiagnosticCodes = {
12
12
  OutlineNumberRegenerated: "wpd/outline-number-regenerated",
13
13
  BoxDropped: "wpd/box-dropped",
14
14
  NoteDropped: "wpd/note-dropped",
15
+ NoteSpansParagraphs: "wpd/note-spans-paragraphs",
15
16
  HeaderFooterDropped: "wpd/header-footer-dropped",
16
17
  CrossReferenceFlattened: "wpd/cross-reference-flattened",
17
18
  MergeCodeDropped: "wpd/merge-code-dropped",
@@ -1,2 +1,2 @@
1
- import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-Dtb2uPw4.cjs";
1
+ import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-DhO7mgqJ.cjs";
2
2
  export { NOOP_WPD_DIAGNOSTIC_SINK, WpdDiagnostic, WpdDiagnosticCodes, WpdDiagnosticSink };
@@ -1,2 +1,2 @@
1
- import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-Dtb2uPw4.js";
1
+ import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-DhO7mgqJ.js";
2
2
  export { NOOP_WPD_DIAGNOSTIC_SINK, WpdDiagnostic, WpdDiagnosticCodes, WpdDiagnosticSink };
@@ -11,6 +11,7 @@ const WpdDiagnosticCodes = {
11
11
  OutlineNumberRegenerated: "wpd/outline-number-regenerated",
12
12
  BoxDropped: "wpd/box-dropped",
13
13
  NoteDropped: "wpd/note-dropped",
14
+ NoteSpansParagraphs: "wpd/note-spans-paragraphs",
14
15
  HeaderFooterDropped: "wpd/header-footer-dropped",
15
16
  CrossReferenceFlattened: "wpd/cross-reference-flattened",
16
17
  MergeCodeDropped: "wpd/merge-code-dropped",
package/dist/errors.cjs CHANGED
@@ -18,6 +18,16 @@ var WpdEncryptedDocumentError = class extends WpdFormatError {
18
18
  this.name = "WpdEncryptedDocumentError";
19
19
  }
20
20
  };
21
+ var WpdWrongPasswordError = class extends WpdFormatError {
22
+ headerEncryptionWord;
23
+ passwordChecksum;
24
+ constructor(headerEncryptionWord, passwordChecksum) {
25
+ super(`The header's encryption word (0x${headerEncryptionWord.toString(16)}) does not match this password's checksum (0x${passwordChecksum.toString(16)}): either the password is wrong, or the file uses the enhanced encryption mode (WordPerfect 9 and later), which this reader does not support.`);
26
+ this.headerEncryptionWord = headerEncryptionWord;
27
+ this.passwordChecksum = passwordChecksum;
28
+ this.name = "WpdWrongPasswordError";
29
+ }
30
+ };
21
31
  var WpdUnsupportedVersionError = class extends WpdFormatError {
22
32
  constructor(message) {
23
33
  super(message);
@@ -29,3 +39,4 @@ exports.WpdEncryptedDocumentError = WpdEncryptedDocumentError;
29
39
  exports.WpdFormatError = WpdFormatError;
30
40
  exports.WpdNotAWordPerfectFileError = WpdNotAWordPerfectFileError;
31
41
  exports.WpdUnsupportedVersionError = WpdUnsupportedVersionError;
42
+ exports.WpdWrongPasswordError = WpdWrongPasswordError;
package/dist/errors.d.cts CHANGED
@@ -8,8 +8,13 @@ declare class WpdNotAWordPerfectFileError extends WpdFormatError {
8
8
  declare class WpdEncryptedDocumentError extends WpdFormatError {
9
9
  constructor(message: string);
10
10
  }
11
+ declare class WpdWrongPasswordError extends WpdFormatError {
12
+ readonly headerEncryptionWord: number;
13
+ readonly passwordChecksum: number;
14
+ constructor(headerEncryptionWord: number, passwordChecksum: number);
15
+ }
11
16
  declare class WpdUnsupportedVersionError extends WpdFormatError {
12
17
  constructor(message: string);
13
18
  }
14
19
  //#endregion
15
- export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError };
20
+ export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError, WpdWrongPasswordError };
package/dist/errors.d.ts CHANGED
@@ -8,8 +8,13 @@ declare class WpdNotAWordPerfectFileError extends WpdFormatError {
8
8
  declare class WpdEncryptedDocumentError extends WpdFormatError {
9
9
  constructor(message: string);
10
10
  }
11
+ declare class WpdWrongPasswordError extends WpdFormatError {
12
+ readonly headerEncryptionWord: number;
13
+ readonly passwordChecksum: number;
14
+ constructor(headerEncryptionWord: number, passwordChecksum: number);
15
+ }
11
16
  declare class WpdUnsupportedVersionError extends WpdFormatError {
12
17
  constructor(message: string);
13
18
  }
14
19
  //#endregion
15
- export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError };
20
+ export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError, WpdWrongPasswordError };
package/dist/errors.js CHANGED
@@ -17,6 +17,16 @@ var WpdEncryptedDocumentError = class extends WpdFormatError {
17
17
  this.name = "WpdEncryptedDocumentError";
18
18
  }
19
19
  };
20
+ var WpdWrongPasswordError = class extends WpdFormatError {
21
+ headerEncryptionWord;
22
+ passwordChecksum;
23
+ constructor(headerEncryptionWord, passwordChecksum) {
24
+ super(`The header's encryption word (0x${headerEncryptionWord.toString(16)}) does not match this password's checksum (0x${passwordChecksum.toString(16)}): either the password is wrong, or the file uses the enhanced encryption mode (WordPerfect 9 and later), which this reader does not support.`);
25
+ this.headerEncryptionWord = headerEncryptionWord;
26
+ this.passwordChecksum = passwordChecksum;
27
+ this.name = "WpdWrongPasswordError";
28
+ }
29
+ };
20
30
  var WpdUnsupportedVersionError = class extends WpdFormatError {
21
31
  constructor(message) {
22
32
  super(message);
@@ -24,4 +34,4 @@ var WpdUnsupportedVersionError = class extends WpdFormatError {
24
34
  }
25
35
  };
26
36
  //#endregion
27
- export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError };
37
+ export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError, WpdWrongPasswordError };
package/dist/index.cjs CHANGED
@@ -67,6 +67,7 @@ exports.WpdEncryptedDocumentError = require_errors.WpdEncryptedDocumentError;
67
67
  exports.WpdFormatError = require_errors.WpdFormatError;
68
68
  exports.WpdNotAWordPerfectFileError = require_errors.WpdNotAWordPerfectFileError;
69
69
  exports.WpdUnsupportedVersionError = require_errors.WpdUnsupportedVersionError;
70
+ exports.WpdWrongPasswordError = require_errors.WpdWrongPasswordError;
70
71
  exports.decodeAttributeByte = require_stream_attributes.decodeAttributeByte;
71
72
  exports.decodeSingleByteCharacter = require_stream_characters.decodeSingleByteCharacter;
72
73
  exports.decodeWordString = require_stream_characters.decodeWordString;
package/dist/index.d.cts CHANGED
@@ -1,11 +1,11 @@
1
- import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-Dtb2uPw4.cjs";
1
+ import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-DhO7mgqJ.cjs";
2
2
  import { ReadWpdOptions, readWpd, readWpdContent } from "./read.cjs";
3
3
  import { WpdBytesSchema, wpdContentCodec } from "./codec.cjs";
4
4
  import { WPD_FILE_ID, WPD_PREFIX_HEADER_SIZE, WpdFileHeader, hasWordPerfectFileId, readFileHeader } from "./container/header.cjs";
5
5
  import { PACKET_TYPE_DESIRED_FONT_DESCRIPTOR, WPD_INDEX_RECORD_SIZE, WpdPrefixPacket, packetByPrefixId, readPrefixPackets, readTypefaceName } from "./container/prefix.cjs";
6
6
  import { PERFECT_OFFICE_MAIN_STREAM, PERFECT_OFFICE_OBJECTS_STORAGE, WpdDocumentContainer, openWpdDocument } from "./container/container.cjs";
7
7
  import { PACKET_TYPE_EXTENDED_DOCUMENT_SUMMARY, readDocumentSummary } from "./container/summary.cjs";
8
- import { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError } from "./errors.cjs";
8
+ import { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError, WpdWrongPasswordError } from "./errors.cjs";
9
9
  import { WPD_FILE_EXTENSION, WPD_MEDIA_TYPE } from "./format.cjs";
10
10
  import { FIRST_FIXED_FUNCTION, FIRST_SINGLE_BYTE_FUNCTION, FIRST_VARIABLE_FUNCTION, WpdCharacterToken, WpdFixedFunctionToken, WpdSingleByteFunctionToken, WpdToken, WpdVariableFunctionToken, tokeniseDocumentArea } from "./stream/tokenise.cjs";
11
11
  import { EOL_GROUP, FIRST_SINGLE_BYTE_EOL, LAST_SINGLE_BYTE_EOL, WpdEolMapping, eolMappingForSubfunction, isSingleByteEol, subfunctionForSingleByteEol } from "./stream/eol.cjs";
@@ -16,4 +16,4 @@ import { COLUMN_GROUP, COLUMN_LEFT_MARGIN_SET, COLUMN_RIGHT_MARGIN_SET, DEFAULT_
16
16
  import { TAB_GROUP, WpdTabEffect, tabEffectFor } from "./stream/tab.cjs";
17
17
  import { DISPLAY_NUMBER_GROUP, STYLE_GROUP, WpdStyleSemantics, isParagraphNumberDisplayOff, isParagraphNumberDisplayOn, isStyleScopeCloser, isStyleScopeOpener, readDisplayNumberLevel, readSystemStyleNumber, styleSemanticsFor } from "./stream/style.cjs";
18
18
  import { CELL_FILL_COLORS_SUBFUNCTION, CELL_INFORMATION_SUBFUNCTION, CELL_SPANNING_SUBFUNCTION, CHARACTER_DEFINE_TABLE_END, CHARACTER_TABLE_COLUMN, CHARACTER_TABLE_DEFINITION, ROW_INFORMATION_SUBFUNCTION, WpdCellFill, WpdCellInformation, WpdCellSpanning, WpdEmbeddedSubfunction, WpdEmbeddedSubfunctions, WpdRowInformation, findEmbeddedSubfunction, readCellFill, readCellInformation, readCellSpanning, readEmbeddedSubfunctions, readRowInformation, readTableColumnWidthPt } from "./stream/table.cjs";
19
- export { ATTRIBUTE_OFF, ATTRIBUTE_ON, CELL_FILL_COLORS_SUBFUNCTION, CELL_INFORMATION_SUBFUNCTION, CELL_SPANNING_SUBFUNCTION, CHARACTER_DEFINE_TABLE_END, CHARACTER_TABLE_COLUMN, CHARACTER_TABLE_DEFINITION, COLUMN_GROUP, COLUMN_LEFT_MARGIN_SET, COLUMN_RIGHT_MARGIN_SET, DEFAULT_MARGIN_PT, DEFAULT_PAGE_HEIGHT_PT, DEFAULT_PAGE_WIDTH_PT, DISPLAY_NUMBER_GROUP, EOL_GROUP, FIRST_ASCII_CHARACTER, FIRST_FIXED_FUNCTION, FIRST_SINGLE_BYTE_EOL, FIRST_SINGLE_BYTE_FUNCTION, FIRST_VARIABLE_FUNCTION, LAST_CHARACTER, LAST_SINGLE_BYTE_EOL, NOOP_WPD_DIAGNOSTIC_SINK, PACKET_TYPE_DESIRED_FONT_DESCRIPTOR, PACKET_TYPE_EXTENDED_DOCUMENT_SUMMARY, PAGE_BOTTOM_MARGIN_SET, PAGE_FORM, PAGE_GROUP, PAGE_TOP_MARGIN_SET, PERFECT_OFFICE_MAIN_STREAM, PERFECT_OFFICE_OBJECTS_STORAGE, POINTS_PER_INCH, ROW_INFORMATION_SUBFUNCTION, type ReadWpdOptions, STYLE_GROUP, TAB_GROUP, UNMAPPED_CHARACTER, WPD_FILE_EXTENSION, WPD_FILE_ID, WPD_INDEX_RECORD_SIZE, WPD_MEDIA_TYPE, WPD_PREFIX_HEADER_SIZE, WPU_PER_INCH, WpdAttribute, type WpdAttributeCode, WpdBytesSchema, type WpdCellFill, type WpdCellInformation, type WpdCellSpanning, type WpdCharacterToken, type WpdDiagnostic, WpdDiagnosticCodes, type WpdDiagnosticSink, type WpdDocumentContainer, type WpdEmbeddedSubfunction, type WpdEmbeddedSubfunctions, WpdEncryptedDocumentError, type WpdEolMapping, type WpdFileHeader, type WpdFixedFunctionToken, WpdFormatError, WpdNotAWordPerfectFileError, type WpdPageForm, type WpdPrefixPacket, type WpdRowInformation, type WpdRunAttributes, type WpdSingleByteFunctionToken, type WpdStyleSemantics, type WpdTabEffect, type WpdToken, WpdUnsupportedVersionError, type WpdVariableFunctionToken, decodeAttributeByte, decodeSingleByteCharacter, decodeWordString, decodeWpCharacter, eolMappingForSubfunction, findEmbeddedSubfunction, hasWordPerfectFileId, isParagraphNumberDisplayOff, isParagraphNumberDisplayOn, isSingleByteEol, isStyleScopeCloser, isStyleScopeOpener, openWpdDocument, packetByPrefixId, pointsFromWpu, readCellFill, readCellInformation, readCellSpanning, readDisplayNumberLevel, readDocumentSummary, readEmbeddedSubfunctions, readFileHeader, readMarginPt, readPageForm, readPrefixPackets, readRowInformation, readSystemStyleNumber, readTableColumnWidthPt, readTypefaceName, readWpd, readWpdContent, runAttributesFrom, styleSemanticsFor, subfunctionForSingleByteEol, tabEffectFor, tokeniseDocumentArea, wpdContentCodec };
19
+ export { ATTRIBUTE_OFF, ATTRIBUTE_ON, CELL_FILL_COLORS_SUBFUNCTION, CELL_INFORMATION_SUBFUNCTION, CELL_SPANNING_SUBFUNCTION, CHARACTER_DEFINE_TABLE_END, CHARACTER_TABLE_COLUMN, CHARACTER_TABLE_DEFINITION, COLUMN_GROUP, COLUMN_LEFT_MARGIN_SET, COLUMN_RIGHT_MARGIN_SET, DEFAULT_MARGIN_PT, DEFAULT_PAGE_HEIGHT_PT, DEFAULT_PAGE_WIDTH_PT, DISPLAY_NUMBER_GROUP, EOL_GROUP, FIRST_ASCII_CHARACTER, FIRST_FIXED_FUNCTION, FIRST_SINGLE_BYTE_EOL, FIRST_SINGLE_BYTE_FUNCTION, FIRST_VARIABLE_FUNCTION, LAST_CHARACTER, LAST_SINGLE_BYTE_EOL, NOOP_WPD_DIAGNOSTIC_SINK, PACKET_TYPE_DESIRED_FONT_DESCRIPTOR, PACKET_TYPE_EXTENDED_DOCUMENT_SUMMARY, PAGE_BOTTOM_MARGIN_SET, PAGE_FORM, PAGE_GROUP, PAGE_TOP_MARGIN_SET, PERFECT_OFFICE_MAIN_STREAM, PERFECT_OFFICE_OBJECTS_STORAGE, POINTS_PER_INCH, ROW_INFORMATION_SUBFUNCTION, type ReadWpdOptions, STYLE_GROUP, TAB_GROUP, UNMAPPED_CHARACTER, WPD_FILE_EXTENSION, WPD_FILE_ID, WPD_INDEX_RECORD_SIZE, WPD_MEDIA_TYPE, WPD_PREFIX_HEADER_SIZE, WPU_PER_INCH, WpdAttribute, type WpdAttributeCode, WpdBytesSchema, type WpdCellFill, type WpdCellInformation, type WpdCellSpanning, type WpdCharacterToken, type WpdDiagnostic, WpdDiagnosticCodes, type WpdDiagnosticSink, type WpdDocumentContainer, type WpdEmbeddedSubfunction, type WpdEmbeddedSubfunctions, WpdEncryptedDocumentError, type WpdEolMapping, type WpdFileHeader, type WpdFixedFunctionToken, WpdFormatError, WpdNotAWordPerfectFileError, type WpdPageForm, type WpdPrefixPacket, type WpdRowInformation, type WpdRunAttributes, type WpdSingleByteFunctionToken, type WpdStyleSemantics, type WpdTabEffect, type WpdToken, WpdUnsupportedVersionError, type WpdVariableFunctionToken, WpdWrongPasswordError, decodeAttributeByte, decodeSingleByteCharacter, decodeWordString, decodeWpCharacter, eolMappingForSubfunction, findEmbeddedSubfunction, hasWordPerfectFileId, isParagraphNumberDisplayOff, isParagraphNumberDisplayOn, isSingleByteEol, isStyleScopeCloser, isStyleScopeOpener, openWpdDocument, packetByPrefixId, pointsFromWpu, readCellFill, readCellInformation, readCellSpanning, readDisplayNumberLevel, readDocumentSummary, readEmbeddedSubfunctions, readFileHeader, readMarginPt, readPageForm, readPrefixPackets, readRowInformation, readSystemStyleNumber, readTableColumnWidthPt, readTypefaceName, readWpd, readWpdContent, runAttributesFrom, styleSemanticsFor, subfunctionForSingleByteEol, tabEffectFor, tokeniseDocumentArea, wpdContentCodec };