@xlsxflow/core 1.1.4 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +15 -6
- package/dist/index.cjs +45 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +45 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -56,21 +56,34 @@ class ZipStreamWriter {
|
|
|
56
56
|
// Stream data, tracking sizes and CRC32
|
|
57
57
|
let uncompressedSize = 0;
|
|
58
58
|
let crc = 0xffffffff;
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
const compressor = new CompressionStream('deflate-raw');
|
|
60
|
+
const writer = compressor.writable.getWriter();
|
|
61
|
+
const reader = compressor.readable.getReader();
|
|
62
|
+
const input = inputStream.getReader();
|
|
63
|
+
// Node's and Bun's CompressionStream accept thousands of writes without backpressure, so one chunk
|
|
64
|
+
// is fed at a time: a write resolves once the chunk is compressed, which waits while nobody reads
|
|
65
|
+
// the output. Rows are then only pulled as fast as the ZIP is consumed.
|
|
66
|
+
const feed = (async () => {
|
|
67
|
+
try {
|
|
68
|
+
while (true) {
|
|
69
|
+
const { done, value } = await input.read();
|
|
70
|
+
if (done)
|
|
71
|
+
break;
|
|
72
|
+
await this.roomInQueue();
|
|
73
|
+
uncompressedSize += value.length;
|
|
74
|
+
crc = crc32Update(crc, value);
|
|
75
|
+
await writer.write(value);
|
|
76
|
+
}
|
|
77
|
+
await writer.close();
|
|
67
78
|
}
|
|
68
|
-
|
|
79
|
+
catch (err) {
|
|
80
|
+
// Stop the source too (a row generator's finally runs, a database cursor closes)
|
|
81
|
+
await input.cancel(err).catch(() => { });
|
|
82
|
+
await writer.abort(err).catch(() => { });
|
|
83
|
+
throw err;
|
|
84
|
+
}
|
|
85
|
+
})();
|
|
69
86
|
let compressedSize = 0;
|
|
70
|
-
const reader = inputStream
|
|
71
|
-
.pipeThrough(crcStream)
|
|
72
|
-
.pipeThrough(new CompressionStream('deflate-raw'))
|
|
73
|
-
.getReader();
|
|
74
87
|
try {
|
|
75
88
|
while (true) {
|
|
76
89
|
const { done, value } = await reader.read();
|
|
@@ -79,10 +92,12 @@ class ZipStreamWriter {
|
|
|
79
92
|
compressedSize += value.length;
|
|
80
93
|
await this.pushChunk(value);
|
|
81
94
|
}
|
|
95
|
+
await feed;
|
|
82
96
|
}
|
|
83
97
|
catch (err) {
|
|
84
|
-
// Stop the source too (a row generator's finally runs, a database cursor closes)
|
|
85
98
|
await reader.cancel(err).catch(() => { });
|
|
99
|
+
await input.cancel(err).catch(() => { });
|
|
100
|
+
await feed.catch(() => { });
|
|
86
101
|
throw err;
|
|
87
102
|
}
|
|
88
103
|
crc = (crc ^ 0xffffffff) >>> 0;
|
|
@@ -3856,6 +3871,10 @@ class SheetWriter {
|
|
|
3856
3871
|
const box = parseRange$1(table.ref, 'table range');
|
|
3857
3872
|
if (boxes.some(b => overlaps(b, box)))
|
|
3858
3873
|
throw new Error(`Table "${table.name}" overlaps another table on sheet "${sheet.name}".`);
|
|
3874
|
+
// Excel tables cannot hold merged cells: it repairs the file by removing the table
|
|
3875
|
+
const merge = sheet.options.mergeCells?.find(ref => overlaps(parseRange$1(ref, 'merge range'), box));
|
|
3876
|
+
if (merge)
|
|
3877
|
+
throw new Error(`Merge "${merge}" overlaps table "${table.name}" on sheet "${sheet.name}"; Excel tables cannot contain merged cells.`);
|
|
3859
3878
|
boxes.push(box);
|
|
3860
3879
|
const first = colIndex(m[1]);
|
|
3861
3880
|
const width = colIndex(m[3]) - first + 1;
|
|
@@ -4357,8 +4376,18 @@ function createBlobReader(blob) {
|
|
|
4357
4376
|
return new Uint8Array(await slice.arrayBuffer());
|
|
4358
4377
|
},
|
|
4359
4378
|
stream(offset, length) {
|
|
4360
|
-
|
|
4361
|
-
|
|
4379
|
+
// Bun's Blob.slice(start, end).stream() runs on to the end of the original blob, so stop at length
|
|
4380
|
+
let left = length;
|
|
4381
|
+
return blob.slice(offset, offset + length).stream().pipeThrough(new TransformStream({
|
|
4382
|
+
start(controller) { if (left <= 0)
|
|
4383
|
+
controller.terminate(); },
|
|
4384
|
+
transform(chunk, controller) {
|
|
4385
|
+
controller.enqueue(chunk.length > left ? chunk.subarray(0, left) : chunk);
|
|
4386
|
+
left -= chunk.length;
|
|
4387
|
+
if (left <= 0)
|
|
4388
|
+
controller.terminate();
|
|
4389
|
+
}
|
|
4390
|
+
}));
|
|
4362
4391
|
},
|
|
4363
4392
|
async close() { }
|
|
4364
4393
|
};
|