ooxml-core 1.6.1 → 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.
@@ -1,6 +1,6 @@
1
- import { findText, replaceText, replaceTextInSlide, mergePresentation } from './chunk-RIFVZP2S.mjs';
2
- import { PresentationBuilder, PptxHandler, SlideBuilder, validateSeriesIndex, removeEmptyDataPoint, ensureDataPoint, ensureChartData, assertChartGradientSupported, toChartGradientFill, STANDARD_LAYOUTS, createTextElement, createShapeElement, createImageElement, createTableElement, createChartElement, createConnectorElement, createMediaElement, createGroupElement, PptxXmlBuilder } from './chunk-CS7HRNHL.mjs';
3
- import { escAttr, EMU_PER_PIXEL, EMU_PER_INCH, hasTextProperties } from './chunk-Q5LESLDA.mjs';
1
+ import { findText, replaceText, replaceTextInSlide, mergePresentation } from './chunk-ZAP5WLEN.mjs';
2
+ import { PresentationBuilder, PptxHandler, SlideBuilder, validateSeriesIndex, removeEmptyDataPoint, ensureDataPoint, ensureChartData, assertChartGradientSupported, toChartGradientFill, STANDARD_LAYOUTS, createTextElement, createShapeElement, createImageElement, createTableElement, createChartElement, createConnectorElement, createMediaElement, createGroupElement, PptxXmlBuilder } from './chunk-GAGSCAR3.mjs';
3
+ import { escAttr, EMU_PER_PIXEL, EMU_PER_INCH, hasTextProperties } from './chunk-TTPZITQN.mjs';
4
4
  import { cloneSlide, cloneElement } from './chunk-54S5A5PZ.mjs';
5
5
  import JSZip from 'jszip';
6
6
 
@@ -1,4 +1,4 @@
1
- import { hasTextProperties } from './chunk-Q5LESLDA.mjs';
1
+ import { hasTextProperties } from './chunk-TTPZITQN.mjs';
2
2
  import { cloneSlide } from './chunk-54S5A5PZ.mjs';
3
3
 
4
4
  // pptx/core/builders/sdk/merge-operations.ts
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-types.js
3
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-types.js
4
4
  var OLE_MAGIC = new Uint8Array([208, 207, 17, 224, 161, 177, 26, 225]);
5
5
  var ENDOFCHAIN = 4294967294;
6
6
  var FREESECT = 4294967295;
@@ -8,7 +8,9 @@ var FATSECT = 4294967293;
8
8
  var DIFSECT = 4294967292;
9
9
  var MAXREGSECT = 4294967290;
10
10
  var ENTRY_TYPE_EMPTY = 0;
11
+ var ENTRY_TYPE_STORAGE = 1;
11
12
  var ENTRY_TYPE_STREAM = 2;
13
+ var NOSTREAM = 4294967295;
12
14
  var ENTRY_TYPE_ROOT = 5;
13
15
  var DIR_ENTRY_SIZE = 128;
14
16
  var Ole2ParseError = class extends Error {
@@ -18,10 +20,174 @@ var Ole2ParseError = class extends Error {
18
20
  }
19
21
  };
20
22
 
