@cj-tech-master/excelts 1.4.5-canary.20251212064440.3eb099f → 1.4.5-canary.20251212160853.7621827

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.
@@ -0,0 +1,458 @@
1
+ "use strict";
2
+ /**
3
+ * Pure Uint8Array-based ZIP parser
4
+ * Works in both Node.js and browser environments
5
+ * No dependency on Node.js stream module
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.ZipParser = void 0;
9
+ exports.parseZipEntries = parseZipEntries;
10
+ exports.extractEntryData = extractEntryData;
11
+ exports.extractEntryDataSync = extractEntryDataSync;
12
+ const compress_js_1 = require("../zip/compress");
13
+ // ZIP file signatures
14
+ const LOCAL_FILE_HEADER_SIG = 0x04034b50;
15
+ const CENTRAL_DIR_HEADER_SIG = 0x02014b50;
16
+ const END_OF_CENTRAL_DIR_SIG = 0x06054b50;
17
+ const ZIP64_END_OF_CENTRAL_DIR_SIG = 0x06064b50;
18
+ const ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50;
19
+ // Compression methods
20
+ const COMPRESSION_STORED = 0;
21
+ const COMPRESSION_DEFLATE = 8;
22
+ /**
23
+ * Parse DOS date/time format to JavaScript Date
24
+ * Dates in zip file entries are stored as DosDateTime
25
+ * Spec: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-dosdatetimetofiletime
26
+ */
27
+ function parseDateTime(date, time) {
28
+ const day = date & 0x1f;
29
+ const month = (date >> 5) & 0x0f;
30
+ const year = ((date >> 9) & 0x7f) + 1980;
31
+ const seconds = time ? (time & 0x1f) * 2 : 0;
32
+ const minutes = time ? (time >> 5) & 0x3f : 0;
33
+ const hours = time ? time >> 11 : 0;
34
+ return new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds));
35
+ }
36
+ /**
37
+ * Parse ZIP64 extra field
38
+ */
39
+ function parseZip64ExtraField(extraField, compressedSize, uncompressedSize, localHeaderOffset) {
40
+ const view = new DataView(extraField.buffer, extraField.byteOffset, extraField.byteLength);
41
+ let offset = 0;
42
+ while (offset + 4 <= extraField.length) {
43
+ const signature = view.getUint16(offset, true);
44
+ const partSize = view.getUint16(offset + 2, true);
45
+ if (signature === 0x0001) {
46
+ // ZIP64 extended information
47
+ let fieldOffset = offset + 4;
48
+ if (uncompressedSize === 0xffffffff && fieldOffset + 8 <= offset + 4 + partSize) {
49
+ uncompressedSize = Number(view.getBigUint64(fieldOffset, true));
50
+ fieldOffset += 8;
51
+ }
52
+ if (compressedSize === 0xffffffff && fieldOffset + 8 <= offset + 4 + partSize) {
53
+ compressedSize = Number(view.getBigUint64(fieldOffset, true));
54
+ fieldOffset += 8;
55
+ }
56
+ if (localHeaderOffset === 0xffffffff && fieldOffset + 8 <= offset + 4 + partSize) {
57
+ localHeaderOffset = Number(view.getBigUint64(fieldOffset, true));
58
+ }
59
+ break;
60
+ }
61
+ offset += 4 + partSize;
62
+ }
63
+ return { compressedSize, uncompressedSize, localHeaderOffset };
64
+ }
65
+ /**
66
+ * DataView helper for reading little-endian values
67
+ */
68
+ class BinaryReader {
69
+ constructor(data, offset = 0) {
70
+ this.data = data;
71
+ this.view = new DataView(data.buffer, data.byteOffset, data.byteLength);
72
+ this.offset = offset;
73
+ }
74
+ get position() {
75
+ return this.offset;
76
+ }
77
+ set position(value) {
78
+ this.offset = value;
79
+ }
80
+ get remaining() {
81
+ return this.data.length - this.offset;
82
+ }
83
+ readUint8() {
84
+ const value = this.view.getUint8(this.offset);
85
+ this.offset += 1;
86
+ return value;
87
+ }
88
+ readUint16() {
89
+ const value = this.view.getUint16(this.offset, true);
90
+ this.offset += 2;
91
+ return value;
92
+ }
93
+ readUint32() {
94
+ const value = this.view.getUint32(this.offset, true);
95
+ this.offset += 4;
96
+ return value;
97
+ }
98
+ readBigUint64() {
99
+ const value = this.view.getBigUint64(this.offset, true);
100
+ this.offset += 8;
101
+ return value;
102
+ }
103
+ readBytes(length) {
104
+ const bytes = this.data.subarray(this.offset, this.offset + length);
105
+ this.offset += length;
106
+ return bytes;
107
+ }
108
+ readString(length, utf8 = true) {
109
+ const bytes = this.readBytes(length);
110
+ if (utf8) {
111
+ return new TextDecoder("utf-8").decode(bytes);
112
+ }
113
+ // Fallback to ASCII/Latin-1
114
+ return String.fromCharCode(...bytes);
115
+ }
116
+ skip(length) {
117
+ this.offset += length;
118
+ }
119
+ slice(start, end) {
120
+ return this.data.subarray(start, end);
121
+ }
122
+ peekUint32(offset) {
123
+ return this.view.getUint32(offset, true);
124
+ }
125
+ }
126
+ /**
127
+ * Find the End of Central Directory record
128
+ * Searches backwards from the end of the file
129
+ */
130
+ function findEndOfCentralDir(data) {
131
+ // EOCD is at least 22 bytes, search backwards
132
+ // Comment can be up to 65535 bytes
133
+ const minOffset = Math.max(0, data.length - 65557);
134
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
135
+ for (let i = data.length - 22; i >= minOffset; i--) {
136
+ if (view.getUint32(i, true) === END_OF_CENTRAL_DIR_SIG) {
137
+ return i;
138
+ }
139
+ }
140
+ return -1;
141
+ }
142
+ /**
143
+ * Find ZIP64 End of Central Directory Locator
144
+ */
145
+ function findZip64EOCDLocator(data, eocdOffset) {
146
+ // ZIP64 EOCD Locator is 20 bytes and appears right before EOCD
147
+ const locatorOffset = eocdOffset - 20;
148
+ if (locatorOffset < 0) {
149
+ return -1;
150
+ }
151
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
152
+ if (view.getUint32(locatorOffset, true) === ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) {
153
+ return locatorOffset;
154
+ }
155
+ return -1;
156
+ }
157
+ /**
158
+ * Parse ZIP file entries from Central Directory
159
+ */
160
+ function parseZipEntries(data, options = {}) {
161
+ const { decodeStrings = true } = options;
162
+ const entries = [];
163
+ // Find End of Central Directory
164
+ const eocdOffset = findEndOfCentralDir(data);
165
+ if (eocdOffset === -1) {
166
+ throw new Error("Invalid ZIP file: End of Central Directory not found");
167
+ }
168
+ const reader = new BinaryReader(data, eocdOffset);
169
+ // Read EOCD
170
+ // Offset Size Description
171
+ // 0 4 EOCD signature (0x06054b50)
172
+ // 4 2 Number of this disk
173
+ // 6 2 Disk where central directory starts
174
+ // 8 2 Number of central directory records on this disk
175
+ // 10 2 Total number of central directory records
176
+ // 12 4 Size of central directory (bytes)
177
+ // 16 4 Offset of start of central directory
178
+ // 20 2 Comment length
179
+ reader.skip(4); // signature
180
+ reader.skip(2); // disk number
181
+ reader.skip(2); // disk where central dir starts
182
+ reader.skip(2); // entries on this disk
183
+ let totalEntries = reader.readUint16(); // total entries
184
+ let centralDirSize = reader.readUint32();
185
+ let centralDirOffset = reader.readUint32();
186
+ // Check for ZIP64
187
+ const zip64LocatorOffset = findZip64EOCDLocator(data, eocdOffset);
188
+ if (zip64LocatorOffset !== -1) {
189
+ const locatorReader = new BinaryReader(data, zip64LocatorOffset);
190
+ locatorReader.skip(4); // signature
191
+ locatorReader.skip(4); // disk number with ZIP64 EOCD
192
+ const zip64EOCDOffset = Number(locatorReader.readBigUint64());
193
+ // Read ZIP64 EOCD
194
+ const zip64Reader = new BinaryReader(data, zip64EOCDOffset);
195
+ const zip64Sig = zip64Reader.readUint32();
196
+ if (zip64Sig === ZIP64_END_OF_CENTRAL_DIR_SIG) {
197
+ zip64Reader.skip(8); // size of ZIP64 EOCD
198
+ zip64Reader.skip(2); // version made by
199
+ zip64Reader.skip(2); // version needed
200
+ zip64Reader.skip(4); // disk number
201
+ zip64Reader.skip(4); // disk with central dir
202
+ const zip64TotalEntries = Number(zip64Reader.readBigUint64());
203
+ const zip64CentralDirSize = Number(zip64Reader.readBigUint64());
204
+ const zip64CentralDirOffset = Number(zip64Reader.readBigUint64());
205
+ // Use ZIP64 values if standard values are maxed out
206
+ if (totalEntries === 0xffff) {
207
+ totalEntries = zip64TotalEntries;
208
+ }
209
+ if (centralDirSize === 0xffffffff) {
210
+ centralDirSize = zip64CentralDirSize;
211
+ }
212
+ if (centralDirOffset === 0xffffffff) {
213
+ centralDirOffset = zip64CentralDirOffset;
214
+ }
215
+ }
216
+ }
217
+ // Read Central Directory entries
218
+ const centralReader = new BinaryReader(data, centralDirOffset);
219
+ for (let i = 0; i < totalEntries; i++) {
220
+ const sig = centralReader.readUint32();
221
+ if (sig !== CENTRAL_DIR_HEADER_SIG) {
222
+ throw new Error(`Invalid Central Directory header signature at entry ${i}`);
223
+ }
224
+ // Central Directory File Header format:
225
+ // Offset Size Description
226
+ // 0 4 Central directory file header signature (0x02014b50)
227
+ // 4 2 Version made by
228
+ // 6 2 Version needed to extract
229
+ // 8 2 General purpose bit flag
230
+ // 10 2 Compression method
231
+ // 12 2 File last modification time
232
+ // 14 2 File last modification date
233
+ // 16 4 CRC-32
234
+ // 20 4 Compressed size
235
+ // 24 4 Uncompressed size
236
+ // 28 2 File name length
237
+ // 30 2 Extra field length
238
+ // 32 2 File comment length
239
+ // 34 2 Disk number where file starts
240
+ // 36 2 Internal file attributes
241
+ // 38 4 External file attributes
242
+ // 42 4 Relative offset of local file header
243
+ // 46 n File name
244
+ // 46+n m Extra field
245
+ // 46+n+m k File comment
246
+ centralReader.skip(2); // version made by
247
+ centralReader.skip(2); // version needed
248
+ const flags = centralReader.readUint16();
249
+ const compressionMethod = centralReader.readUint16();
250
+ const lastModTime = centralReader.readUint16();
251
+ const lastModDate = centralReader.readUint16();
252
+ const crc32 = centralReader.readUint32();
253
+ let compressedSize = centralReader.readUint32();
254
+ let uncompressedSize = centralReader.readUint32();
255
+ const fileNameLength = centralReader.readUint16();
256
+ const extraFieldLength = centralReader.readUint16();
257
+ const commentLength = centralReader.readUint16();
258
+ centralReader.skip(2); // disk number start
259
+ centralReader.skip(2); // internal attributes
260
+ const externalAttributes = centralReader.readUint32();
261
+ let localHeaderOffset = centralReader.readUint32();
262
+ // Check for UTF-8 flag (bit 11)
263
+ const isUtf8 = (flags & 0x800) !== 0;
264
+ const useUtf8 = decodeStrings && isUtf8;
265
+ const fileName = centralReader.readString(fileNameLength, useUtf8);
266
+ const extraField = centralReader.readBytes(extraFieldLength);
267
+ const comment = centralReader.readString(commentLength, useUtf8);
268
+ // Parse extra field for ZIP64 values
269
+ if (extraFieldLength > 0) {
270
+ const parsed = parseZip64ExtraField(extraField, compressedSize, uncompressedSize, localHeaderOffset);
271
+ compressedSize = parsed.compressedSize;
272
+ uncompressedSize = parsed.uncompressedSize;
273
+ localHeaderOffset = parsed.localHeaderOffset;
274
+ }
275
+ const isDirectory = fileName.endsWith("/") || (externalAttributes & 0x10) !== 0;
276
+ const isEncrypted = (flags & 0x01) !== 0;
277
+ entries.push({
278
+ path: fileName,
279
+ isDirectory,
280
+ compressedSize,
281
+ uncompressedSize,
282
+ compressionMethod,
283
+ crc32,
284
+ lastModified: parseDateTime(lastModDate, lastModTime),
285
+ localHeaderOffset,
286
+ comment,
287
+ externalAttributes,
288
+ isEncrypted
289
+ });
290
+ }
291
+ return entries;
292
+ }
293
+ /**
294
+ * Extract file data for a specific entry
295
+ */
296
+ async function extractEntryData(data, entry) {
297
+ if (entry.isDirectory) {
298
+ return new Uint8Array(0);
299
+ }
300
+ if (entry.isEncrypted) {
301
+ throw new Error(`File "${entry.path}" is encrypted and cannot be extracted`);
302
+ }
303
+ const reader = new BinaryReader(data, entry.localHeaderOffset);
304
+ // Read local file header
305
+ const sig = reader.readUint32();
306
+ if (sig !== LOCAL_FILE_HEADER_SIG) {
307
+ throw new Error(`Invalid local file header signature for "${entry.path}"`);
308
+ }
309
+ reader.skip(2); // version needed
310
+ reader.skip(2); // flags
311
+ reader.skip(2); // compression method
312
+ reader.skip(2); // last mod time
313
+ reader.skip(2); // last mod date
314
+ reader.skip(4); // crc32
315
+ reader.skip(4); // compressed size
316
+ reader.skip(4); // uncompressed size
317
+ const fileNameLength = reader.readUint16();
318
+ const extraFieldLength = reader.readUint16();
319
+ reader.skip(fileNameLength);
320
+ reader.skip(extraFieldLength);
321
+ // Extract compressed data
322
+ const compressedData = reader.readBytes(entry.compressedSize);
323
+ // Decompress if needed
324
+ if (entry.compressionMethod === COMPRESSION_STORED) {
325
+ return compressedData;
326
+ }
327
+ else if (entry.compressionMethod === COMPRESSION_DEFLATE) {
328
+ return (0, compress_js_1.decompress)(compressedData);
329
+ }
330
+ else {
331
+ throw new Error(`Unsupported compression method: ${entry.compressionMethod}`);
332
+ }
333
+ }
334
+ /**
335
+ * Extract file data synchronously (Node.js only)
336
+ */
337
+ function extractEntryDataSync(data, entry) {
338
+ if (entry.isDirectory) {
339
+ return new Uint8Array(0);
340
+ }
341
+ if (entry.isEncrypted) {
342
+ throw new Error(`File "${entry.path}" is encrypted and cannot be extracted`);
343
+ }
344
+ const reader = new BinaryReader(data, entry.localHeaderOffset);
345
+ // Read local file header
346
+ const sig = reader.readUint32();
347
+ if (sig !== LOCAL_FILE_HEADER_SIG) {
348
+ throw new Error(`Invalid local file header signature for "${entry.path}"`);
349
+ }
350
+ reader.skip(2); // version needed
351
+ reader.skip(2); // flags
352
+ reader.skip(2); // compression method
353
+ reader.skip(2); // last mod time
354
+ reader.skip(2); // last mod date
355
+ reader.skip(4); // crc32
356
+ reader.skip(4); // compressed size
357
+ reader.skip(4); // uncompressed size
358
+ const fileNameLength = reader.readUint16();
359
+ const extraFieldLength = reader.readUint16();
360
+ reader.skip(fileNameLength);
361
+ reader.skip(extraFieldLength);
362
+ // Extract compressed data
363
+ const compressedData = reader.readBytes(entry.compressedSize);
364
+ // Decompress if needed
365
+ if (entry.compressionMethod === COMPRESSION_STORED) {
366
+ return compressedData;
367
+ }
368
+ else if (entry.compressionMethod === COMPRESSION_DEFLATE) {
369
+ return (0, compress_js_1.decompressSync)(compressedData);
370
+ }
371
+ else {
372
+ throw new Error(`Unsupported compression method: ${entry.compressionMethod}`);
373
+ }
374
+ }
375
+ /**
376
+ * High-level ZIP parser class
377
+ */
378
+ class ZipParser {
379
+ constructor(data, options = {}) {
380
+ this.data = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
381
+ this.entries = parseZipEntries(this.data, options);
382
+ this.entryMap = new Map(this.entries.map(e => [e.path, e]));
383
+ }
384
+ /**
385
+ * Get all entries in the ZIP file
386
+ */
387
+ getEntries() {
388
+ return this.entries;
389
+ }
390
+ /**
391
+ * Get entry by path
392
+ */
393
+ getEntry(path) {
394
+ return this.entryMap.get(path);
395
+ }
396
+ /**
397
+ * Check if entry exists
398
+ */
399
+ hasEntry(path) {
400
+ return this.entryMap.has(path);
401
+ }
402
+ /**
403
+ * List all file paths
404
+ */
405
+ listFiles() {
406
+ return this.entries.map(e => e.path);
407
+ }
408
+ /**
409
+ * Extract a single file (async)
410
+ */
411
+ async extract(path) {
412
+ const entry = this.entryMap.get(path);
413
+ if (!entry) {
414
+ return null;
415
+ }
416
+ return extractEntryData(this.data, entry);
417
+ }
418
+ /**
419
+ * Extract a single file (sync, Node.js only)
420
+ */
421
+ extractSync(path) {
422
+ const entry = this.entryMap.get(path);
423
+ if (!entry) {
424
+ return null;
425
+ }
426
+ return extractEntryDataSync(this.data, entry);
427
+ }
428
+ /**
429
+ * Extract all files (async)
430
+ */
431
+ async extractAll() {
432
+ const result = new Map();
433
+ for (const entry of this.entries) {
434
+ const data = await extractEntryData(this.data, entry);
435
+ result.set(entry.path, data);
436
+ }
437
+ return result;
438
+ }
439
+ /**
440
+ * Iterate over entries with async callback
441
+ */
442
+ async forEach(callback) {
443
+ for (const entry of this.entries) {
444
+ let dataPromise = null;
445
+ const getData = () => {
446
+ if (!dataPromise) {
447
+ dataPromise = extractEntryData(this.data, entry);
448
+ }
449
+ return dataPromise;
450
+ };
451
+ const shouldContinue = await callback(entry, getData);
452
+ if (shouldContinue === false) {
453
+ break;
454
+ }
455
+ }
456
+ }
457
+ }
458
+ exports.ZipParser = ZipParser;
@@ -2,9 +2,11 @@ import { colCache } from "../utils/col-cache.js";
2
2
  import { isEqual } from "../utils/under-dash.js";
