ooxml-core 1.6.0 → 1.6.2

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 (65) hide show
  1. package/dist/{PptxHandler-DDEJ6CKU.mjs → PptxHandler-BL4B7CZO.mjs} +2 -2
  2. package/dist/automation/index.cjs +1 -1
  3. package/dist/automation/index.mjs +1 -1
  4. package/dist/chart/gradient-definition.d.ts +2 -0
  5. package/dist/chart/gradient-definition.d.ts.map +1 -1
  6. package/dist/chart/index.cjs +1 -1
  7. package/dist/chart/index.mjs +1 -1
  8. package/dist/{chunk-5L4DHJV3.mjs → chunk-GAGSCAR3.mjs} +46 -43
  9. package/dist/{chunk-QXZJOUW4.mjs → chunk-NIHPA63A.mjs} +1 -1
  10. package/dist/{chunk-UQQGC6O3.mjs → chunk-TTPZITQN.mjs} +841 -614
  11. package/dist/{chunk-Q52O7SXQ.mjs → chunk-Z7IQR4S4.mjs} +3 -3
  12. package/dist/{chunk-EPNLABIU.mjs → chunk-ZAP5WLEN.mjs} +1 -1
  13. package/dist/crypto/index.cjs +281 -109
  14. package/dist/crypto/index.mjs +281 -109
  15. package/dist/diagram/engine/text-measure.d.ts +1 -1
  16. package/dist/diagram/layout/smartart-font-table.d.ts +1 -1
  17. package/dist/diagram/layout/smartart-layout-interpreter-linear-content-size.d.ts +1 -1
  18. package/dist/diagram/layout/smartart-layout-item-font-size.d.ts +1 -1
  19. package/dist/diagram/layout/smartart-layout-item-font-tier-fit.d.ts +1 -1
  20. package/dist/diagram/layout/smartart-line-pitch.d.ts +1 -1
  21. package/dist/diagram/layout/smartart-text-wrap-fit.d.ts +1 -1
  22. package/dist/docx/index.cjs +1 -1
  23. package/dist/docx/index.mjs +1 -1
  24. package/dist/docx/layout/index.cjs +1 -1
  25. package/dist/docx/layout/index.mjs +1 -1
  26. package/dist/docx/load/index.cjs +481 -254
  27. package/dist/docx/load/index.mjs +481 -254
  28. package/dist/docx/ui/index.cjs +1 -1
  29. package/dist/docx/ui/index.mjs +1 -1
  30. package/dist/index.cjs +1 -1
  31. package/dist/index.mjs +1 -1
  32. package/dist/pptx/automation/index.cjs +1391 -1154
  33. package/dist/pptx/automation/index.d.ts +3 -3
  34. package/dist/pptx/automation/index.mjs +5 -5
  35. package/dist/pptx/chunks/{index-JNv7AJx5.d.ts → index-CKIUurnd.d.ts} +2 -2
  36. package/dist/pptx/chunks/{index-JNv7AJx5.d.ts.map → index-CKIUurnd.d.ts.map} +1 -1
  37. package/dist/pptx/chunks/{index-EZJZ7USt.d.ts → index-Cn-GzYGp.d.ts} +64 -15
  38. package/dist/pptx/chunks/{index-EZJZ7USt.d.ts.map → index-Cn-GzYGp.d.ts.map} +1 -1
  39. package/dist/pptx/chunks/{text-operations-DtCxXrMh.d.ts → text-operations-BHfAm5K9.d.ts} +8 -1
  40. package/dist/pptx/chunks/text-operations-BHfAm5K9.d.ts.map +1 -0
  41. package/dist/pptx/cli/index.cjs +1270 -1088
  42. package/dist/pptx/cli/index.d.ts +1 -1
  43. package/dist/pptx/cli/index.mjs +4 -4
  44. package/dist/pptx/converter/index.d.ts +1 -1
  45. package/dist/pptx/converter/index.mjs +2 -2
  46. package/dist/pptx/index.cjs +1411 -1174
  47. package/dist/pptx/index.d.ts +3 -3
  48. package/dist/pptx/index.mjs +5 -5
  49. package/dist/text/font-metrics/font-advance-widths-aptos-display.generated.d.ts +1 -1
  50. package/dist/text/font-metrics/font-advance-widths-aptos.generated.d.ts +1 -1
  51. package/dist/text/font-metrics/font-advance-widths-arial.generated.d.ts +1 -1
  52. package/dist/text/font-metrics/font-advance-widths-calibri-light.generated.d.ts +1 -1
  53. package/dist/text/font-metrics/font-advance-widths-calibri.generated.d.ts +1 -1
  54. package/dist/text/font-metrics/font-advance-widths-segoe-ui.generated.d.ts +1 -1
  55. package/dist/text/font-metrics/font-advance-widths-times-new-roman.generated.d.ts +1 -1
  56. package/dist/visio/index.cjs +482 -232
  57. package/dist/visio/index.mjs +482 -232
  58. package/dist/visio/ui/data-graphic-rules.d.ts +2 -2
  59. package/dist/xlsx/formula/test-helpers.d.ts +9 -9
  60. package/dist/xlsx/index.cjs +1 -1
  61. package/dist/xlsx/index.mjs +1 -1
  62. package/dist/xlsx/load/index.cjs +415 -188
  63. package/dist/xlsx/load/index.mjs +415 -188
  64. package/package.json +5 -5
  65. package/dist/pptx/chunks/text-operations-DtCxXrMh.d.ts.map +0 -1
