@cj-tech-master/excelts 1.1.0 → 1.4.1
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/dist/browser/excelts.iife.js +1089 -568
- package/dist/browser/excelts.iife.js.map +1 -1
- package/dist/browser/excelts.iife.min.js +18 -18
- package/dist/cjs/doc/data-validations.js +29 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/utils/cell-format.js +815 -0
- package/dist/cjs/utils/parse-sax.js +2 -2
- package/dist/cjs/utils/{extra-utils.js → sheet-utils.js} +114 -89
- package/dist/cjs/utils/stream-buf.js +15 -4
- package/dist/cjs/utils/unzip/parse.js +82 -1
- package/dist/cjs/utils/utils.js +13 -17
- package/dist/cjs/utils/zip-stream.js +20 -32
- package/dist/cjs/xlsx/xform/sheet/data-validations-xform.js +46 -7
- package/dist/cjs/xlsx/xlsx.js +1 -2
- package/dist/esm/doc/data-validations.js +29 -1
- package/dist/esm/index.browser.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/utils/cell-format.js +810 -0
- package/dist/esm/utils/parse-sax.js +1 -1
- package/dist/esm/utils/{extra-utils.js → sheet-utils.js} +97 -72
- package/dist/esm/utils/stream-buf.js +15 -4
- package/dist/esm/utils/unzip/parse.js +83 -2
- package/dist/esm/utils/utils.js +12 -16
- package/dist/esm/utils/zip-stream.js +20 -32
- package/dist/esm/xlsx/xform/sheet/data-validations-xform.js +46 -7
- package/dist/esm/xlsx/xlsx.js +1 -2
- package/dist/types/index.browser.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/utils/cell-format.d.ts +32 -0
- package/dist/types/utils/{extra-utils.d.ts → sheet-utils.d.ts} +51 -52
- package/dist/types/utils/utils.d.ts +5 -2
- package/package.json +5 -5
- package/dist/cjs/utils/browser-buffer-decode.js +0 -13
- package/dist/cjs/utils/browser-buffer-encode.js +0 -13
- package/dist/cjs/utils/browser.js +0 -6
- package/dist/esm/utils/browser-buffer-decode.js +0 -11
- package/dist/esm/utils/browser-buffer-encode.js +0 -11
- package/dist/esm/utils/browser.js +0 -3
- package/dist/types/utils/browser-buffer-decode.d.ts +0 -2
- package/dist/types/utils/browser-buffer-encode.d.ts +0 -2
- package/dist/types/utils/browser.d.ts +0 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseSax = parseSax;
|
|
4
4
|
const saxes_1 = require("saxes");
|
|
5
|
-
const
|
|
5
|
+
const utils_js_1 = require("./utils");
|
|
6
6
|
async function* parseSax(iterable) {
|
|
7
7
|
const saxesParser = new saxes_1.SaxesParser({
|
|
8
8
|
xmlns: false,
|
|
@@ -17,7 +17,7 @@ async function* parseSax(iterable) {
|
|
|
17
17
|
saxesParser.on("text", (value) => events.push({ eventType: "text", value }));
|
|
18
18
|
saxesParser.on("closetag", (value) => events.push({ eventType: "closetag", value }));
|
|
19
19
|
for await (const chunk of iterable) {
|
|
20
|
-
saxesParser.write((0,
|
|
20
|
+
saxesParser.write((0, utils_js_1.bufferToString)(chunk));
|
|
21
21
|
// saxesParser.write and saxesParser.on() are synchronous,
|
|
22
22
|
// so we can only reach the below line once all events have been emitted
|
|
23
23
|
if (error) {
|
|
@@ -2,106 +2,131 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Utility functions for ExcelTS
|
|
4
4
|
* Provides convenient helper functions for common spreadsheet operations
|
|
5
|
-
* compatible with xlsx library's utils API but built on excelts native types
|
|
6
5
|
*/
|
|
7
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
7
|
exports.utils = void 0;
|
|
9
|
-
exports.
|
|
10
|
-
exports.
|
|
11
|
-
exports.
|
|
12
|
-
exports.
|
|
13
|
-
exports.
|
|
14
|
-
exports.
|
|
15
|
-
exports.
|
|
16
|
-
exports.
|
|
17
|
-
exports.
|
|
18
|
-
exports.
|
|
19
|
-
exports.
|
|
20
|
-
exports.
|
|
21
|
-
exports.
|
|
22
|
-
exports.
|
|
23
|
-
exports.
|
|
24
|
-
exports.
|
|
25
|
-
exports.
|
|
8
|
+
exports.decodeCol = decodeCol;
|
|
9
|
+
exports.encodeCol = encodeCol;
|
|
10
|
+
exports.decodeRow = decodeRow;
|
|
11
|
+
exports.encodeRow = encodeRow;
|
|
12
|
+
exports.decodeCell = decodeCell;
|
|
13
|
+
exports.encodeCell = encodeCell;
|
|
14
|
+
exports.decodeRange = decodeRange;
|
|
15
|
+
exports.encodeRange = encodeRange;
|
|
16
|
+
exports.jsonToSheet = jsonToSheet;
|
|
17
|
+
exports.sheetAddJson = sheetAddJson;
|
|
18
|
+
exports.sheetToJson = sheetToJson;
|
|
19
|
+
exports.sheetToCsv = sheetToCsv;
|
|
20
|
+
exports.bookNew = bookNew;
|
|
21
|
+
exports.bookAppendSheet = bookAppendSheet;
|
|
22
|
+
exports.aoaToSheet = aoaToSheet;
|
|
23
|
+
exports.sheetAddAoa = sheetAddAoa;
|
|
24
|
+
exports.sheetToAoa = sheetToAoa;
|
|
26
25
|
const workbook_js_1 = require("../doc/workbook");
|
|
27
26
|
const col_cache_js_1 = require("./col-cache");
|
|
27
|
+
const utils_js_1 = require("./utils");
|
|
28
|
+
const cell_format_js_1 = require("./cell-format");
|
|
29
|
+
/**
|
|
30
|
+
* Get formatted display text for a cell value
|
|
31
|
+
* Returns the value formatted according to the cell's numFmt
|
|
32
|
+
* This matches Excel's display exactly
|
|
33
|
+
*/
|
|
34
|
+
function getCellDisplayText(cell) {
|
|
35
|
+
const value = cell.value;
|
|
36
|
+
const fmt = cell.numFmt || "General";
|
|
37
|
+
// Null/undefined
|
|
38
|
+
if (value == null) {
|
|
39
|
+
return "";
|
|
40
|
+
}
|
|
41
|
+
// Date object - convert to Excel serial number
|
|
42
|
+
if (value instanceof Date) {
|
|
43
|
+
const serial = (0, utils_js_1.dateToExcel)(value, false);
|
|
44
|
+
return (0, cell_format_js_1.format)(fmt, serial);
|
|
45
|
+
}
|
|
46
|
+
// Number/Boolean/String - let cellFormat handle it
|
|
47
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "string") {
|
|
48
|
+
return (0, cell_format_js_1.format)(fmt, value);
|
|
49
|
+
}
|
|
50
|
+
// Fallback to cell.text for other types (rich text, hyperlink, error, formula, etc.)
|
|
51
|
+
return cell.text;
|
|
52
|
+
}
|
|
28
53
|
// =============================================================================
|
|
29
54
|
// Cell Address Encoding/Decoding
|
|
30
55
|
// =============================================================================
|
|
31
56
|
/**
|
|
32
57
|
* Decode column string to 0-indexed number
|
|
33
|
-
* @example
|
|
58
|
+
* @example decodeCol("A") => 0, decodeCol("Z") => 25, decodeCol("AA") => 26
|
|
34
59
|
*/
|
|
35
|
-
function
|
|
60
|
+
function decodeCol(colstr) {
|
|
36
61
|
return col_cache_js_1.colCache.l2n(colstr.toUpperCase()) - 1;
|
|
37
62
|
}
|
|
38
63
|
/**
|
|
39
64
|
* Encode 0-indexed column number to string
|
|
40
|
-
* @example
|
|
65
|
+
* @example encodeCol(0) => "A", encodeCol(25) => "Z", encodeCol(26) => "AA"
|
|
41
66
|
*/
|
|
42
|
-
function
|
|
67
|
+
function encodeCol(col) {
|
|
43
68
|
return col_cache_js_1.colCache.n2l(col + 1);
|
|
44
69
|
}
|
|
45
70
|
/**
|
|
46
71
|
* Decode row string to 0-indexed number
|
|
47
|
-
* @example
|
|
72
|
+
* @example decodeRow("1") => 0, decodeRow("10") => 9
|
|
48
73
|
*/
|
|
49
|
-
function
|
|
74
|
+
function decodeRow(rowstr) {
|
|
50
75
|
return parseInt(rowstr, 10) - 1;
|
|
51
76
|
}
|
|
52
77
|
/**
|
|
53
78
|
* Encode 0-indexed row number to string
|
|
54
|
-
* @example
|
|
79
|
+
* @example encodeRow(0) => "1", encodeRow(9) => "10"
|
|
55
80
|
*/
|
|
56
|
-
function
|
|
81
|
+
function encodeRow(row) {
|
|
57
82
|
return String(row + 1);
|
|
58
83
|
}
|
|
59
84
|
/**
|
|
60
85
|
* Decode cell address string to CellAddress object
|
|
61
|
-
* @example
|
|
86
|
+
* @example decodeCell("A1") => {c: 0, r: 0}, decodeCell("B2") => {c: 1, r: 1}
|
|
62
87
|
*/
|
|
63
|
-
function
|
|
88
|
+
function decodeCell(cstr) {
|
|
64
89
|
const addr = col_cache_js_1.colCache.decodeAddress(cstr.toUpperCase());
|
|
65
90
|
return { c: addr.col - 1, r: addr.row - 1 };
|
|
66
91
|
}
|
|
67
92
|
/**
|
|
68
93
|
* Encode CellAddress object to cell address string
|
|
69
|
-
* @example
|
|
94
|
+
* @example encodeCell({c: 0, r: 0}) => "A1", encodeCell({c: 1, r: 1}) => "B2"
|
|
70
95
|
*/
|
|
71
|
-
function
|
|
96
|
+
function encodeCell(cell) {
|
|
72
97
|
return col_cache_js_1.colCache.encodeAddress(cell.r + 1, cell.c + 1);
|
|
73
98
|
}
|
|
74
99
|
/**
|
|
75
100
|
* Decode range string to Range object
|
|
76
|
-
* @example
|
|
101
|
+
* @example decodeRange("A1:B2") => {s: {c: 0, r: 0}, e: {c: 1, r: 1}}
|
|
77
102
|
*/
|
|
78
|
-
function
|
|
103
|
+
function decodeRange(range) {
|
|
79
104
|
const idx = range.indexOf(":");
|
|
80
105
|
if (idx === -1) {
|
|
81
|
-
const cell =
|
|
106
|
+
const cell = decodeCell(range);
|
|
82
107
|
return { s: cell, e: { ...cell } };
|
|
83
108
|
}
|
|
84
109
|
return {
|
|
85
|
-
s:
|
|
86
|
-
e:
|
|
110
|
+
s: decodeCell(range.slice(0, idx)),
|
|
111
|
+
e: decodeCell(range.slice(idx + 1))
|
|
87
112
|
};
|
|
88
113
|
}
|
|
89
|
-
function
|
|
114
|
+
function encodeRange(startOrRange, end) {
|
|
90
115
|
if (end === undefined) {
|
|
91
116
|
const range = startOrRange;
|
|
92
|
-
return
|
|
117
|
+
return encodeRange(range.s, range.e);
|
|
93
118
|
}
|
|
94
119
|
const start = startOrRange;
|
|
95
|
-
const startStr =
|
|
96
|
-
const endStr =
|
|
120
|
+
const startStr = encodeCell(start);
|
|
121
|
+
const endStr = encodeCell(end);
|
|
97
122
|
return startStr === endStr ? startStr : `${startStr}:${endStr}`;
|
|
98
123
|
}
|
|
99
124
|
/**
|
|
100
125
|
* Create a worksheet from an array of objects (xlsx compatible)
|
|
101
126
|
* @example
|
|
102
|
-
* const ws =
|
|
127
|
+
* const ws = jsonToSheet([{name: "Alice", age: 30}, {name: "Bob", age: 25}])
|
|
103
128
|
*/
|
|
104
|
-
function
|
|
129
|
+
function jsonToSheet(data, opts) {
|
|
105
130
|
const o = opts || {};
|
|
106
131
|
// Create a temporary workbook to get a worksheet
|
|
107
132
|
const tempWb = new workbook_js_1.Workbook();
|
|
@@ -147,7 +172,7 @@ function json_to_sheet(data, opts) {
|
|
|
147
172
|
/**
|
|
148
173
|
* Add data from an array of objects to an existing worksheet (xlsx compatible)
|
|
149
174
|
*/
|
|
150
|
-
function
|
|
175
|
+
function sheetAddJson(worksheet, data, opts) {
|
|
151
176
|
const o = opts || {};
|
|
152
177
|
if (data.length === 0) {
|
|
153
178
|
return worksheet;
|
|
@@ -157,7 +182,7 @@ function sheet_add_json(worksheet, data, opts) {
|
|
|
157
182
|
let startCol = 1;
|
|
158
183
|
if (o.origin !== undefined) {
|
|
159
184
|
if (typeof o.origin === "string") {
|
|
160
|
-
const addr =
|
|
185
|
+
const addr = decodeCell(o.origin);
|
|
161
186
|
startRow = addr.r + 1;
|
|
162
187
|
startCol = addr.c + 1;
|
|
163
188
|
}
|
|
@@ -213,18 +238,18 @@ function sheet_add_json(worksheet, data, opts) {
|
|
|
213
238
|
* Convert worksheet to JSON array (xlsx compatible)
|
|
214
239
|
* @example
|
|
215
240
|
* // Default: array of objects with first row as headers
|
|
216
|
-
* const data =
|
|
241
|
+
* const data = sheetToJson(worksheet)
|
|
217
242
|
* // => [{name: "Alice", age: 30}, {name: "Bob", age: 25}]
|
|
218
243
|
*
|
|
219
244
|
* // Array of arrays
|
|
220
|
-
* const aoa =
|
|
245
|
+
* const aoa = sheetToJson(worksheet, { header: 1 })
|
|
221
246
|
* // => [["name", "age"], ["Alice", 30], ["Bob", 25]]
|
|
222
247
|
*
|
|
223
248
|
* // Column letters as keys
|
|
224
|
-
* const cols =
|
|
249
|
+
* const cols = sheetToJson(worksheet, { header: "A" })
|
|
225
250
|
* // => [{A: "name", B: "age"}, {A: "Alice", B: 30}]
|
|
226
251
|
*/
|
|
227
|
-
function
|
|
252
|
+
function sheetToJson(worksheet, opts) {
|
|
228
253
|
const o = opts || {};
|
|
229
254
|
// Determine range
|
|
230
255
|
let startRow = 1;
|
|
@@ -236,7 +261,7 @@ function sheet_to_json(worksheet, opts) {
|
|
|
236
261
|
startRow = o.range + 1; // 0-indexed to 1-indexed
|
|
237
262
|
}
|
|
238
263
|
else if (typeof o.range === "string") {
|
|
239
|
-
const r =
|
|
264
|
+
const r = decodeRange(o.range);
|
|
240
265
|
startRow = r.s.r + 1;
|
|
241
266
|
endRow = r.e.r + 1;
|
|
242
267
|
startCol = r.s.c + 1;
|
|
@@ -258,8 +283,8 @@ function sheet_to_json(worksheet, opts) {
|
|
|
258
283
|
let isEmpty = true;
|
|
259
284
|
for (let col = startCol; col <= endCol; col++) {
|
|
260
285
|
const cell = worksheet.getCell(row, col);
|
|
261
|
-
const val = cell.value;
|
|
262
|
-
if (val != null) {
|
|
286
|
+
const val = o.raw === false ? getCellDisplayText(cell).trim() : cell.value;
|
|
287
|
+
if (val != null && val !== "") {
|
|
263
288
|
rowData[col - startCol] = val;
|
|
264
289
|
isEmpty = false;
|
|
265
290
|
}
|
|
@@ -286,9 +311,9 @@ function sheet_to_json(worksheet, opts) {
|
|
|
286
311
|
let isEmpty = true;
|
|
287
312
|
for (let col = startCol; col <= endCol; col++) {
|
|
288
313
|
const cell = worksheet.getCell(row, col);
|
|
289
|
-
const val = cell.value;
|
|
290
|
-
const key =
|
|
291
|
-
if (val != null) {
|
|
314
|
+
const val = o.raw === false ? getCellDisplayText(cell).trim() : cell.value;
|
|
315
|
+
const key = encodeCol(col - 1); // 0-indexed for encodeCol
|
|
316
|
+
if (val != null && val !== "") {
|
|
292
317
|
rowData[key] = val;
|
|
293
318
|
isEmpty = false;
|
|
294
319
|
}
|
|
@@ -313,8 +338,8 @@ function sheet_to_json(worksheet, opts) {
|
|
|
313
338
|
const colIdx = col - startCol;
|
|
314
339
|
const key = headerOpt[colIdx] ?? `__EMPTY_${colIdx}`;
|
|
315
340
|
const cell = worksheet.getCell(row, col);
|
|
316
|
-
const val = cell.value;
|
|
317
|
-
if (val != null) {
|
|
341
|
+
const val = o.raw === false ? getCellDisplayText(cell).trim() : cell.value;
|
|
342
|
+
if (val != null && val !== "") {
|
|
318
343
|
rowData[key] = val;
|
|
319
344
|
isEmpty = false;
|
|
320
345
|
}
|
|
@@ -355,9 +380,9 @@ function sheet_to_json(worksheet, opts) {
|
|
|
355
380
|
let isEmpty = true;
|
|
356
381
|
for (let col = startCol; col <= endCol; col++) {
|
|
357
382
|
const cell = worksheet.getCell(row, col);
|
|
358
|
-
const val = cell.value;
|
|
383
|
+
const val = o.raw === false ? getCellDisplayText(cell).trim() : cell.value;
|
|
359
384
|
const key = headers[col - startCol];
|
|
360
|
-
if (val != null) {
|
|
385
|
+
if (val != null && val !== "") {
|
|
361
386
|
rowData[key] = val;
|
|
362
387
|
isEmpty = false;
|
|
363
388
|
}
|
|
@@ -374,7 +399,7 @@ function sheet_to_json(worksheet, opts) {
|
|
|
374
399
|
/**
|
|
375
400
|
* Convert worksheet to CSV string
|
|
376
401
|
*/
|
|
377
|
-
function
|
|
402
|
+
function sheetToCsv(worksheet, opts) {
|
|
378
403
|
const o = opts || {};
|
|
379
404
|
const FS = o.FS ?? ",";
|
|
380
405
|
const RS = o.RS ?? "\n";
|
|
@@ -435,17 +460,17 @@ function sheet_to_csv(worksheet, opts) {
|
|
|
435
460
|
/**
|
|
436
461
|
* Create a new workbook
|
|
437
462
|
*/
|
|
438
|
-
function
|
|
463
|
+
function bookNew() {
|
|
439
464
|
return new workbook_js_1.Workbook();
|
|
440
465
|
}
|
|
441
466
|
/**
|
|
442
467
|
* Append worksheet to workbook (xlsx compatible)
|
|
443
468
|
* @example
|
|
444
|
-
* const wb =
|
|
445
|
-
* const ws =
|
|
446
|
-
*
|
|
469
|
+
* const wb = bookNew();
|
|
470
|
+
* const ws = jsonToSheet([{a: 1, b: 2}]);
|
|
471
|
+
* bookAppendSheet(wb, ws, "Sheet1");
|
|
447
472
|
*/
|
|
448
|
-
function
|
|
473
|
+
function bookAppendSheet(workbook, worksheet, name) {
|
|
449
474
|
// Copy the worksheet data to a new sheet in the workbook
|
|
450
475
|
const newWs = workbook.addWorksheet(name);
|
|
451
476
|
// Copy all cells from source worksheet
|
|
@@ -470,9 +495,9 @@ function book_append_sheet(workbook, worksheet, name) {
|
|
|
470
495
|
/**
|
|
471
496
|
* Create a worksheet from an array of arrays (xlsx compatible)
|
|
472
497
|
* @example
|
|
473
|
-
* const ws =
|
|
498
|
+
* const ws = aoaToSheet([["Name", "Age"], ["Alice", 30], ["Bob", 25]])
|
|
474
499
|
*/
|
|
475
|
-
function
|
|
500
|
+
function aoaToSheet(data, opts) {
|
|
476
501
|
const tempWb = new workbook_js_1.Workbook();
|
|
477
502
|
const worksheet = tempWb.addWorksheet("Sheet1");
|
|
478
503
|
if (data.length === 0) {
|
|
@@ -483,7 +508,7 @@ function aoa_to_sheet(data, opts) {
|
|
|
483
508
|
let startCol = 1;
|
|
484
509
|
if (opts?.origin !== undefined) {
|
|
485
510
|
if (typeof opts.origin === "string") {
|
|
486
|
-
const addr =
|
|
511
|
+
const addr = decodeCell(opts.origin);
|
|
487
512
|
startRow = addr.r + 1;
|
|
488
513
|
startCol = addr.c + 1;
|
|
489
514
|
}
|
|
@@ -510,7 +535,7 @@ function aoa_to_sheet(data, opts) {
|
|
|
510
535
|
/**
|
|
511
536
|
* Add data from an array of arrays to an existing worksheet (xlsx compatible)
|
|
512
537
|
*/
|
|
513
|
-
function
|
|
538
|
+
function sheetAddAoa(worksheet, data, opts) {
|
|
514
539
|
if (data.length === 0) {
|
|
515
540
|
return worksheet;
|
|
516
541
|
}
|
|
@@ -519,7 +544,7 @@ function sheet_add_aoa(worksheet, data, opts) {
|
|
|
519
544
|
let startCol = 1;
|
|
520
545
|
if (opts?.origin !== undefined) {
|
|
521
546
|
if (typeof opts.origin === "string") {
|
|
522
|
-
const addr =
|
|
547
|
+
const addr = decodeCell(opts.origin);
|
|
523
548
|
startRow = addr.r + 1;
|
|
524
549
|
startCol = addr.c + 1;
|
|
525
550
|
}
|
|
@@ -552,7 +577,7 @@ function sheet_add_aoa(worksheet, data, opts) {
|
|
|
552
577
|
/**
|
|
553
578
|
* Convert worksheet to array of arrays
|
|
554
579
|
*/
|
|
555
|
-
function
|
|
580
|
+
function sheetToAoa(worksheet) {
|
|
556
581
|
const result = [];
|
|
557
582
|
worksheet.eachRow({ includeEmpty: true }, (row, rowNumber) => {
|
|
558
583
|
const rowData = [];
|
|
@@ -567,24 +592,24 @@ function sheet_to_aoa(worksheet) {
|
|
|
567
592
|
// Export utils object
|
|
568
593
|
// =============================================================================
|
|
569
594
|
exports.utils = {
|
|
570
|
-
// Cell encoding/decoding
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
// Sheet/JSON conversion
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
// Workbook functions
|
|
588
|
-
|
|
589
|
-
|
|
595
|
+
// Cell encoding/decoding (camelCase)
|
|
596
|
+
decodeCol,
|
|
597
|
+
encodeCol,
|
|
598
|
+
decodeRow,
|
|
599
|
+
encodeRow,
|
|
600
|
+
decodeCell,
|
|
601
|
+
encodeCell,
|
|
602
|
+
decodeRange,
|
|
603
|
+
encodeRange,
|
|
604
|
+
// Sheet/JSON conversion (camelCase)
|
|
605
|
+
jsonToSheet,
|
|
606
|
+
sheetAddJson,
|
|
607
|
+
sheetToJson,
|
|
608
|
+
sheetToCsv,
|
|
609
|
+
aoaToSheet,
|
|
610
|
+
sheetAddAoa,
|
|
611
|
+
sheetToAoa,
|
|
612
|
+
// Workbook functions (camelCase)
|
|
613
|
+
bookNew,
|
|
614
|
+
bookAppendSheet
|
|
590
615
|
};
|
|
@@ -202,14 +202,24 @@ exports.StreamBuf = StreamBuf;
|
|
|
202
202
|
if (data instanceof string_buf_js_1.StringBuf || (data && data.constructor?.name === "StringBuf")) {
|
|
203
203
|
chunk = new StringBufChunk(data);
|
|
204
204
|
}
|
|
205
|
-
else if (data
|
|
205
|
+
else if (Buffer.isBuffer(data)) {
|
|
206
|
+
// Use Buffer.isBuffer() instead of instanceof for cross-realm compatibility
|
|
207
|
+
// (e.g., Web Workers where Buffer polyfill instances may differ)
|
|
206
208
|
chunk = new BufferChunk(data);
|
|
207
209
|
}
|
|
208
|
-
else if (
|
|
210
|
+
else if (ArrayBuffer.isView(data)) {
|
|
211
|
+
// Handle typed arrays (Uint8Array, Int8Array, etc.) - cross-realm safe
|
|
212
|
+
chunk = new BufferChunk(Buffer.from(data.buffer, data.byteOffset, data.byteLength));
|
|
213
|
+
}
|
|
214
|
+
else if (data instanceof ArrayBuffer) {
|
|
215
|
+
// Handle ArrayBuffer - convert to Buffer
|
|
216
|
+
chunk = new BufferChunk(Buffer.from(data));
|
|
217
|
+
}
|
|
218
|
+
else if (typeof data === "string" || data instanceof String) {
|
|
209
219
|
chunk = new StringChunk(String(data), encoding);
|
|
210
220
|
}
|
|
211
221
|
else {
|
|
212
|
-
throw new Error("Chunk must be one of type String, Buffer or StringBuf.");
|
|
222
|
+
throw new Error("Chunk must be one of type String, Buffer, Uint8Array, ArrayBuffer or StringBuf.");
|
|
213
223
|
}
|
|
214
224
|
// now, do something with the chunk
|
|
215
225
|
if (this.pipes.length) {
|
|
@@ -225,7 +235,8 @@ exports.StreamBuf = StreamBuf;
|
|
|
225
235
|
}
|
|
226
236
|
else {
|
|
227
237
|
this._writeToBuffers(chunk);
|
|
228
|
-
|
|
238
|
+
// Use queueMicrotask for cross-platform compatibility (ES2020+)
|
|
239
|
+
queueMicrotask(() => callback());
|
|
229
240
|
}
|
|
230
241
|
}
|
|
231
242
|
else {
|
|
@@ -20,6 +20,87 @@ const buffer_stream_js_1 = require("./buffer-stream");
|
|
|
20
20
|
const parse_extra_field_js_1 = require("./parse-extra-field");
|
|
21
21
|
const parse_datetime_js_1 = require("./parse-datetime");
|
|
22
22
|
const parse_buffer_js_1 = require("./parse-buffer");
|
|
23
|
+
// Check if native zlib is available (Node.js environment)
|
|
24
|
+
// In browser with polyfill, createInflateRaw may not exist or may not work properly
|
|
25
|
+
const hasNativeZlib = typeof zlib_1.default?.createInflateRaw === "function" &&
|
|
26
|
+
typeof process !== "undefined" &&
|
|
27
|
+
process.versions?.node;
|
|
28
|
+
/**
|
|
29
|
+
* A Transform stream that wraps browser's native DecompressionStream.
|
|
30
|
+
* Used when native zlib is not available (browser environment).
|
|
31
|
+
*/
|
|
32
|
+
class BrowserInflateRawStream extends stream_1.Transform {
|
|
33
|
+
constructor() {
|
|
34
|
+
super();
|
|
35
|
+
this.chunks = [];
|
|
36
|
+
this.totalLength = 0;
|
|
37
|
+
}
|
|
38
|
+
_transform(chunk, _encoding, callback) {
|
|
39
|
+
// Avoid unnecessary copy - Buffer extends Uint8Array
|
|
40
|
+
this.chunks.push(chunk);
|
|
41
|
+
this.totalLength += chunk.length;
|
|
42
|
+
callback();
|
|
43
|
+
}
|
|
44
|
+
_flush(callback) {
|
|
45
|
+
try {
|
|
46
|
+
// Use pre-calculated totalLength for better performance
|
|
47
|
+
const combined = new Uint8Array(this.totalLength);
|
|
48
|
+
let offset = 0;
|
|
49
|
+
for (const chunk of this.chunks) {
|
|
50
|
+
combined.set(chunk, offset);
|
|
51
|
+
offset += chunk.length;
|
|
52
|
+
}
|
|
53
|
+
// Clear chunks to free memory
|
|
54
|
+
this.chunks = [];
|
|
55
|
+
// Use native DecompressionStream
|
|
56
|
+
const ds = new DecompressionStream("deflate-raw");
|
|
57
|
+
const writer = ds.writable.getWriter();
|
|
58
|
+
const reader = ds.readable.getReader();
|
|
59
|
+
// Optimized read loop - collect chunks and concatenate at the end
|
|
60
|
+
const readAll = async () => {
|
|
61
|
+
const results = [];
|
|
62
|
+
let total = 0;
|
|
63
|
+
while (true) {
|
|
64
|
+
const { done, value } = await reader.read();
|
|
65
|
+
if (done) {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
results.push(value);
|
|
69
|
+
total += value.length;
|
|
70
|
+
}
|
|
71
|
+
// Single allocation for final result
|
|
72
|
+
const result = Buffer.allocUnsafe(total);
|
|
73
|
+
let off = 0;
|
|
74
|
+
for (const r of results) {
|
|
75
|
+
result.set(r, off);
|
|
76
|
+
off += r.length;
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
};
|
|
80
|
+
writer.write(combined);
|
|
81
|
+
writer.close();
|
|
82
|
+
readAll()
|
|
83
|
+
.then(decompressed => {
|
|
84
|
+
this.push(decompressed);
|
|
85
|
+
callback();
|
|
86
|
+
})
|
|
87
|
+
.catch(callback);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
callback(err);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Creates an InflateRaw stream.
|
|
96
|
+
* Uses native zlib in Node.js for best performance, falls back to DecompressionStream in browser.
|
|
97
|
+
*/
|
|
98
|
+
function createInflateRaw() {
|
|
99
|
+
if (hasNativeZlib) {
|
|
100
|
+
return zlib_1.default.createInflateRaw();
|
|
101
|
+
}
|
|
102
|
+
return new BrowserInflateRawStream();
|
|
103
|
+
}
|
|
23
104
|
const endDirectorySignature = Buffer.alloc(4);
|
|
24
105
|
endDirectorySignature.writeUInt32LE(0x06054b50, 0);
|
|
25
106
|
class Parse extends pull_stream_js_1.PullStream {
|
|
@@ -175,7 +256,7 @@ class Parse extends pull_stream_js_1.PullStream {
|
|
|
175
256
|
const fileSizeKnown = !((vars.flags || 0) & 0x08) || vars.compressedSize > 0;
|
|
176
257
|
let eof;
|
|
177
258
|
entry.__autodraining = __autodraining; // expose __autodraining for test purposes
|
|
178
|
-
const inflater = vars.compressionMethod && !__autodraining ?
|
|
259
|
+
const inflater = vars.compressionMethod && !__autodraining ? createInflateRaw() : new stream_1.PassThrough();
|
|
179
260
|
if (fileSizeKnown) {
|
|
180
261
|
entry.size = vars.uncompressedSize;
|
|
181
262
|
eof = vars.compressedSize;
|
package/dist/cjs/utils/utils.js
CHANGED
|
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.utils = exports.inherits = void 0;
|
|
7
7
|
exports.delay = delay;
|
|
8
8
|
exports.nop = nop;
|
|
9
|
-
exports.promiseImmediate = promiseImmediate;
|
|
10
9
|
exports.dateToExcel = dateToExcel;
|
|
11
10
|
exports.excelToDate = excelToDate;
|
|
12
11
|
exports.parsePath = parsePath;
|
|
@@ -21,26 +20,12 @@ exports.parseBoolean = parseBoolean;
|
|
|
21
20
|
exports.range = range;
|
|
22
21
|
exports.toSortedArray = toSortedArray;
|
|
23
22
|
exports.objectFromProps = objectFromProps;
|
|
23
|
+
exports.bufferToString = bufferToString;
|
|
24
24
|
const fs_1 = __importDefault(require("fs"));
|
|
25
25
|
function delay(ms) {
|
|
26
26
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
27
27
|
}
|
|
28
28
|
function nop() { }
|
|
29
|
-
function promiseImmediate(value) {
|
|
30
|
-
return new Promise(resolve => {
|
|
31
|
-
if (global.setImmediate) {
|
|
32
|
-
setImmediate(() => {
|
|
33
|
-
resolve(value);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
// poorman's setImmediate - must wait at least 1ms
|
|
38
|
-
setTimeout(() => {
|
|
39
|
-
resolve(value);
|
|
40
|
-
}, 1);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
29
|
// useful stuff
|
|
45
30
|
const inherits = function (cls, superCtor, statics, prototype) {
|
|
46
31
|
cls.super_ = superCtor;
|
|
@@ -213,7 +198,6 @@ function objectFromProps(props, value = null) {
|
|
|
213
198
|
/** @deprecated Import functions directly instead of using the utils object */
|
|
214
199
|
exports.utils = {
|
|
215
200
|
nop,
|
|
216
|
-
promiseImmediate,
|
|
217
201
|
inherits: exports.inherits,
|
|
218
202
|
dateToExcel,
|
|
219
203
|
excelToDate,
|
|
@@ -232,3 +216,15 @@ exports.utils = {
|
|
|
232
216
|
toSortedArray,
|
|
233
217
|
objectFromProps
|
|
234
218
|
};
|
|
219
|
+
// TextDecoder is available in ES2020+ and all modern browsers/Node.js
|
|
220
|
+
const textDecoder = new TextDecoder("utf-8");
|
|
221
|
+
/**
|
|
222
|
+
* Convert a Buffer or ArrayBuffer to a UTF-8 string
|
|
223
|
+
* Works in both Node.js and browser environments
|
|
224
|
+
*/
|
|
225
|
+
function bufferToString(chunk) {
|
|
226
|
+
if (typeof chunk === "string") {
|
|
227
|
+
return chunk;
|
|
228
|
+
}
|
|
229
|
+
return textDecoder.decode(chunk);
|
|
230
|
+
}
|
|
@@ -7,8 +7,6 @@ exports.ZipWriter = void 0;
|
|
|
7
7
|
const events_1 = __importDefault(require("events"));
|
|
8
8
|
const fflate_1 = require("fflate");
|
|
9
9
|
const stream_buf_js_1 = require("./stream-buf");
|
|
10
|
-
const browser_buffer_encode_js_1 = require("./browser-buffer-encode");
|
|
11
|
-
const browser_js_1 = require("./browser");
|
|
12
10
|
// =============================================================================
|
|
13
11
|
// The ZipWriter class
|
|
14
12
|
// Packs streamed data into an output zip stream
|
|
@@ -42,39 +40,29 @@ class ZipWriter extends events_1.default.EventEmitter {
|
|
|
42
40
|
append(data, options) {
|
|
43
41
|
let buffer;
|
|
44
42
|
if (Object.prototype.hasOwnProperty.call(options, "base64") && options.base64) {
|
|
45
|
-
//
|
|
43
|
+
// Decode base64 data - Buffer.from works in both Node.js and browser (via polyfill)
|
|
46
44
|
const base64Data = typeof data === "string" ? data : data.toString();
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
45
|
+
buffer = Buffer.from(base64Data, "base64");
|
|
46
|
+
}
|
|
47
|
+
else if (typeof data === "string") {
|
|
48
|
+
// Convert string to Buffer - works in both environments
|
|
49
|
+
buffer = Buffer.from(data, "utf8");
|
|
50
|
+
}
|
|
51
|
+
else if (Buffer.isBuffer(data)) {
|
|
52
|
+
// Buffer extends Uint8Array, fflate can use it directly - no copy needed
|
|
53
|
+
buffer = data;
|
|
54
|
+
}
|
|
55
|
+
else if (ArrayBuffer.isView(data)) {
|
|
56
|
+
// Handle typed arrays - create view without copy
|
|
57
|
+
buffer = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
58
|
+
}
|
|
59
|
+
else if (data instanceof ArrayBuffer) {
|
|
60
|
+
// Handle ArrayBuffer directly
|
|
61
|
+
buffer = new Uint8Array(data);
|
|
61
62
|
}
|
|
62
63
|
else {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (browser_js_1.isBrowser) {
|
|
66
|
-
buffer = (0, browser_buffer_encode_js_1.stringToBuffer)(data);
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
buffer = Buffer.from(data, "utf8");
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
else if (Buffer.isBuffer(data)) {
|
|
73
|
-
buffer = new Uint8Array(data);
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
buffer = data;
|
|
77
|
-
}
|
|
64
|
+
// Assume it's already a Uint8Array or compatible type
|
|
65
|
+
buffer = data;
|
|
78
66
|
}
|
|
79
67
|
// Add file to zip using streaming API
|
|
80
68
|
// Use ZipDeflate for compression or ZipPassThrough for no compression
|