@cj-tech-master/excelts 7.5.0 → 7.6.0
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/modules/excel/stream/hyperlink-reader.js +1 -1
- package/dist/browser/modules/excel/stream/workbook-reader.browser.js +2 -2
- package/dist/browser/modules/excel/stream/worksheet-reader.js +1 -1
- package/dist/browser/modules/excel/xlsx/xform/base-xform.js +1 -1
- package/dist/browser/modules/xml/dom.js +2 -1
- package/dist/browser/modules/xml/index.d.ts +1 -1
- package/dist/browser/modules/xml/sax.d.ts +41 -0
- package/dist/browser/modules/xml/sax.js +265 -76
- package/dist/browser/modules/xml/to-object.js +2 -1
- package/dist/browser/modules/xml/types.d.ts +24 -0
- package/dist/cjs/modules/excel/stream/hyperlink-reader.js +1 -1
- package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +2 -2
- package/dist/cjs/modules/excel/stream/worksheet-reader.js +1 -1
- package/dist/cjs/modules/excel/xlsx/xform/base-xform.js +1 -1
- package/dist/cjs/modules/xml/dom.js +2 -1
- package/dist/cjs/modules/xml/sax.js +265 -76
- package/dist/cjs/modules/xml/to-object.js +2 -1
- package/dist/esm/modules/excel/stream/hyperlink-reader.js +1 -1
- package/dist/esm/modules/excel/stream/workbook-reader.browser.js +2 -2
- package/dist/esm/modules/excel/stream/worksheet-reader.js +1 -1
- package/dist/esm/modules/excel/xlsx/xform/base-xform.js +1 -1
- package/dist/esm/modules/xml/dom.js +2 -1
- package/dist/esm/modules/xml/sax.js +265 -76
- package/dist/esm/modules/xml/to-object.js +2 -1
- package/dist/iife/excelts.iife.js +196 -54
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +44 -44
- package/dist/types/modules/xml/index.d.ts +1 -1
- package/dist/types/modules/xml/sax.d.ts +41 -0
- package/dist/types/modules/xml/types.d.ts +24 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @cj-tech-master/excelts v7.
|
|
2
|
+
* @cj-tech-master/excelts v7.6.0
|
|
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
|
|
@@ -11429,6 +11429,8 @@ var ExcelTS = (function(exports) {
|
|
|
11429
11429
|
const QUESTION = 63;
|
|
11430
11430
|
const OPEN_BRACKET = 91;
|
|
11431
11431
|
const CLOSE_BRACKET = 93;
|
|
11432
|
+
const REPLACEMENT_CHAR = 65533;
|
|
11433
|
+
const REPLACEMENT_STR = "�";
|
|
11432
11434
|
const ASCII_CHARS = /* @__PURE__ */ (() => {
|
|
11433
11435
|
const t = new Array(128);
|
|
11434
11436
|
for (let i = 0; i < 128; i++) t[i] = String.fromCharCode(i);
|
|
@@ -11557,6 +11559,7 @@ var ExcelTS = (function(exports) {
|
|
|
11557
11559
|
this.xmlns = options?.xmlns ?? false;
|
|
11558
11560
|
this.maxDepth = options?.maxDepth !== void 0 ? options.maxDepth : 256;
|
|
11559
11561
|
this.maxEntityExpansions = options?.maxEntityExpansions !== void 0 ? options.maxEntityExpansions : 1e4;
|
|
11562
|
+
this.invalidCharHandling = options?.invalidCharHandling ?? "error";
|
|
11560
11563
|
this._init();
|
|
11561
11564
|
}
|
|
11562
11565
|
get closed() {
|
|
@@ -11650,55 +11653,150 @@ var ExcelTS = (function(exports) {
|
|
|
11650
11653
|
close() {
|
|
11651
11654
|
return this.write(null);
|
|
11652
11655
|
}
|
|
11653
|
-
|
|
11654
|
-
|
|
11655
|
-
|
|
11656
|
-
|
|
11657
|
-
|
|
11658
|
-
|
|
11659
|
-
|
|
11660
|
-
|
|
11661
|
-
|
|
11662
|
-
|
|
11663
|
-
|
|
11664
|
-
|
|
11665
|
-
|
|
11656
|
+
/**
|
|
11657
|
+
* Handle an invalid XML character according to the configured strategy.
|
|
11658
|
+
*
|
|
11659
|
+
* Used by `handleTextInRoot()` fast path which manages its own text accumulation
|
|
11660
|
+
* and cannot use the `getCode()` loop approach.
|
|
11661
|
+
*
|
|
11662
|
+
* - `"error"`: call `fail()` and return the original code.
|
|
11663
|
+
* - `"skip"`: return `REPLACEMENT_CHAR` as a sentinel (caller handles skip).
|
|
11664
|
+
* - `"replace"`: return `REPLACEMENT_CHAR`.
|
|
11665
|
+
*
|
|
11666
|
+
* Note: For `getCode()`, invalid char handling is inlined to avoid recursion.
|
|
11667
|
+
*
|
|
11668
|
+
* @param code - The invalid character code point.
|
|
11669
|
+
* @param kind - Optional description (e.g. "lone surrogate") for error messages.
|
|
11670
|
+
* @returns The code point to use.
|
|
11671
|
+
*/
|
|
11672
|
+
handleInvalidChar(code, kind) {
|
|
11673
|
+
switch (this.invalidCharHandling) {
|
|
11674
|
+
case "replace": return REPLACEMENT_CHAR;
|
|
11675
|
+
case "skip": return -2;
|
|
11676
|
+
default: {
|
|
11677
|
+
const label = kind ? `invalid XML character: ${kind} 0x${code.toString(16)}` : `invalid XML character: 0x${code.toString(16)}`;
|
|
11678
|
+
this.fail(label);
|
|
11679
|
+
return code;
|
|
11680
|
+
}
|
|
11666
11681
|
}
|
|
11667
|
-
|
|
11668
|
-
|
|
11669
|
-
|
|
11670
|
-
|
|
11671
|
-
|
|
11672
|
-
|
|
11682
|
+
}
|
|
11683
|
+
/**
|
|
11684
|
+
* Handle an invalid character inside the `handleTextInRoot()` fast loop.
|
|
11685
|
+
*
|
|
11686
|
+
* Unlike `handleInvalidChar()` (which returns a code point for `getCode()`),
|
|
11687
|
+
* this method manages the text accumulation state (`this.text`, `start`) that
|
|
11688
|
+
* the fast text loop relies on.
|
|
11689
|
+
*
|
|
11690
|
+
* - `"error"`: call `fail()`, leave text accumulation unchanged (char stays in output).
|
|
11691
|
+
* - `"skip"`: flush text up to the invalid char, skip it, return new `start`.
|
|
11692
|
+
* - `"replace"`: flush text up to the invalid char, append U+FFFD, return new `start`.
|
|
11693
|
+
*
|
|
11694
|
+
* @returns The updated `start` index for the text accumulation loop.
|
|
11695
|
+
*/
|
|
11696
|
+
handleInvalidCharInText(code, handler, start, kind) {
|
|
11697
|
+
switch (this.invalidCharHandling) {
|
|
11698
|
+
case "skip":
|
|
11699
|
+
if (handler && start < this.prevI) this.text += this.chunk.slice(start, this.prevI);
|
|
11700
|
+
return this.i;
|
|
11701
|
+
case "replace":
|
|
11702
|
+
if (handler) {
|
|
11703
|
+
if (start < this.prevI) this.text += this.chunk.slice(start, this.prevI);
|
|
11704
|
+
this.text += REPLACEMENT_STR;
|
|
11705
|
+
}
|
|
11706
|
+
return this.i;
|
|
11707
|
+
default: {
|
|
11708
|
+
const label = kind ? `invalid XML character: ${kind} 0x${code.toString(16)}` : `invalid XML character: 0x${code.toString(16)}`;
|
|
11709
|
+
this.fail(label);
|
|
11710
|
+
return start;
|
|
11673
11711
|
}
|
|
11674
|
-
return NL;
|
|
11675
11712
|
}
|
|
11676
|
-
|
|
11677
|
-
|
|
11678
|
-
|
|
11679
|
-
|
|
11680
|
-
|
|
11713
|
+
}
|
|
11714
|
+
/**
|
|
11715
|
+
* Handle an invalid character inside `sAttribValueQuoted()`.
|
|
11716
|
+
*
|
|
11717
|
+
* Same pattern as `handleInvalidCharInText()` but for attribute value
|
|
11718
|
+
* accumulation (always uses `this.text`, no conditional handler check).
|
|
11719
|
+
*
|
|
11720
|
+
* @returns The updated `start` index.
|
|
11721
|
+
*/
|
|
11722
|
+
handleInvalidCharInAttr(code, start, kind) {
|
|
11723
|
+
switch (this.invalidCharHandling) {
|
|
11724
|
+
case "skip":
|
|
11725
|
+
if (start < this.prevI) this.text += this.chunk.slice(start, this.prevI);
|
|
11726
|
+
return this.i;
|
|
11727
|
+
case "replace":
|
|
11728
|
+
if (start < this.prevI) this.text += this.chunk.slice(start, this.prevI);
|
|
11729
|
+
this.text += REPLACEMENT_STR;
|
|
11730
|
+
return this.i;
|
|
11731
|
+
default: {
|
|
11732
|
+
const label = kind ? `invalid XML character: ${kind} 0x${code.toString(16)}` : `invalid XML character: 0x${code.toString(16)}`;
|
|
11733
|
+
this.fail(label);
|
|
11734
|
+
return start;
|
|
11681
11735
|
}
|
|
11682
|
-
return NL;
|
|
11683
11736
|
}
|
|
11684
|
-
|
|
11685
|
-
|
|
11686
|
-
|
|
11687
|
-
|
|
11737
|
+
}
|
|
11738
|
+
getCode() {
|
|
11739
|
+
for (;;) {
|
|
11740
|
+
const { chunk } = this;
|
|
11741
|
+
const i = this.i;
|
|
11742
|
+
this.prevI = i;
|
|
11743
|
+
this.i = i + 1;
|
|
11744
|
+
if (i >= chunk.length) return -1;
|
|
11745
|
+
const code = chunk.charCodeAt(i);
|
|
11746
|
+
if (code >= 32 && code <= 126) {
|
|
11688
11747
|
if (this.trackPosition) this.column++;
|
|
11689
|
-
return
|
|
11748
|
+
return code;
|
|
11749
|
+
}
|
|
11750
|
+
if (code === TAB) {
|
|
11751
|
+
if (this.trackPosition) this.column++;
|
|
11752
|
+
return code;
|
|
11753
|
+
}
|
|
11754
|
+
if (code === CR) {
|
|
11755
|
+
if (chunk.charCodeAt(i + 1) === NL) this.i = i + 2;
|
|
11756
|
+
if (this.trackPosition) {
|
|
11757
|
+
this.line++;
|
|
11758
|
+
this.column = 0;
|
|
11759
|
+
this.positionAtNewLine = this.position;
|
|
11760
|
+
}
|
|
11761
|
+
return NL;
|
|
11762
|
+
}
|
|
11763
|
+
if (code === NL) {
|
|
11764
|
+
if (this.trackPosition) {
|
|
11765
|
+
this.line++;
|
|
11766
|
+
this.column = 0;
|
|
11767
|
+
this.positionAtNewLine = this.position;
|
|
11768
|
+
}
|
|
11769
|
+
return NL;
|
|
11770
|
+
}
|
|
11771
|
+
if (code >= 55296 && code <= 56319) {
|
|
11772
|
+
const next = chunk.charCodeAt(i + 1);
|
|
11773
|
+
if (next >= 56320 && next <= 57343) {
|
|
11774
|
+
this.i = i + 2;
|
|
11775
|
+
if (this.trackPosition) this.column++;
|
|
11776
|
+
return 65536 + ((code - 55296) * 1024 + (next - 56320));
|
|
11777
|
+
}
|
|
11778
|
+
const result = this.handleInvalidChar(code, "lone surrogate");
|
|
11779
|
+
if (result !== -2) return result;
|
|
11780
|
+
continue;
|
|
11781
|
+
}
|
|
11782
|
+
if (code >= 56320 && code <= 57343) {
|
|
11783
|
+
const result = this.handleInvalidChar(code, "lone surrogate");
|
|
11784
|
+
if (result !== -2) return result;
|
|
11785
|
+
continue;
|
|
11786
|
+
}
|
|
11787
|
+
if (code >= 128) {
|
|
11788
|
+
if (this.trackPosition) this.column++;
|
|
11789
|
+
if (code === 65534 || code === 65535) {
|
|
11790
|
+
const result = this.handleInvalidChar(code);
|
|
11791
|
+
if (result !== -2) return result;
|
|
11792
|
+
continue;
|
|
11793
|
+
}
|
|
11794
|
+
return code;
|
|
11690
11795
|
}
|
|
11691
|
-
this.fail("invalid XML character: lone surrogate 0x" + code.toString(16));
|
|
11692
|
-
}
|
|
11693
|
-
if (code >= 56320 && code <= 57343) this.fail("invalid XML character: lone surrogate 0x" + code.toString(16));
|
|
11694
|
-
if (code >= 128) {
|
|
11695
11796
|
if (this.trackPosition) this.column++;
|
|
11696
|
-
|
|
11697
|
-
return
|
|
11797
|
+
const result = this.handleInvalidChar(code);
|
|
11798
|
+
if (result !== -2) return result;
|
|
11698
11799
|
}
|
|
11699
|
-
if (this.trackPosition) this.column++;
|
|
11700
|
-
this.fail("invalid XML character: 0x" + code.toString(16));
|
|
11701
|
-
return code;
|
|
11702
11800
|
}
|
|
11703
11801
|
unget() {
|
|
11704
11802
|
this.i = this.prevI;
|
|
@@ -11863,14 +11961,14 @@ var ExcelTS = (function(exports) {
|
|
|
11863
11961
|
if (next >= 56320 && next <= 57343) this.i += 2;
|
|
11864
11962
|
else {
|
|
11865
11963
|
this.i++;
|
|
11866
|
-
this.
|
|
11964
|
+
start = this.handleInvalidCharInText(code, handler, start, "lone surrogate");
|
|
11867
11965
|
}
|
|
11868
11966
|
} else if (code >= 56320 && code <= 57343) {
|
|
11869
11967
|
this.i++;
|
|
11870
|
-
this.
|
|
11968
|
+
start = this.handleInvalidCharInText(code, handler, start, "lone surrogate");
|
|
11871
11969
|
} else if (code === 65534 || code === 65535) {
|
|
11872
11970
|
this.i++;
|
|
11873
|
-
this.
|
|
11971
|
+
start = this.handleInvalidCharInText(code, handler, start);
|
|
11874
11972
|
} else this.i++;
|
|
11875
11973
|
if (this.trackPosition) this.column++;
|
|
11876
11974
|
continue;
|
|
@@ -11878,7 +11976,7 @@ var ExcelTS = (function(exports) {
|
|
|
11878
11976
|
this.prevI = this.i;
|
|
11879
11977
|
this.i++;
|
|
11880
11978
|
if (this.trackPosition) this.column++;
|
|
11881
|
-
this.
|
|
11979
|
+
start = this.handleInvalidCharInText(code, handler, start);
|
|
11882
11980
|
}
|
|
11883
11981
|
if (handler && start < this.i) this.text += chunk.slice(start, this.i);
|
|
11884
11982
|
}
|
|
@@ -11887,12 +11985,28 @@ var ExcelTS = (function(exports) {
|
|
|
11887
11985
|
let { i: start } = this;
|
|
11888
11986
|
const handler = this._handlers.text;
|
|
11889
11987
|
let nonSpace = false;
|
|
11988
|
+
const isSkip = this.invalidCharHandling === "skip";
|
|
11989
|
+
const isReplace = this.invalidCharHandling === "replace";
|
|
11890
11990
|
while (true) {
|
|
11991
|
+
const iBeforeGet = this.i;
|
|
11891
11992
|
const c = this.getCode();
|
|
11892
11993
|
if (c === -1) {
|
|
11893
|
-
if (handler && start <
|
|
11994
|
+
if (handler && start < iBeforeGet) this.text += chunk.slice(start, iBeforeGet);
|
|
11894
11995
|
break;
|
|
11895
11996
|
}
|
|
11997
|
+
if (isSkip && this.prevI > iBeforeGet) {
|
|
11998
|
+
if (handler && start < iBeforeGet) this.text += chunk.slice(start, iBeforeGet);
|
|
11999
|
+
start = this.prevI;
|
|
12000
|
+
}
|
|
12001
|
+
if (isReplace && c === REPLACEMENT_CHAR && chunk.charCodeAt(this.prevI) !== REPLACEMENT_CHAR) {
|
|
12002
|
+
if (handler) {
|
|
12003
|
+
if (start < this.prevI) this.text += chunk.slice(start, this.prevI);
|
|
12004
|
+
this.text += REPLACEMENT_STR;
|
|
12005
|
+
}
|
|
12006
|
+
start = this.i;
|
|
12007
|
+
nonSpace = true;
|
|
12008
|
+
continue;
|
|
12009
|
+
}
|
|
11896
12010
|
if (c === LESS) {
|
|
11897
12011
|
if (handler) {
|
|
11898
12012
|
const slice = chunk.slice(start, this.prevI);
|
|
@@ -12174,10 +12288,29 @@ var ExcelTS = (function(exports) {
|
|
|
12174
12288
|
start = this.i;
|
|
12175
12289
|
continue;
|
|
12176
12290
|
}
|
|
12177
|
-
if (
|
|
12178
|
-
this.
|
|
12179
|
-
|
|
12291
|
+
if (code >= 128) {
|
|
12292
|
+
this.prevI = this.i;
|
|
12293
|
+
if (code >= 55296 && code <= 56319) {
|
|
12294
|
+
const next = chunk.charCodeAt(this.i + 1);
|
|
12295
|
+
if (next >= 56320 && next <= 57343) this.i += 2;
|
|
12296
|
+
else {
|
|
12297
|
+
this.i++;
|
|
12298
|
+
start = this.handleInvalidCharInAttr(code, start, "lone surrogate");
|
|
12299
|
+
}
|
|
12300
|
+
} else if (code >= 56320 && code <= 57343) {
|
|
12301
|
+
this.i++;
|
|
12302
|
+
start = this.handleInvalidCharInAttr(code, start, "lone surrogate");
|
|
12303
|
+
} else if (code === 65534 || code === 65535) {
|
|
12304
|
+
this.i++;
|
|
12305
|
+
start = this.handleInvalidCharInAttr(code, start);
|
|
12306
|
+
} else this.i++;
|
|
12307
|
+
if (this.trackPosition) this.column++;
|
|
12308
|
+
continue;
|
|
12180
12309
|
}
|
|
12310
|
+
this.prevI = this.i;
|
|
12311
|
+
this.i++;
|
|
12312
|
+
if (this.trackPosition) this.column++;
|
|
12313
|
+
start = this.handleInvalidCharInAttr(code, start);
|
|
12181
12314
|
}
|
|
12182
12315
|
this.text += chunk.slice(start, this.i);
|
|
12183
12316
|
}
|
|
@@ -12688,7 +12821,7 @@ var ExcelTS = (function(exports) {
|
|
|
12688
12821
|
* Use this instead of parse(parseSax(stream)) for hot paths.
|
|
12689
12822
|
*/
|
|
12690
12823
|
async parseStreamDirect(stream) {
|
|
12691
|
-
const parser = new SaxParser();
|
|
12824
|
+
const parser = new SaxParser({ invalidCharHandling: "skip" });
|
|
12692
12825
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
12693
12826
|
let done = false;
|
|
12694
12827
|
let finalModel;
|
|
@@ -38161,7 +38294,10 @@ onmessage = async (ev) => {
|
|
|
38161
38294
|
let c = null;
|
|
38162
38295
|
let current = null;
|
|
38163
38296
|
let worksheetEvents = null;
|
|
38164
|
-
const parser = new SaxParser({
|
|
38297
|
+
const parser = new SaxParser({
|
|
38298
|
+
position: false,
|
|
38299
|
+
invalidCharHandling: "skip"
|
|
38300
|
+
});
|
|
38165
38301
|
parser.on("opentag", (node) => {
|
|
38166
38302
|
if (emitSheet) switch (node.name) {
|
|
38167
38303
|
case "cols":
|
|
@@ -38380,7 +38516,10 @@ onmessage = async (ev) => {
|
|
|
38380
38516
|
return;
|
|
38381
38517
|
}
|
|
38382
38518
|
try {
|
|
38383
|
-
const parser = new SaxParser({
|
|
38519
|
+
const parser = new SaxParser({
|
|
38520
|
+
position: false,
|
|
38521
|
+
invalidCharHandling: "skip"
|
|
38522
|
+
});
|
|
38384
38523
|
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
38385
38524
|
parser.on("opentag", (node) => {
|
|
38386
38525
|
if (node.name !== "Relationship") return;
|
|
@@ -38558,7 +38697,10 @@ onmessage = async (ev) => {
|
|
|
38558
38697
|
let inRichText = false;
|
|
38559
38698
|
if (this.options.sharedStrings === "cache") {
|
|
38560
38699
|
const sharedStrings = this.sharedStrings;
|
|
38561
|
-
const parser = new SaxParser({
|
|
38700
|
+
const parser = new SaxParser({
|
|
38701
|
+
position: false,
|
|
38702
|
+
invalidCharHandling: "skip"
|
|
38703
|
+
});
|
|
38562
38704
|
parser.on("opentag", (node) => {
|
|
38563
38705
|
switch (node.name) {
|
|
38564
38706
|
case "b":
|
|
@@ -38652,7 +38794,7 @@ onmessage = async (ev) => {
|
|
|
38652
38794
|
await saxStream(parser, iterateStream(entry));
|
|
38653
38795
|
return;
|
|
38654
38796
|
}
|
|
38655
|
-
const emitParser = new SaxParser();
|
|
38797
|
+
const emitParser = new SaxParser({ invalidCharHandling: "skip" });
|
|
38656
38798
|
const emitDecoder = new TextDecoder("utf-8", { fatal: true });
|
|
38657
38799
|
let pendingEmits = [];
|
|
38658
38800
|
emitParser.on("opentag", (node) => {
|