ooxml.js 2.5.2 → 2.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/README.md +1 -1
- package/dist/index.cjs +22 -0
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/typed/docx/numbering.cjs +86 -0
- package/dist/typed/docx/numbering.d.cts +23 -0
- package/dist/typed/docx/numbering.d.ts +23 -0
- package/dist/typed/docx/numbering.js +83 -0
- package/dist/typed/docx/read.cjs +115 -15
- package/dist/typed/docx/read.d.cts +8 -0
- package/dist/typed/docx/read.d.ts +8 -0
- package/dist/typed/docx/read.js +117 -17
- package/dist/typed/docx/styles.cjs +26 -2
- package/dist/typed/docx/styles.js +26 -2
- package/dist/typed/pptx/read.cjs +5 -20
- package/dist/typed/pptx/read.js +5 -20
- package/dist/typed/shared/drawingml.cjs +112 -5
- package/dist/typed/shared/drawingml.d.cts +19 -2
- package/dist/typed/shared/drawingml.d.ts +19 -2
- package/dist/typed/shared/drawingml.js +111 -6
- package/dist/typed/shared/units.cjs +10 -0
- package/dist/typed/shared/units.d.cts +4 -1
- package/dist/typed/shared/units.d.ts +4 -1
- package/dist/typed/shared/units.js +8 -1
- package/dist/typed/xlsx/build.cjs +83 -55
- package/dist/typed/xlsx/build.js +83 -55
- package/dist/typed/xlsx/content.cjs +85 -15
- package/dist/typed/xlsx/content.js +85 -15
- package/dist/typed/xlsx/number-format.cjs +324 -0
- package/dist/typed/xlsx/number-format.d.cts +52 -0
- package/dist/typed/xlsx/number-format.d.ts +52 -0
- package/dist/typed/xlsx/number-format.js +312 -0
- package/dist/typed/xlsx/serial.cjs +109 -0
- package/dist/typed/xlsx/serial.d.cts +11 -0
- package/dist/typed/xlsx/serial.d.ts +11 -0
- package/dist/typed/xlsx/serial.js +102 -0
- package/dist/typed/xlsx/styles.cjs +73 -0
- package/dist/typed/xlsx/styles.d.cts +21 -0
- package/dist/typed/xlsx/styles.d.ts +21 -0
- package/dist/typed/xlsx/styles.js +69 -0
- package/package.json +1 -1
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
//#region src/typed/xlsx/number-format.ts
|
|
2
|
+
const MAX_NUMBER_FORMAT_SECTIONS = 4;
|
|
3
|
+
function at(chars, index) {
|
|
4
|
+
return chars[index] ?? "";
|
|
5
|
+
}
|
|
6
|
+
function tokenizeNumberFormat(formatCode) {
|
|
7
|
+
const chars = [...formatCode];
|
|
8
|
+
const tokens = [];
|
|
9
|
+
let index = 0;
|
|
10
|
+
while (index < chars.length) {
|
|
11
|
+
const char = at(chars, index);
|
|
12
|
+
if (char === "\"") {
|
|
13
|
+
let text = "";
|
|
14
|
+
index += 1;
|
|
15
|
+
while (index < chars.length && at(chars, index) !== "\"") {
|
|
16
|
+
text += at(chars, index);
|
|
17
|
+
index += 1;
|
|
18
|
+
}
|
|
19
|
+
index += 1;
|
|
20
|
+
tokens.push({
|
|
21
|
+
kind: "literal",
|
|
22
|
+
text
|
|
23
|
+
});
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (char === "\\" || char === "_" || char === "*") {
|
|
27
|
+
tokens.push({
|
|
28
|
+
kind: "literal",
|
|
29
|
+
text: at(chars, index + 1)
|
|
30
|
+
});
|
|
31
|
+
index += 2;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (char === "[") {
|
|
35
|
+
let body = "";
|
|
36
|
+
index += 1;
|
|
37
|
+
while (index < chars.length && at(chars, index) !== "]") {
|
|
38
|
+
body += at(chars, index);
|
|
39
|
+
index += 1;
|
|
40
|
+
}
|
|
41
|
+
index += 1;
|
|
42
|
+
tokens.push({
|
|
43
|
+
kind: "bracket",
|
|
44
|
+
body
|
|
45
|
+
});
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (char === ";") {
|
|
49
|
+
tokens.push({ kind: "separator" });
|
|
50
|
+
index += 1;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
tokens.push({
|
|
54
|
+
kind: "code",
|
|
55
|
+
char
|
|
56
|
+
});
|
|
57
|
+
index += 1;
|
|
58
|
+
}
|
|
59
|
+
return tokens;
|
|
60
|
+
}
|
|
61
|
+
function splitNumberFormatSections(tokens) {
|
|
62
|
+
const sections = [];
|
|
63
|
+
let current = [];
|
|
64
|
+
for (const token of tokens) {
|
|
65
|
+
if (token.kind === "separator") {
|
|
66
|
+
sections.push(current);
|
|
67
|
+
current = [];
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
current.push(token);
|
|
71
|
+
}
|
|
72
|
+
sections.push(current);
|
|
73
|
+
return sections.slice(0, 4);
|
|
74
|
+
}
|
|
75
|
+
const CURRENCY_SYMBOL = /\p{Sc}/u;
|
|
76
|
+
function containsCurrencySymbol(text) {
|
|
77
|
+
return CURRENCY_SYMBOL.test(text);
|
|
78
|
+
}
|
|
79
|
+
function isIsoCurrencyCodeShape(marker) {
|
|
80
|
+
if (marker.length !== 3) return false;
|
|
81
|
+
for (const char of marker) {
|
|
82
|
+
const upper = char.toUpperCase();
|
|
83
|
+
if (upper < "A" || upper > "Z") return false;
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
function isElapsedBracketBody(body) {
|
|
88
|
+
let letter;
|
|
89
|
+
for (const char of body) {
|
|
90
|
+
const lower = char.toLowerCase();
|
|
91
|
+
if (letter === void 0) {
|
|
92
|
+
if (lower !== "h" && lower !== "m" && lower !== "s") return false;
|
|
93
|
+
letter = lower;
|
|
94
|
+
} else if (lower !== letter) return false;
|
|
95
|
+
}
|
|
96
|
+
return letter !== void 0;
|
|
97
|
+
}
|
|
98
|
+
function classifyBracket(body) {
|
|
99
|
+
if (body.startsWith("$")) {
|
|
100
|
+
const rest = body.slice(1);
|
|
101
|
+
const dashIndex = rest.indexOf("-");
|
|
102
|
+
const marker = dashIndex === -1 ? rest : rest.slice(0, dashIndex);
|
|
103
|
+
if (marker === "") return { kind: "none" };
|
|
104
|
+
return isIsoCurrencyCodeShape(marker) ? {
|
|
105
|
+
kind: "currency",
|
|
106
|
+
code: marker.toUpperCase()
|
|
107
|
+
} : { kind: "currency" };
|
|
108
|
+
}
|
|
109
|
+
return isElapsedBracketBody(body) ? { kind: "elapsed" } : { kind: "none" };
|
|
110
|
+
}
|
|
111
|
+
const AMPM_MARKERS = ["am/pm", "a/p"];
|
|
112
|
+
const AMPM_LETTER = "ampm";
|
|
113
|
+
function matchesAt(chars, index, marker) {
|
|
114
|
+
return [...marker].every((char, offset) => at(chars, index + offset).toLowerCase() === char);
|
|
115
|
+
}
|
|
116
|
+
function codeRunsOf(section) {
|
|
117
|
+
const chars = [];
|
|
118
|
+
for (const token of section) if (token.kind === "code") chars.push(token.char);
|
|
119
|
+
const runs = [];
|
|
120
|
+
let index = 0;
|
|
121
|
+
while (index < chars.length) {
|
|
122
|
+
const marker = AMPM_MARKERS.find((candidate) => matchesAt(chars, index, candidate));
|
|
123
|
+
if (marker !== void 0) {
|
|
124
|
+
runs.push({
|
|
125
|
+
letter: AMPM_LETTER,
|
|
126
|
+
length: marker.length
|
|
127
|
+
});
|
|
128
|
+
index += marker.length;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const char = at(chars, index).toLowerCase();
|
|
132
|
+
let length = 0;
|
|
133
|
+
while (index + length < chars.length && at(chars, index + length).toLowerCase() === char) length += 1;
|
|
134
|
+
runs.push({
|
|
135
|
+
letter: char,
|
|
136
|
+
length
|
|
137
|
+
});
|
|
138
|
+
index += length;
|
|
139
|
+
}
|
|
140
|
+
return runs;
|
|
141
|
+
}
|
|
142
|
+
const RESOLVING_LETTERS = [
|
|
143
|
+
"y",
|
|
144
|
+
"d",
|
|
145
|
+
"h",
|
|
146
|
+
"s"
|
|
147
|
+
];
|
|
148
|
+
function nearestResolvingLetter(runs, from, step) {
|
|
149
|
+
for (let index = from + step; index >= 0 && index < runs.length; index += step) {
|
|
150
|
+
const run = runs[index];
|
|
151
|
+
if (run !== void 0 && RESOLVING_LETTERS.includes(run.letter)) return run.letter;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function monthRunIsMinutes(runs, index) {
|
|
155
|
+
return nearestResolvingLetter(runs, index, -1) === "h" || nearestResolvingLetter(runs, index, 1) === "s";
|
|
156
|
+
}
|
|
157
|
+
const PLAIN_NUMBER = { kind: "number" };
|
|
158
|
+
const NUMERIC_CODES = [
|
|
159
|
+
"0",
|
|
160
|
+
"#",
|
|
161
|
+
"?",
|
|
162
|
+
".",
|
|
163
|
+
","
|
|
164
|
+
];
|
|
165
|
+
function collectSignals(section) {
|
|
166
|
+
const signals = {
|
|
167
|
+
hasDate: false,
|
|
168
|
+
hasTime: false,
|
|
169
|
+
hasElapsed: false,
|
|
170
|
+
hasPercent: false,
|
|
171
|
+
hasNumeric: false,
|
|
172
|
+
hasText: false,
|
|
173
|
+
hasCurrency: false
|
|
174
|
+
};
|
|
175
|
+
for (const token of section) {
|
|
176
|
+
if (token.kind === "literal" && containsCurrencySymbol(token.text)) signals.hasCurrency = true;
|
|
177
|
+
if (token.kind === "bracket") {
|
|
178
|
+
const meaning = classifyBracket(token.body);
|
|
179
|
+
if (meaning.kind === "elapsed") signals.hasElapsed = true;
|
|
180
|
+
if (meaning.kind === "currency") {
|
|
181
|
+
signals.hasCurrency = true;
|
|
182
|
+
if (signals.currencyCode === void 0 && meaning.code !== void 0) signals.currencyCode = meaning.code;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const runs = codeRunsOf(section);
|
|
187
|
+
runs.forEach((run, index) => {
|
|
188
|
+
if (run.letter === "y" || run.letter === "d") {
|
|
189
|
+
signals.hasDate = true;
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (run.letter === "h" || run.letter === "s" || run.letter === AMPM_LETTER) {
|
|
193
|
+
signals.hasTime = true;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (run.letter === "m") {
|
|
197
|
+
if (run.length <= 2 && monthRunIsMinutes(runs, index)) signals.hasTime = true;
|
|
198
|
+
else signals.hasDate = true;
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (run.letter === "e") {
|
|
202
|
+
const next = runs[index + 1];
|
|
203
|
+
signals.hasNumeric = signals.hasNumeric || next?.letter === "+" || next?.letter === "-";
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (run.letter === "%") {
|
|
207
|
+
signals.hasPercent = true;
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (run.letter === "@") {
|
|
211
|
+
signals.hasText = true;
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
if (NUMERIC_CODES.includes(run.letter)) {
|
|
215
|
+
signals.hasNumeric = true;
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (containsCurrencySymbol(run.letter)) signals.hasCurrency = true;
|
|
219
|
+
});
|
|
220
|
+
return signals;
|
|
221
|
+
}
|
|
222
|
+
function classifySection(section) {
|
|
223
|
+
const signals = collectSignals(section);
|
|
224
|
+
if (signals.hasElapsed) return { kind: "elapsedTime" };
|
|
225
|
+
if (signals.hasDate) return signals.hasTime ? { kind: "dateTime" } : { kind: "date" };
|
|
226
|
+
if (signals.hasTime) return { kind: "time" };
|
|
227
|
+
if (signals.hasPercent) return { kind: "percentage" };
|
|
228
|
+
if (signals.hasCurrency) {
|
|
229
|
+
const code = signals.currencyCode;
|
|
230
|
+
return code === void 0 ? { kind: "currency" } : {
|
|
231
|
+
kind: "currency",
|
|
232
|
+
code
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
if (signals.hasText && !signals.hasNumeric) return { kind: "text" };
|
|
236
|
+
return PLAIN_NUMBER;
|
|
237
|
+
}
|
|
238
|
+
function classifyNumberFormat(formatCode) {
|
|
239
|
+
const first = splitNumberFormatSections(tokenizeNumberFormat(formatCode))[0];
|
|
240
|
+
return first === void 0 ? PLAIN_NUMBER : classifySection(first);
|
|
241
|
+
}
|
|
242
|
+
const BUILTIN_NUMBER_FORMATS = /* @__PURE__ */ new Map([
|
|
243
|
+
[0, "General"],
|
|
244
|
+
[1, "0"],
|
|
245
|
+
[2, "0.00"],
|
|
246
|
+
[3, "#,##0"],
|
|
247
|
+
[4, "#,##0.00"],
|
|
248
|
+
[5, "$#,##0_);($#,##0)"],
|
|
249
|
+
[6, "$#,##0_);[Red]($#,##0)"],
|
|
250
|
+
[7, "$#,##0.00_);($#,##0.00)"],
|
|
251
|
+
[8, "$#,##0.00_);[Red]($#,##0.00)"],
|
|
252
|
+
[9, "0%"],
|
|
253
|
+
[10, "0.00%"],
|
|
254
|
+
[11, "0.00E+00"],
|
|
255
|
+
[12, "# ?/?"],
|
|
256
|
+
[13, "# ??/??"],
|
|
257
|
+
[14, "mm-dd-yy"],
|
|
258
|
+
[15, "d-mmm-yy"],
|
|
259
|
+
[16, "d-mmm"],
|
|
260
|
+
[17, "mmm-yy"],
|
|
261
|
+
[18, "h:mm AM/PM"],
|
|
262
|
+
[19, "h:mm:ss AM/PM"],
|
|
263
|
+
[20, "h:mm"],
|
|
264
|
+
[21, "h:mm:ss"],
|
|
265
|
+
[22, "m/d/yy h:mm"],
|
|
266
|
+
[37, "#,##0 ;(#,##0)"],
|
|
267
|
+
[38, "#,##0 ;[Red](#,##0)"],
|
|
268
|
+
[39, "#,##0.00;(#,##0.00)"],
|
|
269
|
+
[40, "#,##0.00;[Red](#,##0.00)"],
|
|
270
|
+
[41, "_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)"],
|
|
271
|
+
[42, "_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)"],
|
|
272
|
+
[43, "_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)"],
|
|
273
|
+
[44, "_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)"],
|
|
274
|
+
[45, "mm:ss"],
|
|
275
|
+
[46, "[h]:mm:ss"],
|
|
276
|
+
[47, "mmss.0"],
|
|
277
|
+
[48, "##0.0E+0"],
|
|
278
|
+
[49, "@"]
|
|
279
|
+
]);
|
|
280
|
+
const PERCENTAGE_NUMBER_FORMAT = {
|
|
281
|
+
kind: "builtin",
|
|
282
|
+
id: 10
|
|
283
|
+
};
|
|
284
|
+
const TIME_NUMBER_FORMAT = {
|
|
285
|
+
kind: "builtin",
|
|
286
|
+
id: 21
|
|
287
|
+
};
|
|
288
|
+
const AMOUNT_NUMBER_FORMAT = {
|
|
289
|
+
kind: "builtin",
|
|
290
|
+
id: 4
|
|
291
|
+
};
|
|
292
|
+
const DATE_NUMBER_FORMAT = {
|
|
293
|
+
kind: "custom",
|
|
294
|
+
code: "yyyy\\-mm\\-dd"
|
|
295
|
+
};
|
|
296
|
+
const DATE_TIME_NUMBER_FORMAT = {
|
|
297
|
+
kind: "custom",
|
|
298
|
+
code: "yyyy\\-mm\\-dd hh:mm:ss"
|
|
299
|
+
};
|
|
300
|
+
const BOOLEAN_NUMBER_FORMAT = {
|
|
301
|
+
kind: "custom",
|
|
302
|
+
code: "\"TRUE\";\"TRUE\";\"FALSE\""
|
|
303
|
+
};
|
|
304
|
+
function currencyNumberFormat(code) {
|
|
305
|
+
if (code === void 0 || !isIsoCurrencyCodeShape(code)) return AMOUNT_NUMBER_FORMAT;
|
|
306
|
+
return {
|
|
307
|
+
kind: "custom",
|
|
308
|
+
code: `[$${code.toUpperCase()}]#,##0.00`
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
//#endregion
|
|
312
|
+
export { AMOUNT_NUMBER_FORMAT, BOOLEAN_NUMBER_FORMAT, BUILTIN_NUMBER_FORMATS, DATE_NUMBER_FORMAT, DATE_TIME_NUMBER_FORMAT, MAX_NUMBER_FORMAT_SECTIONS, PERCENTAGE_NUMBER_FORMAT, TIME_NUMBER_FORMAT, classifyNumberFormat, currencyNumberFormat, splitNumberFormatSections, tokenizeNumberFormat };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_typed_util = require("../util.cjs");
|
|
3
|
+
const require_typed_xlsx_util = require("./util.cjs");
|
|
4
|
+
//#region src/typed/xlsx/serial.ts
|
|
5
|
+
const MS_PER_DAY = 864e5;
|
|
6
|
+
const MS_PER_HOUR = 36e5;
|
|
7
|
+
const MS_PER_MINUTE = 6e4;
|
|
8
|
+
const MS_PER_SECOND = 1e3;
|
|
9
|
+
const WORKBOOK_PATH = "xl/workbook.xml";
|
|
10
|
+
function readDate1904(pkg) {
|
|
11
|
+
const workbook = require_typed_util.rootElement(pkg.parts[WORKBOOK_PATH]);
|
|
12
|
+
if (workbook === void 0) return false;
|
|
13
|
+
const workbookPr = require_typed_util.childrenWithTag(workbook, "workbookPr")[0];
|
|
14
|
+
return workbookPr !== void 0 && require_typed_xlsx_util.readXmlBool(require_typed_util.attr(workbookPr, "date1904"));
|
|
15
|
+
}
|
|
16
|
+
const PHANTOM_LEAP_DAY_SERIAL = 60;
|
|
17
|
+
const ORIGIN_1900_BELOW_PHANTOM_UTC_MS = Date.UTC(1899, 11, 31);
|
|
18
|
+
const ORIGIN_1900_ABOVE_PHANTOM_UTC_MS = Date.UTC(1899, 11, 30);
|
|
19
|
+
const ORIGIN_1904_UTC_MS = Date.UTC(1904, 0, 1);
|
|
20
|
+
function splitSerial(serial) {
|
|
21
|
+
const days = Math.floor(serial);
|
|
22
|
+
const msWithinDay = Math.round((serial - days) * MS_PER_DAY);
|
|
23
|
+
return msWithinDay >= MS_PER_DAY ? {
|
|
24
|
+
days: days + 1,
|
|
25
|
+
msWithinDay: 0
|
|
26
|
+
} : {
|
|
27
|
+
days,
|
|
28
|
+
msWithinDay
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function pad(value, length) {
|
|
32
|
+
return String(value).padStart(length, "0");
|
|
33
|
+
}
|
|
34
|
+
function isoDateOfUtcMs(ms) {
|
|
35
|
+
const date = new Date(ms);
|
|
36
|
+
return `${pad(date.getUTCFullYear(), 4)}-${pad(date.getUTCMonth() + 1, 2)}-${pad(date.getUTCDate(), 2)}`;
|
|
37
|
+
}
|
|
38
|
+
function isoDateOfDayCount(days, date1904) {
|
|
39
|
+
if (days < 0) return;
|
|
40
|
+
if (date1904) return isoDateOfUtcMs(ORIGIN_1904_UTC_MS + days * MS_PER_DAY);
|
|
41
|
+
if (days === PHANTOM_LEAP_DAY_SERIAL) return;
|
|
42
|
+
return isoDateOfUtcMs((days < PHANTOM_LEAP_DAY_SERIAL ? ORIGIN_1900_BELOW_PHANTOM_UTC_MS : ORIGIN_1900_ABOVE_PHANTOM_UTC_MS) + days * MS_PER_DAY);
|
|
43
|
+
}
|
|
44
|
+
function isoTimeOfMsWithinDay(msWithinDay) {
|
|
45
|
+
const hours = Math.floor(msWithinDay / MS_PER_HOUR);
|
|
46
|
+
const minutes = Math.floor(msWithinDay % MS_PER_HOUR / MS_PER_MINUTE);
|
|
47
|
+
const seconds = Math.floor(msWithinDay % MS_PER_MINUTE / MS_PER_SECOND);
|
|
48
|
+
return `${pad(hours, 2)}:${pad(minutes, 2)}:${pad(seconds, 2)}`;
|
|
49
|
+
}
|
|
50
|
+
function serialToIsoDate(serial, date1904) {
|
|
51
|
+
return Number.isFinite(serial) ? isoDateOfDayCount(splitSerial(serial).days, date1904) : void 0;
|
|
52
|
+
}
|
|
53
|
+
function serialToIsoTime(serial) {
|
|
54
|
+
return Number.isFinite(serial) && serial >= 0 ? isoTimeOfMsWithinDay(splitSerial(serial).msWithinDay) : void 0;
|
|
55
|
+
}
|
|
56
|
+
function serialToIsoDateTime(serial, date1904) {
|
|
57
|
+
if (!Number.isFinite(serial)) return;
|
|
58
|
+
const { days, msWithinDay } = splitSerial(serial);
|
|
59
|
+
const date = isoDateOfDayCount(days, date1904);
|
|
60
|
+
return date === void 0 ? void 0 : `${date}T${isoTimeOfMsWithinDay(msWithinDay)}`;
|
|
61
|
+
}
|
|
62
|
+
const ISO_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
63
|
+
const ISO_TIME_PATTERN = /^(\d{2}):(\d{2}):(\d{2})$/;
|
|
64
|
+
const ISO_DATE_TIME_SEPARATOR = "T";
|
|
65
|
+
function utcMsOfCalendarDate(year, month, day) {
|
|
66
|
+
const utcMs = Date.UTC(year, month - 1, day);
|
|
67
|
+
const date = new Date(utcMs);
|
|
68
|
+
return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day ? utcMs : void 0;
|
|
69
|
+
}
|
|
70
|
+
function dayCountOfUtcMs(utcMs) {
|
|
71
|
+
const abovePhantom = (utcMs - ORIGIN_1900_ABOVE_PHANTOM_UTC_MS) / MS_PER_DAY;
|
|
72
|
+
if (abovePhantom > PHANTOM_LEAP_DAY_SERIAL) return abovePhantom;
|
|
73
|
+
const belowPhantom = (utcMs - ORIGIN_1900_BELOW_PHANTOM_UTC_MS) / MS_PER_DAY;
|
|
74
|
+
return belowPhantom >= 0 ? belowPhantom : void 0;
|
|
75
|
+
}
|
|
76
|
+
function isoDateToSerial(iso) {
|
|
77
|
+
const match = ISO_DATE_PATTERN.exec(iso);
|
|
78
|
+
if (match === null) return;
|
|
79
|
+
const [, year, month, day] = match;
|
|
80
|
+
if (year === void 0 || month === void 0 || day === void 0) return;
|
|
81
|
+
const utcMs = utcMsOfCalendarDate(Number.parseInt(year, 10), Number.parseInt(month, 10), Number.parseInt(day, 10));
|
|
82
|
+
return utcMs === void 0 ? void 0 : dayCountOfUtcMs(utcMs);
|
|
83
|
+
}
|
|
84
|
+
function isoTimeToSerial(iso) {
|
|
85
|
+
const match = ISO_TIME_PATTERN.exec(iso);
|
|
86
|
+
if (match === null) return;
|
|
87
|
+
const [, hours, minutes, seconds] = match;
|
|
88
|
+
if (hours === void 0 || minutes === void 0 || seconds === void 0) return;
|
|
89
|
+
const hourCount = Number.parseInt(hours, 10);
|
|
90
|
+
const minuteCount = Number.parseInt(minutes, 10);
|
|
91
|
+
const secondCount = Number.parseInt(seconds, 10);
|
|
92
|
+
if (hourCount > 23 || minuteCount > 59 || secondCount > 59) return;
|
|
93
|
+
return (hourCount * MS_PER_HOUR + minuteCount * MS_PER_MINUTE + secondCount * MS_PER_SECOND) / MS_PER_DAY;
|
|
94
|
+
}
|
|
95
|
+
function isoDateTimeToSerial(iso) {
|
|
96
|
+
const separatorIndex = iso.indexOf(ISO_DATE_TIME_SEPARATOR);
|
|
97
|
+
if (separatorIndex === -1) return;
|
|
98
|
+
const days = isoDateToSerial(iso.slice(0, separatorIndex));
|
|
99
|
+
const fractionOfDay = isoTimeToSerial(iso.slice(separatorIndex + 1));
|
|
100
|
+
return days === void 0 || fractionOfDay === void 0 ? void 0 : days + fractionOfDay;
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
exports.isoDateTimeToSerial = isoDateTimeToSerial;
|
|
104
|
+
exports.isoDateToSerial = isoDateToSerial;
|
|
105
|
+
exports.isoTimeToSerial = isoTimeToSerial;
|
|
106
|
+
exports.readDate1904 = readDate1904;
|
|
107
|
+
exports.serialToIsoDate = serialToIsoDate;
|
|
108
|
+
exports.serialToIsoDateTime = serialToIsoDateTime;
|
|
109
|
+
exports.serialToIsoTime = serialToIsoTime;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { r as Package } from "../../package-L24lkba-.cjs";
|
|
2
|
+
//#region src/typed/xlsx/serial.d.ts
|
|
3
|
+
declare function readDate1904(pkg: Package): boolean;
|
|
4
|
+
declare function serialToIsoDate(serial: number, date1904: boolean): string | undefined;
|
|
5
|
+
declare function serialToIsoTime(serial: number): string | undefined;
|
|
6
|
+
declare function serialToIsoDateTime(serial: number, date1904: boolean): string | undefined;
|
|
7
|
+
declare function isoDateToSerial(iso: string): number | undefined;
|
|
8
|
+
declare function isoTimeToSerial(iso: string): number | undefined;
|
|
9
|
+
declare function isoDateTimeToSerial(iso: string): number | undefined;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { isoDateTimeToSerial, isoDateToSerial, isoTimeToSerial, readDate1904, serialToIsoDate, serialToIsoDateTime, serialToIsoTime };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { r as Package } from "../../package-BUojjTXf.js";
|
|
2
|
+
//#region src/typed/xlsx/serial.d.ts
|
|
3
|
+
declare function readDate1904(pkg: Package): boolean;
|
|
4
|
+
declare function serialToIsoDate(serial: number, date1904: boolean): string | undefined;
|
|
5
|
+
declare function serialToIsoTime(serial: number): string | undefined;
|
|
6
|
+
declare function serialToIsoDateTime(serial: number, date1904: boolean): string | undefined;
|
|
7
|
+
declare function isoDateToSerial(iso: string): number | undefined;
|
|
8
|
+
declare function isoTimeToSerial(iso: string): number | undefined;
|
|
9
|
+
declare function isoDateTimeToSerial(iso: string): number | undefined;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { isoDateTimeToSerial, isoDateToSerial, isoTimeToSerial, readDate1904, serialToIsoDate, serialToIsoDateTime, serialToIsoTime };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { attr, childrenWithTag, rootElement } from "../util.js";
|
|
2
|
+
import { readXmlBool } from "./util.js";
|
|
3
|
+
//#region src/typed/xlsx/serial.ts
|
|
4
|
+
const MS_PER_DAY = 864e5;
|
|
5
|
+
const MS_PER_HOUR = 36e5;
|
|
6
|
+
const MS_PER_MINUTE = 6e4;
|
|
7
|
+
const MS_PER_SECOND = 1e3;
|
|
8
|
+
const WORKBOOK_PATH = "xl/workbook.xml";
|
|
9
|
+
function readDate1904(pkg) {
|
|
10
|
+
const workbook = rootElement(pkg.parts[WORKBOOK_PATH]);
|
|
11
|
+
if (workbook === void 0) return false;
|
|
12
|
+
const workbookPr = childrenWithTag(workbook, "workbookPr")[0];
|
|
13
|
+
return workbookPr !== void 0 && readXmlBool(attr(workbookPr, "date1904"));
|
|
14
|
+
}
|
|
15
|
+
const PHANTOM_LEAP_DAY_SERIAL = 60;
|
|
16
|
+
const ORIGIN_1900_BELOW_PHANTOM_UTC_MS = Date.UTC(1899, 11, 31);
|
|
17
|
+
const ORIGIN_1900_ABOVE_PHANTOM_UTC_MS = Date.UTC(1899, 11, 30);
|
|
18
|
+
const ORIGIN_1904_UTC_MS = Date.UTC(1904, 0, 1);
|
|
19
|
+
function splitSerial(serial) {
|
|
20
|
+
const days = Math.floor(serial);
|
|
21
|
+
const msWithinDay = Math.round((serial - days) * MS_PER_DAY);
|
|
22
|
+
return msWithinDay >= MS_PER_DAY ? {
|
|
23
|
+
days: days + 1,
|
|
24
|
+
msWithinDay: 0
|
|
25
|
+
} : {
|
|
26
|
+
days,
|
|
27
|
+
msWithinDay
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function pad(value, length) {
|
|
31
|
+
return String(value).padStart(length, "0");
|
|
32
|
+
}
|
|
33
|
+
function isoDateOfUtcMs(ms) {
|
|
34
|
+
const date = new Date(ms);
|
|
35
|
+
return `${pad(date.getUTCFullYear(), 4)}-${pad(date.getUTCMonth() + 1, 2)}-${pad(date.getUTCDate(), 2)}`;
|
|
36
|
+
}
|
|
37
|
+
function isoDateOfDayCount(days, date1904) {
|
|
38
|
+
if (days < 0) return;
|
|
39
|
+
if (date1904) return isoDateOfUtcMs(ORIGIN_1904_UTC_MS + days * MS_PER_DAY);
|
|
40
|
+
if (days === PHANTOM_LEAP_DAY_SERIAL) return;
|
|
41
|
+
return isoDateOfUtcMs((days < PHANTOM_LEAP_DAY_SERIAL ? ORIGIN_1900_BELOW_PHANTOM_UTC_MS : ORIGIN_1900_ABOVE_PHANTOM_UTC_MS) + days * MS_PER_DAY);
|
|
42
|
+
}
|
|
43
|
+
function isoTimeOfMsWithinDay(msWithinDay) {
|
|
44
|
+
const hours = Math.floor(msWithinDay / MS_PER_HOUR);
|
|
45
|
+
const minutes = Math.floor(msWithinDay % MS_PER_HOUR / MS_PER_MINUTE);
|
|
46
|
+
const seconds = Math.floor(msWithinDay % MS_PER_MINUTE / MS_PER_SECOND);
|
|
47
|
+
return `${pad(hours, 2)}:${pad(minutes, 2)}:${pad(seconds, 2)}`;
|
|
48
|
+
}
|
|
49
|
+
function serialToIsoDate(serial, date1904) {
|
|
50
|
+
return Number.isFinite(serial) ? isoDateOfDayCount(splitSerial(serial).days, date1904) : void 0;
|
|
51
|
+
}
|
|
52
|
+
function serialToIsoTime(serial) {
|
|
53
|
+
return Number.isFinite(serial) && serial >= 0 ? isoTimeOfMsWithinDay(splitSerial(serial).msWithinDay) : void 0;
|
|
54
|
+
}
|
|
55
|
+
function serialToIsoDateTime(serial, date1904) {
|
|
56
|
+
if (!Number.isFinite(serial)) return;
|
|
57
|
+
const { days, msWithinDay } = splitSerial(serial);
|
|
58
|
+
const date = isoDateOfDayCount(days, date1904);
|
|
59
|
+
return date === void 0 ? void 0 : `${date}T${isoTimeOfMsWithinDay(msWithinDay)}`;
|
|
60
|
+
}
|
|
61
|
+
const ISO_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
62
|
+
const ISO_TIME_PATTERN = /^(\d{2}):(\d{2}):(\d{2})$/;
|
|
63
|
+
const ISO_DATE_TIME_SEPARATOR = "T";
|
|
64
|
+
function utcMsOfCalendarDate(year, month, day) {
|
|
65
|
+
const utcMs = Date.UTC(year, month - 1, day);
|
|
66
|
+
const date = new Date(utcMs);
|
|
67
|
+
return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day ? utcMs : void 0;
|
|
68
|
+
}
|
|
69
|
+
function dayCountOfUtcMs(utcMs) {
|
|
70
|
+
const abovePhantom = (utcMs - ORIGIN_1900_ABOVE_PHANTOM_UTC_MS) / MS_PER_DAY;
|
|
71
|
+
if (abovePhantom > PHANTOM_LEAP_DAY_SERIAL) return abovePhantom;
|
|
72
|
+
const belowPhantom = (utcMs - ORIGIN_1900_BELOW_PHANTOM_UTC_MS) / MS_PER_DAY;
|
|
73
|
+
return belowPhantom >= 0 ? belowPhantom : void 0;
|
|
74
|
+
}
|
|
75
|
+
function isoDateToSerial(iso) {
|
|
76
|
+
const match = ISO_DATE_PATTERN.exec(iso);
|
|
77
|
+
if (match === null) return;
|
|
78
|
+
const [, year, month, day] = match;
|
|
79
|
+
if (year === void 0 || month === void 0 || day === void 0) return;
|
|
80
|
+
const utcMs = utcMsOfCalendarDate(Number.parseInt(year, 10), Number.parseInt(month, 10), Number.parseInt(day, 10));
|
|
81
|
+
return utcMs === void 0 ? void 0 : dayCountOfUtcMs(utcMs);
|
|
82
|
+
}
|
|
83
|
+
function isoTimeToSerial(iso) {
|
|
84
|
+
const match = ISO_TIME_PATTERN.exec(iso);
|
|
85
|
+
if (match === null) return;
|
|
86
|
+
const [, hours, minutes, seconds] = match;
|
|
87
|
+
if (hours === void 0 || minutes === void 0 || seconds === void 0) return;
|
|
88
|
+
const hourCount = Number.parseInt(hours, 10);
|
|
89
|
+
const minuteCount = Number.parseInt(minutes, 10);
|
|
90
|
+
const secondCount = Number.parseInt(seconds, 10);
|
|
91
|
+
if (hourCount > 23 || minuteCount > 59 || secondCount > 59) return;
|
|
92
|
+
return (hourCount * MS_PER_HOUR + minuteCount * MS_PER_MINUTE + secondCount * MS_PER_SECOND) / MS_PER_DAY;
|
|
93
|
+
}
|
|
94
|
+
function isoDateTimeToSerial(iso) {
|
|
95
|
+
const separatorIndex = iso.indexOf(ISO_DATE_TIME_SEPARATOR);
|
|
96
|
+
if (separatorIndex === -1) return;
|
|
97
|
+
const days = isoDateToSerial(iso.slice(0, separatorIndex));
|
|
98
|
+
const fractionOfDay = isoTimeToSerial(iso.slice(separatorIndex + 1));
|
|
99
|
+
return days === void 0 || fractionOfDay === void 0 ? void 0 : days + fractionOfDay;
|
|
100
|
+
}
|
|
101
|
+
//#endregion
|
|
102
|
+
export { isoDateTimeToSerial, isoDateToSerial, isoTimeToSerial, readDate1904, serialToIsoDate, serialToIsoDateTime, serialToIsoTime };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_typed_util = require("../util.cjs");
|
|
3
|
+
const require_typed_xlsx_number_format = require("./number-format.cjs");
|
|
4
|
+
//#region src/typed/xlsx/styles.ts
|
|
5
|
+
const STYLES_PATH = "xl/styles.xml";
|
|
6
|
+
const GENERAL_NUM_FMT_ID = 0;
|
|
7
|
+
function readNumberFormatCodesById(styleSheet) {
|
|
8
|
+
const codes = new Map(require_typed_xlsx_number_format.BUILTIN_NUMBER_FORMATS);
|
|
9
|
+
const numFmtsEl = require_typed_util.childrenWithTag(styleSheet, "numFmts")[0];
|
|
10
|
+
if (numFmtsEl === void 0) return codes;
|
|
11
|
+
for (const numFmt of require_typed_util.childrenWithTag(numFmtsEl, "numFmt")) {
|
|
12
|
+
const idRaw = require_typed_util.attr(numFmt, "numFmtId");
|
|
13
|
+
const formatCode = require_typed_util.attr(numFmt, "formatCode");
|
|
14
|
+
if (idRaw === void 0 || formatCode === void 0) continue;
|
|
15
|
+
const id = Number.parseInt(idRaw, 10);
|
|
16
|
+
if (Number.isInteger(id)) codes.set(id, require_typed_util.decodeEntities(formatCode));
|
|
17
|
+
}
|
|
18
|
+
return codes;
|
|
19
|
+
}
|
|
20
|
+
function readCellFormatCodes(pkg) {
|
|
21
|
+
const styleSheet = require_typed_util.rootElement(pkg.parts[STYLES_PATH]);
|
|
22
|
+
if (styleSheet === void 0) return [];
|
|
23
|
+
const cellXfsEl = require_typed_util.childrenWithTag(styleSheet, "cellXfs")[0];
|
|
24
|
+
if (cellXfsEl === void 0) return [];
|
|
25
|
+
const codes = readNumberFormatCodesById(styleSheet);
|
|
26
|
+
return require_typed_util.childrenWithTag(cellXfsEl, "xf").map((xf) => {
|
|
27
|
+
const raw = require_typed_util.attr(xf, "numFmtId");
|
|
28
|
+
const id = raw === void 0 ? 0 : Number.parseInt(raw, 10);
|
|
29
|
+
return Number.isInteger(id) ? codes.get(id) : void 0;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const FIRST_CUSTOM_NUM_FMT_ID = 164;
|
|
33
|
+
const DEFAULT_CELL_FORMAT_INDEX = 0;
|
|
34
|
+
function signatureOf(format) {
|
|
35
|
+
return format.kind === "builtin" ? `builtin:${format.id}` : `custom:${format.code}`;
|
|
36
|
+
}
|
|
37
|
+
var CellFormatTable = class {
|
|
38
|
+
indexBySignature = /* @__PURE__ */ new Map([[signatureOf({
|
|
39
|
+
kind: "builtin",
|
|
40
|
+
id: 0
|
|
41
|
+
}), 0]]);
|
|
42
|
+
numFmtIdByIndex = [0];
|
|
43
|
+
declared = [];
|
|
44
|
+
intern(format) {
|
|
45
|
+
const signature = signatureOf(format);
|
|
46
|
+
const existing = this.indexBySignature.get(signature);
|
|
47
|
+
if (existing !== void 0) return existing;
|
|
48
|
+
const numFmtId = format.kind === "builtin" ? format.id : this.declare(format.code);
|
|
49
|
+
const index = this.numFmtIdByIndex.length;
|
|
50
|
+
this.numFmtIdByIndex.push(numFmtId);
|
|
51
|
+
this.indexBySignature.set(signature, index);
|
|
52
|
+
return index;
|
|
53
|
+
}
|
|
54
|
+
declarations() {
|
|
55
|
+
return this.declared;
|
|
56
|
+
}
|
|
57
|
+
cellFormats() {
|
|
58
|
+
return this.numFmtIdByIndex;
|
|
59
|
+
}
|
|
60
|
+
declare(code) {
|
|
61
|
+
const id = FIRST_CUSTOM_NUM_FMT_ID + this.declared.length;
|
|
62
|
+
this.declared.push({
|
|
63
|
+
id,
|
|
64
|
+
code
|
|
65
|
+
});
|
|
66
|
+
return id;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
//#endregion
|
|
70
|
+
exports.CellFormatTable = CellFormatTable;
|
|
71
|
+
exports.DEFAULT_CELL_FORMAT_INDEX = DEFAULT_CELL_FORMAT_INDEX;
|
|
72
|
+
exports.GENERAL_NUM_FMT_ID = GENERAL_NUM_FMT_ID;
|
|
73
|
+
exports.readCellFormatCodes = readCellFormatCodes;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { r as Package } from "../../package-L24lkba-.cjs";
|
|
2
|
+
import { CellNumberFormat } from "./number-format.cjs";
|
|
3
|
+
//#region src/typed/xlsx/styles.d.ts
|
|
4
|
+
declare const GENERAL_NUM_FMT_ID = 0;
|
|
5
|
+
declare function readCellFormatCodes(pkg: Package): readonly (string | undefined)[];
|
|
6
|
+
declare const DEFAULT_CELL_FORMAT_INDEX = 0;
|
|
7
|
+
interface DeclaredNumberFormat {
|
|
8
|
+
id: number;
|
|
9
|
+
code: string;
|
|
10
|
+
}
|
|
11
|
+
declare class CellFormatTable {
|
|
12
|
+
private readonly indexBySignature;
|
|
13
|
+
private readonly numFmtIdByIndex;
|
|
14
|
+
private readonly declared;
|
|
15
|
+
intern(format: CellNumberFormat): number;
|
|
16
|
+
declarations(): readonly DeclaredNumberFormat[];
|
|
17
|
+
cellFormats(): readonly number[];
|
|
18
|
+
private declare;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { CellFormatTable, DEFAULT_CELL_FORMAT_INDEX, DeclaredNumberFormat, GENERAL_NUM_FMT_ID, readCellFormatCodes };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { r as Package } from "../../package-BUojjTXf.js";
|
|
2
|
+
import { CellNumberFormat } from "./number-format.js";
|
|
3
|
+
//#region src/typed/xlsx/styles.d.ts
|
|
4
|
+
declare const GENERAL_NUM_FMT_ID = 0;
|
|
5
|
+
declare function readCellFormatCodes(pkg: Package): readonly (string | undefined)[];
|
|
6
|
+
declare const DEFAULT_CELL_FORMAT_INDEX = 0;
|
|
7
|
+
interface DeclaredNumberFormat {
|
|
8
|
+
id: number;
|
|
9
|
+
code: string;
|
|
10
|
+
}
|
|
11
|
+
declare class CellFormatTable {
|
|
12
|
+
private readonly indexBySignature;
|
|
13
|
+
private readonly numFmtIdByIndex;
|
|
14
|
+
private readonly declared;
|
|
15
|
+
intern(format: CellNumberFormat): number;
|
|
16
|
+
declarations(): readonly DeclaredNumberFormat[];
|
|
17
|
+
cellFormats(): readonly number[];
|
|
18
|
+
private declare;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { CellFormatTable, DEFAULT_CELL_FORMAT_INDEX, DeclaredNumberFormat, GENERAL_NUM_FMT_ID, readCellFormatCodes };
|