3
3
  import { Enums } from "./enums.js";
4
4
  const DEFAULT_COLUMN_WIDTH = 9;
5
- // Column defines the column properties for 1 column.
6
- // This includes header rows, widths, key, (style), etc.
7
- // Worksheet will condense the columns as appropriate during serialization
5
+ /**
6
+ * Column defines the column properties for 1 column.
7
+ * This includes header rows, widths, key, (style), etc.
8
+ * Worksheet will condense the columns as appropriate during serialization
9
+ */
8
10
  class Column {
9
11
  constructor(worksheet, number, defn) {
10
12
  this._worksheet = worksheet;
@@ -20,6 +22,9 @@ class Column {
20
22
  get worksheet() {
21
23
  return this._worksheet;
22
24
  }
25
+ /**
26
+ * Column letter key
27
+ */
23
28
  get letter() {
24
29
  return colCache.n2l(this._number);
25
30
  }
@@ -68,6 +73,9 @@ class Column {
68
73
  }
69
74
  return [];
70
75
  }
76
+ /**
77
+ * Can be a string to set one row high header or an array to set multi-row high header
78
+ */
71
79
  get header() {
72
80
  return this._header;
73
81
  }
@@ -82,6 +90,9 @@ class Column {
82
90
  this._header = undefined;
83
91
  }
84
92
  }
93
+ /**
94
+ * The name of the properties associated with this column in each row
95
+ */
85
96
  get key() {
86
97
  return this._key;
87
98
  }
@@ -95,18 +106,27 @@ class Column {
95
106
  this._worksheet.setColumnKey(this._key, this);
96
107
  }
97
108
  }
