@l1yp/file-viewer 0.1.5 → 0.1.6
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/README.md +55 -6
- package/dist/assets/step.worker-CfDTYOf_.js.map +1 -0
- package/dist/components/CertViewer.js +1 -1
- package/dist/components/CertViewer.js.map +1 -1
- package/dist/components/CertViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/DocxNavigationPane.js +1 -1
- package/dist/components/DocxNavigationPane.js.map +1 -1
- package/dist/components/DocxNavigationPane.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/DocxViewer.js +1 -1
- package/dist/components/DocxViewer.js.map +1 -1
- package/dist/components/DocxViewer.vue.d.ts +1 -1
- package/dist/components/DocxViewer.vue_vue_type_script_setup_true_lang.js +80 -78
- package/dist/components/DocxViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/EplViewer.js +1 -1
- package/dist/components/EplViewer.js.map +1 -1
- package/dist/components/EplViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/FileViewerBody.js +1 -1
- package/dist/components/FileViewerBody.js.map +1 -1
- package/dist/components/FileViewerBody.vue_vue_type_script_setup_true_lang.js +265 -257
- package/dist/components/FileViewerBody.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/FileViewerPanel.js +1 -1
- package/dist/components/FileViewerPanel.js.map +1 -1
- package/dist/components/FileViewerPanel.vue.d.ts +6 -1
- package/dist/components/FileViewerPanel.vue_vue_type_script_setup_true_lang.js +42 -40
- package/dist/components/FileViewerPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/HarViewer.js +1 -1
- package/dist/components/HarViewer.js.map +1 -1
- package/dist/components/HarViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/JksViewer.js +1 -1
- package/dist/components/JksViewer.js.map +1 -1
- package/dist/components/JksViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/ModelViewModes.js +9 -0
- package/dist/components/ModelViewModes.js.map +1 -0
- package/dist/components/ModelViewModes.vue.d.ts +11 -0
- package/dist/components/ModelViewModes.vue_vue_type_script_setup_true_lang.js +49 -0
- package/dist/components/ModelViewModes.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/ModelViewer.js +1 -1
- package/dist/components/ModelViewer.js.map +1 -1
- package/dist/components/ModelViewer.vue.d.ts +2 -1
- package/dist/components/ModelViewer.vue_vue_type_script_setup_true_lang.js +183 -96
- package/dist/components/ModelViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/PdfNavigationPane.js +1 -1
- package/dist/components/PdfNavigationPane.js.map +1 -1
- package/dist/components/PdfNavigationPane.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/PdfViewer.js +1 -1
- package/dist/components/PdfViewer.js.map +1 -1
- package/dist/components/PdfViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/PptxNavigationPane.js +1 -1
- package/dist/components/PptxNavigationPane.js.map +1 -1
- package/dist/components/PptxNavigationPane.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/PsdViewer.js +1 -1
- package/dist/components/PsdViewer.js.map +1 -1
- package/dist/components/PsdViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/SqliteViewer.js +1 -1
- package/dist/components/SqliteViewer.js.map +1 -1
- package/dist/components/SqliteViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/ViewerLoadError.js +9 -0
- package/dist/components/ViewerLoadError.js.map +1 -0
- package/dist/components/ViewerLoadError.vue.d.ts +17 -0
- package/dist/components/ViewerLoadError.vue_vue_type_script_setup_true_lang.js +58 -0
- package/dist/components/ViewerLoadError.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/XlsxChart.js +1 -1
- package/dist/components/XlsxChart.js.map +1 -1
- package/dist/components/XlsxChart.vue_vue_type_script_setup_true_lang.js +9 -9
- package/dist/components/XlsxChart.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/XlsxImageLayer.js +9 -0
- package/dist/components/XlsxImageLayer.js.map +1 -0
- package/dist/components/XlsxImageLayer.vue.d.ts +9 -0
- package/dist/components/XlsxImageLayer.vue_vue_type_script_setup_true_lang.js +46 -0
- package/dist/components/XlsxImageLayer.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/XlsxViewer.js +1 -1
- package/dist/components/XlsxViewer.js.map +1 -1
- package/dist/components/XlsxViewer.vue_vue_type_script_setup_true_lang.js +230 -216
- package/dist/components/XlsxViewer.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/epl/EplResource.js +1 -1
- package/dist/components/epl/EplResource.js.map +1 -1
- package/dist/components/epl/EplResource.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/optionalViewer.d.ts +3 -2
- package/dist/components/optionalViewer.js +6 -3
- package/dist/components/optionalViewer.js.map +1 -1
- package/dist/composables/useFileViewer.d.ts +11 -3
- package/dist/composables/useFileViewer.js.map +1 -1
- package/dist/composables/useTeleportTheme.d.ts +7 -0
- package/dist/composables/useTeleportTheme.js +42 -0
- package/dist/composables/useTeleportTheme.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +29 -28
- package/dist/lib/docxTheme.d.ts +6 -0
- package/dist/lib/docxTheme.js +64 -0
- package/dist/lib/docxTheme.js.map +1 -0
- package/dist/lib/epl/code/structures.js +82 -0
- package/dist/lib/epl/code/structures.js.map +1 -0
- package/dist/lib/epl/code/variable.js +16 -0
- package/dist/lib/epl/code/variable.js.map +1 -0
- package/dist/lib/epl/eplDocument.js +28 -22
- package/dist/lib/epl/eplDocument.js.map +1 -1
- package/dist/lib/epl/index.d.ts +2 -1
- package/dist/lib/epl/index.js.map +1 -1
- package/dist/lib/epl/sections/code.js +37 -0
- package/dist/lib/epl/sections/code.js.map +1 -0
- package/dist/lib/epl/sections/esystemInfo.js +29 -0
- package/dist/lib/epl/sections/esystemInfo.js.map +1 -0
- package/dist/lib/epl/sections/losable.js +33 -0
- package/dist/lib/epl/sections/losable.js.map +1 -0
- package/dist/lib/epl/sections/projectConfig.js +39 -0
- package/dist/lib/epl/sections/projectConfig.js.map +1 -0
- package/dist/lib/epl/sections/resource.js +84 -0
- package/dist/lib/epl/sections/resource.js.map +1 -0
- package/dist/lib/fileType.d.ts +3 -1
- package/dist/lib/fileType.js +150 -137
- package/dist/lib/fileType.js.map +1 -1
- package/dist/lib/modelAppearance.d.ts +7 -0
- package/dist/lib/modelAppearance.js +41 -0
- package/dist/lib/modelAppearance.js.map +1 -0
- package/dist/lib/step.d.ts +10 -0
- package/dist/lib/step.js +35 -0
- package/dist/lib/step.js.map +1 -0
- package/dist/lib/step.worker.d.ts +1 -0
- package/dist/lib/step.worker.js +18 -0
- package/dist/lib/step.worker.js.map +1 -0
- package/dist/lib/stepObject.d.ts +4 -0
- package/dist/lib/stepObject.js +52 -0
- package/dist/lib/stepObject.js.map +1 -0
- package/dist/lib/stepTypes.d.ts +60 -0
- package/dist/lib/viewerKind.js +10 -5
- package/dist/lib/viewerKind.js.map +1 -1
- package/dist/lib/xlsx.d.ts +1 -1
- package/dist/lib/xlsx.js +106 -89
- package/dist/lib/xlsx.js.map +1 -1
- package/dist/lib/xlsxCharts.js +71 -119
- package/dist/lib/xlsxCharts.js.map +1 -1
- package/dist/lib/xlsxImages.d.ts +43 -0
- package/dist/lib/xlsxImages.js +114 -0
- package/dist/lib/xlsxImages.js.map +1 -0
- package/dist/lib/xlsxParts.d.ts +17 -0
- package/dist/lib/xlsxParts.js +86 -0
- package/dist/lib/xlsxParts.js.map +1 -0
- package/dist/style.css +1 -1
- package/package.json +8 -3
package/dist/lib/xlsx.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import * as e from "exceljs";
|
|
2
|
-
import
|
|
2
|
+
import t from "jszip";
|
|
3
|
+
import { format as n, isDateFormat as r } from "numfmt";
|
|
3
4
|
//#region src/lib/xlsx.ts
|
|
4
|
-
var
|
|
5
|
-
function
|
|
5
|
+
var i = 2e3, a = 200;
|
|
6
|
+
function o(e) {
|
|
6
7
|
let t = 0;
|
|
7
8
|
for (let n = 0; n < e.length; n++) t = t * 26 + (e.charCodeAt(n) - 64);
|
|
8
9
|
return t;
|
|
9
10
|
}
|
|
10
|
-
function
|
|
11
|
+
function s(e) {
|
|
11
12
|
let t = "";
|
|
12
13
|
for (; e > 0;) {
|
|
13
14
|
let n = (e - 1) % 26;
|
|
@@ -15,12 +16,12 @@ function o(e) {
|
|
|
15
16
|
}
|
|
16
17
|
return t;
|
|
17
18
|
}
|
|
18
|
-
function
|
|
19
|
+
function c(e) {
|
|
19
20
|
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Set();
|
|
20
21
|
for (let r of e) {
|
|
21
22
|
let e = /^([A-Z]+)(\d+):([A-Z]+)(\d+)$/.exec(r);
|
|
22
23
|
if (!e) continue;
|
|
23
|
-
let i =
|
|
24
|
+
let i = o(e[1]), a = parseInt(e[2], 10), s = o(e[3]), c = parseInt(e[4], 10), l = Math.min(a, c), u = Math.max(a, c), d = Math.min(i, s), f = Math.max(i, s);
|
|
24
25
|
t.set(`${l},${d}`, {
|
|
25
26
|
rowSpan: u - l + 1,
|
|
26
27
|
colSpan: f - d + 1
|
|
@@ -32,7 +33,7 @@ function s(e) {
|
|
|
32
33
|
covered: n
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
|
-
var
|
|
36
|
+
var l = /* @__PURE__ */ "000000.FFFFFF.FF0000.00FF00.0000FF.FFFF00.FF00FF.00FFFF.000000.FFFFFF.FF0000.00FF00.0000FF.FFFF00.FF00FF.00FFFF.800000.008000.000080.808000.800080.008080.C0C0C0.808080.9999FF.993366.FFFFCC.CCFFFF.660066.FF8080.0066CC.CCCCFF.000080.FF00FF.FFFF00.00FFFF.800080.800000.008080.0000FF.00CCFF.CCFFFF.CCFFCC.FFFF99.99CCFF.FF99CC.CC99FF.FFCC99.3366FF.33CCCC.99CC00.FFCC00.FF9900.FF6600.666699.969696.003366.339966.003300.333300.993300.993366.333399.333333".split("."), u = [
|
|
36
37
|
"FFFFFF",
|
|
37
38
|
"000000",
|
|
38
39
|
"E7E6E6",
|
|
@@ -46,7 +47,7 @@ var c = /* @__PURE__ */ "000000.FFFFFF.FF0000.00FF00.0000FF.FFFF00.FF00FF.00FFFF
|
|
|
46
47
|
"0563C1",
|
|
47
48
|
"954F72"
|
|
48
49
|
];
|
|
49
|
-
function
|
|
50
|
+
function d(e, t, n) {
|
|
50
51
|
e /= 255, t /= 255, n /= 255;
|
|
51
52
|
let r = Math.max(e, t, n), i = Math.min(e, t, n), a = 0, o = 0, s = (r + i) / 2;
|
|
52
53
|
if (r !== i) {
|
|
@@ -59,10 +60,10 @@ function u(e, t, n) {
|
|
|
59
60
|
s
|
|
60
61
|
];
|
|
61
62
|
}
|
|
62
|
-
function
|
|
63
|
+
function f(e, t, n) {
|
|
63
64
|
return n < 0 && (n += 1), n > 1 && --n, n < 1 / 6 ? e + (t - e) * 6 * n : n < 1 / 2 ? t : n < 2 / 3 ? e + (t - e) * (2 / 3 - n) * 6 : e;
|
|
64
65
|
}
|
|
65
|
-
function
|
|
66
|
+
function p(e, t, n) {
|
|
66
67
|
if (t === 0) {
|
|
67
68
|
let e = Math.round(n * 255);
|
|
68
69
|
return [
|
|
@@ -73,48 +74,55 @@ function f(e, t, n) {
|
|
|
73
74
|
}
|
|
74
75
|
let r = n < .5 ? n * (1 + t) : n + t - n * t, i = 2 * n - r;
|
|
75
76
|
return [
|
|
76
|
-
Math.round(
|
|
77
|
-
Math.round(
|
|
78
|
-
Math.round(
|
|
77
|
+
Math.round(f(i, r, e + 1 / 3) * 255),
|
|
78
|
+
Math.round(f(i, r, e) * 255),
|
|
79
|
+
Math.round(f(i, r, e - 1 / 3) * 255)
|
|
79
80
|
];
|
|
80
81
|
}
|
|
81
|
-
function
|
|
82
|
-
let [n, r, i] =
|
|
82
|
+
function m(e, t) {
|
|
83
|
+
let [n, r, i] = d(parseInt(e.slice(0, 2), 16), parseInt(e.slice(2, 4), 16), parseInt(e.slice(4, 6), 16)), a = t < 0 ? i * (1 + t) : i * (1 - t) + t;
|
|
83
84
|
a = Math.max(0, Math.min(1, a));
|
|
84
|
-
let [o, s, c] =
|
|
85
|
+
let [o, s, c] = p(n, r, a), l = (e) => e.toString(16).padStart(2, "0");
|
|
85
86
|
return l(o) + l(s) + l(c);
|
|
86
87
|
}
|
|
87
|
-
function
|
|
88
|
+
function h(e) {
|
|
88
89
|
if (!e || typeof e != "object") return;
|
|
89
90
|
let t = e, n;
|
|
90
91
|
if (typeof t.argb == "string") if (t.argb.length === 8) {
|
|
91
92
|
if (t.argb.slice(0, 2).toLowerCase() === "00") return;
|
|
92
93
|
n = t.argb.slice(2);
|
|
93
94
|
} else t.argb.length === 6 && (n = t.argb);
|
|
94
|
-
else if (typeof t.theme == "number") n =
|
|
95
|
+
else if (typeof t.theme == "number") n = u[t.theme];
|
|
95
96
|
else if (typeof t.indexed == "number") {
|
|
96
97
|
if (t.indexed === 64) return;
|
|
97
|
-
n = t.indexed === 65 ? "FFFFFF" :
|
|
98
|
+
n = t.indexed === 65 ? "FFFFFF" : l[t.indexed];
|
|
98
99
|
}
|
|
99
|
-
if (!(!n || !/^[0-9a-fA-F]{6}$/.test(n))) return typeof t.tint == "number" && t.tint !== 0 && (n =
|
|
100
|
-
}
|
|
101
|
-
function h(e) {
|
|
102
|
-
if (!(!e || e <= 0)) return Math.round(e * 4 / 3);
|
|
100
|
+
if (!(!n || !/^[0-9a-fA-F]{6}$/.test(n))) return typeof t.tint == "number" && t.tint !== 0 && (n = m(n, t.tint)), `#${n}`;
|
|
103
101
|
}
|
|
104
102
|
function g(e) {
|
|
105
|
-
|
|
103
|
+
if (e && typeof e == "object") {
|
|
104
|
+
let t = e;
|
|
105
|
+
if (t.argb == null && t.theme === 1 && !t.tint) return;
|
|
106
|
+
}
|
|
107
|
+
return h(e);
|
|
106
108
|
}
|
|
107
109
|
function _(e) {
|
|
108
|
-
|
|
110
|
+
if (!(!e || e <= 0)) return Math.round(e * 4 / 3);
|
|
109
111
|
}
|
|
110
112
|
function v(e) {
|
|
111
|
-
|
|
112
|
-
return !n && !r && !i ? t : `${t} ${_(n)}:${_(r)}${i ? `:${_(i)}` : ""}`;
|
|
113
|
+
return !e || e <= 0 ? 80 : Math.round(e * 7 + 9);
|
|
113
114
|
}
|
|
114
115
|
function y(e) {
|
|
116
|
+
return e < 10 ? `0${e}` : String(e);
|
|
117
|
+
}
|
|
118
|
+
function b(e) {
|
|
119
|
+
let t = `${e.getFullYear()}-${y(e.getMonth() + 1)}-${y(e.getDate())}`, n = e.getHours(), r = e.getMinutes(), i = e.getSeconds();
|
|
120
|
+
return !n && !r && !i ? t : `${t} ${y(n)}:${y(r)}${i ? `:${y(i)}` : ""}`;
|
|
121
|
+
}
|
|
122
|
+
function x(e) {
|
|
115
123
|
return Array.isArray(e) ? e.map((e) => e && typeof e == "object" ? e.text ?? "" : "").join("") : "";
|
|
116
124
|
}
|
|
117
|
-
var
|
|
125
|
+
var S = [
|
|
118
126
|
"零",
|
|
119
127
|
"一",
|
|
120
128
|
"二",
|
|
@@ -125,7 +133,7 @@ var b = [
|
|
|
125
133
|
"七",
|
|
126
134
|
"八",
|
|
127
135
|
"九"
|
|
128
|
-
],
|
|
136
|
+
], C = [
|
|
129
137
|
"零",
|
|
130
138
|
"壹",
|
|
131
139
|
"贰",
|
|
@@ -136,23 +144,23 @@ var b = [
|
|
|
136
144
|
"柒",
|
|
137
145
|
"捌",
|
|
138
146
|
"玖"
|
|
139
|
-
],
|
|
147
|
+
], w = [
|
|
140
148
|
"",
|
|
141
149
|
"十",
|
|
142
150
|
"百",
|
|
143
151
|
"千"
|
|
144
|
-
],
|
|
152
|
+
], T = [
|
|
145
153
|
"",
|
|
146
154
|
"拾",
|
|
147
155
|
"佰",
|
|
148
156
|
"仟"
|
|
149
|
-
],
|
|
157
|
+
], E = [
|
|
150
158
|
"",
|
|
151
159
|
"万",
|
|
152
160
|
"亿",
|
|
153
161
|
"兆"
|
|
154
162
|
];
|
|
155
|
-
function
|
|
163
|
+
function D(e, t, n) {
|
|
156
164
|
let r = "", i = !1;
|
|
157
165
|
for (let a = 3; a >= 0; a--) {
|
|
158
166
|
let o = Math.floor(e / 10 ** a) % 10;
|
|
@@ -160,8 +168,8 @@ function T(e, t, n) {
|
|
|
160
168
|
}
|
|
161
169
|
return r;
|
|
162
170
|
}
|
|
163
|
-
function
|
|
164
|
-
let n = t ?
|
|
171
|
+
function O(e, t) {
|
|
172
|
+
let n = t ? C : S, r = t ? T : w;
|
|
165
173
|
if (e === 0) return n[0];
|
|
166
174
|
let i = [], a = e;
|
|
167
175
|
for (; a > 0;) i.push(a % 1e4), a = Math.floor(a / 1e4);
|
|
@@ -169,71 +177,71 @@ function E(e, t) {
|
|
|
169
177
|
for (let e = i.length - 1; e >= 0; e--) {
|
|
170
178
|
let t = i[e];
|
|
171
179
|
if (t === 0) continue;
|
|
172
|
-
let a =
|
|
173
|
-
e < i.length - 1 && t < 1e3 && (a = n[0] + a), o += a +
|
|
180
|
+
let a = D(t, n, r);
|
|
181
|
+
e < i.length - 1 && t < 1e3 && (a = n[0] + a), o += a + E[e];
|
|
174
182
|
}
|
|
175
183
|
return o;
|
|
176
184
|
}
|
|
177
|
-
function
|
|
185
|
+
function k(e) {
|
|
178
186
|
return e.replace(/[0-9]/g, (e) => "0123456789"[Number(e)]);
|
|
179
187
|
}
|
|
180
|
-
function
|
|
181
|
-
if (
|
|
188
|
+
function A(e, t, r) {
|
|
189
|
+
if (t === 3) {
|
|
182
190
|
try {
|
|
183
|
-
let
|
|
184
|
-
if (typeof
|
|
191
|
+
let t = n(r, e);
|
|
192
|
+
if (typeof t == "string") return k(t);
|
|
185
193
|
} catch {}
|
|
186
194
|
return null;
|
|
187
195
|
}
|
|
188
|
-
return Number.isInteger(e) && e >= 0 ?
|
|
196
|
+
return Number.isInteger(e) && e >= 0 ? O(e, t === 2) : null;
|
|
189
197
|
}
|
|
190
|
-
function
|
|
198
|
+
function j(e) {
|
|
191
199
|
return e.replace(/G\/(通用格式|標準|标准|표준)/g, "General");
|
|
192
200
|
}
|
|
193
|
-
function
|
|
194
|
-
let r =
|
|
201
|
+
function M(e, t) {
|
|
202
|
+
let r = j(t || "General"), i = /\[DBNum([123])\]/.exec(r);
|
|
195
203
|
if (i) {
|
|
196
|
-
let t =
|
|
204
|
+
let t = A(e, Number(i[1]), r);
|
|
197
205
|
if (t != null) return t;
|
|
198
206
|
}
|
|
199
207
|
try {
|
|
200
|
-
let
|
|
201
|
-
return typeof
|
|
208
|
+
let t = n(r, e);
|
|
209
|
+
return typeof t == "string" ? t : String(e);
|
|
202
210
|
} catch {
|
|
203
211
|
return String(e);
|
|
204
212
|
}
|
|
205
213
|
}
|
|
206
|
-
function
|
|
207
|
-
if (
|
|
208
|
-
let
|
|
209
|
-
if (typeof
|
|
214
|
+
function N(e, t) {
|
|
215
|
+
if (t && t !== "General" && r(t)) try {
|
|
216
|
+
let r = n(t, e);
|
|
217
|
+
if (typeof r == "string" && r !== "") return r;
|
|
210
218
|
} catch {}
|
|
211
|
-
return
|
|
219
|
+
return b(e);
|
|
212
220
|
}
|
|
213
|
-
function
|
|
221
|
+
function P(e) {
|
|
214
222
|
let t = e.value;
|
|
215
223
|
if (t == null) return "";
|
|
216
|
-
if (typeof t == "number") return
|
|
224
|
+
if (typeof t == "number") return M(t, e.numFmt);
|
|
217
225
|
if (typeof t == "string" || typeof t == "boolean") return String(t);
|
|
218
|
-
if (t instanceof Date) return
|
|
226
|
+
if (t instanceof Date) return N(t, e.numFmt);
|
|
219
227
|
if (typeof t == "object") {
|
|
220
228
|
let n = t;
|
|
221
229
|
if (typeof n.error == "string") return n.error;
|
|
222
|
-
if (Array.isArray(n.richText)) return
|
|
230
|
+
if (Array.isArray(n.richText)) return x(n.richText);
|
|
223
231
|
if ("hyperlink" in n) {
|
|
224
232
|
let e = n.text;
|
|
225
|
-
return Array.isArray(e?.richText) ?
|
|
233
|
+
return Array.isArray(e?.richText) ? x(e.richText) : String(e ?? n.hyperlink);
|
|
226
234
|
}
|
|
227
235
|
if ("result" in n || "formula" in n || "sharedFormula" in n) {
|
|
228
236
|
let t = n.result;
|
|
229
237
|
if (t == null) return "";
|
|
230
|
-
if (typeof t == "number") return
|
|
238
|
+
if (typeof t == "number") return M(t, e.numFmt);
|
|
231
239
|
if (typeof t == "string" || typeof t == "boolean") return String(t);
|
|
232
|
-
if (t instanceof Date) return
|
|
240
|
+
if (t instanceof Date) return N(t, e.numFmt);
|
|
233
241
|
if (t && typeof t == "object") {
|
|
234
242
|
let e = t;
|
|
235
243
|
if (typeof e.error == "string") return e.error;
|
|
236
|
-
if (Array.isArray(e.richText)) return
|
|
244
|
+
if (Array.isArray(e.richText)) return x(e.richText);
|
|
237
245
|
}
|
|
238
246
|
return "";
|
|
239
247
|
}
|
|
@@ -245,7 +253,7 @@ function M(e) {
|
|
|
245
253
|
return "";
|
|
246
254
|
}
|
|
247
255
|
}
|
|
248
|
-
function
|
|
256
|
+
function F(e) {
|
|
249
257
|
if (typeof e == "number" || e instanceof Date) return !0;
|
|
250
258
|
if (e && typeof e == "object" && "result" in e) {
|
|
251
259
|
let t = e.result;
|
|
@@ -253,23 +261,23 @@ function N(e) {
|
|
|
253
261
|
}
|
|
254
262
|
return !1;
|
|
255
263
|
}
|
|
256
|
-
function
|
|
257
|
-
let { spans: t, covered: n } =
|
|
258
|
-
for (let t = 1; t <=
|
|
264
|
+
function I(e) {
|
|
265
|
+
let { spans: t, covered: n } = c(Array.isArray(e.model?.merges) ? e.model.merges : []), r = Math.min(e.columnCount || 0, a), o = Math.min(e.rowCount || 0, i), s = [], l = [];
|
|
266
|
+
for (let t = 1; t <= r; t++) {
|
|
259
267
|
let n = e.getColumn(t);
|
|
260
|
-
|
|
268
|
+
s.push(v(n?.width)), l.push(!!n?.hidden);
|
|
261
269
|
}
|
|
262
270
|
let u = [];
|
|
263
|
-
for (let
|
|
264
|
-
let
|
|
265
|
-
for (let e = 1; e <=
|
|
266
|
-
if (n.has(`${
|
|
267
|
-
let
|
|
271
|
+
for (let i = 1; i <= o; i++) {
|
|
272
|
+
let a = e.getRow(i), o = [];
|
|
273
|
+
for (let e = 1; e <= r; e++) {
|
|
274
|
+
if (n.has(`${i},${e}`)) continue;
|
|
275
|
+
let r = a.getCell(e), s = t.get(`${i},${e}`), c = P(r), l, u = r.value;
|
|
268
276
|
if (u && typeof u == "object") {
|
|
269
277
|
let e = u;
|
|
270
278
|
typeof e.formula == "string" && e.formula ? l = e.formula : typeof e.sharedFormula == "string" && e.sharedFormula && (l = e.sharedFormula);
|
|
271
279
|
}
|
|
272
|
-
let d =
|
|
280
|
+
let d = r.font || {}, f = r.alignment || {}, p = r.border || {}, m = f.horizontal === "center" || f.horizontal === "centerContinuous" ? "center" : f.horizontal === "right" ? "right" : f.horizontal === "left" ? "left" : F(r.value) ? "right" : void 0, v = f.vertical === "top" ? "top" : f.vertical === "bottom" ? "bottom" : f.vertical === "middle" ? "middle" : void 0;
|
|
273
281
|
o.push({
|
|
274
282
|
text: c,
|
|
275
283
|
col: e,
|
|
@@ -279,12 +287,12 @@ function P(e) {
|
|
|
279
287
|
italic: d.italic || void 0,
|
|
280
288
|
underline: !!d.underline || void 0,
|
|
281
289
|
strike: d.strike || void 0,
|
|
282
|
-
fontSize:
|
|
290
|
+
fontSize: _(d.size),
|
|
283
291
|
formula: l,
|
|
284
|
-
color:
|
|
285
|
-
bg:
|
|
286
|
-
align:
|
|
287
|
-
valign:
|
|
292
|
+
color: g(d.color),
|
|
293
|
+
bg: r.fill && r.fill.type === "pattern" ? h(r.fill.fgColor) : void 0,
|
|
294
|
+
align: m,
|
|
295
|
+
valign: v,
|
|
288
296
|
wrap: f.wrapText || void 0,
|
|
289
297
|
bt: !!p.top?.style || void 0,
|
|
290
298
|
br: !!p.right?.style || void 0,
|
|
@@ -293,31 +301,40 @@ function P(e) {
|
|
|
293
301
|
});
|
|
294
302
|
}
|
|
295
303
|
u.push({
|
|
296
|
-
num:
|
|
297
|
-
height:
|
|
298
|
-
hidden: !!
|
|
304
|
+
num: i,
|
|
305
|
+
height: a.height ? Math.round(a.height * 4 / 3) : void 0,
|
|
306
|
+
hidden: !!a.hidden,
|
|
299
307
|
cells: o
|
|
300
308
|
});
|
|
301
309
|
}
|
|
302
|
-
let d = Array.isArray(e.views) ? e.views[0] : void 0, f = d && d.state === "frozen" ? d : void 0, p = f ? Math.min(Math.max(0, f.xSplit ?? 0),
|
|
310
|
+
let d = Array.isArray(e.views) ? e.views[0] : void 0, f = d && d.state === "frozen" ? d : void 0, p = f ? Math.min(Math.max(0, f.xSplit ?? 0), r) : 0, m = f ? Math.min(Math.max(0, f.ySplit ?? 0), o) : 0;
|
|
303
311
|
return {
|
|
304
312
|
name: e.name || "Sheet",
|
|
305
|
-
colWidths:
|
|
313
|
+
colWidths: s,
|
|
306
314
|
colHidden: l,
|
|
307
315
|
rows: u,
|
|
308
|
-
cols:
|
|
309
|
-
frozenRows:
|
|
316
|
+
cols: r,
|
|
317
|
+
frozenRows: m,
|
|
310
318
|
frozenCols: p
|
|
311
319
|
};
|
|
312
320
|
}
|
|
313
|
-
async function
|
|
321
|
+
async function L(e) {
|
|
322
|
+
let n = await t.loadAsync(e), r = Object.keys(n.files).filter((e) => /^xl\/drawings\/(?:_rels\/)?[^/]+\.xml(?:\.rels)?$/.test(e));
|
|
323
|
+
if (r.length === 0) return e;
|
|
324
|
+
for (let e of r) n.remove(e);
|
|
325
|
+
return n.generateAsync({
|
|
326
|
+
type: "arraybuffer",
|
|
327
|
+
compression: "DEFLATE"
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
async function R(t) {
|
|
314
331
|
let n = new e.Workbook();
|
|
315
|
-
await n.xlsx.load(t);
|
|
316
|
-
let r = n.worksheets.filter((e) => e && e.state !== "hidden" && e.state !== "veryHidden").map(
|
|
332
|
+
await n.xlsx.load(await L(t), { ignoreNodes: ["drawing"] });
|
|
333
|
+
let r = n.worksheets.filter((e) => e && e.state !== "hidden" && e.state !== "veryHidden").map(I);
|
|
317
334
|
if (r.length === 0) throw Error("工作簿中没有可显示的工作表");
|
|
318
335
|
return { sheets: r };
|
|
319
336
|
}
|
|
320
337
|
//#endregion
|
|
321
|
-
export {
|
|
338
|
+
export { s as numToCol, R as parseXlsx };
|
|
322
339
|
|
|
323
340
|
//# sourceMappingURL=xlsx.js.map
|
package/dist/lib/xlsx.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xlsx.js","names":[],"sources":["../../src/lib/xlsx.ts"],"sourcesContent":["/**\n * In-browser `.xlsx` (and `.xlsm`) parsing for the side viewer's spreadsheet preview.\n *\n * exceljs does the OOXML heavy lifting (unzip + parse the SpreadsheetML); here we flatten one of its\n * Workbooks into a small, serializable model the {@link XlsxViewer} renders as plain HTML `<table>`s —\n * one table per worksheet, with merged cells, column widths, and the common cell styling (bold/italic/\n * color/fill/alignment/borders) carried over so the preview reads like the original sheet.\n *\n * exceljs is heavy (~1MB), so this module is only ever imported by the async-loaded XlsxViewer — it never\n * lands in the main bundle. We import the namespace (not named exports) because exceljs's browser entry is\n * a UMD bundle: `new ExcelJS.Workbook()` resolves identically under Vite's CJS interop and the .d.ts.\n */\nimport * as ExcelJS from 'exceljs'\nimport { format as nfFormat, isDateFormat as nfIsDateFormat } from 'numfmt'\n\n/** One rendered cell. A cell covered by a merge is dropped from the row entirely (see {@link XlsxRow}). */\nexport interface XlsxCell {\n text: string\n rowSpan: number\n colSpan: number\n /** 1-based column index of this cell's left edge — lets the renderer place cells after merge gaps. */\n col: number\n bold?: boolean\n italic?: boolean\n underline?: boolean\n strike?: boolean\n /** Font size in px (converted from the workbook's points), or undefined to use the table default. */\n fontSize?: number\n /** The cell's formula expression WITHOUT a leading `=` (e.g. `数据基表!B10`, `#REF!`), for the source view. */\n formula?: string\n /** CSS color for the text / the cell background, derived from the workbook's ARGB colors. */\n color?: string\n bg?: string\n align?: 'left' | 'center' | 'right'\n valign?: 'top' | 'middle' | 'bottom'\n wrap?: boolean\n /** Which borders the cell draws (true = a visible edge in the source). */\n bt?: boolean\n br?: boolean\n bb?: boolean\n bl?: boolean\n}\n\nexport interface XlsxRow {\n /** 1-based row number in the worksheet (so the viewer can label the gutter and key frozen/hidden state). */\n num: number\n /** Row height in px (converted from Excel points), or undefined to size to content. */\n height?: number\n /** Hidden in the source (\"hide rows\") — the viewer collapses it behind an expander, like Excel/WPS. */\n hidden?: boolean\n /** Only the cells that actually render — merge-covered slots are omitted; use {@link XlsxCell.col}. */\n cells: XlsxCell[]\n}\n\nexport interface XlsxSheet {\n name: string\n /** Per-column width in px (index 0 = column A); columns past this use a default width. */\n colWidths: number[]\n /** Per-column hidden flag (index 0 = column A) — collapsed behind an expander, like Excel/WPS. */\n colHidden: boolean[]\n rows: XlsxRow[]\n cols: number\n /** Frozen pane sizes (Excel \"freeze panes\"): the first N rows / M columns stay pinned while scrolling. */\n frozenRows: number\n frozenCols: number\n}\n\nexport interface XlsxModel {\n sheets: XlsxSheet[]\n}\n\n// Guardrails: a corrupt or absurdly large sheet shouldn't lock up the tab. We cap the rendered range and\n// let the viewer note the truncation. (Real attachments are tiny; these only bite pathological files.)\nconst MAX_ROWS = 2000\nconst MAX_COLS = 200\n\n// Excel column-letter (A, B, …, AA) → 1-based index.\nfunction colToNum(s: string): number {\n let n = 0\n for (let i = 0; i < s.length; i++) n = n * 26 + (s.charCodeAt(i) - 64)\n return n\n}\n\n// 1-based index → Excel column-letter (1→A, 26→Z, 27→AA). Used by the viewer's A/B/C… header row.\nexport function numToCol(n: number): string {\n let s = ''\n while (n > 0) {\n const m = (n - 1) % 26\n s = String.fromCharCode(65 + m) + s\n n = Math.floor((n - 1) / 26)\n }\n return s\n}\n\ninterface Span {\n rowSpan: number\n colSpan: number\n}\n\n// Parse exceljs's merge ranges (\"A1:B2\") into: span info keyed at each master cell, and a set of the\n// addresses (`r,c`) covered by a merge (which we then skip rendering).\nfunction parseMerges(merges: string[]): { spans: Map<string, Span>; covered: Set<string> } {\n const spans = new Map<string, Span>()\n const covered = new Set<string>()\n for (const range of merges) {\n const m = /^([A-Z]+)(\\d+):([A-Z]+)(\\d+)$/.exec(range)\n if (!m) continue\n const c1 = colToNum(m[1])\n const r1 = parseInt(m[2], 10)\n const c2 = colToNum(m[3])\n const r2 = parseInt(m[4], 10)\n const top = Math.min(r1, r2)\n const bottom = Math.max(r1, r2)\n const left = Math.min(c1, c2)\n const right = Math.max(c1, c2)\n spans.set(`${top},${left}`, { rowSpan: bottom - top + 1, colSpan: right - left + 1 })\n for (let r = top; r <= bottom; r++) {\n for (let c = left; c <= right; c++) {\n if (r === top && c === left) continue\n covered.add(`${r},${c}`)\n }\n }\n }\n return { spans, covered }\n}\n\n// Excel's legacy 56-colour indexed palette (BIFF8). Cells/fonts that don't carry an explicit ARGB reference\n// a palette slot instead (e.g. `{ indexed: 47 }`) — very common in older workbooks. 64/65 are the system\n// foreground/background (\"automatic\"), handled specially below.\n// prettier-ignore\nconst INDEXED_COLORS = [\n '000000', 'FFFFFF', 'FF0000', '00FF00', '0000FF', 'FFFF00', 'FF00FF', '00FFFF',\n '000000', 'FFFFFF', 'FF0000', '00FF00', '0000FF', 'FFFF00', 'FF00FF', '00FFFF',\n '800000', '008000', '000080', '808000', '800080', '008080', 'C0C0C0', '808080',\n '9999FF', '993366', 'FFFFCC', 'CCFFFF', '660066', 'FF8080', '0066CC', 'CCCCFF',\n '000080', 'FF00FF', 'FFFF00', '00FFFF', '800080', '800000', '008080', '0000FF',\n '00CCFF', 'CCFFFF', 'CCFFCC', 'FFFF99', '99CCFF', 'FF99CC', 'CC99FF', 'FFCC99',\n '3366FF', '33CCCC', '99CC00', 'FFCC00', 'FF9900', 'FF6600', '666699', '969696',\n '003366', '339966', '003300', '333300', '993300', '993366', '333399', '333333',\n]\n\n// Default Office theme colours, in the order the styles `theme` attribute indexes them (0=bg1/white,\n// 1=text1/black, 2=bg2, 3=text2, 4..9=accent1..6, 10=hlink, 11=folHlink). We don't parse the workbook's\n// actual theme XML (exceljs doesn't surface it), so this default scheme is a best-effort — but it gets the\n// common cases right (notably theme 1 = black text, theme 0 = white) and `tint` is applied on top.\n// prettier-ignore\nconst THEME_COLORS = [\n 'FFFFFF', '000000', 'E7E6E6', '44546A', '4472C4', 'ED7D31',\n 'A5A5A5', 'FFC000', '5B9BD5', '70AD47', '0563C1', '954F72',\n]\n\nfunction rgbToHsl(r: number, g: number, b: number): [number, number, number] {\n r /= 255\n g /= 255\n b /= 255\n const max = Math.max(r, g, b)\n const min = Math.min(r, g, b)\n let h = 0\n let s = 0\n const l = (max + min) / 2\n if (max !== min) {\n const d = max - min\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min)\n if (max === r) h = (g - b) / d + (g < b ? 6 : 0)\n else if (max === g) h = (b - r) / d + 2\n else h = (r - g) / d + 4\n h /= 6\n }\n return [h, s, l]\n}\n\nfunction hue2rgb(p: number, q: number, t: number): number {\n if (t < 0) t += 1\n if (t > 1) t -= 1\n if (t < 1 / 6) return p + (q - p) * 6 * t\n if (t < 1 / 2) return q\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6\n return p\n}\n\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n if (s === 0) {\n const v = Math.round(l * 255)\n return [v, v, v]\n }\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s\n const p = 2 * l - q\n return [\n Math.round(hue2rgb(p, q, h + 1 / 3) * 255),\n Math.round(hue2rgb(p, q, h) * 255),\n Math.round(hue2rgb(p, q, h - 1 / 3) * 255),\n ]\n}\n\n// Excel applies `tint` to a theme/indexed colour by shifting its HSL luminance: negative darkens, positive\n// lightens. Mirrors the algorithm in the OOXML spec so shaded theme fills come out the right tone.\nfunction applyTint(hex: string, tint: number): string {\n const r = parseInt(hex.slice(0, 2), 16)\n const g = parseInt(hex.slice(2, 4), 16)\n const b = parseInt(hex.slice(4, 6), 16)\n const [h, s, l0] = rgbToHsl(r, g, b)\n let l = tint < 0 ? l0 * (1 + tint) : l0 * (1 - tint) + tint\n l = Math.max(0, Math.min(1, l))\n const [nr, ng, nb] = hslToRgb(h, s, l)\n const hx = (n: number): string => n.toString(16).padStart(2, '0')\n return hx(nr) + hx(ng) + hx(nb)\n}\n\n/**\n * Resolve any exceljs colour object to a CSS `#RRGGBB`, covering all three references Excel uses: explicit\n * `argb`, the legacy `indexed` palette, and `theme` index (+ optional `tint`). Returns undefined for \"no\n * colour\" — a fully-transparent argb, the system-automatic indices, or an unresolvable shape.\n */\nfunction colorToCss(color: unknown): string | undefined {\n if (!color || typeof color !== 'object') return undefined\n const c = color as { argb?: string; theme?: number; indexed?: number; tint?: number }\n let hex: string | undefined\n if (typeof c.argb === 'string') {\n if (c.argb.length === 8) {\n if (c.argb.slice(0, 2).toLowerCase() === '00') return undefined // fully transparent → no colour\n hex = c.argb.slice(2)\n } else if (c.argb.length === 6) {\n hex = c.argb\n }\n } else if (typeof c.theme === 'number') {\n hex = THEME_COLORS[c.theme]\n } else if (typeof c.indexed === 'number') {\n if (c.indexed === 64) return undefined // system foreground / automatic → let the default apply\n hex = c.indexed === 65 ? 'FFFFFF' : INDEXED_COLORS[c.indexed]\n }\n if (!hex || !/^[0-9a-fA-F]{6}$/.test(hex)) return undefined\n if (typeof c.tint === 'number' && c.tint !== 0) hex = applyTint(hex, c.tint)\n return `#${hex}`\n}\n\n// Excel font sizes are in points; CSS wants px. The conventional screen conversion is pt × 96/72 (= ×4/3),\n// which keeps relative sizing faithful (a 24pt title reads clearly larger than 10pt body text).\nfunction fontSizeToPx(size: number | undefined): number | undefined {\n if (!size || size <= 0) return undefined\n return Math.round((size * 4) / 3)\n}\n\n// Excel column width is in \"character\" units; the conventional pixel conversion to the COLUMN's total width is\n// width*7 + 5 (the +5 is Excel's own internal cell padding). But our HTML cell adds its OWN padding (~4px each\n// side) and a gridline border on top of the `<col>` width, so reusing Excel's total width would leave the\n// content area ~8px short and clip text into \"…\". We add that HTML chrome back (+9 instead of +5) so the\n// usable content width matches Excel's, keeping the cell `padding`/border in sync (see XlsxViewer .xv__cell).\nfunction colWidthToPx(w: number | undefined): number {\n if (!w || w <= 0) return 80\n return Math.round(w * 7 + 9)\n}\n\n// A two-digit zero-pad for the date formatter.\nfunction pad2(n: number): string {\n return n < 10 ? `0${n}` : String(n)\n}\n\n// Render a Date the way a spreadsheet preview should — `YYYY-MM-DD`, plus a `HH:MM[:SS]` tail only when the\n// value carries a time-of-day. (exceljs's own `cell.text` gives the raw JS `Date.toString()`, e.g.\n// \"Sat May 04 2019 08:00:00 GMT+0800 (中国标准时间)\", which is useless in a cell.)\nfunction formatDate(d: Date): string {\n const date = `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`\n const h = d.getHours()\n const mi = d.getMinutes()\n const s = d.getSeconds()\n if (!h && !mi && !s) return date\n return `${date} ${pad2(h)}:${pad2(mi)}${s ? `:${pad2(s)}` : ''}`\n}\n\nfunction richTextToString(runs: unknown): string {\n if (!Array.isArray(runs)) return ''\n return runs\n .map((r) => (r && typeof r === 'object' ? ((r as { text?: string }).text ?? '') : ''))\n .join('')\n}\n\n// CJK numeral digits/units for Excel's `[DBNum1]` (中文小写) and `[DBNum2]` (中文大写/financial) — numfmt does\n// not implement these (Excel's 特殊 → 中文数字), so we convert the integer ourselves with proper 万/亿 grouping.\nconst DBNUM_DIGITS = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']\nconst DBNUM_DIGITS_UP = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']\nconst DBNUM_UNITS = ['', '十', '百', '千']\nconst DBNUM_UNITS_UP = ['', '拾', '佰', '仟']\nconst DBNUM_BIG = ['', '万', '亿', '兆']\n\n// Convert one 0..9999 group to CJK numerals, collapsing internal zeros to a single 零 (no trailing zero unit).\nfunction dbNumGroup(n: number, digits: string[], units: string[]): string {\n let s = ''\n let pendingZero = false\n for (let i = 3; i >= 0; i--) {\n const x = Math.floor(n / 10 ** i) % 10\n if (x === 0) {\n if (s !== '') pendingZero = true\n } else {\n if (pendingZero) {\n s += digits[0]\n pendingZero = false\n }\n s += digits[x] + units[i]\n }\n }\n return s\n}\n\n// Excel `[DBNum1]`/`[DBNum2]` of a non-negative integer: e.g. 1234 → 一千二百三十四 / 壹仟贰佰叁拾肆, 10001 → 一万零一,\n// 100000001 → 一亿零一. (Keeps Excel's leading 一十 for 10-19, single 零 between groups, like Excel's own output.)\nfunction toChineseNumeral(n: number, upper: boolean): string {\n const digits = upper ? DBNUM_DIGITS_UP : DBNUM_DIGITS\n const units = upper ? DBNUM_UNITS_UP : DBNUM_UNITS\n if (n === 0) return digits[0]\n const groups: number[] = []\n let x = n\n while (x > 0) {\n groups.push(x % 10000)\n x = Math.floor(x / 10000)\n }\n let s = ''\n for (let i = groups.length - 1; i >= 0; i--) {\n const g = groups[i]\n if (g === 0) continue // an all-zero group: the next non-zero group's leading 零 covers the gap\n let gs = dbNumGroup(g, digits, units)\n if (i < groups.length - 1 && g < 1000) gs = digits[0] + gs // 1,0001 → 一万零一 (zero after a higher group)\n s += gs + DBNUM_BIG[i]\n }\n return s\n}\n\n// Map ASCII digits to full-width — Excel's `[DBNum3]` (全角数字); applied over numfmt's normal output so any\n// separators / decimals survive.\nfunction toFullWidthDigits(s: string): string {\n return s.replace(/[0-9]/g, (d) => '0123456789'[Number(d)])\n}\n\n// Honor Excel's `[DBNumN]` CJK-numeral prefixes that numfmt can't render. Returns null to fall back to numfmt\n// (negatives / non-integers for DBNum1/2, where Excel's behavior is fiddly — a plain number is safer than a guess).\nfunction formatDbNum(value: number, n: number, fmt: string): string | null {\n if (n === 3) {\n try {\n const out = nfFormat(fmt, value) // numfmt strips the [DBNum3] tag and formats the rest\n if (typeof out === 'string') return toFullWidthDigits(out)\n } catch {\n /* fall through */\n }\n return null\n }\n if (Number.isInteger(value) && value >= 0) return toChineseNumeral(value, n === 2)\n return null\n}\n\n// numfmt understands the English \"General\" keyword but not Excel's LOCALIZED one (Simplified Chinese \"G/通用格式\",\n// Japanese \"G/標準\", etc.), throwing \"Invalid pattern\" — normalize those to \"General\" so a locale-tagged General\n// format (common in CJK files after a [DBNum]/[$-…] prefix) parses. (Plain \"[$-NNN]\" locale tags numfmt handles.)\nfunction cleanFmt(fmt: string): string {\n return fmt.replace(/G\\/(通用格式|標準|标准|표준)/g, 'General')\n}\n\n// Apply the cell's Excel number format (`cell.numFmt`) to a numeric value the way Excel DISPLAYS it — exceljs's\n// `cell.text` returns the raw stored number, so an integer-formatted cell (\"0\") shows the stored float\n// \"2.9999999999\" instead of \"3\", a percent format shows \"0.5\" instead of \"50%\", thousands separators go missing,\n// etc. An undefined format → \"General\", which (like Excel) also strips IEEE float noise (0.1+0.2 → \"0.3\"); this is\n// why a cell *referencing* a formatted one rendered wrong too — its cached result is the noisy float. numfmt covers\n// currency / accounting / fraction / scientific / percent / text(@) / 邮编 / custom codes; `[DBNumN]` CJK numerals\n// (which numfmt doesn't implement) are handled here. Unsupported codes / unexpected output fall back to a plain\n// string, never throwing.\nfunction formatNumber(value: number, numFmt: string | undefined): string {\n const fmt = cleanFmt(numFmt || 'General')\n const dbnum = /\\[DBNum([123])\\]/.exec(fmt)\n if (dbnum) {\n const out = formatDbNum(value, Number(dbnum[1]), fmt)\n if (out != null) return out\n }\n try {\n const out = nfFormat(fmt, value)\n return typeof out === 'string' ? out : String(value)\n } catch {\n return String(value)\n }\n}\n\n// Format a date the way Excel's number format dictates — exceljs hands us a JS `Date`, and numfmt formats it\n// directly (reading its local components) for any date/time format code: ISO, 中文 yyyy\"年\"m\"月\"d\"日\", h:mm AM/PM,\n// custom date-times, etc. Only route through numfmt when the format actually IS a date format; otherwise (no/General\n// format) keep the viewer's plain YYYY-MM-DD default from {@link formatDate}.\nfunction formatDateValue(d: Date, numFmt: string | undefined): string {\n if (numFmt && numFmt !== 'General' && nfIsDateFormat(numFmt)) {\n try {\n const out = nfFormat(numFmt, d)\n if (typeof out === 'string' && out !== '') return out\n } catch {\n /* fall through to the plain default */\n }\n }\n return formatDate(d)\n}\n\n/**\n * Resolve a cell's display text from its value SHAPE rather than exceljs's `cell.text` — which returns the\n * raw object for some value kinds (so a formula whose cached result is an error renders as \"[object Object]\")\n * and even throws on certain merged cells. We cover every {@link ExcelJS.ValueType}: numbers/strings/booleans\n * verbatim, dates formatted, rich text joined, hyperlinks as their label, formula results unwrapped (errors →\n * their code like \"#REF!\", a nested date/rich-text result resolved), and error cells as their code. Anything\n * unexpected falls back to a guarded `cell.text`, never to a stringified object.\n */\nfunction cellText(cell: ExcelJS.Cell): string {\n const v = cell.value as unknown\n if (v == null) return ''\n if (typeof v === 'number') return formatNumber(v, cell.numFmt)\n if (typeof v === 'string' || typeof v === 'boolean') return String(v)\n if (v instanceof Date) return formatDateValue(v, cell.numFmt)\n if (typeof v === 'object') {\n const o = v as Record<string, unknown>\n if (typeof o.error === 'string') return o.error // error cell: { error: '#DIV/0!' }\n if (Array.isArray(o.richText)) return richTextToString(o.richText) // rich text\n if ('hyperlink' in o) {\n // hyperlink: { text, hyperlink } — text may itself be rich text\n const t = o.text\n if (Array.isArray((t as { richText?: unknown })?.richText)) {\n return richTextToString((t as { richText?: unknown }).richText)\n }\n return t == null ? String(o.hyperlink) : String(t)\n }\n if ('result' in o || 'formula' in o || 'sharedFormula' in o) {\n // formula: { formula, result } — the result is what Excel shows in the cell\n const res = o.result as unknown\n if (res == null) return ''\n if (typeof res === 'number') return formatNumber(res, cell.numFmt)\n if (typeof res === 'string' || typeof res === 'boolean') return String(res)\n if (res instanceof Date) return formatDateValue(res, cell.numFmt)\n if (res && typeof res === 'object') {\n const ro = res as Record<string, unknown>\n if (typeof ro.error === 'string') return ro.error // formula result is an error → its code\n if (Array.isArray(ro.richText)) return richTextToString(ro.richText)\n }\n return ''\n }\n }\n // Unknown shape: try exceljs's own text, but never surface a stringified object (and never throw).\n try {\n const t = cell.text\n return t != null && t !== '[object Object]' ? String(t) : ''\n } catch {\n return ''\n }\n}\n\n// Numbers and dates align right by default in Excel (text aligns left). Mirror that when the cell has no\n// explicit horizontal alignment — including formula cells whose cached result is a number or date.\nfunction defaultRight(value: unknown): boolean {\n if (typeof value === 'number') return true\n if (value instanceof Date) return true\n if (value && typeof value === 'object' && 'result' in value) {\n const res = (value as { result?: unknown }).result\n return typeof res === 'number' || res instanceof Date\n }\n return false\n}\n\nfunction buildSheet(ws: ExcelJS.Worksheet): XlsxSheet {\n const merges = Array.isArray(ws.model?.merges) ? (ws.model.merges as string[]) : []\n const { spans, covered } = parseMerges(merges)\n\n const cols = Math.min(ws.columnCount || 0, MAX_COLS)\n const rowCount = Math.min(ws.rowCount || 0, MAX_ROWS)\n\n const colWidths: number[] = []\n const colHidden: boolean[] = []\n for (let c = 1; c <= cols; c++) {\n const col = ws.getColumn(c)\n colWidths.push(colWidthToPx(col?.width))\n colHidden.push(!!col?.hidden)\n }\n\n const rows: XlsxRow[] = []\n for (let r = 1; r <= rowCount; r++) {\n const row = ws.getRow(r)\n const cells: XlsxCell[] = []\n for (let c = 1; c <= cols; c++) {\n if (covered.has(`${r},${c}`)) continue\n const cell = row.getCell(c)\n const span = spans.get(`${r},${c}`)\n const text = cellText(cell)\n // Formula source (without leading `=`): regular cells carry `{ formula }`, shared-formula dependents\n // carry `{ sharedFormula }` (exceljs's per-cell expression). Read from the value shape to avoid the\n // `.formula` getter's side effects.\n let formula: string | undefined\n const cv = cell.value as unknown\n if (cv && typeof cv === 'object') {\n const o = cv as Record<string, unknown>\n if (typeof o.formula === 'string' && o.formula) formula = o.formula\n else if (typeof o.sharedFormula === 'string' && o.sharedFormula) formula = o.sharedFormula\n }\n // Skip truly empty, unstyled, unmerged cells but still emit a placeholder so columns line up — we do\n // that by always pushing a cell (with its `col`), letting the renderer position via colSpan gaps.\n const font = cell.font || {}\n const align = cell.alignment || {}\n const border = cell.border || {}\n const horizontal =\n align.horizontal === 'center' || align.horizontal === 'centerContinuous'\n ? 'center'\n : align.horizontal === 'right'\n ? 'right'\n : align.horizontal === 'left'\n ? 'left'\n : defaultRight(cell.value)\n ? 'right'\n : undefined\n const vertical =\n align.vertical === 'top'\n ? 'top'\n : align.vertical === 'bottom'\n ? 'bottom'\n : align.vertical === 'middle'\n ? 'middle'\n : undefined\n cells.push({\n text,\n col: c,\n rowSpan: span?.rowSpan ?? 1,\n colSpan: span?.colSpan ?? 1,\n bold: font.bold || undefined,\n italic: font.italic || undefined,\n underline: !!font.underline || undefined,\n strike: font.strike || undefined,\n fontSize: fontSizeToPx(font.size),\n formula,\n color: colorToCss(font.color),\n bg:\n cell.fill && cell.fill.type === 'pattern'\n ? colorToCss((cell.fill as { fgColor?: unknown }).fgColor)\n : undefined,\n align: horizontal,\n valign: vertical,\n wrap: align.wrapText || undefined,\n bt: !!border.top?.style || undefined,\n br: !!border.right?.style || undefined,\n bb: !!border.bottom?.style || undefined,\n bl: !!border.left?.style || undefined,\n })\n }\n rows.push({\n num: r,\n height: row.height ? Math.round((row.height * 4) / 3) : undefined,\n hidden: !!row.hidden,\n cells,\n })\n }\n\n // Freeze panes: exceljs surfaces the active view as { state:'frozen', xSplit, ySplit } where xSplit/ySplit\n // are the counts of columns/rows held fixed. Clamp to the rendered range so a stale split can't pin offscreen.\n const view = Array.isArray(ws.views) ? ws.views[0] : undefined\n const frozen = view && (view as { state?: string }).state === 'frozen' ? view : undefined\n const frozenCols = frozen\n ? Math.min(Math.max(0, (frozen as { xSplit?: number }).xSplit ?? 0), cols)\n : 0\n const frozenRows = frozen\n ? Math.min(Math.max(0, (frozen as { ySplit?: number }).ySplit ?? 0), rowCount)\n : 0\n\n return { name: ws.name || `Sheet`, colWidths, colHidden, rows, cols, frozenRows, frozenCols }\n}\n\n/** Parse `.xlsx` bytes into the render model. Throws on a non-spreadsheet / corrupt file. */\nexport async function parseXlsx(buf: ArrayBuffer): Promise<XlsxModel> {\n const wb = new ExcelJS.Workbook()\n await wb.xlsx.load(buf)\n const sheets = wb.worksheets\n // Hidden sheets (state 'hidden'/'veryHidden') aren't shown in Excel's tab bar; skip them too.\n .filter((ws) => ws && ws.state !== 'hidden' && ws.state !== 'veryHidden')\n .map(buildSheet)\n if (sheets.length === 0) throw new Error('工作簿中没有可显示的工作表')\n return { sheets }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"xlsx.js","names":[],"sources":["../../src/lib/xlsx.ts"],"sourcesContent":["/**\n * In-browser `.xlsx` (and `.xlsm`) parsing for the side viewer's spreadsheet preview.\n *\n * exceljs does the OOXML heavy lifting (unzip + parse the SpreadsheetML); here we flatten one of its\n * Workbooks into a small, serializable model the {@link XlsxViewer} renders as plain HTML `<table>`s —\n * one table per worksheet, with merged cells, column widths, and the common cell styling (bold/italic/\n * color/fill/alignment/borders) carried over so the preview reads like the original sheet.\n *\n * exceljs is heavy (~1MB), so this module is only ever imported by the async-loaded XlsxViewer — it never\n * lands in the main bundle. We import the namespace (not named exports) because exceljs's browser entry is\n * a UMD bundle: `new ExcelJS.Workbook()` resolves identically under Vite's CJS interop and the .d.ts.\n */\nimport * as ExcelJS from 'exceljs'\nimport JSZip from 'jszip'\nimport { format as nfFormat, isDateFormat as nfIsDateFormat } from 'numfmt'\n\n/** One rendered cell. A cell covered by a merge is dropped from the row entirely (see {@link XlsxRow}). */\nexport interface XlsxCell {\n text: string\n rowSpan: number\n colSpan: number\n /** 1-based column index of this cell's left edge — lets the renderer place cells after merge gaps. */\n col: number\n bold?: boolean\n italic?: boolean\n underline?: boolean\n strike?: boolean\n /** Font size in px (converted from the workbook's points), or undefined to use the table default. */\n fontSize?: number\n /** The cell's formula expression WITHOUT a leading `=` (e.g. `数据基表!B10`, `#REF!`), for the source view. */\n formula?: string\n /** Authored text/fill colors; automatic and untinted Office text1 use the viewer's default text. */\n color?: string\n bg?: string\n align?: 'left' | 'center' | 'right'\n valign?: 'top' | 'middle' | 'bottom'\n wrap?: boolean\n /** Which borders the cell draws (true = a visible edge in the source). */\n bt?: boolean\n br?: boolean\n bb?: boolean\n bl?: boolean\n}\n\nexport interface XlsxRow {\n /** 1-based row number in the worksheet (so the viewer can label the gutter and key frozen/hidden state). */\n num: number\n /** Row height in px (converted from Excel points), or undefined to size to content. */\n height?: number\n /** Hidden in the source (\"hide rows\") — the viewer collapses it behind an expander, like Excel/WPS. */\n hidden?: boolean\n /** Only the cells that actually render — merge-covered slots are omitted; use {@link XlsxCell.col}. */\n cells: XlsxCell[]\n}\n\nexport interface XlsxSheet {\n name: string\n /** Per-column width in px (index 0 = column A); columns past this use a default width. */\n colWidths: number[]\n /** Per-column hidden flag (index 0 = column A) — collapsed behind an expander, like Excel/WPS. */\n colHidden: boolean[]\n rows: XlsxRow[]\n cols: number\n /** Frozen pane sizes (Excel \"freeze panes\"): the first N rows / M columns stay pinned while scrolling. */\n frozenRows: number\n frozenCols: number\n}\n\nexport interface XlsxModel {\n sheets: XlsxSheet[]\n}\n\n// Guardrails: a corrupt or absurdly large sheet shouldn't lock up the tab. We cap the rendered range and\n// let the viewer note the truncation. (Real attachments are tiny; these only bite pathological files.)\nconst MAX_ROWS = 2000\nconst MAX_COLS = 200\n\n// Excel column-letter (A, B, …, AA) → 1-based index.\nfunction colToNum(s: string): number {\n let n = 0\n for (let i = 0; i < s.length; i++) n = n * 26 + (s.charCodeAt(i) - 64)\n return n\n}\n\n// 1-based index → Excel column-letter (1→A, 26→Z, 27→AA). Used by the viewer's A/B/C… header row.\nexport function numToCol(n: number): string {\n let s = ''\n while (n > 0) {\n const m = (n - 1) % 26\n s = String.fromCharCode(65 + m) + s\n n = Math.floor((n - 1) / 26)\n }\n return s\n}\n\ninterface Span {\n rowSpan: number\n colSpan: number\n}\n\n// Parse exceljs's merge ranges (\"A1:B2\") into: span info keyed at each master cell, and a set of the\n// addresses (`r,c`) covered by a merge (which we then skip rendering).\nfunction parseMerges(merges: string[]): { spans: Map<string, Span>; covered: Set<string> } {\n const spans = new Map<string, Span>()\n const covered = new Set<string>()\n for (const range of merges) {\n const m = /^([A-Z]+)(\\d+):([A-Z]+)(\\d+)$/.exec(range)\n if (!m) continue\n const c1 = colToNum(m[1])\n const r1 = parseInt(m[2], 10)\n const c2 = colToNum(m[3])\n const r2 = parseInt(m[4], 10)\n const top = Math.min(r1, r2)\n const bottom = Math.max(r1, r2)\n const left = Math.min(c1, c2)\n const right = Math.max(c1, c2)\n spans.set(`${top},${left}`, { rowSpan: bottom - top + 1, colSpan: right - left + 1 })\n for (let r = top; r <= bottom; r++) {\n for (let c = left; c <= right; c++) {\n if (r === top && c === left) continue\n covered.add(`${r},${c}`)\n }\n }\n }\n return { spans, covered }\n}\n\n// Excel's legacy 56-colour indexed palette (BIFF8). Cells/fonts that don't carry an explicit ARGB reference\n// a palette slot instead (e.g. `{ indexed: 47 }`) — very common in older workbooks. 64/65 are the system\n// foreground/background (\"automatic\"), handled specially below.\n// prettier-ignore\nconst INDEXED_COLORS = [\n '000000', 'FFFFFF', 'FF0000', '00FF00', '0000FF', 'FFFF00', 'FF00FF', '00FFFF',\n '000000', 'FFFFFF', 'FF0000', '00FF00', '0000FF', 'FFFF00', 'FF00FF', '00FFFF',\n '800000', '008000', '000080', '808000', '800080', '008080', 'C0C0C0', '808080',\n '9999FF', '993366', 'FFFFCC', 'CCFFFF', '660066', 'FF8080', '0066CC', 'CCCCFF',\n '000080', 'FF00FF', 'FFFF00', '00FFFF', '800080', '800000', '008080', '0000FF',\n '00CCFF', 'CCFFFF', 'CCFFCC', 'FFFF99', '99CCFF', 'FF99CC', 'CC99FF', 'FFCC99',\n '3366FF', '33CCCC', '99CC00', 'FFCC00', 'FF9900', 'FF6600', '666699', '969696',\n '003366', '339966', '003300', '333300', '993300', '993366', '333399', '333333',\n]\n\n// Default Office theme colours, in the order the styles `theme` attribute indexes them (0=bg1/white,\n// 1=text1/black, 2=bg2, 3=text2, 4..9=accent1..6, 10=hlink, 11=folHlink). We don't parse the workbook's\n// actual theme XML (exceljs doesn't surface it), so this default scheme is a best-effort — but it gets the\n// common cases right (notably theme 1 = black text, theme 0 = white) and `tint` is applied on top.\n// prettier-ignore\nconst THEME_COLORS = [\n 'FFFFFF', '000000', 'E7E6E6', '44546A', '4472C4', 'ED7D31',\n 'A5A5A5', 'FFC000', '5B9BD5', '70AD47', '0563C1', '954F72',\n]\n\nfunction rgbToHsl(r: number, g: number, b: number): [number, number, number] {\n r /= 255\n g /= 255\n b /= 255\n const max = Math.max(r, g, b)\n const min = Math.min(r, g, b)\n let h = 0\n let s = 0\n const l = (max + min) / 2\n if (max !== min) {\n const d = max - min\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min)\n if (max === r) h = (g - b) / d + (g < b ? 6 : 0)\n else if (max === g) h = (b - r) / d + 2\n else h = (r - g) / d + 4\n h /= 6\n }\n return [h, s, l]\n}\n\nfunction hue2rgb(p: number, q: number, t: number): number {\n if (t < 0) t += 1\n if (t > 1) t -= 1\n if (t < 1 / 6) return p + (q - p) * 6 * t\n if (t < 1 / 2) return q\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6\n return p\n}\n\nfunction hslToRgb(h: number, s: number, l: number): [number, number, number] {\n if (s === 0) {\n const v = Math.round(l * 255)\n return [v, v, v]\n }\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s\n const p = 2 * l - q\n return [\n Math.round(hue2rgb(p, q, h + 1 / 3) * 255),\n Math.round(hue2rgb(p, q, h) * 255),\n Math.round(hue2rgb(p, q, h - 1 / 3) * 255),\n ]\n}\n\n// Excel applies `tint` to a theme/indexed colour by shifting its HSL luminance: negative darkens, positive\n// lightens. Mirrors the algorithm in the OOXML spec so shaded theme fills come out the right tone.\nfunction applyTint(hex: string, tint: number): string {\n const r = parseInt(hex.slice(0, 2), 16)\n const g = parseInt(hex.slice(2, 4), 16)\n const b = parseInt(hex.slice(4, 6), 16)\n const [h, s, l0] = rgbToHsl(r, g, b)\n let l = tint < 0 ? l0 * (1 + tint) : l0 * (1 - tint) + tint\n l = Math.max(0, Math.min(1, l))\n const [nr, ng, nb] = hslToRgb(h, s, l)\n const hx = (n: number): string => n.toString(16).padStart(2, '0')\n return hx(nr) + hx(ng) + hx(nb)\n}\n\n/**\n * Resolve any exceljs colour object to a CSS `#RRGGBB`, covering all three references Excel uses: explicit\n * `argb`, the legacy `indexed` palette, and `theme` index (+ optional `tint`). Returns undefined for \"no\n * colour\" — a fully-transparent argb, the system-automatic indices, or an unresolvable shape.\n */\nfunction colorToCss(color: unknown): string | undefined {\n if (!color || typeof color !== 'object') return undefined\n const c = color as { argb?: string; theme?: number; indexed?: number; tint?: number }\n let hex: string | undefined\n if (typeof c.argb === 'string') {\n if (c.argb.length === 8) {\n if (c.argb.slice(0, 2).toLowerCase() === '00') return undefined // fully transparent → no colour\n hex = c.argb.slice(2)\n } else if (c.argb.length === 6) {\n hex = c.argb\n }\n } else if (typeof c.theme === 'number') {\n hex = THEME_COLORS[c.theme]\n } else if (typeof c.indexed === 'number') {\n if (c.indexed === 64) return undefined // system foreground / automatic → let the default apply\n hex = c.indexed === 65 ? 'FFFFFF' : INDEXED_COLORS[c.indexed]\n }\n if (!hex || !/^[0-9a-fA-F]{6}$/.test(hex)) return undefined\n if (typeof c.tint === 'number' && c.tint !== 0) hex = applyTint(hex, c.tint)\n return `#${hex}`\n}\n\n/** Office's default text1 is a semantic foreground, not an authored black font. */\nfunction fontColorToCss(color: unknown): string | undefined {\n if (color && typeof color === 'object') {\n const c = color as { argb?: string; theme?: number; tint?: number }\n if (c.argb == null && c.theme === 1 && !c.tint) return undefined\n }\n return colorToCss(color)\n}\n\n// Excel font sizes are in points; CSS wants px. The conventional screen conversion is pt × 96/72 (= ×4/3),\n// which keeps relative sizing faithful (a 24pt title reads clearly larger than 10pt body text).\nfunction fontSizeToPx(size: number | undefined): number | undefined {\n if (!size || size <= 0) return undefined\n return Math.round((size * 4) / 3)\n}\n\n// Excel column width is in \"character\" units; the conventional pixel conversion to the COLUMN's total width is\n// width*7 + 5 (the +5 is Excel's own internal cell padding). But our HTML cell adds its OWN padding (~4px each\n// side) and a gridline border on top of the `<col>` width, so reusing Excel's total width would leave the\n// content area ~8px short and clip text into \"…\". We add that HTML chrome back (+9 instead of +5) so the\n// usable content width matches Excel's, keeping the cell `padding`/border in sync (see XlsxViewer .xv__cell).\nfunction colWidthToPx(w: number | undefined): number {\n if (!w || w <= 0) return 80\n return Math.round(w * 7 + 9)\n}\n\n// A two-digit zero-pad for the date formatter.\nfunction pad2(n: number): string {\n return n < 10 ? `0${n}` : String(n)\n}\n\n// Render a Date the way a spreadsheet preview should — `YYYY-MM-DD`, plus a `HH:MM[:SS]` tail only when the\n// value carries a time-of-day. (exceljs's own `cell.text` gives the raw JS `Date.toString()`, e.g.\n// \"Sat May 04 2019 08:00:00 GMT+0800 (中国标准时间)\", which is useless in a cell.)\nfunction formatDate(d: Date): string {\n const date = `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`\n const h = d.getHours()\n const mi = d.getMinutes()\n const s = d.getSeconds()\n if (!h && !mi && !s) return date\n return `${date} ${pad2(h)}:${pad2(mi)}${s ? `:${pad2(s)}` : ''}`\n}\n\nfunction richTextToString(runs: unknown): string {\n if (!Array.isArray(runs)) return ''\n return runs\n .map((r) => (r && typeof r === 'object' ? ((r as { text?: string }).text ?? '') : ''))\n .join('')\n}\n\n// CJK numeral digits/units for Excel's `[DBNum1]` (中文小写) and `[DBNum2]` (中文大写/financial) — numfmt does\n// not implement these (Excel's 特殊 → 中文数字), so we convert the integer ourselves with proper 万/亿 grouping.\nconst DBNUM_DIGITS = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']\nconst DBNUM_DIGITS_UP = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']\nconst DBNUM_UNITS = ['', '十', '百', '千']\nconst DBNUM_UNITS_UP = ['', '拾', '佰', '仟']\nconst DBNUM_BIG = ['', '万', '亿', '兆']\n\n// Convert one 0..9999 group to CJK numerals, collapsing internal zeros to a single 零 (no trailing zero unit).\nfunction dbNumGroup(n: number, digits: string[], units: string[]): string {\n let s = ''\n let pendingZero = false\n for (let i = 3; i >= 0; i--) {\n const x = Math.floor(n / 10 ** i) % 10\n if (x === 0) {\n if (s !== '') pendingZero = true\n } else {\n if (pendingZero) {\n s += digits[0]\n pendingZero = false\n }\n s += digits[x] + units[i]\n }\n }\n return s\n}\n\n// Excel `[DBNum1]`/`[DBNum2]` of a non-negative integer: e.g. 1234 → 一千二百三十四 / 壹仟贰佰叁拾肆, 10001 → 一万零一,\n// 100000001 → 一亿零一. (Keeps Excel's leading 一十 for 10-19, single 零 between groups, like Excel's own output.)\nfunction toChineseNumeral(n: number, upper: boolean): string {\n const digits = upper ? DBNUM_DIGITS_UP : DBNUM_DIGITS\n const units = upper ? DBNUM_UNITS_UP : DBNUM_UNITS\n if (n === 0) return digits[0]\n const groups: number[] = []\n let x = n\n while (x > 0) {\n groups.push(x % 10000)\n x = Math.floor(x / 10000)\n }\n let s = ''\n for (let i = groups.length - 1; i >= 0; i--) {\n const g = groups[i]\n if (g === 0) continue // an all-zero group: the next non-zero group's leading 零 covers the gap\n let gs = dbNumGroup(g, digits, units)\n if (i < groups.length - 1 && g < 1000) gs = digits[0] + gs // 1,0001 → 一万零一 (zero after a higher group)\n s += gs + DBNUM_BIG[i]\n }\n return s\n}\n\n// Map ASCII digits to full-width — Excel's `[DBNum3]` (全角数字); applied over numfmt's normal output so any\n// separators / decimals survive.\nfunction toFullWidthDigits(s: string): string {\n return s.replace(/[0-9]/g, (d) => '0123456789'[Number(d)])\n}\n\n// Honor Excel's `[DBNumN]` CJK-numeral prefixes that numfmt can't render. Returns null to fall back to numfmt\n// (negatives / non-integers for DBNum1/2, where Excel's behavior is fiddly — a plain number is safer than a guess).\nfunction formatDbNum(value: number, n: number, fmt: string): string | null {\n if (n === 3) {\n try {\n const out = nfFormat(fmt, value) // numfmt strips the [DBNum3] tag and formats the rest\n if (typeof out === 'string') return toFullWidthDigits(out)\n } catch {\n /* fall through */\n }\n return null\n }\n if (Number.isInteger(value) && value >= 0) return toChineseNumeral(value, n === 2)\n return null\n}\n\n// numfmt understands the English \"General\" keyword but not Excel's LOCALIZED one (Simplified Chinese \"G/通用格式\",\n// Japanese \"G/標準\", etc.), throwing \"Invalid pattern\" — normalize those to \"General\" so a locale-tagged General\n// format (common in CJK files after a [DBNum]/[$-…] prefix) parses. (Plain \"[$-NNN]\" locale tags numfmt handles.)\nfunction cleanFmt(fmt: string): string {\n return fmt.replace(/G\\/(通用格式|標準|标准|표준)/g, 'General')\n}\n\n// Apply the cell's Excel number format (`cell.numFmt`) to a numeric value the way Excel DISPLAYS it — exceljs's\n// `cell.text` returns the raw stored number, so an integer-formatted cell (\"0\") shows the stored float\n// \"2.9999999999\" instead of \"3\", a percent format shows \"0.5\" instead of \"50%\", thousands separators go missing,\n// etc. An undefined format → \"General\", which (like Excel) also strips IEEE float noise (0.1+0.2 → \"0.3\"); this is\n// why a cell *referencing* a formatted one rendered wrong too — its cached result is the noisy float. numfmt covers\n// currency / accounting / fraction / scientific / percent / text(@) / 邮编 / custom codes; `[DBNumN]` CJK numerals\n// (which numfmt doesn't implement) are handled here. Unsupported codes / unexpected output fall back to a plain\n// string, never throwing.\nfunction formatNumber(value: number, numFmt: string | undefined): string {\n const fmt = cleanFmt(numFmt || 'General')\n const dbnum = /\\[DBNum([123])\\]/.exec(fmt)\n if (dbnum) {\n const out = formatDbNum(value, Number(dbnum[1]), fmt)\n if (out != null) return out\n }\n try {\n const out = nfFormat(fmt, value)\n return typeof out === 'string' ? out : String(value)\n } catch {\n return String(value)\n }\n}\n\n// Format a date the way Excel's number format dictates — exceljs hands us a JS `Date`, and numfmt formats it\n// directly (reading its local components) for any date/time format code: ISO, 中文 yyyy\"年\"m\"月\"d\"日\", h:mm AM/PM,\n// custom date-times, etc. Only route through numfmt when the format actually IS a date format; otherwise (no/General\n// format) keep the viewer's plain YYYY-MM-DD default from {@link formatDate}.\nfunction formatDateValue(d: Date, numFmt: string | undefined): string {\n if (numFmt && numFmt !== 'General' && nfIsDateFormat(numFmt)) {\n try {\n const out = nfFormat(numFmt, d)\n if (typeof out === 'string' && out !== '') return out\n } catch {\n /* fall through to the plain default */\n }\n }\n return formatDate(d)\n}\n\n/**\n * Resolve a cell's display text from its value SHAPE rather than exceljs's `cell.text` — which returns the\n * raw object for some value kinds (so a formula whose cached result is an error renders as \"[object Object]\")\n * and even throws on certain merged cells. We cover every {@link ExcelJS.ValueType}: numbers/strings/booleans\n * verbatim, dates formatted, rich text joined, hyperlinks as their label, formula results unwrapped (errors →\n * their code like \"#REF!\", a nested date/rich-text result resolved), and error cells as their code. Anything\n * unexpected falls back to a guarded `cell.text`, never to a stringified object.\n */\nfunction cellText(cell: ExcelJS.Cell): string {\n const v = cell.value as unknown\n if (v == null) return ''\n if (typeof v === 'number') return formatNumber(v, cell.numFmt)\n if (typeof v === 'string' || typeof v === 'boolean') return String(v)\n if (v instanceof Date) return formatDateValue(v, cell.numFmt)\n if (typeof v === 'object') {\n const o = v as Record<string, unknown>\n if (typeof o.error === 'string') return o.error // error cell: { error: '#DIV/0!' }\n if (Array.isArray(o.richText)) return richTextToString(o.richText) // rich text\n if ('hyperlink' in o) {\n // hyperlink: { text, hyperlink } — text may itself be rich text\n const t = o.text\n if (Array.isArray((t as { richText?: unknown })?.richText)) {\n return richTextToString((t as { richText?: unknown }).richText)\n }\n return t == null ? String(o.hyperlink) : String(t)\n }\n if ('result' in o || 'formula' in o || 'sharedFormula' in o) {\n // formula: { formula, result } — the result is what Excel shows in the cell\n const res = o.result as unknown\n if (res == null) return ''\n if (typeof res === 'number') return formatNumber(res, cell.numFmt)\n if (typeof res === 'string' || typeof res === 'boolean') return String(res)\n if (res instanceof Date) return formatDateValue(res, cell.numFmt)\n if (res && typeof res === 'object') {\n const ro = res as Record<string, unknown>\n if (typeof ro.error === 'string') return ro.error // formula result is an error → its code\n if (Array.isArray(ro.richText)) return richTextToString(ro.richText)\n }\n return ''\n }\n }\n // Unknown shape: try exceljs's own text, but never surface a stringified object (and never throw).\n try {\n const t = cell.text\n return t != null && t !== '[object Object]' ? String(t) : ''\n } catch {\n return ''\n }\n}\n\n// Numbers and dates align right by default in Excel (text aligns left). Mirror that when the cell has no\n// explicit horizontal alignment — including formula cells whose cached result is a number or date.\nfunction defaultRight(value: unknown): boolean {\n if (typeof value === 'number') return true\n if (value instanceof Date) return true\n if (value && typeof value === 'object' && 'result' in value) {\n const res = (value as { result?: unknown }).result\n return typeof res === 'number' || res instanceof Date\n }\n return false\n}\n\nfunction buildSheet(ws: ExcelJS.Worksheet): XlsxSheet {\n const merges = Array.isArray(ws.model?.merges) ? (ws.model.merges as string[]) : []\n const { spans, covered } = parseMerges(merges)\n\n const cols = Math.min(ws.columnCount || 0, MAX_COLS)\n const rowCount = Math.min(ws.rowCount || 0, MAX_ROWS)\n\n const colWidths: number[] = []\n const colHidden: boolean[] = []\n for (let c = 1; c <= cols; c++) {\n const col = ws.getColumn(c)\n colWidths.push(colWidthToPx(col?.width))\n colHidden.push(!!col?.hidden)\n }\n\n const rows: XlsxRow[] = []\n for (let r = 1; r <= rowCount; r++) {\n const row = ws.getRow(r)\n const cells: XlsxCell[] = []\n for (let c = 1; c <= cols; c++) {\n if (covered.has(`${r},${c}`)) continue\n const cell = row.getCell(c)\n const span = spans.get(`${r},${c}`)\n const text = cellText(cell)\n // Formula source (without leading `=`): regular cells carry `{ formula }`, shared-formula dependents\n // carry `{ sharedFormula }` (exceljs's per-cell expression). Read from the value shape to avoid the\n // `.formula` getter's side effects.\n let formula: string | undefined\n const cv = cell.value as unknown\n if (cv && typeof cv === 'object') {\n const o = cv as Record<string, unknown>\n if (typeof o.formula === 'string' && o.formula) formula = o.formula\n else if (typeof o.sharedFormula === 'string' && o.sharedFormula) formula = o.sharedFormula\n }\n // Skip truly empty, unstyled, unmerged cells but still emit a placeholder so columns line up — we do\n // that by always pushing a cell (with its `col`), letting the renderer position via colSpan gaps.\n const font = cell.font || {}\n const align = cell.alignment || {}\n const border = cell.border || {}\n const horizontal =\n align.horizontal === 'center' || align.horizontal === 'centerContinuous'\n ? 'center'\n : align.horizontal === 'right'\n ? 'right'\n : align.horizontal === 'left'\n ? 'left'\n : defaultRight(cell.value)\n ? 'right'\n : undefined\n const vertical =\n align.vertical === 'top'\n ? 'top'\n : align.vertical === 'bottom'\n ? 'bottom'\n : align.vertical === 'middle'\n ? 'middle'\n : undefined\n cells.push({\n text,\n col: c,\n rowSpan: span?.rowSpan ?? 1,\n colSpan: span?.colSpan ?? 1,\n bold: font.bold || undefined,\n italic: font.italic || undefined,\n underline: !!font.underline || undefined,\n strike: font.strike || undefined,\n fontSize: fontSizeToPx(font.size),\n formula,\n color: fontColorToCss(font.color),\n bg:\n cell.fill && cell.fill.type === 'pattern'\n ? colorToCss((cell.fill as { fgColor?: unknown }).fgColor)\n : undefined,\n align: horizontal,\n valign: vertical,\n wrap: align.wrapText || undefined,\n bt: !!border.top?.style || undefined,\n br: !!border.right?.style || undefined,\n bb: !!border.bottom?.style || undefined,\n bl: !!border.left?.style || undefined,\n })\n }\n rows.push({\n num: r,\n height: row.height ? Math.round((row.height * 4) / 3) : undefined,\n hidden: !!row.hidden,\n cells,\n })\n }\n\n // Freeze panes: exceljs surfaces the active view as { state:'frozen', xSplit, ySplit } where xSplit/ySplit\n // are the counts of columns/rows held fixed. Clamp to the rendered range so a stale split can't pin offscreen.\n const view = Array.isArray(ws.views) ? ws.views[0] : undefined\n const frozen = view && (view as { state?: string }).state === 'frozen' ? view : undefined\n const frozenCols = frozen\n ? Math.min(Math.max(0, (frozen as { xSplit?: number }).xSplit ?? 0), cols)\n : 0\n const frozenRows = frozen\n ? Math.min(Math.max(0, (frozen as { ySplit?: number }).ySplit ?? 0), rowCount)\n : 0\n\n return { name: ws.name || `Sheet`, colWidths, colHidden, rows, cols, frozenRows, frozenCols }\n}\n\n/**\n * ExcelJS's drawing parser requires literal `xdr:` prefixes and crashes on valid default-namespace\n * drawings (e.g. openpyxl's `<wsDr xmlns=\"…\">`). This model only consumes cells; charts are read separately\n * from the original bytes by parseXlsxCharts. Omit DrawingML parts from ExcelJS's private input so graphics\n * cannot break the table preview. Keep VML drawings, which ExcelJS needs to reconcile cell comments.\n */\nasync function cellWorkbookBytes(buf: ArrayBuffer): Promise<ArrayBuffer> {\n const zip = await JSZip.loadAsync(buf)\n const drawings = Object.keys(zip.files).filter((path) =>\n /^xl\\/drawings\\/(?:_rels\\/)?[^/]+\\.xml(?:\\.rels)?$/.test(path),\n )\n if (drawings.length === 0) return buf\n for (const path of drawings) zip.remove(path)\n // Reuse already-deflated entries rather than expanding embedded media into a much larger STORE archive.\n return zip.generateAsync({ type: 'arraybuffer', compression: 'DEFLATE' })\n}\n\n/** Parse `.xlsx` bytes into the render model. Throws on a non-spreadsheet / corrupt file. */\nexport async function parseXlsx(buf: ArrayBuffer): Promise<XlsxModel> {\n const wb = new ExcelJS.Workbook()\n // ignoreNodes alone does not skip drawing ZIP parts; both layers must exclude them.\n await wb.xlsx.load(await cellWorkbookBytes(buf), { ignoreNodes: ['drawing'] })\n const sheets = wb.worksheets\n // Hidden sheets (state 'hidden'/'veryHidden') aren't shown in Excel's tab bar; skip them too.\n .filter((ws) => ws && ws.state !== 'hidden' && ws.state !== 'veryHidden')\n .map(buildSheet)\n if (sheets.length === 0) throw new Error('工作簿中没有可显示的工作表')\n return { sheets }\n}\n"],"mappings":"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"}
|