21
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-read.js
22
- function parseOle2(buffer) {
23
- const data = new Uint8Array(buffer);
24
- const view = new DataView(buffer);
23
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-directory.js
24
+ var FILETIME_UNIX_EPOCH = 116444736000000000n;
25
+ function readFileTime(view, offset) {
26
+ const ticks = view.getBigUint64(offset, true);
27
+ if (ticks === 0n)
28
+ return void 0;
29
+ const ms = Number((ticks - FILETIME_UNIX_EPOCH) / 10000n);
30
+ const date = new Date(ms);
31
+ return Number.isNaN(date.getTime()) ? void 0 : date;
32
+ }
33
+ function decodeSlot(dir, id, majorVersion, warnings) {
34
+ const view = new DataView(dir.buffer, dir.byteOffset + id * DIR_ENTRY_SIZE, DIR_ENTRY_SIZE);
35
+ const nameLen = view.getUint16(64, true);
36
+ const type = view.getUint8(66);
37
+ const nameValid = nameLen >= 2 && nameLen <= 64 && nameLen % 2 === 0 && view.getUint16(nameLen - 2, true) === 0;
38
+ let name = "";
39
+ if (nameValid)
40
+ for (let j = 0; j < nameLen - 2; j += 2)
41
+ name += String.fromCharCode(view.getUint16(j, true));
42
+ const link = (offset) => {
43
+ const value = view.getUint32(offset, true);
44
+ return value === NOSTREAM ? -1 : value;
45
+ };
46
+ const sizeLow = view.getUint32(120, true);
47
+ const sizeHigh = view.getUint32(124, true);
48
+ let size = sizeLow;
49
+ if (majorVersion === 4)
50
+ size = sizeLow + sizeHigh * 4294967296;
51
+ else if (sizeHigh !== 0 && type !== ENTRY_TYPE_EMPTY) {
52
+ warnings.push({ code: "size-high-bits", message: `Ignored v3 stream-size high bits on directory entry ${id}` });
53
+ }
54
+ return {
55
+ id,
56
+ type,
57
+ nameValid,
58
+ entry: {
59
+ id,
60
+ name,
61
+ type,
62
+ color: view.getUint8(67),
63
+ leftSiblingId: link(68),
64
+ rightSiblingId: link(72),
65
+ childId: link(76),
66
+ clsid: new Uint8Array(view.buffer.slice(view.byteOffset + 80, view.byteOffset + 96)),
67
+ stateBits: view.getUint32(96, true),
68
+ created: readFileTime(view, 100),
69
+ modified: readFileTime(view, 108),
70
+ startSector: view.getUint32(116, true),
71
+ size,
72
+ parentId: -1
73
+ }
74
+ };
75
+ }
76
+ function readDirectory(dir, majorVersion, strict, warnings) {
77
+ const count = Math.floor(dir.length / DIR_ENTRY_SIZE);
78
+ const slots = [];
79
+ for (let id = 0; id < count; id++)
80
+ slots.push(decodeSlot(dir, id, majorVersion, warnings));
81
+ const roots = slots.filter((slot) => slot.type === ENTRY_TYPE_ROOT);
82
+ if (roots.length !== 1 || !roots[0].nameValid)
83
+ throw new Ole2ParseError("Invalid root directory entry");
84
+ const root = roots[0];
85
+ root.entry.path = [];
86
+ const reached = /* @__PURE__ */ new Set([root.id]);
87
+ const fail = (message) => {
88
+ if (strict)
89
+ throw new Ole2ParseError(message);
90
+ warnings.push({ code: "directory-link", message });
91
+ };
92
+ const pending = [];
93
+ const push = (id, parent, from) => {
94
+ if (id === -1)
95
+ return;
96
+ const target = slots[id];
97
+ if (!target || target.type === ENTRY_TYPE_EMPTY || target.type === ENTRY_TYPE_ROOT) {
98
+ fail(`Directory entry ${from} links to invalid entry ${id}`);
99
+ return;
100
+ }
101
+ if (reached.has(id)) {
102
+ fail(`Cyclic directory tree at entry ${id}`);
103
+ return;
104
+ }
105
+ reached.add(id);
106
+ pending.push({ id, parent });
107
+ };
108
+ push(root.entry.childId, root, root.id);
109
+ while (pending.length) {
110
+ const { id, parent } = pending.pop();
111
+ const slot = slots[id];
112
+ if (!slot.nameValid)
113
+ throw new Ole2ParseError("Invalid directory entry name");
114
+ slot.entry.parentId = parent.id;
115
+ slot.entry.path = [...parent.entry.path, slot.entry.name];
116
+ push(slot.entry.leftSiblingId, parent, id);
117
+ push(slot.entry.rightSiblingId, parent, id);
118
+ if (slot.type === ENTRY_TYPE_STORAGE)
119
+ push(slot.entry.childId, slot, id);
120
+ }
121
+ const entries = [];
122
+ for (const slot of slots) {
123
+ if (slot.type === ENTRY_TYPE_EMPTY)
124
+ continue;
125
+ if (!reached.has(slot.id)) {
126
+ if (!slot.nameValid) {
127
+ if (strict)
128
+ throw new Ole2ParseError("Invalid directory entry name");
129
+ warnings.push({ code: "invalid-unreachable-entry", message: `Skipped undecodable stale directory entry ${slot.id}` });
130
+ continue;
131
+ }
132
+ if (strict)
133
+ throw new Ole2ParseError(`Directory entry ${slot.id} is not reachable from the root`);
134
+ warnings.push({ code: "unreachable-entry", message: `Directory entry ${slot.id} (${slot.entry.name}) is not reachable from the root` });
135
+ }
136
+ entries.push(slot.entry);
137
+ }
138
+ return entries;
139
+ }
140
+ function sameName(a, b) {
141
+ return a.length === b.length && a.toUpperCase() === b.toUpperCase();
142
+ }
143
+ function bareName(name) {
144
+ return name.replace(/^[\u0001-\u0006]/, "");
145
+ }
146
+ function normalizePath(path, rootName) {
147
+ const parts = typeof path === "string" ? path.split("/").filter((part) => part !== "") : [...path];
148
+ if (parts.length && sameName(parts[0], rootName) && typeof path === "string")
149
+ parts.shift();
150
+ return parts;
151
+ }
152
+ function child(entries, parentId, name) {
153
+ const children = entries.filter((entry) => entry.parentId === parentId && entry.path !== void 0);
154
+ const pick = (matches) => matches.length === 1 ? matches[0] : void 0;
155
+ const exact = children.filter((entry) => entry.name === name);
156
+ if (exact.length)
157
+ return pick(exact);
158
+ const folded = children.filter((entry) => sameName(entry.name, name));
159
+ if (folded.length)
160
+ return pick(folded);
161
+ return pick(children.filter((entry) => sameName(bareName(entry.name), bareName(name))));
162
+ }
163
+ function findDirectoryEntry(entries, path) {
164
+ const root = entries.find((entry) => entry.type === ENTRY_TYPE_ROOT);
165
+ if (!root)
166
+ return void 0;
167
+ let current = root;
168
+ for (const name of normalizePath(path, root.name)) {
169
+ if (current.type !== ENTRY_TYPE_ROOT && current.type !== ENTRY_TYPE_STORAGE)
170
+ return void 0;
171
+ current = child(entries, current.id, name);
172
+ if (!current)
173
+ return void 0;
174
+ }
175
+ return current;
176
+ }
177
+ function findStreamByName(entries, name, isReadable) {
178
+ const root = entries.find((entry) => entry.type === ENTRY_TYPE_ROOT);
179
+ if (root && root.name === name)
180
+ return root;
181
+ const top = entries.filter((entry) => entry.parentId === root?.id && isReadable(entry));
182
+ return top.find((entry) => entry.name === name) ?? top.find((entry) => sameName(entry.name, name)) ?? entries.find((entry) => entry.name === name && isReadable(entry));
183
+ }
184
+
185
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-read.js
186
+ function parseOle2(buffer, options = {}) {
187
+ const strict = options.strict === true;
188
+ const data = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
189
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
190
+ const warnings = [];
25
191
  if (data.length < 512) {
26
192
  throw new Ole2ParseError("Truncated OLE2 compound file header");
27
193
  }
@@ -30,11 +196,12 @@ function parseOle2(buffer) {
30
196
  throw new Ole2ParseError("Not a valid OLE2 compound file");
31
197
  }
32
198
  }
33
- view.getUint16(24, true);
34
199
  const majorVersion = view.getUint16(26, true);
35
200
  const byteOrder = view.getUint16(28, true);
36
201
  if (byteOrder !== 65534) {
37
- throw new Ole2ParseError("Invalid byte order mark");
202
+ if (strict)
203
+ throw new Ole2ParseError("Invalid byte order mark");
204
+ warnings.push({ code: "byte-order", message: `Ignored byte order mark 0x${byteOrder.toString(16)}` });
38
205
  }
39
206
  const sectorSizePower = view.getUint16(30, true);
40
207
  const miniSectorSizePower = view.getUint16(32, true);
@@ -43,10 +210,14 @@ function parseOle2(buffer) {
43
210
  }
44
211
  const sectorSize = 1 << sectorSizePower;
45
212
  const miniSectorSize = 1 << miniSectorSizePower;
46
- if (data.length < sectorSize || data.length % sectorSize !== 0) {
213
+ if (data.length < sectorSize)
47
214
  throw new Ole2ParseError("Truncated OLE2 sector");
215
+ if (data.length % sectorSize !== 0) {
216
+ if (strict)
217
+ throw new Ole2ParseError("Truncated OLE2 sector");
218
+ warnings.push({ code: "unaligned-length", message: `File length ${data.length} is not a multiple of ${sectorSize}` });
48
219
  }
49
- const sectorCount = data.length / sectorSize - 1;
220
+ const sectorCount = Math.ceil(data.length / sectorSize) - 1;
50
221
  const totalFATSectors = view.getUint32(44, true);
51
222
  const firstDirectorySector = view.getUint32(48, true);
52
223
  const miniStreamCutoff = view.getUint32(56, true);
@@ -67,6 +238,13 @@ function parseOle2(buffer) {
67
238
  }
68
239
  return data.subarray(offset, offset + sectorSize);
69
240
  }
241
+ function copySector(sector, target, at, want) {
242
+ const offset = sectorOffset(sector);
243
+ if (sector >= sectorCount || offset + want > data.length) {
244
+ throw new Ole2ParseError(`Sector ${sector} at offset ${offset} exceeds file size ${data.length}`);
245
+ }
246
+ target.set(data.subarray(offset, offset + want), at);
247
+ }
70
248
  const fatSectors = [];
71
249
  for (let i2 = 0; i2 < 109 && fatSectors.length < totalFATSectors; i2++) {
72
250
  const sector = view.getUint32(76 + i2 * 4, true);
@@ -102,29 +280,36 @@ function parseOle2(buffer) {
102
280
  fatEntries.push(fatView.getUint32(i2 * 4, true));
103
281
  }
104
282
  }
105
- function readSectorChain(startSector) {
106
- const sectors = [];
107
- let current = startSector;
283
+ function followChain(table, start, label, needed) {
284
+ const ids = [];
108
285
  const visited = /* @__PURE__ */ new Set();
286
+ let current = start;
109
287
  while (current <= MAXREGSECT) {
288
+ if (!strict && needed !== void 0 && ids.length >= needed)
289
+ return ids;
110
290
  if (visited.has(current)) {
111
- throw new Ole2ParseError(`Circular reference in FAT chain at sector ${current}`);
291
+ throw new Ole2ParseError(`Circular reference in ${label} chain at sector ${current}`);
112
292
  }
113
293
  visited.add(current);
114
- sectors.push(readSector(current));
115
- if (fatEntries[current] === void 0)
116
- throw new Ole2ParseError("Missing FAT chain entry");
117
- current = fatEntries[current];
294
+ ids.push(current);
295
+ if (table[current] === void 0)
296
+ throw new Ole2ParseError(`Missing ${label} chain entry`);
297
+ current = table[current];
118
298
  }
119
- if (current !== ENDOFCHAIN)
120
- throw new Ole2ParseError("Invalid FAT chain terminator");
121
- const totalLength = sectors.length * sectorSize;
122
- const result = new Uint8Array(totalLength);
123
- let offset = 0;
124
- for (const sector of sectors) {
125
- result.set(sector, offset);
126
- offset += sectorSize;
299
+ if (current !== ENDOFCHAIN) {
300
+ if (strict || needed === void 0 || ids.length < needed) {
301
+ throw new Ole2ParseError(`Invalid ${label} chain terminator`);
302
+ }
303
+ warnings.push({ code: "chain-terminator", message: `Accepted ${label} chain ending in 0x${current.toString(16)}` });
127
304
  }
305
+ return ids;
306
+ }
307
+ function readMetadataChain(startSector, label) {
308
+ if (startSector > MAXREGSECT)
309
+ return new Uint8Array(0);
310
+ const ids = followChain(fatEntries, startSector, label === "directory" ? "FAT" : label);
311
+ const result = new Uint8Array(ids.length * sectorSize);
312
+ ids.forEach((id, i2) => result.set(readSector(id), i2 * sectorSize));
128
313
  return result;
129
314
  }
130
315
  function readStream(startSector, size) {
@@ -132,68 +317,44 @@ function parseOle2(buffer) {
132
317
  return new Uint8Array(0);
133
318
  if (size > sectorCount * sectorSize)
134
319
  throw new Ole2ParseError("Stream size exceeds file size");
135
- const raw = readSectorChain(startSector);
136
- if (raw.length < size)
320
+ const needed = Math.ceil(size / sectorSize);
321
+ const ids = followChain(fatEntries, startSector, "FAT", needed);
322
+ if (ids.length < needed)
137
323
  throw new Ole2ParseError("Truncated stream sector chain");
138
- return raw.subarray(0, size);
139
- }
140
- const dirRaw = readSectorChain(firstDirectorySector);
141
- const numEntries = Math.floor(dirRaw.length / DIR_ENTRY_SIZE);
142
- const entries = [];
143
- for (let i2 = 0; i2 < numEntries; i2++) {
144
- const entryOffset = i2 * DIR_ENTRY_SIZE;
145
- const entryView = new DataView(dirRaw.buffer, dirRaw.byteOffset + entryOffset, DIR_ENTRY_SIZE);
146
- const nameLen = entryView.getUint16(64, true);
147
- const objectType = entryView.getUint8(66);
148
- if (objectType === ENTRY_TYPE_EMPTY) {
149
- continue;
324
+ const result = new Uint8Array(size);
325
+ for (let i2 = 0; i2 < needed; i2++) {
326
+ copySector(ids[i2], result, i2 * sectorSize, Math.min(sectorSize, size - i2 * sectorSize));
150
327
  }
151
- if (nameLen < 2 || nameLen > 64 || nameLen % 2 !== 0 || entryView.getUint16(nameLen - 2, true) !== 0) {
152
- throw new Ole2ParseError("Invalid directory entry name");
153
- }
154
- const nameBytes = Math.max(0, nameLen - 2);
155
- let name = "";
156
- for (let j = 0; j < nameBytes; j += 2) {
157
- name += String.fromCharCode(entryView.getUint16(j, true));
158
- }
159
- const leftSiblingId = entryView.getUint32(68, true);
160
- const rightSiblingId = entryView.getUint32(72, true);
161
- const childId = entryView.getUint32(76, true);
162
- const clsid = new Uint8Array(entryView.buffer.slice(entryView.byteOffset + 80, entryView.byteOffset + 96));
163
- const startSector = entryView.getUint32(116, true);
164
- const sizeLow = entryView.getUint32(120, true);
165
- let size = sizeLow;
166
- if (majorVersion === 4) {
167
- const sizeHigh = entryView.getUint32(124, true);
168
- size = sizeLow + sizeHigh * 4294967296;
169
- if (!Number.isSafeInteger(size) || size > sectorCount * sectorSize) {
170
- throw new Ole2ParseError("Stream size exceeds supported file bounds");
171
- }
328
+ return result;
329
+ }
330
+ if (firstDirectorySector > MAXREGSECT)
331
+ throw new Ole2ParseError("Missing directory chain");
332
+ const entries = readDirectory(readMetadataChain(firstDirectorySector, "directory"), majorVersion, strict, warnings);
333
+ for (const entry of entries) {
334
+ if (majorVersion === 4 && (!Number.isSafeInteger(entry.size) || entry.size > sectorCount * sectorSize)) {
335
+ throw new Ole2ParseError("Stream size exceeds supported file bounds");
172
336
  }
173
- entries.push({
174
- name,
175
- type: objectType,
176
- startSector,
177
- size,
178
- childId: childId === 4294967295 ? -1 : childId,
179
- leftSiblingId: leftSiblingId === 4294967295 ? -1 : leftSiblingId,
180
- rightSiblingId: rightSiblingId === 4294967295 ? -1 : rightSiblingId,
181
- clsid
182
- });
183
337
  }
184
338
  const rootEntry = entries.find((e) => e.type === ENTRY_TYPE_ROOT);
185
- if (!rootEntry || entries.filter((e) => e.type === ENTRY_TYPE_ROOT).length !== 1) {
186
- throw new Ole2ParseError("Invalid root directory entry");
187
- }
188
339
  let miniStreamData;
189
- if (rootEntry && rootEntry.startSector <= MAXREGSECT) {
340
+ if (rootEntry.startSector <= MAXREGSECT) {
190
341
  miniStreamData = readStream(rootEntry.startSector, rootEntry.size);
191
342
  }
192
343
  const miniFatEntries = [];
193
- if (firstMiniFATSector <= MAXREGSECT && totalMiniFATSectors > 0) {
194
- const miniFatRaw = readSectorChain(firstMiniFATSector);
195
- if (miniFatRaw.length !== totalMiniFATSectors * sectorSize) {
344
+ if (firstMiniFATSector > MAXREGSECT && totalMiniFATSectors > 0) {
345
+ if (strict)
196
346
  throw new Ole2ParseError("Unexpected mini FAT chain length");
347
+ warnings.push({ code: "mini-fat-count", message: `Header lists ${totalMiniFATSectors} mini FAT sectors but no chain` });
348
+ }
349
+ if (firstMiniFATSector <= MAXREGSECT && (totalMiniFATSectors > 0 || !strict)) {
350
+ const miniFatRaw = readMetadataChain(firstMiniFATSector, "mini FAT");
351
+ if (miniFatRaw.length !== totalMiniFATSectors * sectorSize) {
352
+ if (strict)
353
+ throw new Ole2ParseError("Unexpected mini FAT chain length");
354
+ warnings.push({
355
+ code: "mini-fat-count",
356
+ message: `Header lists ${totalMiniFATSectors} mini FAT sectors; chain has ${miniFatRaw.length / sectorSize}`
357
+ });
197
358
  }
198
359
  const miniFatView = new DataView(miniFatRaw.buffer, miniFatRaw.byteOffset, miniFatRaw.byteLength);
199
360
  const miniCapacity = Math.floor((miniStreamData?.length ?? 0) / miniSectorSize);
@@ -207,45 +368,56 @@ function parseOle2(buffer) {
207
368
  if (!miniStreamData) {
208
369
  throw new Ole2ParseError("Mini stream container not found");
209
370
  }
210
- const sectors = [];
211
- let current = startSector;
212
- const visited = /* @__PURE__ */ new Set();
213
- while (current <= MAXREGSECT) {
214
- if (visited.has(current)) {
215
- throw new Ole2ParseError(`Circular reference in mini FAT chain at sector ${current}`);
371
+ const needed = Math.ceil(size / miniSectorSize);
372
+ const capacity = miniStreamData.length / miniSectorSize;
373
+ let ids;
374
+ try {
375
+ ids = followChain(miniFatEntries, startSector, "mini FAT", needed);
376
+ } catch (error) {
377
+ if (error instanceof Ole2ParseError && /Missing mini FAT/.test(error.message)) {
378
+ throw new Ole2ParseError("Mini stream sector exceeds allocation bounds");
216
379
  }
217
- visited.add(current);
218
- const offset2 = current * miniSectorSize;
219
- if (offset2 + miniSectorSize > miniStreamData.length || miniFatEntries[current] === void 0) {
380
+ throw error;
381
+ }
382
+ const result = new Uint8Array(size);
383
+ for (let i2 = 0; i2 < ids.length && i2 < needed; i2++) {
384
+ const id = ids[i2];
385
+ if (id >= capacity || (id + 1) * miniSectorSize > miniStreamData.length) {
220
386
  throw new Ole2ParseError("Mini stream sector exceeds allocation bounds");
221
387
  }
222
- sectors.push(miniStreamData.subarray(offset2, offset2 + miniSectorSize));
223
- current = miniFatEntries[current];
388
+ const want = Math.min(miniSectorSize, size - i2 * miniSectorSize);
389
+ result.set(miniStreamData.subarray(id * miniSectorSize, id * miniSectorSize + want), i2 * miniSectorSize);
224
390
  }
225
- if (current !== ENDOFCHAIN)
226
- throw new Ole2ParseError("Invalid mini FAT chain terminator");
227
- const totalLength = sectors.length * miniSectorSize;
228
- if (totalLength < size)
391
+ if (ids.length < needed)
229
392
  throw new Ole2ParseError("Truncated mini stream sector chain");
230
- const result = new Uint8Array(totalLength);
231
- let offset = 0;
232
- for (const sector of sectors) {
233
- result.set(sector, offset);
234
- offset += miniSectorSize;
235
- }
236
- return result.subarray(0, size);
393
+ return result;
237
394
  }
238
- function getStream(name) {
239
- const entry = entries.find((e) => (e.type === ENTRY_TYPE_STREAM || e.type === ENTRY_TYPE_ROOT) && e.name === name);
240
- if (!entry) {
241
- return void 0;
242
- }
395
+ function readEntry(entry) {
243
396
  if (entry.size < miniStreamCutoff && entry.type !== ENTRY_TYPE_ROOT) {
244
397
  return readMiniStream(entry.startSector, entry.size);
245
398
  }
246
399
  return readStream(entry.startSector, entry.size);
247
400
  }
248
- return { entries, getStream };
401
+ const readable = (entry) => entry.type === ENTRY_TYPE_STREAM || entry.type === ENTRY_TYPE_ROOT;
402
+ return {
403
+ entries,
404
+ warnings,
405
+ getStream(name) {
406
+ const entry = findStreamByName(entries, name, readable);
407
+ return entry ? readEntry(entry) : void 0;
408
+ },
409
+ getStreamByPath(path) {
410
+ const entry = findDirectoryEntry(entries, path);
411
+ return entry && entry.type === ENTRY_TYPE_STREAM ? readEntry(entry) : void 0;
412
+ },
413
+ getStreamById(id) {
414
+ const entry = entries.find((candidate) => candidate.id === id);
415
+ return entry && readable(entry) ? readEntry(entry) : void 0;
416
+ },
417
+ findEntry(path) {
418
+ return findDirectoryEntry(entries, path);
419
+ }
420
+ };
249
421
  }
250
422
 
251
423
  // crypto/uuid.ts
@@ -265,7 +437,7 @@ function createOfficeGuid() {
265
437
  return `{${uuid.toUpperCase()}}`;
266
438
  }
267
439
 
268
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/utils/ooxml-crypto-primitives.js
440
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/utils/ooxml-crypto-primitives.js
269
441
  function getSubtle() {
270
442
  if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.subtle) {
271
443
  return globalThis.crypto.subtle;
@@ -2419,7 +2591,7 @@ var EncryptedFileError = class extends Error {
2419
2591
  }
2420
2592
  };
2421
2593
 
2422
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-helpers.js
2594
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-helpers.js
2423
2595
  function compareDirEntryNames(a, b) {
2424
2596
  const ua = a.toUpperCase();
2425
2597
  const ub = b.toUpperCase();
@@ -2486,7 +2658,7 @@ function writeInt32Sectors(outBytes, int32Data, firstSector, numSectors, sectorS
2486
2658
  }
2487
2659
  }
2488
2660
 
2489
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-serialize.js
2661
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-serialize.js
2490
2662
  function writeHeader(outView, outBytes, params) {
2491
2663
  outBytes.set(OLE_MAGIC, 0);
2492
2664
  outView.setUint16(24, 62, true);
@@ -2579,7 +2751,7 @@ function writeStreamSectors(outBytes, streamData, chain, sectorSize) {
2579
2751
  }
2580
2752
  }
2581
2753
 
2582
- // ../../node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write.js
2754
+ // ../../node_modules/.bun/@christophervr+ole2@0.13.0/node_modules/@christophervr/ole2/dist/ole2-parser-write.js
2583
2755
  function buildOle2(streams2, rootClsid, miniStreamCutoff = 4096) {
2584
2756
  const sectorSize = 512;
2585
2757
  const miniSectorSize = 64;