wpd-codec 3.5.1 → 3.5.3

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 (39) hide show
  1. package/dist/container/container.cjs +2 -3
  2. package/dist/container/container.js +2 -3
  3. package/dist/container/encryption.cjs +7 -3
  4. package/dist/container/encryption.d.cts +2 -1
  5. package/dist/container/encryption.d.ts +2 -1
  6. package/dist/container/encryption.js +7 -4
  7. package/dist/container/header.cjs +0 -1
  8. package/dist/container/header.js +0 -1
  9. package/dist/container/prefix.cjs +19 -16
  10. package/dist/container/prefix.js +19 -16
  11. package/dist/container/summary.cjs +10 -4
  12. package/dist/container/summary.js +10 -4
  13. package/dist/read.cjs +10 -17
  14. package/dist/read.d.cts +3 -1
  15. package/dist/read.d.ts +3 -1
  16. package/dist/read.js +9 -18
  17. package/dist/stream/box.cjs +61 -70
  18. package/dist/stream/box.js +61 -70
  19. package/dist/stream/characters.cjs +2 -0
  20. package/dist/stream/characters.d.cts +2 -1
  21. package/dist/stream/characters.d.ts +2 -1
  22. package/dist/stream/characters.js +2 -1
  23. package/dist/stream/formula.cjs +14 -16
  24. package/dist/stream/formula.js +15 -17
  25. package/dist/stream/image.cjs +55 -41
  26. package/dist/stream/image.d.cts +3 -1
  27. package/dist/stream/image.d.ts +3 -1
  28. package/dist/stream/image.js +55 -43
  29. package/dist/stream/ole.cjs +1 -1
  30. package/dist/stream/ole.js +2 -2
  31. package/dist/stream/style.cjs +15 -13
  32. package/dist/stream/style.js +15 -13
  33. package/dist/stream/table.cjs +47 -33
  34. package/dist/stream/table.d.cts +3 -2
  35. package/dist/stream/table.d.ts +3 -2
  36. package/dist/stream/table.js +48 -35
  37. package/dist/stream/wpg.cjs +38 -40
  38. package/dist/stream/wpg.js +38 -40
  39. package/package.json +3 -3
@@ -29,8 +29,7 @@ const SYSTEM_STYLE_NUMBER_OFFSET = 2;
29
29
  const SYSTEM_STYLE_NONE = 255;
30
30
  function readSystemStyleNumber(nonDeletable) {
31
31
  const value = nonDeletable[SYSTEM_STYLE_NUMBER_OFFSET];
32
- if (value === void 0 || value === SYSTEM_STYLE_NONE) return;
33
- return value;
32
+ return value === SYSTEM_STYLE_NONE ? void 0 : value;
34
33
  }
35
34
  const FIRST_HEADING_LEVEL_STYLE = 68;
36
35
  const LAST_HEADING_LEVEL_STYLE = 75;
@@ -73,17 +72,20 @@ const PACKET_TYPE_NORMAL_STYLE = 48;
73
72
  const PID_COUNT_OFFSET = 0;
74
73
  const TEXT_BLOCK_HEADER_SIZE = 18;
75
74
  function readStyleBeginBlock(packet) {
76
- if (packet.length < 2) return;
77
- const afterPids = 2 + require_bytes_view.uint16At(packet, PID_COUNT_OFFSET) * 2;
78
- if (afterPids + TEXT_BLOCK_HEADER_SIZE > packet.length) return;
79
- const relativeOffset = require_bytes_view.uint32At(packet, afterPids + 2);
80
- const paragraphTextSize = require_bytes_view.uint32At(packet, afterPids + 6);
81
- const beginningStyleTextSize = require_bytes_view.uint32At(packet, afterPids + 10);
82
- if (beginningStyleTextSize === 0) return;
83
- const start = relativeOffset + paragraphTextSize;
84
- const end = start + beginningStyleTextSize;
85
- if (start < 0 || end > packet.length) return;
86
- return packet.subarray(start, end);
75
+ try {
76
+ const afterPids = 2 + require_bytes_view.uint16At(packet, PID_COUNT_OFFSET) * 2;
77
+ if (afterPids + TEXT_BLOCK_HEADER_SIZE > packet.length) return;
78
+ const relativeOffset = require_bytes_view.uint32At(packet, afterPids + 2);
79
+ const paragraphTextSize = require_bytes_view.uint32At(packet, afterPids + 6);
80
+ const beginningStyleTextSize = require_bytes_view.uint32At(packet, afterPids + 10);
81
+ if (beginningStyleTextSize === 0) return;
82
+ const start = relativeOffset + paragraphTextSize;
83
+ const end = start + beginningStyleTextSize;
84
+ if (end > packet.length) return;
85
+ return packet.subarray(start, end);
86
+ } catch {
87
+ return;
88
+ }
87
89
  }
88
90
  //#endregion
89
91
  exports.DISPLAY_NUMBER_GROUP = DISPLAY_NUMBER_GROUP;
