@cj-tech-master/excelts 5.1.15 → 5.1.16-canary.20260310044403.090b2e4

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.
@@ -119,6 +119,9 @@ const colCache = {
119
119
  },
120
120
  // convert address string into structure
121
121
  decodeAddress(value) {
122
+ if (!value || typeof value !== "string") {
123
+ throw new Error(`Invalid Address: ${value}`);
124
+ }
122
125
  const addr = value.length < 5 && this._hash[value];
123
126
  if (addr) {
124
127
  return addr;
@@ -187,6 +190,9 @@ const colCache = {
187
190
  },
188
191
  // convert [address], [tl:br] into address structures
189
192
  decode(value) {
193
+ if (!value || typeof value !== "string") {
194
+ throw new Error(`Invalid Address: ${value}`);
195
+ }
190
196
  const parts = value.split(":");
191
197
  if (parts.length === 2) {
192
198
  const tl = this.decodeAddress(parts[0]);
@@ -210,6 +216,9 @@ const colCache = {
210
216
  },
211
217
  // convert [sheetName!][$]col[$]row[[$]col[$]row] into address or range structures
212
218
  decodeEx(value) {
219
+ if (!value || typeof value !== "string") {
220
+ throw new Error(`Invalid Address: ${value}`);
221
+ }
213
222
  // Use possessive quantifiers to prevent catastrophic backtracking (ReDoS)
214
223
  const groups = value.match(/^(?:(?:(?:'((?:[^']|'')+?)')|([^'^ !]+?))!)?(.*)$/);
215
224
  const sheetName = groups[1] || groups[2]; // Quoted and unquoted groups
@@ -242,15 +242,28 @@ class StreamBuf extends EventEmitter {
242
242
  }
243
243
  else {
244
244
  const chunkBuffer = chunk.toBuffer();
245
- if (!this.paused) {
245
+ // Track whether the data has been delivered to a consumer.
246
+ // When a consumer exists ("data" listeners or a native WritableStream),
247
+ // the data is consumed externally and must NOT also be accumulated in
248
+ // internal buffers — otherwise the buffers grow without bound (memory leak)
249
+ // since no one ever calls read()/toBuffer() to drain them.
250
+ let consumed = false;
251
+ if (!this.paused && this.listenerCount("data") > 0) {
246
252
  this.emit("data", chunkBuffer);
253
+ consumed = true;
247
254
  }
248
255
  // Also write to native WritableStream if connected
249
256
  if (this._writableStreamWriter) {
250
257
  this._asyncWriteQueue = this._asyncWriteQueue.then(() => this._writableStreamWriter.write(chunkBuffer));
258
+ consumed = true;
259
+ }
260
+ // Only buffer internally when no consumer has received the data.
261
+ // This keeps StreamBuf working as a memory buffer (write then read/toBuffer)
262
+ // while preventing unbounded growth when used as an event-driven pass-through.
263
+ if (!consumed) {
264
+ this._writeToBuffers(chunk);
265
+ this.emit("readable");
251
266
  }
252
- this._writeToBuffers(chunk);
253
- this.emit("readable");
254
267
  }
255
268
  return true;
256
269
  }
@@ -75,6 +75,7 @@ interface PageSetup {
75
75
  horizontalCentered: boolean;
76
76
  verticalCentered: boolean;
77
77
  rowBreaks: RowBreak[];
78
+ printArea?: string;
78
79
  printTitlesRow?: string;
79
80
  printTitlesColumn?: string;
80
81
  }
@@ -43,9 +43,11 @@ class WorkbookXform extends BaseXform {
43
43
  if (sheet.pageSetup && sheet.pageSetup.printArea) {
44
44
  sheet.pageSetup.printArea.split("&&").forEach((printArea) => {
45
45
  const printAreaComponents = printArea.split(":");
46
+ const start = printAreaComponents[0];
47
+ const end = printAreaComponents[1] ?? start;
46
48
  const definedName = {
47
49
  name: "_xlnm.Print_Area",
48
- ranges: [`'${sheet.name}'!$${printAreaComponents[0]}:$${printAreaComponents[1]}`],
50
+ ranges: [`'${sheet.name}'!$${start}:$${end}`],
49
51
  localSheetId: index
50
52
  };
51
53
  printAreas.push(definedName);
@@ -56,11 +58,15 @@ class WorkbookXform extends BaseXform {
56
58
  const ranges = [];
57
59
  if (sheet.pageSetup.printTitlesColumn) {
58
60
  const titlesColumns = sheet.pageSetup.printTitlesColumn.split(":");
59
- ranges.push(`'${sheet.name}'!$${titlesColumns[0]}:$${titlesColumns[1]}`);
61
+ const start = titlesColumns[0];
62
+ const end = titlesColumns[1] ?? start;
63
+ ranges.push(`'${sheet.name}'!$${start}:$${end}`);
60
64
  }
61
65
  if (sheet.pageSetup.printTitlesRow) {
62
66
  const titlesRows = sheet.pageSetup.printTitlesRow.split(":");
63
- ranges.push(`'${sheet.name}'!$${titlesRows[0]}:$${titlesRows[1]}`);
67
+ const start = titlesRows[0];
68
+ const end = titlesRows[1] ?? start;
69
+ ranges.push(`'${sheet.name}'!$${start}:$${end}`);
64
70
  }
65
71
  const definedName = {
66
72
  name: "_xlnm.Print_Titles",
@@ -186,7 +192,7 @@ class WorkbookXform extends BaseXform {
186
192
  model.definedNames.forEach((definedName) => {
187
193
  if (definedName.name === "_xlnm.Print_Area") {
188
194
  worksheet = worksheets[definedName.localSheetId];
189
- if (worksheet) {
195
+ if (worksheet && definedName.ranges?.length > 0) {
190
196
  if (!worksheet.pageSetup) {
191
197
  worksheet.pageSetup = {};
192
198
  }
@@ -198,7 +204,7 @@ class WorkbookXform extends BaseXform {
198
204
  }
199
205
  else if (definedName.name === "_xlnm.Print_Titles") {
200
206
  worksheet = worksheets[definedName.localSheetId];
201
- if (worksheet) {
207
+ if (worksheet && definedName.ranges?.length > 0) {
202
208
  if (!worksheet.pageSetup) {
203
209
  worksheet.pageSetup = {};
204
210
  }
@@ -122,6 +122,9 @@ const colCache = {
122
122
  },
123
123
  // convert address string into structure
124
124
  decodeAddress(value) {
125
+ if (!value || typeof value !== "string") {
126
+ throw new Error(`Invalid Address: ${value}`);
127
+ }
125
128
  const addr = value.length < 5 && this._hash[value];
126
129
  if (addr) {
127
130
  return addr;
@@ -190,6 +193,9 @@ const colCache = {
190
193
  },
191
194
  // convert [address], [tl:br] into address structures
192
195
  decode(value) {
196
+ if (!value || typeof value !== "string") {
197
+ throw new Error(`Invalid Address: ${value}`);
198
+ }
193
199
  const parts = value.split(":");
194
200
  if (parts.length === 2) {
195
201
  const tl = this.decodeAddress(parts[0]);
@@ -213,6 +219,9 @@ const colCache = {
213
219
  },
214
220
  // convert [sheetName!][$]col[$]row[[$]col[$]row] into address or range structures
215
221
  decodeEx(value) {
222
+ if (!value || typeof value !== "string") {
223
+ throw new Error(`Invalid Address: ${value}`);
224
+ }
216
225
  // Use possessive quantifiers to prevent catastrophic backtracking (ReDoS)
217
226
  const groups = value.match(/^(?:(?:(?:'((?:[^']|'')+?)')|([^'^ !]+?))!)?(.*)$/);
218
227
  const sheetName = groups[1] || groups[2]; // Quoted and unquoted groups
@@ -245,15 +245,28 @@ class StreamBuf extends _stream_1.EventEmitter {
245
245
  }
246
246
  else {
247
247
  const chunkBuffer = chunk.toBuffer();
248
- if (!this.paused) {
248
+ // Track whether the data has been delivered to a consumer.
249
+ // When a consumer exists ("data" listeners or a native WritableStream),
250
+ // the data is consumed externally and must NOT also be accumulated in
251
+ // internal buffers — otherwise the buffers grow without bound (memory leak)
252
+ // since no one ever calls read()/toBuffer() to drain them.
253
+ let consumed = false;
254
+ if (!this.paused && this.listenerCount("data") > 0) {
249
255
  this.emit("data", chunkBuffer);
256
+ consumed = true;
250
257
  }
251
258
  // Also write to native WritableStream if connected
252
259
  if (this._writableStreamWriter) {
253
260
  this._asyncWriteQueue = this._asyncWriteQueue.then(() => this._writableStreamWriter.write(chunkBuffer));
261
+ consumed = true;
262
+ }
263
+ // Only buffer internally when no consumer has received the data.
264
+ // This keeps StreamBuf working as a memory buffer (write then read/toBuffer)
265
+ // while preventing unbounded growth when used as an event-driven pass-through.
266
+ if (!consumed) {
267
+ this._writeToBuffers(chunk);
268
+ this.emit("readable");
254
269
  }
255
- this._writeToBuffers(chunk);
256
- this.emit("readable");
257
270
  }
258
271
  return true;
259
272
  }
@@ -46,9 +46,11 @@ class WorkbookXform extends base_xform_1.BaseXform {
46
46
  if (sheet.pageSetup && sheet.pageSetup.printArea) {
47
47
  sheet.pageSetup.printArea.split("&&").forEach((printArea) => {
48
48
  const printAreaComponents = printArea.split(":");
49
+ const start = printAreaComponents[0];
50
+ const end = printAreaComponents[1] ?? start;
49
51
  const definedName = {
50
52
  name: "_xlnm.Print_Area",
51
- ranges: [`'${sheet.name}'!$${printAreaComponents[0]}:$${printAreaComponents[1]}`],
53
+ ranges: [`'${sheet.name}'!$${start}:$${end}`],
52
54
  localSheetId: index
53
55
  };
54
56
  printAreas.push(definedName);
@@ -59,11 +61,15 @@ class WorkbookXform extends base_xform_1.BaseXform {
59
61
  const ranges = [];
60
62
  if (sheet.pageSetup.printTitlesColumn) {
61
63
  const titlesColumns = sheet.pageSetup.printTitlesColumn.split(":");
62
- ranges.push(`'${sheet.name}'!$${titlesColumns[0]}:$${titlesColumns[1]}`);
64
+ const start = titlesColumns[0];
65
+ const end = titlesColumns[1] ?? start;
66
+ ranges.push(`'${sheet.name}'!$${start}:$${end}`);
63
67
  }
64
68
  if (sheet.pageSetup.printTitlesRow) {
65
69
  const titlesRows = sheet.pageSetup.printTitlesRow.split(":");
66
- ranges.push(`'${sheet.name}'!$${titlesRows[0]}:$${titlesRows[1]}`);
70
+ const start = titlesRows[0];
71
+ const end = titlesRows[1] ?? start;
72
+ ranges.push(`'${sheet.name}'!$${start}:$${end}`);
67
73
  }
68
74
  const definedName = {
69
75
  name: "_xlnm.Print_Titles",
@@ -189,7 +195,7 @@ class WorkbookXform extends base_xform_1.BaseXform {
189
195
  model.definedNames.forEach((definedName) => {
190
196
  if (definedName.name === "_xlnm.Print_Area") {
191
197
  worksheet = worksheets[definedName.localSheetId];
192
- if (worksheet) {
198
+ if (worksheet && definedName.ranges?.length > 0) {
193
199
  if (!worksheet.pageSetup) {
194
200
  worksheet.pageSetup = {};
195
201
  }
@@ -201,7 +207,7 @@ class WorkbookXform extends base_xform_1.BaseXform {
201
207
  }
202
208
  else if (definedName.name === "_xlnm.Print_Titles") {
203
209
  worksheet = worksheets[definedName.localSheetId];
204
- if (worksheet) {
210
+ if (worksheet && definedName.ranges?.length > 0) {
205
211
  if (!worksheet.pageSetup) {
206
212
  worksheet.pageSetup = {};
207
213
  }
@@ -119,6 +119,9 @@ const colCache = {
119
119
  },
120
120
  // convert address string into structure
121
121
  decodeAddress(value) {
122
+ if (!value || typeof value !== "string") {
123
+ throw new Error(`Invalid Address: ${value}`);
124
+ }
122
125
  const addr = value.length < 5 && this._hash[value];
123
126
  if (addr) {
124
127
  return addr;
@@ -187,6 +190,9 @@ const colCache = {
187
190
  },
188
191
  // convert [address], [tl:br] into address structures
189
192
  decode(value) {
193
+ if (!value || typeof value !== "string") {
194
+ throw new Error(`Invalid Address: ${value}`);
195
+ }
190
196
  const parts = value.split(":");
191
197
  if (parts.length === 2) {
192
198
  const tl = this.decodeAddress(parts[0]);
@@ -210,6 +216,9 @@ const colCache = {
210
216
  },
211
217
  // convert [sheetName!][$]col[$]row[[$]col[$]row] into address or range structures
212
218
  decodeEx(value) {
219
+ if (!value || typeof value !== "string") {
220
+ throw new Error(`Invalid Address: ${value}`);
221
+ }
213
222
  // Use possessive quantifiers to prevent catastrophic backtracking (ReDoS)
214
223
  const groups = value.match(/^(?:(?:(?:'((?:[^']|'')+?)')|([^'^ !]+?))!)?(.*)$/);
215
224
  const sheetName = groups[1] || groups[2]; // Quoted and unquoted groups
@@ -242,15 +242,28 @@ class StreamBuf extends EventEmitter {
242
242
  }
243
243
  else {
244
244
  const chunkBuffer = chunk.toBuffer();
245
- if (!this.paused) {
245
+ // Track whether the data has been delivered to a consumer.
246
+ // When a consumer exists ("data" listeners or a native WritableStream),
247
+ // the data is consumed externally and must NOT also be accumulated in
248
+ // internal buffers — otherwise the buffers grow without bound (memory leak)
249
+ // since no one ever calls read()/toBuffer() to drain them.
250
+ let consumed = false;
251
+ if (!this.paused && this.listenerCount("data") > 0) {
246
252
  this.emit("data", chunkBuffer);
253
+ consumed = true;
247
254
  }
248
255
  // Also write to native WritableStream if connected
249
256
  if (this._writableStreamWriter) {
250
257
  this._asyncWriteQueue = this._asyncWriteQueue.then(() => this._writableStreamWriter.write(chunkBuffer));
258
+ consumed = true;
259
+ }
260
+ // Only buffer internally when no consumer has received the data.
261
+ // This keeps StreamBuf working as a memory buffer (write then read/toBuffer)
262
+ // while preventing unbounded growth when used as an event-driven pass-through.
263
+ if (!consumed) {
264
+ this._writeToBuffers(chunk);
265
+ this.emit("readable");
251
266
  }
252
- this._writeToBuffers(chunk);
253
- this.emit("readable");
254
267
  }
255
268
  return true;
256
269
  }
@@ -43,9 +43,11 @@ class WorkbookXform extends BaseXform {
43
43
  if (sheet.pageSetup && sheet.pageSetup.printArea) {
44
44
  sheet.pageSetup.printArea.split("&&").forEach((printArea) => {
45
45
  const printAreaComponents = printArea.split(":");
46
+ const start = printAreaComponents[0];
47
+ const end = printAreaComponents[1] ?? start;
46
48
  const definedName = {
47
49
  name: "_xlnm.Print_Area",
48
- ranges: [`'${sheet.name}'!$${printAreaComponents[0]}:$${printAreaComponents[1]}`],
50
+ ranges: [`'${sheet.name}'!$${start}:$${end}`],
49
51
  localSheetId: index
50
52
  };
51
53
  printAreas.push(definedName);
@@ -56,11 +58,15 @@ class WorkbookXform extends BaseXform {
56
58
  const ranges = [];
57
59
  if (sheet.pageSetup.printTitlesColumn) {
58
60
  const titlesColumns = sheet.pageSetup.printTitlesColumn.split(":");
59
- ranges.push(`'${sheet.name}'!$${titlesColumns[0]}:$${titlesColumns[1]}`);
61
+ const start = titlesColumns[0];
62
+ const end = titlesColumns[1] ?? start;
63
+ ranges.push(`'${sheet.name}'!$${start}:$${end}`);
60
64
  }
61
65
  if (sheet.pageSetup.printTitlesRow) {
62
66
  const titlesRows = sheet.pageSetup.printTitlesRow.split(":");
63
- ranges.push(`'${sheet.name}'!$${titlesRows[0]}:$${titlesRows[1]}`);
67
+ const start = titlesRows[0];
68
+ const end = titlesRows[1] ?? start;
69
+ ranges.push(`'${sheet.name}'!$${start}:$${end}`);
64
70
  }
65
71
  const definedName = {
66
72
  name: "_xlnm.Print_Titles",
@@ -186,7 +192,7 @@ class WorkbookXform extends BaseXform {
186
192
  model.definedNames.forEach((definedName) => {
187
193
  if (definedName.name === "_xlnm.Print_Area") {
188
194
  worksheet = worksheets[definedName.localSheetId];
189
- if (worksheet) {
195
+ if (worksheet && definedName.ranges?.length > 0) {
190
196
  if (!worksheet.pageSetup) {
191
197
  worksheet.pageSetup = {};
192
198
  }
@@ -198,7 +204,7 @@ class WorkbookXform extends BaseXform {
198
204
  }
199
205
  else if (definedName.name === "_xlnm.Print_Titles") {
200
206
  worksheet = worksheets[definedName.localSheetId];
201
- if (worksheet) {
207
+ if (worksheet && definedName.ranges?.length > 0) {
202
208
  if (!worksheet.pageSetup) {
203
209
  worksheet.pageSetup = {};
204
210
  }
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @cj-tech-master/excelts v5.1.15
2
+ * @cj-tech-master/excelts v5.1.16-canary.20260310044403.090b2e4
3
3
  * TypeScript Excel Workbook Manager - Read and Write xlsx and csv Files.
4
4
  * (c) 2026 cjnoname
5
5
  * Released under the MIT License
@@ -107,6 +107,7 @@ var ExcelTS = (function(exports) {
107
107
  return true;
108
108
  },
109
109
  decodeAddress(value) {
110
+ if (!value || typeof value !== "string") throw new Error(`Invalid Address: ${value}`);
110
111
  const addr = value.length < 5 && this._hash[value];
111
112
  if (addr) return addr;
112
113
  let hasCol = false;
@@ -151,6 +152,7 @@ var ExcelTS = (function(exports) {
151
152
  return this.decodeAddress(r);
152
153
  },
153
154
  decode(value) {
155
+ if (!value || typeof value !== "string") throw new Error(`Invalid Address: ${value}`);
154
156
  const parts = value.split(":");
155
157
  if (parts.length === 2) {
156
158
  const tl = this.decodeAddress(parts[0]);
@@ -172,6 +174,7 @@ var ExcelTS = (function(exports) {
172
174
  return this.decodeAddress(value);
173
175
  },
174
176
  decodeEx(value) {
177
+ if (!value || typeof value !== "string") throw new Error(`Invalid Address: ${value}`);
175
178
  const groups = value.match(/^(?:(?:(?:'((?:[^']|'')+?)')|([^'^ !]+?))!)?(.*)$/);
176
179
  const sheetName = groups[1] || groups[2];
177
180
  const reference = groups[3];
@@ -11351,9 +11354,11 @@ var ExcelTS = (function(exports) {
11351
11354
  model.sheets.forEach((sheet) => {
11352
11355
  if (sheet.pageSetup && sheet.pageSetup.printArea) sheet.pageSetup.printArea.split("&&").forEach((printArea) => {
11353
11356
  const printAreaComponents = printArea.split(":");
11357
+ const start = printAreaComponents[0];
11358
+ const end = printAreaComponents[1] ?? start;
11354
11359
  const definedName = {
11355
11360
  name: "_xlnm.Print_Area",
11356
- ranges: [`'${sheet.name}'!$${printAreaComponents[0]}:$${printAreaComponents[1]}`],
11361
+ ranges: [`'${sheet.name}'!$${start}:$${end}`],
11357
11362
  localSheetId: index
11358
11363
  };
11359
11364
  printAreas.push(definedName);
@@ -11362,11 +11367,15 @@ var ExcelTS = (function(exports) {
11362
11367
  const ranges = [];
11363
11368
  if (sheet.pageSetup.printTitlesColumn) {
11364
11369
  const titlesColumns = sheet.pageSetup.printTitlesColumn.split(":");
11365
- ranges.push(`'${sheet.name}'!$${titlesColumns[0]}:$${titlesColumns[1]}`);
11370
+ const start = titlesColumns[0];
11371
+ const end = titlesColumns[1] ?? start;
11372
+ ranges.push(`'${sheet.name}'!$${start}:$${end}`);
11366
11373
  }
11367
11374
  if (sheet.pageSetup.printTitlesRow) {
11368
11375
  const titlesRows = sheet.pageSetup.printTitlesRow.split(":");
11369
- ranges.push(`'${sheet.name}'!$${titlesRows[0]}:$${titlesRows[1]}`);
11376
+ const start = titlesRows[0];
11377
+ const end = titlesRows[1] ?? start;
11378
+ ranges.push(`'${sheet.name}'!$${start}:$${end}`);
11370
11379
  }
11371
11380
  const definedName = {
11372
11381
  name: "_xlnm.Print_Titles",
@@ -11459,14 +11468,14 @@ var ExcelTS = (function(exports) {
11459
11468
  if (model.definedNames) model.definedNames.forEach((definedName) => {
11460
11469
  if (definedName.name === "_xlnm.Print_Area") {
11461
11470
  worksheet = worksheets[definedName.localSheetId];
11462
- if (worksheet) {
11471
+ if (worksheet && definedName.ranges?.length > 0) {
11463
11472
  if (!worksheet.pageSetup) worksheet.pageSetup = {};
11464
11473
  const range = colCache.decodeEx(definedName.ranges[0]);
11465
11474
  worksheet.pageSetup.printArea = worksheet.pageSetup.printArea ? `${worksheet.pageSetup.printArea}&&${range.dimensions}` : range.dimensions;
11466
11475
  }
11467
11476
  } else if (definedName.name === "_xlnm.Print_Titles") {
11468
11477
  worksheet = worksheets[definedName.localSheetId];
11469
- if (worksheet) {
11478
+ if (worksheet && definedName.ranges?.length > 0) {
11470
11479
  if (!worksheet.pageSetup) worksheet.pageSetup = {};
11471
11480
  const rangeString = definedName.ranges.join(",");
11472
11481
  const dollarRegex = /\$/g;
@@ -18702,10 +18711,19 @@ var ExcelTS = (function(exports) {
18702
18711
  }
18703
18712
  else {
18704
18713
  const chunkBuffer = chunk.toBuffer();
18705
- if (!this.paused) this.emit("data", chunkBuffer);
18706
- if (this._writableStreamWriter) this._asyncWriteQueue = this._asyncWriteQueue.then(() => this._writableStreamWriter.write(chunkBuffer));
18707
- this._writeToBuffers(chunk);
18708
- this.emit("readable");
18714
+ let consumed = false;
18715
+ if (!this.paused && this.listenerCount("data") > 0) {
18716
+ this.emit("data", chunkBuffer);
18717
+ consumed = true;
18718
+ }
18719
+ if (this._writableStreamWriter) {
18720
+ this._asyncWriteQueue = this._asyncWriteQueue.then(() => this._writableStreamWriter.write(chunkBuffer));
18721
+ consumed = true;
18722
+ }
18723
+ if (!consumed) {
18724
+ this._writeToBuffers(chunk);
18725
+ this.emit("readable");
18726
+ }
18709
18727
  }
18710
18728
  return true;
18711
18729
  }