@cj-tech-master/excelts 6.1.0 → 6.1.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/modules/csv/worker/worker-script.generated.d.ts +1 -1
- package/dist/browser/modules/csv/worker/worker-script.generated.js +1 -1
- package/dist/browser/modules/excel/stream/sheet-rels-writer.d.ts +2 -1
- package/dist/browser/modules/excel/stream/sheet-rels-writer.js +10 -1
- package/dist/browser/modules/excel/stream/workbook-writer.browser.js +2 -1
- package/dist/browser/modules/excel/stream/worksheet-reader.d.ts +2 -1
- package/dist/browser/modules/excel/stream/worksheet-reader.js +4 -1
- package/dist/browser/modules/excel/workbook.browser.js +2 -1
- package/dist/browser/modules/excel/worksheet.js +2 -1
- package/dist/browser/modules/excel/xlsx/xform/sheet/hyperlink-xform.d.ts +8 -3
- package/dist/browser/modules/excel/xlsx/xform/sheet/hyperlink-xform.js +20 -10
- package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +11 -1
- package/dist/cjs/modules/csv/worker/worker-script.generated.js +1 -1
- package/dist/cjs/modules/excel/stream/sheet-rels-writer.js +10 -1
- package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +2 -1
- package/dist/cjs/modules/excel/stream/worksheet-reader.js +4 -1
- package/dist/cjs/modules/excel/workbook.browser.js +2 -1
- package/dist/cjs/modules/excel/worksheet.js +2 -1
- package/dist/cjs/modules/excel/xlsx/xform/sheet/hyperlink-xform.js +20 -9
- package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +11 -1
- package/dist/esm/modules/csv/worker/worker-script.generated.js +1 -1
- package/dist/esm/modules/excel/stream/sheet-rels-writer.js +10 -1
- package/dist/esm/modules/excel/stream/workbook-writer.browser.js +2 -1
- package/dist/esm/modules/excel/stream/worksheet-reader.js +4 -1
- package/dist/esm/modules/excel/workbook.browser.js +2 -1
- package/dist/esm/modules/excel/worksheet.js +2 -1
- package/dist/esm/modules/excel/xlsx/xform/sheet/hyperlink-xform.js +20 -10
- package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +11 -1
- package/dist/iife/excelts.iife.js +77 -72
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +34 -34
- package/dist/types/modules/csv/worker/worker-script.generated.d.ts +1 -1
- package/dist/types/modules/excel/stream/sheet-rels-writer.d.ts +2 -1
- package/dist/types/modules/excel/stream/worksheet-reader.d.ts +2 -1
- package/dist/types/modules/excel/xlsx/xform/sheet/hyperlink-xform.d.ts +8 -3
- package/package.json +13 -13
|
@@ -227,9 +227,12 @@ class WorksheetReader extends EventEmitter {
|
|
|
227
227
|
break;
|
|
228
228
|
case "hyperlink":
|
|
229
229
|
if (inHyperlinks) {
|
|
230
|
+
const loc = node.attributes.location;
|
|
230
231
|
const hyperlink = {
|
|
231
232
|
ref: node.attributes.ref,
|
|
232
|
-
rId: node.attributes["r:id"]
|
|
233
|
+
rId: node.attributes["r:id"],
|
|
234
|
+
// Internal links: resolve target from location attribute
|
|
235
|
+
target: loc ? (loc.startsWith("#") ? loc : `#${loc}`) : undefined
|
|
233
236
|
};
|
|
234
237
|
if (emitHyperlinks) {
|
|
235
238
|
(worksheetEvents || (worksheetEvents = [])).push({ eventType: "hyperlink", value: hyperlink });
|
|
@@ -666,7 +666,8 @@ class Workbook {
|
|
|
666
666
|
return this._worksheets[id];
|
|
667
667
|
}
|
|
668
668
|
if (typeof id === "string") {
|
|
669
|
-
|
|
669
|
+
const idLower = id.toLowerCase();
|
|
670
|
+
return this._worksheets.find(worksheet => worksheet && worksheet.name.toLowerCase() === idLower);
|
|
670
671
|
}
|
|
671
672
|
return undefined;
|
|
672
673
|
}
|
|
@@ -138,7 +138,8 @@ class Worksheet {
|
|
|
138
138
|
}
|
|
139
139
|
name = name.substring(0, 31);
|
|
140
140
|
}
|
|
141
|
-
|
|
141
|
+
const nameLower = name.toLowerCase();
|
|
142
|
+
if (this._workbook.worksheets.find(ws => ws && ws !== this && ws.name.toLowerCase() === nameLower)) {
|
|
142
143
|
throw new WorksheetNameError(`Worksheet name already exists: ${name}`);
|
|
143
144
|
}
|
|
144
145
|
this._name = name;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseXform } from "../base-xform.js";
|
|
2
2
|
interface HyperlinkModel {
|
|
3
3
|
address: string;
|
|
4
|
-
rId
|
|
4
|
+
rId?: string;
|
|
5
5
|
tooltip?: string;
|
|
6
6
|
target?: string;
|
|
7
7
|
}
|
|
@@ -11,6 +11,11 @@ declare class HyperlinkXform extends BaseXform {
|
|
|
11
11
|
parseOpen(node: any): boolean;
|
|
12
12
|
parseText(): void;
|
|
13
13
|
parseClose(): boolean;
|
|
14
|
-
isInternalLink(model: HyperlinkModel): boolean;
|
|
15
14
|
}
|
|
16
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Internal hyperlinks start with "#" (e.g. "#Sheet2!A1").
|
|
17
|
+
* This matches Excel's convention and the OOXML spec where internal links
|
|
18
|
+
* use the `location` attribute instead of a relationship.
|
|
19
|
+
*/
|
|
20
|
+
declare function isInternalLink(target: string): boolean;
|
|
21
|
+
export { HyperlinkXform, isInternalLink };
|
|
@@ -4,15 +4,17 @@ class HyperlinkXform extends BaseXform {
|
|
|
4
4
|
return "hyperlink";
|
|
5
5
|
}
|
|
6
6
|
render(xmlStream, model) {
|
|
7
|
-
if (
|
|
7
|
+
if (model.target && isInternalLink(model.target)) {
|
|
8
|
+
// Internal link: use location attribute only (no relationship)
|
|
9
|
+
// Strip the leading "#" — OOXML location attribute is without "#"
|
|
8
10
|
xmlStream.leafNode("hyperlink", {
|
|
9
11
|
ref: model.address,
|
|
10
|
-
"r:id": model.rId,
|
|
11
12
|
tooltip: model.tooltip,
|
|
12
|
-
location: model.target
|
|
13
|
+
location: model.target.slice(1)
|
|
13
14
|
});
|
|
14
15
|
}
|
|
15
16
|
else {
|
|
17
|
+
// External link: use r:id relationship reference
|
|
16
18
|
xmlStream.leafNode("hyperlink", {
|
|
17
19
|
ref: model.address,
|
|
18
20
|
"r:id": model.rId,
|
|
@@ -27,9 +29,13 @@ class HyperlinkXform extends BaseXform {
|
|
|
27
29
|
rId: node.attributes["r:id"],
|
|
28
30
|
tooltip: node.attributes.tooltip
|
|
29
31
|
};
|
|
30
|
-
//
|
|
32
|
+
// Internal link: location attribute stores the target without "#"
|
|
33
|
+
// Normalize: always store as "#Location" in the model regardless of
|
|
34
|
+
// whether the source had a leading "#" (our old buggy output) or not
|
|
35
|
+
// (correct OOXML from Excel or the fixed writer).
|
|
31
36
|
if (node.attributes.location) {
|
|
32
|
-
|
|
37
|
+
const loc = node.attributes.location;
|
|
38
|
+
this.model.target = loc.startsWith("#") ? loc : `#${loc}`;
|
|
33
39
|
}
|
|
34
40
|
return true;
|
|
35
41
|
}
|
|
@@ -39,9 +45,13 @@ class HyperlinkXform extends BaseXform {
|
|
|
39
45
|
parseClose() {
|
|
40
46
|
return false;
|
|
41
47
|
}
|
|
42
|
-
isInternalLink(model) {
|
|
43
|
-
// @example: Sheet2!D3, return true
|
|
44
|
-
return !!(model.target && /^[^!]+![a-zA-Z]+[\d]+$/.test(model.target));
|
|
45
|
-
}
|
|
46
48
|
}
|
|
47
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Internal hyperlinks start with "#" (e.g. "#Sheet2!A1").
|
|
51
|
+
* This matches Excel's convention and the OOXML spec where internal links
|
|
52
|
+
* use the `location` attribute instead of a relationship.
|
|
53
|
+
*/
|
|
54
|
+
function isInternalLink(target) {
|
|
55
|
+
return target.startsWith("#");
|
|
56
|
+
}
|
|
57
|
+
export { HyperlinkXform, isInternalLink };
|
|
@@ -3,11 +3,11 @@ import { XmlStream } from "../../../utils/xml-stream.js";
|
|
|
3
3
|
import { RelType } from "../../rel-type.js";
|
|
4
4
|
import { Merges } from "./merges.js";
|
|
5
5
|
import { BaseXform } from "../base-xform.js";
|
|
6
|
+
import { isInternalLink, HyperlinkXform } from "./hyperlink-xform.js";
|
|
6
7
|
import { ListXform } from "../list-xform.js";
|
|
7
8
|
import { RowXform } from "./row-xform.js";
|
|
8
9
|
import { ColXform } from "./col-xform.js";
|
|
9
10
|
import { DimensionXform } from "./dimension-xform.js";
|
|
10
|
-
import { HyperlinkXform } from "./hyperlink-xform.js";
|
|
11
11
|
import { MergeCellXform } from "./merge-cell-xform.js";
|
|
12
12
|
import { DataValidationsXform } from "./data-validations-xform.js";
|
|
13
13
|
import { SheetPropertiesXform } from "./sheet-properties-xform.js";
|
|
@@ -158,6 +158,11 @@ class WorkSheetXform extends BaseXform {
|
|
|
158
158
|
return `rId${r.length + 1}`;
|
|
159
159
|
}
|
|
160
160
|
model.hyperlinks.forEach(hyperlink => {
|
|
161
|
+
// Internal links (e.g. "#Sheet2!A1") use the location attribute only,
|
|
162
|
+
// no relationship is needed in the .rels file.
|
|
163
|
+
if (isInternalLink(hyperlink.target)) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
161
166
|
const rId = nextRid(rels);
|
|
162
167
|
hyperlink.rId = rId;
|
|
163
168
|
rels.push({
|
|
@@ -594,8 +599,13 @@ class WorkSheetXform extends BaseXform {
|
|
|
594
599
|
}, {});
|
|
595
600
|
options.hyperlinkMap = (model.hyperlinks ?? []).reduce((h, hyperlink) => {
|
|
596
601
|
if (hyperlink.rId) {
|
|
602
|
+
// External link: resolve target from relationship
|
|
597
603
|
h[hyperlink.address] = rels[hyperlink.rId].Target;
|
|
598
604
|
}
|
|
605
|
+
else if (hyperlink.target) {
|
|
606
|
+
// Internal link: target was restored from location attribute (with "#" prefix)
|
|
607
|
+
h[hyperlink.address] = hyperlink.target;
|
|
608
|
+
}
|
|
599
609
|
return h;
|
|
600
610
|
}, {});
|
|
601
611
|
options.formulae = {};
|