@@ -28,8 +28,7 @@ const SYSTEM_STYLE_NUMBER_OFFSET = 2;
28
28
  const SYSTEM_STYLE_NONE = 255;
29
29
  function readSystemStyleNumber(nonDeletable) {
30
30
  const value = nonDeletable[SYSTEM_STYLE_NUMBER_OFFSET];
31
- if (value === void 0 || value === SYSTEM_STYLE_NONE) return;
32
- return value;
31
+ return value === SYSTEM_STYLE_NONE ? void 0 : value;
33
32
  }
34
33
  const FIRST_HEADING_LEVEL_STYLE = 68;
35
34
  const LAST_HEADING_LEVEL_STYLE = 75;
@@ -72,17 +71,20 @@ const PACKET_TYPE_NORMAL_STYLE = 48;
72
71
  const PID_COUNT_OFFSET = 0;
73
72
  const TEXT_BLOCK_HEADER_SIZE = 18;
74
73
  function readStyleBeginBlock(packet) {
75
- if (packet.length < 2) return;
76
- const afterPids = 2 + uint16At(packet, PID_COUNT_OFFSET) * 2;
77
- if (afterPids + TEXT_BLOCK_HEADER_SIZE > packet.length) return;
78
- const relativeOffset = uint32At(packet, afterPids + 2);
79
- const paragraphTextSize = uint32At(packet, afterPids + 6);
80
- const beginningStyleTextSize = uint32At(packet, afterPids + 10);
81
- if (beginningStyleTextSize === 0) return;
82
- const start = relativeOffset + paragraphTextSize;
83
- const end = start + beginningStyleTextSize;
84
- if (start < 0 || end > packet.length) return;
85
- return packet.subarray(start, end);
74
+ try {
75
+ const afterPids = 2 + uint16At(packet, PID_COUNT_OFFSET) * 2;
76
+ if (afterPids + TEXT_BLOCK_HEADER_SIZE > packet.length) return;
77
+ const relativeOffset = uint32At(packet, afterPids + 2);
78
+ const paragraphTextSize = uint32At(packet, afterPids + 6);
79
+ const beginningStyleTextSize = uint32At(packet, afterPids + 10);
80
+ if (beginningStyleTextSize === 0) return;
81
+ const start = relativeOffset + paragraphTextSize;
82
+ const end = start + beginningStyleTextSize;
83
+ if (end > packet.length) return;
84
+ return packet.subarray(start, end);
85
+ } catch {
86
+ return;
87
+ }
86
88
  }
87
89
  //#endregion
88
90
  export { DISPLAY_NUMBER_GROUP, PACKET_TYPE_NORMAL_STYLE, STYLE_GROUP, isParagraphNumberDisplayOff, isParagraphNumberDisplayOn, isStyleScopeCloser, isStyleScopeOpener, readDisplayNumberLevel, readStyleBeginBlock, readSystemStyleNumber, styleSemanticsFor };
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_errors = require("../errors.cjs");
3
2
  const require_bytes_view = require("../bytes/view.cjs");
4
3
  const require_stream_units = require("./units.cjs");
5
4
  //#region src/stream/table.ts
@@ -45,31 +44,39 @@ function readEmbeddedSubfunctions(nonDeletable) {
45
44
  truncated: true
46
45
  };
47
46
  const subfunctions = [];