@@ -1,4 +1,4 @@
1
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-types.js
1
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-types.js
2
2
  var OLE_MAGIC = new Uint8Array([208, 207, 17, 224, 161, 177, 26, 225]);
3
3
  var ENDOFCHAIN = 4294967294;
4
4
  var FREESECT = 4294967295;
@@ -6,7 +6,9 @@ var FATSECT = 4294967293;
6
6
  var DIFSECT = 4294967292;
7
7
  var MAXREGSECT = 4294967290;
8
8
  var ENTRY_TYPE_EMPTY = 0;
9
+ var ENTRY_TYPE_STORAGE = 1;
9
10
  var ENTRY_TYPE_STREAM = 2;
11
+ var NOSTREAM = 4294967295;
10
12
  var ENTRY_TYPE_ROOT = 5;
11
13
  var DIR_ENTRY_SIZE = 128;
12
14
  var Ole2ParseError = class extends Error {
@@ -16,10 +18,174 @@ var Ole2ParseError = class extends Error {
16
18
  }
17
19
  };
18
20
 
19
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-read.js
20
- function parseOle2(buffer) {
21
- const data = new Uint8Array(buffer);
22
- const view = new DataView(buffer);
21
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-directory.js
22
+ var FILETIME_UNIX_EPOCH = 116444736000000000n;
23
+ function readFileTime(view, offset) {
24
+ const ticks = view.getBigUint64(offset, true);
25
+ if (ticks === 0n)
26
+ return void 0;
27
+ const ms = Number((ticks - FILETIME_UNIX_EPOCH) / 10000n);
28
+ const date = new Date(ms);
29
+ return Number.isNaN(date.getTime()) ? void 0 : date;
30
+ }
31
+ function decodeSlot(dir, id, majorVersion, warnings) {
32
+ const view = new DataView(dir.buffer, dir.byteOffset + id * DIR_ENTRY_SIZE, DIR_ENTRY_SIZE);
33
+ const nameLen = view.getUint16(64, true);
34
+ const type = view.getUint8(66);
35
+ const nameValid = nameLen >= 2 && nameLen <= 64 && nameLen % 2 === 0 && view.getUint16(nameLen - 2, true) === 0;
36
+ let name = "";
37
+ if (nameValid)
38
+ for (let j = 0; j < nameLen - 2; j += 2)
39
+ name += String.fromCharCode(view.getUint16(j, true));
40
+ const link = (offset) => {
41
+ const value = view.getUint32(offset, true);
42
+ return value === NOSTREAM ? -1 : value;
43
+ };
44
+ const sizeLow = view.getUint32(120, true);
45
+ const sizeHigh = view.getUint32(124, true);
46
+ let size = sizeLow;
47
+ if (majorVersion === 4)
48
+ size = sizeLow + sizeHigh * 4294967296;
49
+ else if (sizeHigh !== 0 && type !== ENTRY_TYPE_EMPTY) {
50
+ warnings.push({ code: "size-high-bits", message: `Ignored v3 stream-size high bits on directory entry ${id}` });
51
+ }
52
+ return {
53
+ id,
54
+ type,
55
+ nameValid,
56
+ entry: {
57
+ id,
58
+ name,
59
+ type,
60
+ color: view.getUint8(67),
61
+ leftSiblingId: link(68),
62
+ rightSiblingId: link(72),
63
+ childId: link(76),
64
+ clsid: new Uint8Array(view.buffer.slice(view.byteOffset + 80, view.byteOffset + 96)),
65
+ stateBits: view.getUint32(96, true),
66
+ created: readFileTime(view, 100),
67
+ modified: readFileTime(view, 108),
68
+ startSector: view.getUint32(116, true),
69
+ size,
70
+ parentId: -1
71
+ }
72
+ };
73
+ }
74
+ function readDirectory(dir, majorVersion, strict, warnings) {
75
+ const count = Math.floor(dir.length / DIR_ENTRY_SIZE);
76
+ const slots = [];
77
+ for (let id = 0; id < count; id++)
78
+ slots.push(decodeSlot(dir, id, majorVersion, warnings));
79
+ const roots = slots.filter((slot) => slot.type === ENTRY_TYPE_ROOT);
80
+ if (roots.length !== 1 || !roots[0].nameValid)
81
+ throw new Ole2ParseError("Invalid root directory entry");
82
+ const root = roots[0];
83
+ root.entry.path = [];
84
+ const reached = /* @__PURE__ */ new Set([root.id]);
85
+ const fail = (message) => {
86
+ if (strict)
87
+ throw new Ole2ParseError(message);
88
+ warnings.push({ code: "directory-link", message });
89
+ };
90
+ const pending = [];
91
+ const push = (id, parent, from) => {
92
+ if (id === -1)
93
+ return;
94
+ const target = slots[id];
95
+ if (!target || target.type === ENTRY_TYPE_EMPTY || target.type === ENTRY_TYPE_ROOT) {
96
+ fail(`Directory entry ${from} links to invalid entry ${id}`);
97
+ return;
98
+ }
99
+ if (reached.has(id)) {
100
+ fail(`Cyclic directory tree at entry ${id}`);
101
+ return;
102
+ }
103
+ reached.add(id);
104
+ pending.push({ id, parent });
105
+ };
106
+ push(root.entry.childId, root, root.id);
107
+ while (pending.length) {
108
+ const { id, parent } = pending.pop();
109
+ const slot = slots[id];
110
+ if (!slot.nameValid)
111
+ throw new Ole2ParseError("Invalid directory entry name");
112
+ slot.entry.parentId = parent.id;
113
+ slot.entry.path = [...parent.entry.path, slot.entry.name];
114
+ push(slot.entry.leftSiblingId, parent, id);
115
+ push(slot.entry.rightSiblingId, parent, id);
116
+ if (slot.type === ENTRY_TYPE_STORAGE)
117
+ push(slot.entry.childId, slot, id);
118
+ }
119
+ const entries = [];
120
+ for (const slot of slots) {
121
+ if (slot.type === ENTRY_TYPE_EMPTY)
122
+ continue;
123
+ if (!reached.has(slot.id)) {
124
+ if (!slot.nameValid) {
125
+ if (strict)
126
+ throw new Ole2ParseError("Invalid directory entry name");
127
+ warnings.push({ code: "invalid-unreachable-entry", message: `Skipped undecodable stale directory entry ${slot.id}` });
128
+ continue;
129
+ }
130
+ if (strict)
131
+ throw new Ole2ParseError(`Directory entry ${slot.id} is not reachable from the root`);
132
+ warnings.push({ code: "unreachable-entry", message: `Directory entry ${slot.id} (${slot.entry.name}) is not reachable from the root` });
133
+ }
134
+ entries.push(slot.entry);
135
+ }
136
+ return entries;
137
+ }
138
+ function sameName(a, b) {
139
+ return a.length === b.length && a.toUpperCase() === b.toUpperCase();
140
+ }
141
+ function bareName(name) {
142
+ return name.replace(/^[\u0001-\u0006]/, "");
143
+ }
144
+ function normalizePath(path, rootName) {
145
+ const parts = typeof path === "string" ? path.split("/").filter((part) => part !== "") : [...path];
146
+ if (parts.length && sameName(parts[0], rootName) && typeof path === "string")
147
+ parts.shift();
148
+ return parts;
149
+ }
150
+ function child(entries, parentId, name) {
151
+ const children = entries.filter((entry) => entry.parentId === parentId && entry.path !== void 0);
152
+ const pick = (matches) => matches.length === 1 ? matches[0] : void 0;
153
+ const exact = children.filter((entry) => entry.name === name);
154
+ if (exact.length)
155
+ return pick(exact);
156
+ const folded = children.filter((entry) => sameName(entry.name, name));
157
+ if (folded.length)
158
+ return pick(folded);
159
+ return pick(children.filter((entry) => sameName(bareName(entry.name), bareName(name))));
160
+ }
161
+ function findDirectoryEntry(entries, path) {
162
+ const root = entries.find((entry) => entry.type === ENTRY_TYPE_ROOT);
163
+ if (!root)
164
+ return void 0;
165
+ let current = root;
166
+ for (const name of normalizePath(path, root.name)) {
167
+ if (current.type !== ENTRY_TYPE_ROOT && current.type !== ENTRY_TYPE_STORAGE)
168
+ return void 0;
169
+ current = child(entries, current.id, name);
170
+ if (!current)
171
+ return void 0;
172
+ }
173
+ return current;
174
+ }
175
+ function findStreamByName(entries, name, isReadable) {
176
+ const root = entries.find((entry) => entry.type === ENTRY_TYPE_ROOT);
177
+ if (root && root.name === name)
178
+ return root;
179
+ const top = entries.filter((entry) => entry.parentId === root?.id && isReadable(entry));
180
+ return top.find((entry) => entry.name === name) ?? top.find((entry) => sameName(entry.name, name)) ?? entries.find((entry) => entry.name === name && isReadable(entry));
181
+ }
182
+
183
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-read.js
184
+ function parseOle2(buffer, options = {}) {
185
+ const strict = options.strict === true;
186
+ const data = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
187
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
188
+ const warnings = [];
23
189
  if (data.length < 512) {
24
190
  throw new Ole2ParseError("Truncated OLE2 compound file header");
25
191
  }
@@ -28,11 +194,12 @@ function parseOle2(buffer) {
28
194
  throw new Ole2ParseError("Not a valid OLE2 compound file");
29
195
  }
30
196
  }
31
- view.getUint16(24, true);
32
197
  const majorVersion = view.getUint16(26, true);
33
198
  const byteOrder = view.getUint16(28, true);
34
199
  if (byteOrder !== 65534) {
35
- throw new Ole2ParseError("Invalid byte order mark");
200
+ if (strict)
201
+ throw new Ole2ParseError("Invalid byte order mark");
202
+ warnings.push({ code: "byte-order", message: `Ignored byte order mark 0x${byteOrder.toString(16)}` });
36
203
  }
37
204
  const sectorSizePower = view.getUint16(30, true);
38
205
  const miniSectorSizePower = view.getUint16(32, true);
@@ -41,10 +208,14 @@ function parseOle2(buffer) {
41
208
  }
42
209
  const sectorSize = 1 << sectorSizePower;
43
210
  const miniSectorSize = 1 << miniSectorSizePower;
44
- if (data.length < sectorSize || data.length % sectorSize !== 0) {
211
+ if (data.length < sectorSize)
45
212
  throw new Ole2ParseError("Truncated OLE2 sector");
213
+ if (data.length % sectorSize !== 0) {
214
+ if (strict)
215
+ throw new Ole2ParseError("Truncated OLE2 sector");
216
+ warnings.push({ code: "unaligned-length", message: `File length ${data.length} is not a multiple of ${sectorSize}` });
46
217
  }
47
- const sectorCount = data.length / sectorSize - 1;
218
+ const sectorCount = Math.ceil(data.length / sectorSize) - 1;
48
219
  const totalFATSectors = view.getUint32(44, true);
49
220
  const firstDirectorySector = view.getUint32(48, true);
50
221
  const miniStreamCutoff = view.getUint32(56, true);
@@ -65,6 +236,13 @@ function parseOle2(buffer) {
65
236
  }
66
237
  return data.subarray(offset, offset + sectorSize);
67
238
  }
239
+ function copySector(sector, target, at, want) {
240
+ const offset = sectorOffset(sector);
241
+ if (sector >= sectorCount || offset + want > data.length) {
242
+ throw new Ole2ParseError(`Sector ${sector} at offset ${offset} exceeds file size ${data.length}`);
243
+ }
244
+ target.set(data.subarray(offset, offset + want), at);
245
+ }
68
246
  const fatSectors = [];
69
247
  for (let i2 = 0; i2 < 109 && fatSectors.length < totalFATSectors; i2++) {
70
248
  const sector = view.getUint32(76 + i2 * 4, true);
@@ -100,29 +278,36 @@ function parseOle2(buffer) {
100
278
  fatEntries.push(fatView.getUint32(i2 * 4, true));
101
279
  }
102
280
  }
103
- function readSectorChain(startSector) {
104
- const sectors = [];
105
- let current = startSector;
281
+ function followChain(table, start, label, needed) {
282
+ const ids = [];
106
283
  const visited = /* @__PURE__ */ new Set();
284
+ let current = start;
107
285
  while (current <= MAXREGSECT) {
286
+ if (!strict && needed !== void 0 && ids.length >= needed)
287
+ return ids;
108
288
  if (visited.has(current)) {
109
- throw new Ole2ParseError(`Circular reference in FAT chain at sector ${current}`);
289
+ throw new Ole2ParseError(`Circular reference in ${label} chain at sector ${current}`);
110
290
  }
111
291
  visited.add(current);
112
- sectors.push(readSector(current));
113
- if (fatEntries[current] === void 0)
114
- throw new Ole2ParseError("Missing FAT chain entry");
115
- current = fatEntries[current];
292
+ ids.push(current);
293
+ if (table[current] === void 0)
294
+ throw new Ole2ParseError(`Missing ${label} chain entry`);
295
+ current = table[current];
116
296
  }
117
- if (current !== ENDOFCHAIN)
118
- throw new Ole2ParseError("Invalid FAT chain terminator");
119
- const totalLength = sectors.length * sectorSize;
120
- const result = new Uint8Array(totalLength);
121
- let offset = 0;
122
- for (const sector of sectors) {
123
- result.set(sector, offset);
124
- offset += sectorSize;
297
+ if (current !== ENDOFCHAIN) {
298
+ if (strict || needed === void 0 || ids.length < needed) {
299
+ throw new Ole2ParseError(`Invalid ${label} chain terminator`);
300
+ }
301
+ warnings.push({ code: "chain-terminator", message: `Accepted ${label} chain ending in 0x${current.toString(16)}` });
125
302
  }
303
+ return ids;
304
+ }
305
+ function readMetadataChain(startSector, label) {
306
+ if (startSector > MAXREGSECT)
307
+ return new Uint8Array(0);
308
+ const ids = followChain(fatEntries, startSector, label === "directory" ? "FAT" : label);
309
+ const result = new Uint8Array(ids.length * sectorSize);
310
+ ids.forEach((id, i2) => result.set(readSector(id), i2 * sectorSize));
126
311
  return result;
127
312
  }
128
313
  function readStream(startSector, size) {
@@ -130,68 +315,44 @@ function parseOle2(buffer) {
130
315
  return new Uint8Array(0);
131
316
  if (size > sectorCount * sectorSize)
132
317
  throw new Ole2ParseError("Stream size exceeds file size");
133
- const raw = readSectorChain(startSector);
134
- if (raw.length < size)
318
+ const needed = Math.ceil(size / sectorSize);
319
+ const ids = followChain(fatEntries, startSector, "FAT", needed);
320
+ if (ids.length < needed)
135
321
  throw new Ole2ParseError("Truncated stream sector chain");
136
- return raw.subarray(0, size);
137
- }
138
- const dirRaw = readSectorChain(firstDirectorySector);
139
- const numEntries = Math.floor(dirRaw.length / DIR_ENTRY_SIZE);
140
- const entries = [];
141
- for (let i2 = 0; i2 < numEntries; i2++) {
142
- const entryOffset = i2 * DIR_ENTRY_SIZE;
143
- const entryView = new DataView(dirRaw.buffer, dirRaw.byteOffset + entryOffset, DIR_ENTRY_SIZE);
144
- const nameLen = entryView.getUint16(64, true);
145
- const objectType = entryView.getUint8(66);
146
- if (objectType === ENTRY_TYPE_EMPTY) {
147
- continue;
322
+ const result = new Uint8Array(size);
323
+ for (let i2 = 0; i2 < needed; i2++) {
324
+ copySector(ids[i2], result, i2 * sectorSize, Math.min(sectorSize, size - i2 * sectorSize));
148
325
  }
149
- if (nameLen < 2 || nameLen > 64 || nameLen % 2 !== 0 || entryView.getUint16(nameLen - 2, true) !== 0) {
150
- throw new Ole2ParseError("Invalid directory entry name");
151
- }
152
- const nameBytes = Math.max(0, nameLen - 2);
153
- let name = "";
154
- for (let j = 0; j < nameBytes; j += 2) {
155
- name += String.fromCharCode(entryView.getUint16(j, true));
156
- }
157
- const leftSiblingId = entryView.getUint32(68, true);
158
- const rightSiblingId = entryView.getUint32(72, true);
159
- const childId = entryView.getUint32(76, true);
160
- const clsid = new Uint8Array(entryView.buffer.slice(entryView.byteOffset + 80, entryView.byteOffset + 96));
161
- const startSector = entryView.getUint32(116, true);
162
- const sizeLow = entryView.getUint32(120, true);
163
- let size = sizeLow;
164
- if (majorVersion === 4) {
165
- const sizeHigh = entryView.getUint32(124, true);
166
- size = sizeLow + sizeHigh * 4294967296;
167
- if (!Number.isSafeInteger(size) || size > sectorCount * sectorSize) {
168
- throw new Ole2ParseError("Stream size exceeds supported file bounds");
169
- }
326
+ return result;
327
+ }
328
+ if (firstDirectorySector > MAXREGSECT)
329
+ throw new Ole2ParseError("Missing directory chain");
330
+ const entries = readDirectory(readMetadataChain(firstDirectorySector, "directory"), majorVersion, strict, warnings);
331
+ for (const entry of entries) {
332
+ if (majorVersion === 4 && (!Number.isSafeInteger(entry.size) || entry.size > sectorCount * sectorSize)) {
333
+ throw new Ole2ParseError("Stream size exceeds supported file bounds");
170
334
  }
171
- entries.push({
172
- name,
173
- type: objectType,
174
- startSector,
175
- size,
176
- childId: childId === 4294967295 ? -1 : childId,
177
- leftSiblingId: leftSiblingId === 4294967295 ? -1 : leftSiblingId,
178
- rightSiblingId: rightSiblingId === 4294967295 ? -1 : rightSiblingId,
179
- clsid
180
- });
181
335
  }
182
336
  const rootEntry = entries.find((e) => e.type === ENTRY_TYPE_ROOT);
183
- if (!rootEntry || entries.filter((e) => e.type === ENTRY_TYPE_ROOT).length !== 1) {
184
- throw new Ole2ParseError("Invalid root directory entry");
185
- }
186
337
  let miniStreamData;
187
- if (rootEntry && rootEntry.startSector <= MAXREGSECT) {
338
+ if (rootEntry.startSector <= MAXREGSECT) {
188
339
  miniStreamData = readStream(rootEntry.startSector, rootEntry.size);
189
340
  }
190
341
  const miniFatEntries = [];
191
- if (firstMiniFATSector <= MAXREGSECT && totalMiniFATSectors > 0) {
192
- const miniFatRaw = readSectorChain(firstMiniFATSector);
193
- if (miniFatRaw.length !== totalMiniFATSectors * sectorSize) {
342
+ if (firstMiniFATSector > MAXREGSECT && totalMiniFATSectors > 0) {
343
+ if (strict)
194
344
  throw new Ole2ParseError("Unexpected mini FAT chain length");
345
+ warnings.push({ code: "mini-fat-count", message: `Header lists ${totalMiniFATSectors} mini FAT sectors but no chain` });
346
+ }
347
+ if (firstMiniFATSector <= MAXREGSECT && (totalMiniFATSectors > 0 || !strict)) {
348
+ const miniFatRaw = readMetadataChain(firstMiniFATSector, "mini FAT");
349
+ if (miniFatRaw.length !== totalMiniFATSectors * sectorSize) {
350
+ if (strict)
351
+ throw new Ole2ParseError("Unexpected mini FAT chain length");
352
+ warnings.push({
353
+ code: "mini-fat-count",
354
+ message: `Header lists ${totalMiniFATSectors} mini FAT sectors; chain has ${miniFatRaw.length / sectorSize}`
355
+ });
195
356
  }
196
357
  const miniFatView = new DataView(miniFatRaw.buffer, miniFatRaw.byteOffset, miniFatRaw.byteLength);
197
358
  const miniCapacity = Math.floor((miniStreamData?.length ?? 0) / miniSectorSize);
@@ -205,45 +366,56 @@ function parseOle2(buffer) {
205
366
  if (!miniStreamData) {
206
367
  throw new Ole2ParseError("Mini stream container not found");
207
368
  }
208
- const sectors = [];
209
- let current = startSector;
210
- const visited = /* @__PURE__ */ new Set();
211
- while (current <= MAXREGSECT) {
212
- if (visited.has(current)) {
213
- throw new Ole2ParseError(`Circular reference in mini FAT chain at sector ${current}`);
369
+ const needed = Math.ceil(size / miniSectorSize);
370
+ const capacity = miniStreamData.length / miniSectorSize;
371
+ let ids;
372
+ try {
373
+ ids = followChain(miniFatEntries, startSector, "mini FAT", needed);
374
+ } catch (error) {
375
+ if (error instanceof Ole2ParseError && /Missing mini FAT/.test(error.message)) {
376
+ throw new Ole2ParseError("Mini stream sector exceeds allocation bounds");
214
377
  }
215
- visited.add(current);
216
- const offset2 = current * miniSectorSize;
217
- if (offset2 + miniSectorSize > miniStreamData.length || miniFatEntries[current] === void 0) {
378
+ throw error;
379
+ }
380
+ const result = new Uint8Array(size);
381
+ for (let i2 = 0; i2 < ids.length && i2 < needed; i2++) {
382
+ const id = ids[i2];
383
+ if (id >= capacity || (id + 1) * miniSectorSize > miniStreamData.length) {
218
384
  throw new Ole2ParseError("Mini stream sector exceeds allocation bounds");
219
385
  }
220
- sectors.push(miniStreamData.subarray(offset2, offset2 + miniSectorSize));
221
- current = miniFatEntries[current];
386
+ const want = Math.min(miniSectorSize, size - i2 * miniSectorSize);
387
+ result.set(miniStreamData.subarray(id * miniSectorSize, id * miniSectorSize + want), i2 * miniSectorSize);
222
388
  }
223
- if (current !== ENDOFCHAIN)
224
- throw new Ole2ParseError("Invalid mini FAT chain terminator");
225
- const totalLength = sectors.length * miniSectorSize;
226
- if (totalLength < size)
389
+ if (ids.length < needed)
227
390
  throw new Ole2ParseError("Truncated mini stream sector chain");
228
- const result = new Uint8Array(totalLength);
229
- let offset = 0;
230
- for (const sector of sectors) {
231
- result.set(sector, offset);
232
- offset += miniSectorSize;
233
- }
234
- return result.subarray(0, size);
391
+ return result;
235
392
  }
236
- function getStream(name) {
237
- const entry = entries.find((e) => (e.type === ENTRY_TYPE_STREAM || e.type === ENTRY_TYPE_ROOT) && e.name === name);
238
- if (!entry) {
239
- return void 0;
240
- }
393
+ function readEntry(entry) {
241
394
  if (entry.size < miniStreamCutoff && entry.type !== ENTRY_TYPE_ROOT) {
242
395
  return readMiniStream(entry.startSector, entry.size);
243
396
  }
244
397
  return readStream(entry.startSector, entry.size);
245
398
  }
246
- return { entries, getStream };
399
+ const readable = (entry) => entry.type === ENTRY_TYPE_STREAM || entry.type === ENTRY_TYPE_ROOT;
400
+ return {
401
+ entries,
402
+ warnings,
403
+ getStream(name) {
404
+ const entry = findStreamByName(entries, name, readable);
405
+ return entry ? readEntry(entry) : void 0;
406
+ },
407
+ getStreamByPath(path) {
408
+ const entry = findDirectoryEntry(entries, path);
409
+ return entry && entry.type === ENTRY_TYPE_STREAM ? readEntry(entry) : void 0;
410
+ },
411
+ getStreamById(id) {
412
+ const entry = entries.find((candidate) => candidate.id === id);
413
+ return entry && readable(entry) ? readEntry(entry) : void 0;
414
+ },
415
+ findEntry(path) {
416
+ return findDirectoryEntry(entries, path);
417
+ }
418
+ };
247
419
  }
248
420
 
249
421
  // crypto/uuid.ts
@@ -263,7 +435,7 @@ function createOfficeGuid() {
263
435
  return `{${uuid.toUpperCase()}}`;
264
436
  }
265
437
 
266
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/utils/ooxml-crypto-primitives.js
438
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/utils/ooxml-crypto-primitives.js
267
439
  function getSubtle() {
268
440
  if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.subtle) {
269
441
  return globalThis.crypto.subtle;
@@ -2417,7 +2589,7 @@ var EncryptedFileError = class extends Error {
2417
2589
  }
2418
2590
  };
2419
2591
 
2420
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-helpers.js
2592
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-helpers.js
2421
2593
  function compareDirEntryNames(a, b) {
2422
2594
  const ua = a.toUpperCase();
2423
2595
  const ub = b.toUpperCase();
@@ -2484,7 +2656,7 @@ function writeInt32Sectors(outBytes, int32Data, firstSector, numSectors, sectorS
2484
2656
  }
2485
2657
  }
2486
2658
 
2487
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-serialize.js
2659
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-serialize.js
2488
2660
  function writeHeader(outView, outBytes, params) {
2489
2661
  outBytes.set(OLE_MAGIC, 0);
2490
2662
  outView.setUint16(24, 62, true);
@@ -2577,7 +2749,7 @@ function writeStreamSectors(outBytes, streamData, chain, sectorSize) {
2577
2749
  }
2578
2750
  }
2579
2751
 
2580
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write.js
2752
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-write.js
2581
2753
  function buildOle2(streams2, rootClsid, miniStreamCutoff = 4096) {
2582
2754
  const sectorSize = 512;
2583
2755
  const miniSectorSize = 64;
@@ -16,7 +16,7 @@
16
16
  * `spcAft` (35% after the node's own, 15% after a folded descendant, 20% in
17
17
  * a descendant-only box), never after the last paragraph.
18
18
  */
19
- import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated';
19
+ import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated.js';
20
20
  /** A folded descendant paragraph's size relative to the node's own text (cached corpus: 54/56 pairs). */
21
21
  export declare const DESCENDANT_FONT_SCALE = 0.78;
22
22
  /**
@@ -3,7 +3,7 @@
3
3
  * Moved from `pptx/core/utils/smartart-layout-item-font-size.ts`, which
4
4
  * re-exports it.
5
5
  */
6
- import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated';
6
+ import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated.js';
7
7
  /**
8
8
  * Resolve the {@link FontAdvanceTable} for `fontName`, defaulting to Calibri
9
9
  * (the Office theme's default minor font, and what SmartArt renders in
@@ -18,7 +18,7 @@
18
18
  * falls back to the existing uniform-slot behaviour rather than reaching
19
19
  * unverified code.
20
20
  */
21
- import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated';
21
+ import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated.js';
22
22
  import type { ConstraintIndex } from './smartart-constraint-solver.js';
23
23
  /**
24
24
  * True when the arranger declares `itemRole`'s own `mainAxisType` extent as
@@ -49,7 +49,7 @@
49
49
  */
50
50
  import type { DiagramLayoutNode } from '../model/index.js';
51
51
  import { resolveFontTable } from './smartart-font-table.js';
52
- import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated';
52
+ import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated.js';
53
53
  import type { ConstraintIndex } from './smartart-constraint-solver.js';
54
54
  import type { ArrangementPlan } from './smartart-layout-interpreter-model.js';
55
55
  export { primFontSzCeilingPx, resolveItemSelfAspect } from './smartart-layout-item-font-role.js';
@@ -37,7 +37,7 @@
37
37
  *
38
38
  * @module smartart-layout-item-font-tier-fit
39
39
  */
40
- import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated';
40
+ import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated.js';
41
41
  /** A folded item's own top-level text plus its descendant paragraphs, kept SEPARATE (see module doc comment). */
42
42
  export interface TieredFontFitItem {
43
43
  rootText: string;
@@ -13,7 +13,7 @@
13
13
  * Only fonts measured this way are listed; any other font keeps its table's
14
14
  * own `lineHeightRatio`.
15
15
  */
16
- import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated';
16
+ import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated.js';
17
17
  /**
18
18
  * A laid-out text block is taller than its lines by a fixed 0.00695em of the
19
19
  * first line's size: COM `TextRange.BoundHeight` of Aptos at 10, 20, 37 and
@@ -12,7 +12,7 @@
12
12
  * largest size (bounded by `[floor, ceiling]`) whose wrapped line count still
13
13
  * fits `maxHeight` at that font's own measured line-height ratio.
14
14
  */
15
- import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated';
15
+ import type { FontAdvanceTable } from '../../text/font-metrics/font-advance-widths.generated.js';
16
16
  /**
17
17
  * PowerPoint's own baked-in SmartArt paragraph line spacing: every gallery
18
18
  * fixture's cached `dsp:txBody` carries `<a:lnSpc><a:spcPct val="90000"/>`
@@ -6187,7 +6187,7 @@ function buildChartGradientDef(id, fill, bounds) {
6187
6187
  function chartGradientMarkup(def) {
6188
6188
  if (def.kind === "rectPath")
6189
6189
  return `<pattern id="${escapeXmlAttr(def.id)}" patternUnits="objectBoundingBox" patternContentUnits="objectBoundingBox" width="1" height="1"><image href="${escapeXmlAttr(def.href)}" width="1" height="1" preserveAspectRatio="none"/></pattern>`;
6190
- const geometry = def.kind === "linearGradient" ? `x1="${def.x1}" y1="${def.y1}" x2="${def.x2}" y2="${def.y2}"` : `cx="${def.cx}" cy="${def.cy}" r="${def.r}"`;
6190
+ const geometry = def.kind === "linearGradient" ? `${def.gradientUnits ? `gradientUnits="${def.gradientUnits}" ` : ""}x1="${def.x1}" y1="${def.y1}" x2="${def.x2}" y2="${def.y2}"` : `cx="${def.cx}" cy="${def.cy}" r="${def.r}"`;
6191
6191
  const stops = def.stops.map(
6192
6192
  (stop) => `<stop offset="${stop.offset}" stop-color="${escapeXmlAttr(stop.color)}" stop-opacity="${stop.opacity ?? 1}"/>`
6193
6193
  ).join("");
@@ -6181,7 +6181,7 @@ function buildChartGradientDef(id, fill, bounds) {
6181
6181
  function chartGradientMarkup(def) {
6182
6182
  if (def.kind === "rectPath")
6183
6183
  return `<pattern id="${escapeXmlAttr(def.id)}" patternUnits="objectBoundingBox" patternContentUnits="objectBoundingBox" width="1" height="1"><image href="${escapeXmlAttr(def.href)}" width="1" height="1" preserveAspectRatio="none"/></pattern>`;
6184
- const geometry = def.kind === "linearGradient" ? `x1="${def.x1}" y1="${def.y1}" x2="${def.x2}" y2="${def.y2}"` : `cx="${def.cx}" cy="${def.cy}" r="${def.r}"`;
6184
+ const geometry = def.kind === "linearGradient" ? `${def.gradientUnits ? `gradientUnits="${def.gradientUnits}" ` : ""}x1="${def.x1}" y1="${def.y1}" x2="${def.x2}" y2="${def.y2}"` : `cx="${def.cx}" cy="${def.cy}" r="${def.r}"`;
6185
6185
  const stops = def.stops.map(
6186
6186
  (stop) => `<stop offset="${stop.offset}" stop-color="${escapeXmlAttr(stop.color)}" stop-opacity="${stop.opacity ?? 1}"/>`
6187
6187
  ).join("");
@@ -2037,7 +2037,7 @@ function buildChartGradientDef(id, fill, bounds) {
2037
2037
  function chartGradientMarkup(def) {
2038
2038
  if (def.kind === "rectPath")
2039
2039
  return `<pattern id="${escapeXmlAttr(def.id)}" patternUnits="objectBoundingBox" patternContentUnits="objectBoundingBox" width="1" height="1"><image href="${escapeXmlAttr(def.href)}" width="1" height="1" preserveAspectRatio="none"/></pattern>`;
2040
- const geometry = def.kind === "linearGradient" ? `x1="${def.x1}" y1="${def.y1}" x2="${def.x2}" y2="${def.y2}"` : `cx="${def.cx}" cy="${def.cy}" r="${def.r}"`;
2040
+ const geometry = def.kind === "linearGradient" ? `${def.gradientUnits ? `gradientUnits="${def.gradientUnits}" ` : ""}x1="${def.x1}" y1="${def.y1}" x2="${def.x2}" y2="${def.y2}"` : `cx="${def.cx}" cy="${def.cy}" r="${def.r}"`;
2041
2041
  const stops = def.stops.map(
2042
2042
  (stop) => `<stop offset="${stop.offset}" stop-color="${escapeXmlAttr(stop.color)}" stop-opacity="${stop.opacity ?? 1}"/>`
2043
2043
  ).join("");
@@ -2035,7 +2035,7 @@ function buildChartGradientDef(id, fill, bounds) {
2035
2035
  function chartGradientMarkup(def) {
2036
2036
  if (def.kind === "rectPath")
2037
2037
  return `<pattern id="${escapeXmlAttr(def.id)}" patternUnits="objectBoundingBox" patternContentUnits="objectBoundingBox" width="1" height="1"><image href="${escapeXmlAttr(def.href)}" width="1" height="1" preserveAspectRatio="none"/></pattern>`;
2038
- const geometry = def.kind === "linearGradient" ? `x1="${def.x1}" y1="${def.y1}" x2="${def.x2}" y2="${def.y2}"` : `cx="${def.cx}" cy="${def.cy}" r="${def.r}"`;
2038
+ const geometry = def.kind === "linearGradient" ? `${def.gradientUnits ? `gradientUnits="${def.gradientUnits}" ` : ""}x1="${def.x1}" y1="${def.y1}" x2="${def.x2}" y2="${def.y2}"` : `cx="${def.cx}" cy="${def.cy}" r="${def.r}"`;
2039
2039
  const stops = def.stops.map(
2040
2040
  (stop) => `<stop offset="${stop.offset}" stop-color="${escapeXmlAttr(stop.color)}" stop-opacity="${stop.opacity ?? 1}"/>`
2041
2041
  ).join("");