109
+ /**
110
+ * Hides the column
111
+ */
98
112
  get hidden() {
99
113
  return !!this._hidden;
100
114
  }
101
115
  set hidden(value) {
102
116
  this._hidden = value;
103
117
  }
118
+ /**
119
+ * Set an outline level for columns
120
+ */
104
121
  get outlineLevel() {
105
122
  return this._outlineLevel || 0;
106
123
  }
107
124
  set outlineLevel(value) {
108
125
  this._outlineLevel = value;
109
126
  }
127
+ /**
128
+ * Indicate the collapsed state based on outlineLevel
129
+ */
110
130
  get collapsed() {
111
131
  return !!(this._outlineLevel && this._outlineLevel >= this._worksheet.properties.outlineLevelCol);
112
132
  }
@@ -148,16 +168,25 @@ class Column {
148
168
  get headerCount() {
149
169
  return this.headers.length;
150
170
  }
151
- eachCell(options, iteratee) {
171
+ eachCell(optionsOrCallback, maybeCallback) {
152
172
  const colNumber = this.number;
153
- if (!iteratee) {
154
- iteratee = options;
173
+ let options;
174
+ let callback;
175
+ if (typeof optionsOrCallback === "function") {
155
176
  options = {};
177
+ callback = optionsOrCallback;
178
+ }
179
+ else {
180
+ options = optionsOrCallback;
181
+ callback = maybeCallback;
156
182
  }
157
183
  this._worksheet.eachRow(options, (row, rowNumber) => {
158
- iteratee(row.getCell(colNumber), rowNumber);
184
+ callback(row.getCell(colNumber), rowNumber);
159
185
  });
160
186
  }
187
+ /**
188
+ * The cell values in the column
189
+ */
161
190
  get values() {
162
191
  const v = [];
163
192
  this.eachCell((cell, rowNumber) => {
@@ -9,19 +9,29 @@ class Row {
9
9
  this.style = {};
10
10
  this.outlineLevel = 0;
11
11
  }
12
- // return the row number
12
+ /**
13
+ * The row number
14
+ */
13
15
  get number() {
14
16
  return this._number;
15
17
  }
18
+ /**
19
+ * The worksheet that contains this row
20
+ */
16
21
  get worksheet() {
17
22
  return this._worksheet;
18
23
  }
19
- // Inform Streaming Writer that this row (and all rows before it) are complete
20
- // and ready to write. Has no effect on Worksheet document
24
+ /**
25
+ * Commit a completed row to stream.
26
+ * Inform Streaming Writer that this row (and all rows before it) are complete
27
+ * and ready to write. Has no effect on Worksheet document.
28
+ */
21
29
  commit() {
22
30
  this._worksheet._commitRow(this);
23
31
  }
24
- // helps GC by breaking cyclic references
32
+ /**
33
+ * Helps GC by breaking cyclic references
34
+ */
25
35
  destroy() {
26
36
  delete this._worksheet;
27
37
  delete this._cells;
@@ -40,7 +50,9 @@ class Row {
40
50
  }
41
51
  return cell;
42
52
  }
43
- // get cell by key, letter or column number
53
+ /**
54
+ * Get cell by number, column letter or column key
55
+ */
44
56
  getCell(col) {
45
57
  let colNum;
46
58
  if (typeof col === "string") {
@@ -63,7 +75,11 @@ class Row {
63
75
  col: colNum
64
76
  }));
65
77
  }
66
- // remove cell(s) and shift all higher cells down by count
78
+ /**
79
+ * Cut one or more cells (cells to the right are shifted left)
80
+ *
81
+ * Note: this operation will not affect other rows
82
+ */
67
83
  splice(start, count, ...inserts) {
68
84
  const nKeep = start + count;
69
85
  const nExpand = inserts.length - count;
@@ -112,26 +128,26 @@ class Row {
112
128
  cDst.comment = undefined;
113
129
  }
114
130
  }
115
- eachCell(optionsOrIteratee, maybeIteratee) {
131
+ eachCell(optOrCallback, maybeCallback) {
116
132
  let options = null;
117
- let iteratee;
118
- if (typeof optionsOrIteratee === "function") {
119
- iteratee = optionsOrIteratee;
133
+ let callback;
134
+ if (typeof optOrCallback === "function") {
135
+ callback = optOrCallback;
120
136
  }
121
137
  else {
122
- options = optionsOrIteratee;
123
- iteratee = maybeIteratee;
138
+ options = optOrCallback;
139
+ callback = maybeCallback;
124
140
  }
125
141
  if (options && options.includeEmpty) {
126
142
  const n = this._cells.length;
127
143
  for (let i = 1; i <= n; i++) {
128
- iteratee(this.getCell(i), i);
144
+ callback(this.getCell(i), i);
129
145
  }
130
146
  }
131
147
  else {
132
148
  this._cells.forEach((cell, index) => {
133
149
  if (cell && cell.type !== Enums.ValueType.Null) {
134
- iteratee(cell, index + 1);
150
+ callback(cell, index + 1);
135
151
  }
136
152
  });
137
153
  }
@@ -152,7 +168,9 @@ class Row {
152
168
  }
153
169
  ws.rowBreaks.push(pb);
154
170
  }
155
- // return a sparse array of cell values
171
+ /**
172
+ * Get a row as a sparse array
173
+ */
156
174
  get values() {
157
175
  const values = [];
158
176
  this._cells.forEach(cell => {
@@ -162,7 +180,9 @@ class Row {
162
180
  });
163
181
  return values;
164
182
  }
165
- // set the values by contiguous or sparse array, or by key'd object literal
183
+ /**
184
+ * Set the values by contiguous or sparse array, or by key'd object literal
185
+ */
166
186
  set values(value) {
167
187
  // this operation is not additive - any prior cells are removed
168
188
  this._cells = [];
@@ -198,13 +218,21 @@ class Row {
198
218
  });
199
219
  }
200
220
  }
201
- // returns true if the row includes at least one cell with a value
221
+ /**
222
+ * Returns true if the row includes at least one cell with a value
223
+ */
202
224
  get hasValues() {
203
225
  return this._cells.some(cell => cell && cell.type !== Enums.ValueType.Null);
204
226
  }
227
+ /**
228
+ * Number of cells including empty ones
229
+ */
205
230
  get cellCount() {
206
231
  return this._cells.length;
207
232
  }
233
+ /**
234
+ * Number of non-empty cells
235
+ */
208
236
  get actualCellCount() {
209
237
  let count = 0;
210
238
  this.eachCell(() => {
@@ -212,7 +240,9 @@ class Row {
212
240
  });
213
241
  return count;
214
242
  }
215
- // get the min and max column number for the non-null cells in this row or null
243
+ /**
244
+ * Get the min and max column number for the non-null cells in this row or null
245
+ */
216
246
  get dimensions() {
217
247
  let min = 0;
218
248
  let max = 0;