48
- while (cursor < nonDeletable.length) {
49
- const code = nonDeletable[cursor];
50
- if (code === void 0) break;
51
- if (code === DONT_END_PARAGRAPH_STYLE_SUBFUNCTION) {
47
+ try {
48
+ for (;;) {
49
+ const code = nonDeletable[cursor];
50
+ if (code === void 0) break;
51
+ if (code === DONT_END_PARAGRAPH_STYLE_SUBFUNCTION) {
52
+ subfunctions.push({
53
+ code,
54
+ data: /* @__PURE__ */ new Uint8Array(0)
55
+ });
56
+ cursor += 1;
57
+ continue;
58
+ }
59
+ const formulaLength = code === 129 ? require_bytes_view.uint16At(nonDeletable, cursor + 1) : void 0;
60
+ const size = formulaLength === void 0 ? EMBEDDED_SUBFUNCTION_SIZES.get(code) : formulaLength + CELL_FORMULA_FRAMING_SIZE;
61
+ if (size === void 0) return {
62
+ subfunctions,
63
+ truncated: true
64
+ };
65
+ if (nonDeletable[cursor + size - 1] !== code) return {
66
+ subfunctions,
67
+ truncated: true
68
+ };
52
69
  subfunctions.push({
53
70
  code,
54
- data: /* @__PURE__ */ new Uint8Array(0)
71
+ data: formulaLength === void 0 ? nonDeletable.subarray(cursor + 1, cursor + size - 1) : nonDeletable.subarray(cursor + 3, cursor + 3 + formulaLength)
55
72
  });
56
- cursor += 1;
57
- continue;
73
+ cursor += size;
58
74
  }
59
- const size = code === 129 ? cursor + 3 <= nonDeletable.length ? require_bytes_view.uint16At(nonDeletable, cursor + 1) + CELL_FORMULA_FRAMING_SIZE : void 0 : EMBEDDED_SUBFUNCTION_SIZES.get(code);
60
- if (size === void 0 || cursor + size > nonDeletable.length) return {
75
+ } catch {
76
+ return {
61
77
  subfunctions,
62
78
  truncated: true
63
79
  };
64
- if (nonDeletable[cursor + size - 1] !== code) return {
65
- subfunctions,
66
- truncated: true
67
- };
68
- subfunctions.push({
69
- code,
70
- data: nonDeletable.subarray(cursor + 1, cursor + size - 1)
71
- });
72
- cursor += size;
73
80
  }
74
81
  return {
75
82
  subfunctions,
@@ -149,24 +156,31 @@ const PERCENT_STEPS = [
149
156
  [90, "percent90"],
150
157
  [95, "percent95"]
151
158
  ];
152
- function nearestPercentType(percent) {
153
- return PERCENT_STEPS.reduce((best, step) => Math.abs(step[0] - percent) < Math.abs(best[0] - percent) ? step : best)[1];
159
+ const PATTERN_TYPE_BY_SHADE = Array.from({ length: 256 }, (_, shade) => {
160
+ const foregroundCoveragePercent = 100 - shade / COLOR_COMPONENT_MAX * 100;
161
+ return PERCENT_STEPS.reduce((best, step) => Math.abs(step[0] - foregroundCoveragePercent) < Math.abs(best[0] - foregroundCoveragePercent) ? step : best)[1];
162
+ });
163
+ function nearestPercentType(shade) {
164
+ const patternType = PATTERN_TYPE_BY_SHADE[shade];
165
+ if (patternType === void 0) throw new RangeError(`Shade byte ${String(shade)} is outside the 0-255 range a fill's own shading byte can ever hold.`);
166
+ return patternType;
154
167
  }
155
168
  function colorAt(data, offset) {
156
- const r = data[offset];
157
- const g = data[offset + 1];
158
- const b = data[offset + 2];
159
- if (r === void 0 || g === void 0 || b === void 0) return;
160
169
  return {
161
- r: r / COLOR_COMPONENT_MAX,
162
- g: g / COLOR_COMPONENT_MAX,
163
- b: b / COLOR_COMPONENT_MAX
170
+ r: require_bytes_view.byteAt(data, offset) / COLOR_COMPONENT_MAX,
171
+ g: require_bytes_view.byteAt(data, offset + 1) / COLOR_COMPONENT_MAX,
172
+ b: require_bytes_view.byteAt(data, offset + 2) / COLOR_COMPONENT_MAX
164
173
  };
165
174
  }
166
175
  function readCellFill(data) {
167
- const background = colorAt(data, RGBS_SIZE);
168
- if (background === void 0) return;
169
- const backgroundShade = data[7];
176
+ let background;
177
+ let backgroundShade;
178
+ try {
179
+ background = colorAt(data, RGBS_SIZE);
180
+ backgroundShade = data[7];
181
+ } catch {
182
+ return;
183
+ }
170
184
  if (backgroundShade === void 0 || backgroundShade === FULL_SHADE) return {
171
185
  fill: {
172
186
  kind: "solid",
@@ -175,11 +189,10 @@ function readCellFill(data) {
175
189
  blended: false
176
190
  };
177
191
  const foreground = colorAt(data, 0);
178
- if (foreground === void 0) throw new require_errors.WpdFormatError("Cell fill has a readable background colour but an unreadable foreground colour, which the RGBS pair's own contiguous layout should make impossible.");
179
192
  return {
180
193
  fill: {
181
194
  kind: "pattern",
182
- patternType: nearestPercentType(100 - backgroundShade / COLOR_COMPONENT_MAX * 100),
195
+ patternType: nearestPercentType(backgroundShade),
183
196
  foregroundColor: foreground,
184
197
  backgroundColor: background
185
198
  },
@@ -196,6 +209,7 @@ exports.CHARACTER_TABLE_COLUMN = CHARACTER_TABLE_COLUMN;
196
209
  exports.CHARACTER_TABLE_DEFINITION = CHARACTER_TABLE_DEFINITION;
197
210
  exports.ROW_INFORMATION_SUBFUNCTION = ROW_INFORMATION_SUBFUNCTION;
198
211
  exports.findEmbeddedSubfunction = findEmbeddedSubfunction;
212
+ exports.nearestPercentType = nearestPercentType;
199
213
  exports.readCellFill = readCellFill;
200
214
  exports.readCellInformation = readCellInformation;
201
215
  exports.readCellSpanning = readCellSpanning;
@@ -1,4 +1,4 @@
1
- import { Alignment, ContentCellFill } from "document-schema.js";
1
+ import { Alignment, ContentCellFill, ContentCellPatternType } from "document-schema.js";
2
2
  //#region src/stream/table.d.ts
3
3
  declare const CHARACTER_TABLE_DEFINITION = 42;
4
4
  declare const CHARACTER_DEFINE_TABLE_END = 43;
@@ -35,10 +35,11 @@ interface WpdCellSpanning {
35
35
  readonly coveredFromAbove: boolean;
36
36
  }
37
37
  declare function readCellSpanning(data: Uint8Array): WpdCellSpanning | undefined;
38
+ declare function nearestPercentType(shade: number): ContentCellPatternType;
38
39
  interface WpdCellFill {
39
40
  readonly fill: ContentCellFill;
40
41
  readonly blended: boolean;
41
42
  }
42
43
  declare function readCellFill(data: Uint8Array): WpdCellFill | undefined;
43
44
  //#endregion
44
- export { CELL_FILL_COLORS_SUBFUNCTION, CELL_FORMULA_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 };
45
+ export { CELL_FILL_COLORS_SUBFUNCTION, CELL_FORMULA_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, nearestPercentType, readCellFill, readCellInformation, readCellSpanning, readEmbeddedSubfunctions, readRowInformation, readTableColumnWidthPt };
@@ -1,4 +1,4 @@
1
- import { Alignment, ContentCellFill } from "document-schema.js";
1
+ import { Alignment, ContentCellFill, ContentCellPatternType } from "document-schema.js";
2
2
  //#region src/stream/table.d.ts
3
3
  declare const CHARACTER_TABLE_DEFINITION = 42;
4
4
  declare const CHARACTER_DEFINE_TABLE_END = 43;
@@ -35,10 +35,11 @@ interface WpdCellSpanning {
35
35
  readonly coveredFromAbove: boolean;
36
36
  }
37
37
  declare function readCellSpanning(data: Uint8Array): WpdCellSpanning | undefined;
38
+ declare function nearestPercentType(shade: number): ContentCellPatternType;
38
39
  interface WpdCellFill {
39
40
  readonly fill: ContentCellFill;
40
41
  readonly blended: boolean;
41
42
  }
42
43
  declare function readCellFill(data: Uint8Array): WpdCellFill | undefined;
43
44
  //#endregion
44
- export { CELL_FILL_COLORS_SUBFUNCTION, CELL_FORMULA_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 };
45
+ export { CELL_FILL_COLORS_SUBFUNCTION, CELL_FORMULA_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, nearestPercentType, readCellFill, readCellInformation, readCellSpanning, readEmbeddedSubfunctions, readRowInformation, readTableColumnWidthPt };
@@ -1,5 +1,4 @@
1
- import { WpdFormatError } from "../errors.js";
2
- import { uint16At } from "../bytes/view.js";
1
+ import { byteAt, uint16At } from "../bytes/view.js";
3
2
  import { pointsFromWpu } from "./units.js";
4
3
  //#region src/stream/table.ts
5
4
  const CHARACTER_TABLE_DEFINITION = 42;
@@ -44,31 +43,39 @@ function readEmbeddedSubfunctions(nonDeletable) {
44
43
  truncated: true
45
44
  };
46
45
  const subfunctions = [];
47
- while (cursor < nonDeletable.length) {
48
- const code = nonDeletable[cursor];
49
- if (code === void 0) break;
50
- if (code === DONT_END_PARAGRAPH_STYLE_SUBFUNCTION) {
46
+ try {
47
+ for (;;) {
48
+ const code = nonDeletable[cursor];
49
+ if (code === void 0) break;
50
+ if (code === DONT_END_PARAGRAPH_STYLE_SUBFUNCTION) {
51
+ subfunctions.push({
52
+ code,
53
+ data: /* @__PURE__ */ new Uint8Array(0)
54
+ });
55
+ cursor += 1;
56
+ continue;
57
+ }
58
+ const formulaLength = code === 129 ? uint16At(nonDeletable, cursor + 1) : void 0;
59
+ const size = formulaLength === void 0 ? EMBEDDED_SUBFUNCTION_SIZES.get(code) : formulaLength + CELL_FORMULA_FRAMING_SIZE;
60
+ if (size === void 0) return {
61
+ subfunctions,
62
+ truncated: true
63
+ };
64
+ if (nonDeletable[cursor + size - 1] !== code) return {
65
+ subfunctions,
66
+ truncated: true
67
+ };
51
68
  subfunctions.push({
52
69
  code,
53
- data: /* @__PURE__ */ new Uint8Array(0)
70
+ data: formulaLength === void 0 ? nonDeletable.subarray(cursor + 1, cursor + size - 1) : nonDeletable.subarray(cursor + 3, cursor + 3 + formulaLength)
54
71
  });
55
- cursor += 1;
56
- continue;
72
+ cursor += size;
57
73
  }
58
- const size = code === 129 ? cursor + 3 <= nonDeletable.length ? uint16At(nonDeletable, cursor + 1) + CELL_FORMULA_FRAMING_SIZE : void 0 : EMBEDDED_SUBFUNCTION_SIZES.get(code);
59
- if (size === void 0 || cursor + size > nonDeletable.length) return {
74
+ } catch {
75
+ return {
60
76
  subfunctions,
61
77
  truncated: true
62
78
  };
63
- if (nonDeletable[cursor + size - 1] !== code) return {
64
- subfunctions,
65
- truncated: true
66
- };
67
- subfunctions.push({
68
- code,
69
- data: nonDeletable.subarray(cursor + 1, cursor + size - 1)
70
- });
71
- cursor += size;
72
79
  }
73
80
  return {
74
81
  subfunctions,
@@ -148,24 +155,31 @@ const PERCENT_STEPS = [
148
155
  [90, "percent90"],
149
156
  [95, "percent95"]
150
157
  ];
151
- function nearestPercentType(percent) {
152
- return PERCENT_STEPS.reduce((best, step) => Math.abs(step[0] - percent) < Math.abs(best[0] - percent) ? step : best)[1];
158
+ const PATTERN_TYPE_BY_SHADE = Array.from({ length: 256 }, (_, shade) => {
159
+ const foregroundCoveragePercent = 100 - shade / COLOR_COMPONENT_MAX * 100;
160
+ return PERCENT_STEPS.reduce((best, step) => Math.abs(step[0] - foregroundCoveragePercent) < Math.abs(best[0] - foregroundCoveragePercent) ? step : best)[1];
161
+ });
162
+ function nearestPercentType(shade) {
163
+ const patternType = PATTERN_TYPE_BY_SHADE[shade];
164
+ if (patternType === void 0) throw new RangeError(`Shade byte ${String(shade)} is outside the 0-255 range a fill's own shading byte can ever hold.`);
165
+ return patternType;
153
166
  }
154
167
  function colorAt(data, offset) {
155
- const r = data[offset];
156
- const g = data[offset + 1];
157
- const b = data[offset + 2];
158
- if (r === void 0 || g === void 0 || b === void 0) return;
159
168
  return {
160
- r: r / COLOR_COMPONENT_MAX,
161
- g: g / COLOR_COMPONENT_MAX,
162
- b: b / COLOR_COMPONENT_MAX
169
+ r: byteAt(data, offset) / COLOR_COMPONENT_MAX,
170
+ g: byteAt(data, offset + 1) / COLOR_COMPONENT_MAX,
171
+ b: byteAt(data, offset + 2) / COLOR_COMPONENT_MAX
163
172
  };
164
173
  }
165
174
  function readCellFill(data) {
166
- const background = colorAt(data, RGBS_SIZE);
167
- if (background === void 0) return;
168
- const backgroundShade = data[7];
175
+ let background;
176
+ let backgroundShade;
177
+ try {
178
+ background = colorAt(data, RGBS_SIZE);
179
+ backgroundShade = data[7];
180
+ } catch {
181
+ return;
182
+ }
169
183
  if (backgroundShade === void 0 || backgroundShade === FULL_SHADE) return {
170
184
  fill: {
171
185
  kind: "solid",
@@ -174,11 +188,10 @@ function readCellFill(data) {
174
188
  blended: false
175
189
  };
176
190
  const foreground = colorAt(data, 0);
177
- if (foreground === void 0) throw new WpdFormatError("Cell fill has a readable background colour but an unreadable foreground colour, which the RGBS pair's own contiguous layout should make impossible.");
178
191
  return {
179
192
  fill: {
180
193
  kind: "pattern",
181
- patternType: nearestPercentType(100 - backgroundShade / COLOR_COMPONENT_MAX * 100),
194
+ patternType: nearestPercentType(backgroundShade),
182
195
  foregroundColor: foreground,
183
196
  backgroundColor: background
184
197
  },
@@ -186,4 +199,4 @@ function readCellFill(data) {
186
199
  };
187
200
  }
188
201
  //#endregion
189
- export { CELL_FILL_COLORS_SUBFUNCTION, CELL_FORMULA_SUBFUNCTION, CELL_INFORMATION_SUBFUNCTION, CELL_SPANNING_SUBFUNCTION, CHARACTER_DEFINE_TABLE_END, CHARACTER_TABLE_COLUMN, CHARACTER_TABLE_DEFINITION, ROW_INFORMATION_SUBFUNCTION, findEmbeddedSubfunction, readCellFill, readCellInformation, readCellSpanning, readEmbeddedSubfunctions, readRowInformation, readTableColumnWidthPt };
202
+ export { CELL_FILL_COLORS_SUBFUNCTION, CELL_FORMULA_SUBFUNCTION, CELL_INFORMATION_SUBFUNCTION, CELL_SPANNING_SUBFUNCTION, CHARACTER_DEFINE_TABLE_END, CHARACTER_TABLE_COLUMN, CHARACTER_TABLE_DEFINITION, ROW_INFORMATION_SUBFUNCTION, findEmbeddedSubfunction, nearestPercentType, readCellFill, readCellInformation, readCellSpanning, readEmbeddedSubfunctions, readRowInformation, readTableColumnWidthPt };
@@ -111,24 +111,20 @@ function coordinateAt(bytes, offset, doublePrecision) {
111
111
  if (!doublePrecision) return require_bytes_view.int16At(bytes, offset);
112
112
  return require_bytes_view.uint32At(bytes, offset) / 65536;
113
113
  }
114
- function readCharacterization(bytes, cursor, recordEnd) {
115
- if (cursor + 2 > recordEnd) return;
116
- const flags = require_bytes_view.uint16At(bytes, cursor);
117
- if ((flags & 31) !== 0) return {
118
- flags,
119
- geometryAt: -1
120
- };
121
- let geometryAt = cursor + 2;
122
- if ((flags & FLAG_EDIT_LOCK) !== 0) geometryAt += 4;
123
- if ((flags & FLAG_OBJECT_ID) !== 0) {
124
- if (geometryAt + 2 > recordEnd) return;
125
- geometryAt += (require_bytes_view.uint16At(bytes, geometryAt) & 32768) !== 0 ? 4 : 2;
114
+ function readCharacterization(bytes, cursor) {
115
+ try {
116
+ const flags = require_bytes_view.uint16At(bytes, cursor);
117
+ if ((flags & 31) !== 0) return;
118
+ let geometryAt = cursor + 2;
119
+ if ((flags & FLAG_EDIT_LOCK) !== 0) geometryAt += 4;
120
+ if ((flags & FLAG_OBJECT_ID) !== 0) geometryAt += (require_bytes_view.uint16At(bytes, geometryAt) & 32768) !== 0 ? 4 : 2;
121
+ return {
122
+ flags,
123
+ geometryAt
124
+ };
125
+ } catch {
126
+ return;
126
127
  }
127
- if (geometryAt > recordEnd) return;
128
- return {
129
- flags,
130
- geometryAt
131
- };
132
128
  }
133
129
  function xToPt(geometry, x) {
134
130
  return x / geometry.xPpi * POINTS_PER_INCH;
@@ -200,10 +196,6 @@ function decodeWpgGraphic(bytes, options) {
200
196
  reason: "encrypted"
201
197
  };
202
198
  const recordStart = require_bytes_view.uint32At(bytes, start + 4);
203
- if (recordStart < start + WPG_PREFIX_HEAD_SIZE || recordStart >= bytes.length) return {
204
- status: "refused",
205
- reason: "malformed"
206
- };
207
199
  const state = {
208
200
  penColor: { ...WPG_DEFAULT_BLACK },
209
201
  penWidthUnits: 0,
@@ -218,9 +210,13 @@ function decodeWpgGraphic(bytes, options) {
218
210
  let pendingTextBlockFrame;
219
211
  let cursor = start + recordStart;
220
212
  const recordName = (type) => RECORD_NAMES.get(type) ?? `record type 0x${type.toString(16)}`;
221
- while (cursor < bytes.length) {
222
- if (cursor + 2 > bytes.length) break;
223
- const type = require_bytes_view.byteAt(bytes, cursor + 1);
213
+ for (;;) {
214
+ let type;
215
+ try {
216
+ type = require_bytes_view.byteAt(bytes, cursor + 1);
217
+ } catch {
218
+ break;
219
+ }
224
220
  let after = cursor + 2;
225
221
  const extension = readCountField(bytes, after);
226
222
  if (extension === void 0) break;
@@ -328,10 +324,10 @@ function decodeWpgGraphic(bytes, options) {
328
324
  }
329
325
  if (type !== RECORD_TEXT_BLOCK) pendingTextBlockFrame = void 0;
330
326
  }
331
- while (groups.length > 0 && groups[groups.length - 1]?.remaining === 0) groups.pop();
327
+ while (groups[groups.length - 1]?.remaining === 0) groups.pop();
332
328
  if (extension.value > 0) groups.push({
333
329
  remaining: extension.value,
334
- membersWalk: !swallowed && (type === RECORD_GROUP || type === RECORD_TEXT_BLOCK && pendingTextBlockFrame !== void 0)
330
+ membersWalk: !swallowed && (type === RECORD_GROUP || pendingTextBlockFrame !== void 0)
335
331
  });
336
332
  cursor = recordEnd;
337
333
  }
@@ -356,8 +352,8 @@ function swallowedByOpenGroup(groups) {
356
352
  }
357
353
  function readTextBlockFrame(data, geometry) {
358
354
  if (geometry === void 0) return;
359
- const characterization = readCharacterization(data, 0, data.length);
360
- if (characterization === void 0 || characterization.geometryAt < 0 || characterization.geometryAt + geometry.coordinateSize * 4 > data.length) return;
355
+ const characterization = readCharacterization(data, 0);
356
+ if (characterization === void 0 || characterization.geometryAt + geometry.coordinateSize * 4 > data.length) return;
361
357
  const at = characterization.geometryAt;
362
358
  return frameFromCorners(geometry, coordinateAt(data, at, geometry.doublePrecision), coordinateAt(data, at + geometry.coordinateSize, geometry.doublePrecision), coordinateAt(data, at + geometry.coordinateSize * 2, geometry.doublePrecision), coordinateAt(data, at + geometry.coordinateSize * 3, geometry.doublePrecision));
363
359
  }
@@ -374,8 +370,8 @@ function frameFromCorners(geometry, x1, y1, x2, y2) {
374
370
  };
375
371
  }
376
372
  function readPrimitiveVector(type, data, geometry, state) {
377
- const characterization = readCharacterization(data, 0, data.length);
378
- if (characterization === void 0 || characterization.geometryAt < 0) return;
373
+ const characterization = readCharacterization(data, 0);
374
+ if (characterization === void 0) return;
379
375
  const { flags, geometryAt } = characterization;
380
376
  const stroke = (flags & FLAG_FRAME) !== 0 ? strokeOf(geometry, state) : void 0;
381
377
  switch (type) {
@@ -386,17 +382,19 @@ function readPrimitiveVector(type, data, geometry, state) {
386
382
  }
387
383
  }
388
384
  function readPolyline(data, geometry, flags, geometryAt, stroke, state) {
389
- if (geometryAt + 2 > data.length) return;
390
- const count = require_bytes_view.uint16At(data, geometryAt);
391
- let at = geometryAt + 2;
392
385
  const points = [];
393
- for (let index = 0; index < count; index += 1) {
394
- if (at + geometry.coordinateSize * 2 > data.length) return;
395
- points.push({
396
- xPt: xToPt(geometry, coordinateAt(data, at, geometry.doublePrecision)),
397
- yPt: yToPt(geometry, coordinateAt(data, at + geometry.coordinateSize, geometry.doublePrecision))
398
- });
399
- at += geometry.coordinateSize * 2;
386
+ try {
387
+ const count = require_bytes_view.uint16At(data, geometryAt);
388
+ let at = geometryAt + 2;
389
+ for (let index = 0; index < count; index += 1) {
390
+ points.push({
391
+ xPt: xToPt(geometry, coordinateAt(data, at, geometry.doublePrecision)),
392
+ yPt: yToPt(geometry, coordinateAt(data, at + geometry.coordinateSize, geometry.doublePrecision))
393
+ });
394
+ at += geometry.coordinateSize * 2;
395
+ }
396
+ } catch {
397
+ return;
400
398
  }
401
399
  const firstPoint = points[0];
402
400
  if (firstPoint === void 0) return;
@@ -110,24 +110,20 @@ function coordinateAt(bytes, offset, doublePrecision) {
110
110
  if (!doublePrecision) return int16At(bytes, offset);
111
111
  return uint32At(bytes, offset) / 65536;
112
112
  }
113
- function readCharacterization(bytes, cursor, recordEnd) {
114
- if (cursor + 2 > recordEnd) return;
115
- const flags = uint16At(bytes, cursor);
116
- if ((flags & 31) !== 0) return {
117
- flags,
118
- geometryAt: -1
119
- };
120
- let geometryAt = cursor + 2;
121
- if ((flags & FLAG_EDIT_LOCK) !== 0) geometryAt += 4;
122
- if ((flags & FLAG_OBJECT_ID) !== 0) {
123
- if (geometryAt + 2 > recordEnd) return;
124
- geometryAt += (uint16At(bytes, geometryAt) & 32768) !== 0 ? 4 : 2;
113
+ function readCharacterization(bytes, cursor) {
114
+ try {
115
+ const flags = uint16At(bytes, cursor);
116
+ if ((flags & 31) !== 0) return;
117
+ let geometryAt = cursor + 2;
118
+ if ((flags & FLAG_EDIT_LOCK) !== 0) geometryAt += 4;
119
+ if ((flags & FLAG_OBJECT_ID) !== 0) geometryAt += (uint16At(bytes, geometryAt) & 32768) !== 0 ? 4 : 2;
120
+ return {
121
+ flags,
122
+ geometryAt
123
+ };
124
+ } catch {
125
+ return;
125
126
  }
126
- if (geometryAt > recordEnd) return;
127
- return {
128
- flags,
129
- geometryAt
130
- };
131
127
  }
132
128
  function xToPt(geometry, x) {
133
129
  return x / geometry.xPpi * POINTS_PER_INCH;
@@ -199,10 +195,6 @@ function decodeWpgGraphic(bytes, options) {
199
195
  reason: "encrypted"
200
196
  };
201
197
  const recordStart = uint32At(bytes, start + 4);
202
- if (recordStart < start + WPG_PREFIX_HEAD_SIZE || recordStart >= bytes.length) return {
203
- status: "refused",
204
- reason: "malformed"
205
- };
206
198
  const state = {
207
199
  penColor: { ...WPG_DEFAULT_BLACK },
208
200
  penWidthUnits: 0,
@@ -217,9 +209,13 @@ function decodeWpgGraphic(bytes, options) {
217
209
  let pendingTextBlockFrame;
218
210
  let cursor = start + recordStart;
219
211
  const recordName = (type) => RECORD_NAMES.get(type) ?? `record type 0x${type.toString(16)}`;
220
- while (cursor < bytes.length) {
221
- if (cursor + 2 > bytes.length) break;
222
- const type = byteAt(bytes, cursor + 1);
212
+ for (;;) {
213
+ let type;
214
+ try {
215
+ type = byteAt(bytes, cursor + 1);
216
+ } catch {
217
+ break;
218
+ }
223
219
  let after = cursor + 2;
224
220
  const extension = readCountField(bytes, after);
225
221
  if (extension === void 0) break;
@@ -327,10 +323,10 @@ function decodeWpgGraphic(bytes, options) {
327
323
  }
328
324
  if (type !== RECORD_TEXT_BLOCK) pendingTextBlockFrame = void 0;
329
325
  }
330
- while (groups.length > 0 && groups[groups.length - 1]?.remaining === 0) groups.pop();
326
+ while (groups[groups.length - 1]?.remaining === 0) groups.pop();
331
327
  if (extension.value > 0) groups.push({
332
328
  remaining: extension.value,
333
- membersWalk: !swallowed && (type === RECORD_GROUP || type === RECORD_TEXT_BLOCK && pendingTextBlockFrame !== void 0)
329
+ membersWalk: !swallowed && (type === RECORD_GROUP || pendingTextBlockFrame !== void 0)
334
330
  });
335
331
  cursor = recordEnd;
336
332
  }
@@ -355,8 +351,8 @@ function swallowedByOpenGroup(groups) {
355
351
  }
356
352
  function readTextBlockFrame(data, geometry) {
357
353
  if (geometry === void 0) return;
358
- const characterization = readCharacterization(data, 0, data.length);
359
- if (characterization === void 0 || characterization.geometryAt < 0 || characterization.geometryAt + geometry.coordinateSize * 4 > data.length) return;
354
+ const characterization = readCharacterization(data, 0);
355
+ if (characterization === void 0 || characterization.geometryAt + geometry.coordinateSize * 4 > data.length) return;
360
356
  const at = characterization.geometryAt;
361
357
  return frameFromCorners(geometry, coordinateAt(data, at, geometry.doublePrecision), coordinateAt(data, at + geometry.coordinateSize, geometry.doublePrecision), coordinateAt(data, at + geometry.coordinateSize * 2, geometry.doublePrecision), coordinateAt(data, at + geometry.coordinateSize * 3, geometry.doublePrecision));
362
358
  }
@@ -373,8 +369,8 @@ function frameFromCorners(geometry, x1, y1, x2, y2) {
373
369
  };
374
370
  }
375
371
  function readPrimitiveVector(type, data, geometry, state) {
376
- const characterization = readCharacterization(data, 0, data.length);
377
- if (characterization === void 0 || characterization.geometryAt < 0) return;
372
+ const characterization = readCharacterization(data, 0);
373
+ if (characterization === void 0) return;
378
374
  const { flags, geometryAt } = characterization;
379
375
  const stroke = (flags & FLAG_FRAME) !== 0 ? strokeOf(geometry, state) : void 0;
380
376
  switch (type) {
@@ -385,17 +381,19 @@ function readPrimitiveVector(type, data, geometry, state) {
385
381
  }
386
382
  }
387
383
  function readPolyline(data, geometry, flags, geometryAt, stroke, state) {
388
- if (geometryAt + 2 > data.length) return;
389
- const count = uint16At(data, geometryAt);
390
- let at = geometryAt + 2;
391
384
  const points = [];
392
- for (let index = 0; index < count; index += 1) {
393
- if (at + geometry.coordinateSize * 2 > data.length) return;
394
- points.push({
395
- xPt: xToPt(geometry, coordinateAt(data, at, geometry.doublePrecision)),
396
- yPt: yToPt(geometry, coordinateAt(data, at + geometry.coordinateSize, geometry.doublePrecision))
397
- });
398
- at += geometry.coordinateSize * 2;
385
+ try {
386
+ const count = uint16At(data, geometryAt);
387
+ let at = geometryAt + 2;
388
+ for (let index = 0; index < count; index += 1) {
389
+ points.push({
390
+ xPt: xToPt(geometry, coordinateAt(data, at, geometry.doublePrecision)),
391
+ yPt: yToPt(geometry, coordinateAt(data, at + geometry.coordinateSize, geometry.doublePrecision))
392
+ });
393
+ at += geometry.coordinateSize * 2;
394
+ }
395
+ } catch {
396
+ return;
399
397
  }
400
398
  const firstPoint = points[0];
401
399
  if (firstPoint === void 0) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wpd-codec",
3
- "version": "3.5.1",
3
+ "version": "3.5.3",
4
4
  "description": "Hand-written read-only WordPerfect 6.x-X6 (.wpd) reader over document-schema.js's ContentDocument",
5
5
  "type": "module",
6
6
  "repository": {
@@ -80,8 +80,8 @@
80
80
  "license": "MIT",
81
81
  "packageManager": "pnpm@11.6.0",
82
82
  "dependencies": {
83
- "archive-codec": "1.11.1",
84
- "document-schema.js": "7.11.1",
83
+ "archive-codec": "1.11.2",
84
+ "document-schema.js": "7.11.2",
85
85
  "zod": "4.4.3"
86
86
  },
87
87
  "devDependencies": {