@shbernal/ts-xlsx 2.0.0 → 3.0.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 +20 -10
- package/dist/bytes.d.ts +24 -0
- package/dist/bytes.js +34 -0
- package/dist/core/address.d.ts +26 -4
- package/dist/core/address.js +21 -9
- package/dist/core/autofilter.d.ts +12 -1
- package/dist/core/autofilter.js +35 -12
- package/dist/core/axis-handle.d.ts +8 -0
- package/dist/core/axis-handle.js +14 -0
- package/dist/core/cell.d.ts +24 -0
- package/dist/core/cell.js +9 -1
- package/dist/core/color-resolution.d.ts +1 -1
- package/dist/core/color-resolution.js +7 -8
- package/dist/core/column.d.ts +4 -1
- package/dist/core/column.js +31 -35
- package/dist/core/conditional-formatting-overlay.d.ts +5 -0
- package/dist/core/conditional-formatting-overlay.js +11 -0
- package/dist/core/conditional-formatting.d.ts +45 -5
- package/dist/core/conditional-formatting.js +74 -0
- package/dist/core/data-validation-overlay.d.ts +11 -0
- package/dist/core/data-validation-overlay.js +21 -2
- package/dist/core/data-validation.d.ts +9 -2
- package/dist/core/data-validation.js +26 -0
- package/dist/core/grid-edits.d.ts +16 -0
- package/dist/core/grid-edits.js +26 -8
- package/dist/core/grid-shift.d.ts +19 -0
- package/dist/core/grid-shift.js +8 -0
- package/dist/core/image.d.ts +2 -0
- package/dist/core/image.js +2 -0
- package/dist/core/merge-index.d.ts +31 -0
- package/dist/core/merge-index.js +60 -0
- package/dist/core/merge.d.ts +12 -11
- package/dist/core/merge.js +36 -10
- package/dist/core/page-setup.d.ts +86 -2
- package/dist/core/page-setup.js +34 -1
- package/dist/core/pivot-table.d.ts +2 -0
- package/dist/core/pivot-table.js +23 -18
- package/dist/core/protection.d.ts +3 -0
- package/dist/core/protection.js +20 -14
- package/dist/core/row-input.d.ts +7 -0
- package/dist/core/row-input.js +10 -8
- package/dist/core/row.d.ts +4 -1
- package/dist/core/row.js +19 -23
- package/dist/core/style.d.ts +78 -7
- package/dist/core/style.js +90 -80
- package/dist/core/table.d.ts +26 -12
- package/dist/core/table.js +67 -33
- package/dist/core/theme.d.ts +3 -1
- package/dist/core/theme.js +4 -0
- package/dist/core/used-extent.d.ts +44 -0
- package/dist/core/used-extent.js +102 -0
- package/dist/core/workbook.d.ts +2 -2
- package/dist/core/worksheet-comments.d.ts +8 -0
- package/dist/core/worksheet-comments.js +18 -0
- package/dist/core/worksheet.d.ts +31 -7
- package/dist/core/worksheet.js +72 -86
- package/dist/customui/ribbon.js +23 -24
- package/dist/entries/core.d.ts +3 -3
- package/dist/entries/csv.d.ts +1 -1
- package/dist/entries/node-unavailable.d.ts +15 -0
- package/dist/entries/node-unavailable.js +20 -0
- package/dist/entries/node.d.ts +1 -0
- package/dist/entries/node.js +1 -0
- package/dist/entries/xlsx.d.ts +0 -1
- package/dist/entries/xlsx.js +0 -1
- package/dist/io/csv/read.js +1 -1
- package/dist/io/csv/write.d.ts +12 -2
- package/dist/io/csv/write.js +17 -2
- package/dist/io/opc/inflate.js +3 -13
- package/dist/io/opc/part-paths.d.ts +1 -0
- package/dist/io/opc/part-paths.js +15 -0
- package/dist/io/opc/read-opc.d.ts +22 -3
- package/dist/io/opc/read-opc.js +11 -39
- package/dist/io/opc/rels.d.ts +12 -6
- package/dist/io/opc/rels.js +3 -5
- package/dist/io/style/xf-style.d.ts +33 -4
- package/dist/io/style/xf-style.js +12 -1
- package/dist/io/xlsb/read-styles.js +6 -3
- package/dist/io/xlsb/read.d.ts +1 -1
- package/dist/io/xlsb/read.js +5 -8
- package/dist/io/xlsx/cell-accumulator.d.ts +2 -4
- package/dist/io/xlsx/cell-accumulator.js +20 -58
- package/dist/io/xlsx/cell-value.d.ts +1 -1
- package/dist/io/xlsx/cell-value.js +7 -4
- package/dist/io/xlsx/color-xml.d.ts +1 -1
- package/dist/io/xlsx/color-xml.js +8 -7
- package/dist/io/xlsx/comments.js +6 -3
- package/dist/io/xlsx/conditional-formatting.d.ts +4 -3
- package/dist/io/xlsx/conditional-formatting.js +81 -65
- package/dist/io/xlsx/data-validation.d.ts +10 -8
- package/dist/io/xlsx/data-validation.js +44 -41
- package/dist/io/xlsx/edit-vba.js +4 -11
- package/dist/io/xlsx/hyperlinks.d.ts +4 -2
- package/dist/io/xlsx/hyperlinks.js +26 -31
- package/dist/io/xlsx/images.js +33 -35
- package/dist/io/xlsx/package-plan.d.ts +9 -1
- package/dist/io/xlsx/package-plan.js +29 -16
- package/dist/io/xlsx/part-names.d.ts +41 -0
- package/dist/io/xlsx/part-names.js +46 -0
- package/dist/io/xlsx/read-pivot.js +4 -9
- package/dist/io/xlsx/read-rows.js +12 -13
- package/dist/io/xlsx/read-shared-strings.js +9 -47
- package/dist/io/xlsx/read-styles.d.ts +1 -1
- package/dist/io/xlsx/read-styles.js +65 -43
- package/dist/io/xlsx/read-worksheet.d.ts +10 -1
- package/dist/io/xlsx/read-worksheet.js +48 -63
- package/dist/io/xlsx/read.d.ts +3 -4
- package/dist/io/xlsx/read.js +124 -146
- package/dist/io/xlsx/rich-runs.d.ts +41 -7
- package/dist/io/xlsx/rich-runs.js +95 -30
- package/dist/io/xlsx/sheet-properties.d.ts +1 -1
- package/dist/io/xlsx/sheet-properties.js +23 -26
- package/dist/io/xlsx/styles.d.ts +3 -15
- package/dist/io/xlsx/styles.js +83 -105
- package/dist/io/xlsx/tables.js +14 -13
- package/dist/io/xlsx/theme-xml.js +8 -5
- package/dist/io/xlsx/threaded-comments.js +20 -19
- package/dist/io/xlsx/workbook-xml.js +43 -36
- package/dist/io/xlsx/worksheet-xml.d.ts +1 -1
- package/dist/io/xlsx/worksheet-xml.js +47 -52
- package/dist/io/xlsx/write-stream.d.ts +14 -1
- package/dist/io/xlsx/write-stream.js +40 -33
- package/dist/io/xlsx/write.d.ts +5 -0
- package/dist/io/xlsx/write.js +155 -131
- package/dist/sha512.d.ts +2 -0
- package/dist/sha512.js +146 -0
- package/dist/token-set.d.ts +15 -0
- package/dist/token-set.js +4 -0
- package/dist/vba/bytes.d.ts +1 -2
- package/dist/vba/bytes.js +1 -12
- package/dist/vba/cfb-format.d.ts +24 -0
- package/dist/vba/cfb-format.js +12 -0
- package/dist/vba/cfb-writer.js +17 -17
- package/dist/vba/cfb.js +1 -7
- package/dist/vba/dir-records.d.ts +53 -0
- package/dist/vba/dir-records.js +28 -0
- package/dist/vba/ms-ovba.js +32 -11
- package/dist/vba/project-editor.js +5 -34
- package/dist/vba/project.js +15 -31
- package/dist/vba/vba-encoding.js +1 -1
- package/dist/xml/xml-read.d.ts +117 -72
- package/dist/xml/xml-read.js +123 -169
- package/dist/xml/xml-scan.d.ts +100 -0
- package/dist/xml/xml-scan.js +208 -0
- package/dist/xml/xml.d.ts +44 -2
- package/dist/xml/xml.js +17 -5
- package/package.json +22 -6
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { XmlParseError } from './errors.js';
|
|
2
|
+
const PREDEFINED_ENTITIES = new Map([
|
|
3
|
+
['amp', '&'],
|
|
4
|
+
['lt', '<'],
|
|
5
|
+
['gt', '>'],
|
|
6
|
+
['quot', '"'],
|
|
7
|
+
['apos', "'"],
|
|
8
|
+
]);
|
|
9
|
+
const ENTITY = /&(#x[0-9a-fA-F]+|#[0-9]+|[a-zA-Z][a-zA-Z0-9]*);/g;
|
|
10
|
+
export function decodeEntities(value) {
|
|
11
|
+
if (!value.includes('&'))
|
|
12
|
+
return value;
|
|
13
|
+
return value.replace(ENTITY, (match, body) => {
|
|
14
|
+
if (body.charCodeAt(0) === 0x23) {
|
|
15
|
+
const codePoint = body.charCodeAt(1) === 0x78
|
|
16
|
+
? Number.parseInt(body.slice(2), 16)
|
|
17
|
+
: Number.parseInt(body.slice(1), 10);
|
|
18
|
+
if (!Number.isInteger(codePoint) || codePoint < 0 || codePoint > 0x10ffff)
|
|
19
|
+
return match;
|
|
20
|
+
try {
|
|
21
|
+
return String.fromCodePoint(codePoint);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return match;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return PREDEFINED_ENTITIES.get(body) ?? match;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export function decodeSpreadsheetText(value) {
|
|
31
|
+
if (!value.includes('_'))
|
|
32
|
+
return value;
|
|
33
|
+
return value.replace(/_x([0-9A-Fa-f]{4})_/g, (_match, hex) => String.fromCharCode(Number.parseInt(hex, 16)));
|
|
34
|
+
}
|
|
35
|
+
const ATTRIBUTE = /([^\s=/>]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
|
|
36
|
+
export function parseAttributes(source) {
|
|
37
|
+
const attrs = Object.create(null);
|
|
38
|
+
ATTRIBUTE.lastIndex = 0;
|
|
39
|
+
let match = ATTRIBUTE.exec(source);
|
|
40
|
+
while (match !== null) {
|
|
41
|
+
const value = match[2] ?? match[3] ?? '';
|
|
42
|
+
attrs[match[1]] = decodeEntities(value);
|
|
43
|
+
match = ATTRIBUTE.exec(source);
|
|
44
|
+
}
|
|
45
|
+
return attrs;
|
|
46
|
+
}
|
|
47
|
+
function findTagEnd(source, start) {
|
|
48
|
+
let quote = '';
|
|
49
|
+
for (let i = start + 1; i < source.length; i++) {
|
|
50
|
+
const ch = source[i];
|
|
51
|
+
if (quote !== '') {
|
|
52
|
+
if (ch === quote)
|
|
53
|
+
quote = '';
|
|
54
|
+
}
|
|
55
|
+
else if (ch === '"' || ch === "'") {
|
|
56
|
+
quote = ch;
|
|
57
|
+
}
|
|
58
|
+
else if (ch === '>') {
|
|
59
|
+
return i;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
throw new XmlParseError('unterminated tag: missing ">"');
|
|
63
|
+
}
|
|
64
|
+
function skipDeclaration(source, start) {
|
|
65
|
+
let depth = 0;
|
|
66
|
+
for (let i = start; i < source.length; i++) {
|
|
67
|
+
const ch = source[i];
|
|
68
|
+
if (ch === '[')
|
|
69
|
+
depth++;
|
|
70
|
+
else if (ch === ']')
|
|
71
|
+
depth--;
|
|
72
|
+
else if (ch === '>' && depth <= 0)
|
|
73
|
+
return i + 1;
|
|
74
|
+
}
|
|
75
|
+
throw new XmlParseError('unterminated markup declaration: missing ">"');
|
|
76
|
+
}
|
|
77
|
+
export function markupAt(source, lt) {
|
|
78
|
+
if (source.startsWith('<!--', lt)) {
|
|
79
|
+
const end = source.indexOf('-->', lt + 4);
|
|
80
|
+
if (end === -1)
|
|
81
|
+
throw new XmlParseError('unterminated comment');
|
|
82
|
+
return { kind: 'comment', next: end + 3 };
|
|
83
|
+
}
|
|
84
|
+
if (source.startsWith('<![CDATA[', lt)) {
|
|
85
|
+
const end = source.indexOf(']]>', lt + 9);
|
|
86
|
+
if (end === -1)
|
|
87
|
+
throw new XmlParseError('unterminated CDATA section');
|
|
88
|
+
return { kind: 'cdata', contentStart: lt + 9, contentEnd: end, next: end + 3 };
|
|
89
|
+
}
|
|
90
|
+
if (source.startsWith('<?', lt)) {
|
|
91
|
+
const end = source.indexOf('?>', lt + 2);
|
|
92
|
+
if (end === -1)
|
|
93
|
+
throw new XmlParseError('unterminated processing instruction');
|
|
94
|
+
return { kind: 'pi', next: end + 2 };
|
|
95
|
+
}
|
|
96
|
+
if (source.startsWith('<!', lt))
|
|
97
|
+
return { kind: 'declaration', next: skipDeclaration(source, lt) };
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
export function tagAt(source, lt) {
|
|
101
|
+
const gt = findTagEnd(source, lt);
|
|
102
|
+
const raw = source.slice(lt + 1, gt);
|
|
103
|
+
const next = gt + 1;
|
|
104
|
+
if (raw.charCodeAt(0) === 0x2f) {
|
|
105
|
+
return { close: true, name: raw.slice(1).trim(), attrSource: '', selfClosing: false, next };
|
|
106
|
+
}
|
|
107
|
+
const selfClosing = raw.charCodeAt(raw.length - 1) === 0x2f;
|
|
108
|
+
const body = selfClosing ? raw.slice(0, -1) : raw;
|
|
109
|
+
const nameEnd = firstWhitespace(body);
|
|
110
|
+
return {
|
|
111
|
+
close: false,
|
|
112
|
+
name: nameEnd === -1 ? body : body.slice(0, nameEnd),
|
|
113
|
+
attrSource: nameEnd === -1 ? '' : body.slice(nameEnd),
|
|
114
|
+
selfClosing,
|
|
115
|
+
next,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
export function* xmlEvents(source) {
|
|
119
|
+
const length = source.length;
|
|
120
|
+
let i = 0;
|
|
121
|
+
while (i < length) {
|
|
122
|
+
const lt = source.indexOf('<', i);
|
|
123
|
+
if (lt === -1) {
|
|
124
|
+
const chunk = source.slice(i);
|
|
125
|
+
if (chunk.length > 0)
|
|
126
|
+
yield { kind: 'text', text: decodeEntities(normalizeLineEndings(chunk)) };
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (lt > i) {
|
|
130
|
+
const chunk = source.slice(i, lt);
|
|
131
|
+
if (chunk.length > 0)
|
|
132
|
+
yield { kind: 'text', text: decodeEntities(normalizeLineEndings(chunk)) };
|
|
133
|
+
}
|
|
134
|
+
const markup = markupAt(source, lt);
|
|
135
|
+
if (markup !== undefined) {
|
|
136
|
+
if (markup.kind === 'cdata') {
|
|
137
|
+
yield { kind: 'text', text: source.slice(markup.contentStart, markup.contentEnd) };
|
|
138
|
+
}
|
|
139
|
+
i = markup.next;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const tag = tagAt(source, lt);
|
|
143
|
+
yield tag.close
|
|
144
|
+
? { kind: 'close', name: tag.name }
|
|
145
|
+
: {
|
|
146
|
+
kind: 'open',
|
|
147
|
+
name: tag.name,
|
|
148
|
+
attrs: parseAttributes(tag.attrSource),
|
|
149
|
+
selfClosing: tag.selfClosing,
|
|
150
|
+
};
|
|
151
|
+
i = tag.next;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function normalizeLineEndings(chunk) {
|
|
155
|
+
if (!chunk.includes('\r'))
|
|
156
|
+
return chunk;
|
|
157
|
+
return chunk.replace(/\r\n?/g, '\n');
|
|
158
|
+
}
|
|
159
|
+
function firstWhitespace(source) {
|
|
160
|
+
for (let i = 0; i < source.length; i++) {
|
|
161
|
+
const code = source.charCodeAt(i);
|
|
162
|
+
if (code === 0x20 || code === 0x09 || code === 0x0a || code === 0x0d)
|
|
163
|
+
return i;
|
|
164
|
+
}
|
|
165
|
+
return -1;
|
|
166
|
+
}
|
|
167
|
+
export function localName(qualified) {
|
|
168
|
+
const colon = qualified.indexOf(':');
|
|
169
|
+
return colon === -1 ? qualified : qualified.slice(colon + 1);
|
|
170
|
+
}
|
|
171
|
+
export function boolPresent(val) {
|
|
172
|
+
return val === undefined || (val !== '0' && val !== 'false');
|
|
173
|
+
}
|
|
174
|
+
export function boolStrict(val) {
|
|
175
|
+
return val === '1' || val === 'true';
|
|
176
|
+
}
|
|
177
|
+
export function boolTristate(val) {
|
|
178
|
+
if (val === '1' || val === 'true')
|
|
179
|
+
return true;
|
|
180
|
+
if (val === '0' || val === 'false')
|
|
181
|
+
return false;
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
export function numInteger(val, min = -Number.MAX_SAFE_INTEGER) {
|
|
185
|
+
const n = parseAttrNumber(val);
|
|
186
|
+
if (n === undefined || !Number.isSafeInteger(n) || n < min)
|
|
187
|
+
return undefined;
|
|
188
|
+
return n;
|
|
189
|
+
}
|
|
190
|
+
export function numFinite(val, min = -Infinity) {
|
|
191
|
+
const n = parseAttrNumber(val);
|
|
192
|
+
if (n === undefined || n < min)
|
|
193
|
+
return undefined;
|
|
194
|
+
return n;
|
|
195
|
+
}
|
|
196
|
+
function parseAttrNumber(val) {
|
|
197
|
+
if (val === undefined || val.trim() === '')
|
|
198
|
+
return undefined;
|
|
199
|
+
const n = Number(val);
|
|
200
|
+
return Number.isFinite(n) ? n : undefined;
|
|
201
|
+
}
|
|
202
|
+
export function coerceNumericLiteral(text) {
|
|
203
|
+
const trimmed = text.trim();
|
|
204
|
+
return /^-?\d+(?:\.\d+)?$/.test(trimmed) ? Number(trimmed) : text;
|
|
205
|
+
}
|
|
206
|
+
export function enumToken(val, isMember) {
|
|
207
|
+
return val !== undefined && isMember(val) ? val : undefined;
|
|
208
|
+
}
|
package/dist/xml/xml.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export declare function escapeAttr(value: string): string;
|
|
|
25
25
|
* `escapeText` runs last and sees no unrepresentable character left, so its guard is a
|
|
26
26
|
* standing proof that the escape was complete rather than a second check of the same thing.
|
|
27
27
|
*
|
|
28
|
-
* Reversed by `decodeSpreadsheetText` in `./xml-
|
|
28
|
+
* Reversed by `decodeSpreadsheetText` in `./xml-scan.ts`, whose single left-to-right pass is what
|
|
29
29
|
* makes the `_x005F_` step above reversible. Change either and read its comment first.
|
|
30
30
|
*/
|
|
31
31
|
export declare function escapeSpreadsheetText(value: string): string;
|
|
@@ -50,11 +50,53 @@ export declare function stripFormulaEquals(value: string | number): string;
|
|
|
50
50
|
* entirely: the two-state-plus-absent contract every flag writer here shares.
|
|
51
51
|
*/
|
|
52
52
|
export declare function boolAttr(name: string, value: boolean | undefined): string;
|
|
53
|
+
/**
|
|
54
|
+
* A free-string attribute rendered with a leading space (` name="a & b"`), or '' when the value
|
|
55
|
+
* is undefined. The third of the trio with {@link boolAttr} and {@link numAttr}: the value is prose
|
|
56
|
+
* the caller chose, so it is escaped rather than checked.
|
|
57
|
+
*
|
|
58
|
+
* A token from a closed OOXML enumeration is the other case and goes through {@link checkedToken}
|
|
59
|
+
* instead. Escaping a bogus token would produce a well-formed document that Excel still rejects,
|
|
60
|
+
* which hides the mistake in the file rather than raising it at the call.
|
|
61
|
+
*/
|
|
62
|
+
export declare function textAttr(name: string, value: string | undefined): string;
|
|
63
|
+
/**
|
|
64
|
+
* Refuse a token from a closed OOXML enumeration that the writer would otherwise emit verbatim, and
|
|
65
|
+
* return it unchanged when it belongs. The public types already forbid an out-of-contract value, so
|
|
66
|
+
* this fires only for one smuggled past them by an untyped caller, a `JSON.parse`, or a cast.
|
|
67
|
+
*
|
|
68
|
+
* The writer must never serialise such a value: it would be schema-invalid OOXML that Excel
|
|
69
|
+
* sometimes tolerates yet the library's own reader, which narrows every such token through the same
|
|
70
|
+
* guard, discards on read-back. Refusing at the write boundary keeps the two symmetric, garbage out
|
|
71
|
+
* refused exactly as garbage in, so a value the writer accepts is always one that round-trips.
|
|
72
|
+
*
|
|
73
|
+
* @throws {AuthoringError} naming the value and the enumeration.
|
|
74
|
+
*/
|
|
75
|
+
export declare function checkedToken(value: string, isValid: (candidate: string) => boolean, kind: string): string;
|
|
53
76
|
/**
|
|
54
77
|
* A numeric attribute rendered with a leading space (` name="42"`), or '' when the value is undefined
|
|
55
78
|
* so that a count an author never set stays out of the element rather than fabricating a default.
|
|
79
|
+
*
|
|
80
|
+
* The value goes through {@link numberText}, so a non-finite one is refused here rather than written
|
|
81
|
+
* as `NaN`. Every attribute on this path is `xsd:double` or `xsd:unsignedInt`, neither of which has a
|
|
82
|
+
* spelling for it, so the alternative is a package Excel reports as damaged.
|
|
83
|
+
*
|
|
84
|
+
* @throws {AuthoringError} when the value is not finite.
|
|
85
|
+
*/
|
|
86
|
+
export declare function numAttr(name: string, value: number | undefined): string;
|
|
87
|
+
/**
|
|
88
|
+
* Refuse a number OOXML cannot spell. Every numeric attribute in the format is `xsd:double`,
|
|
89
|
+
* `xsd:unsignedInt` or a bounded flavour of one, and none of those lexical spaces has a form for a
|
|
90
|
+
* NaN or an infinity, so a value that reaches the file as `NaN` is a package Excel reports as
|
|
91
|
+
* damaged.
|
|
92
|
+
*
|
|
93
|
+
* Exported for the callers that must refuse before they write. A number can be unwritable and still
|
|
94
|
+
* be read on the way to the bytes: compared, summed, walked. A comparison against `NaN` or an
|
|
95
|
+
* infinity silently takes the wrong branch long before the value would have been serialised.
|
|
96
|
+
*
|
|
97
|
+
* @throws {AuthoringError} naming the value.
|
|
56
98
|
*/
|
|
57
|
-
export declare function
|
|
99
|
+
export declare function assertWritableNumber(value: number): void;
|
|
58
100
|
/**
|
|
59
101
|
* A finite number serialises as its shortest round-trippable decimal; a non-finite one
|
|
60
102
|
* has no OOXML numeric representation, so the writer refuses it rather than emit `NaN`.
|
package/dist/xml/xml.js
CHANGED
|
@@ -55,13 +55,25 @@ export function stripFormulaEquals(value) {
|
|
|
55
55
|
export function boolAttr(name, value) {
|
|
56
56
|
return value === undefined ? '' : ` ${name}="${value ? 1 : 0}"`;
|
|
57
57
|
}
|
|
58
|
-
export function
|
|
59
|
-
return value === undefined ? '' : ` ${name}="${value}"`;
|
|
58
|
+
export function textAttr(name, value) {
|
|
59
|
+
return value === undefined ? '' : ` ${name}="${escapeAttr(value)}"`;
|
|
60
60
|
}
|
|
61
|
-
export function
|
|
62
|
-
if (!
|
|
63
|
-
throw new AuthoringError(`
|
|
61
|
+
export function checkedToken(value, isValid, kind) {
|
|
62
|
+
if (!isValid(value)) {
|
|
63
|
+
throw new AuthoringError(`Invalid ${kind} ${JSON.stringify(value)}: not a value the OOXML enumeration allows`);
|
|
64
64
|
}
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
export function numAttr(name, value) {
|
|
68
|
+
return value === undefined ? '' : ` ${name}="${numberText(value)}"`;
|
|
69
|
+
}
|
|
70
|
+
export function assertWritableNumber(value) {
|
|
71
|
+
if (Number.isFinite(value))
|
|
72
|
+
return;
|
|
73
|
+
throw new AuthoringError(`cannot write a non-finite number (${value}): it has no OOXML representation`);
|
|
74
|
+
}
|
|
75
|
+
export function numberText(value) {
|
|
76
|
+
assertWritableNumber(value);
|
|
65
77
|
return String(value);
|
|
66
78
|
}
|
|
67
79
|
export const XML_DECLARATION = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shbernal/ts-xlsx",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "A TypeScript-first library for reading and writing xlsx (OOXML) spreadsheets.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"csv",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"workbook",
|
|
13
13
|
"xlsx"
|
|
14
14
|
],
|
|
15
|
-
"homepage": "https://github.
|
|
15
|
+
"homepage": "https://shbernal.github.io/ts-xlsx/",
|
|
16
16
|
"bugs": {
|
|
17
17
|
"url": "https://github.com/shbernal/ts-xlsx/issues"
|
|
18
18
|
},
|
|
@@ -61,6 +61,11 @@
|
|
|
61
61
|
"types": "./dist/entries/customui.d.ts",
|
|
62
62
|
"default": "./dist/entries/customui.js"
|
|
63
63
|
},
|
|
64
|
+
"./node": {
|
|
65
|
+
"types": "./dist/entries/node.d.ts",
|
|
66
|
+
"browser": "./dist/entries/node-unavailable.js",
|
|
67
|
+
"default": "./dist/entries/node.js"
|
|
68
|
+
},
|
|
64
69
|
"./errors": {
|
|
65
70
|
"types": "./dist/entries/errors.d.ts",
|
|
66
71
|
"default": "./dist/entries/errors.js"
|
|
@@ -72,18 +77,24 @@
|
|
|
72
77
|
},
|
|
73
78
|
"scripts": {
|
|
74
79
|
"prepare": "node scripts/install-hooks.ts",
|
|
75
|
-
"
|
|
76
|
-
"build": "pnpm run clean && tsc -p tsconfig.build.json && tsc -p tsconfig.build.dts.json",
|
|
80
|
+
"build": "node scripts/build.ts",
|
|
77
81
|
"size": "node scripts/size-budget.ts",
|
|
78
82
|
"smoke:dist": "node scripts/smoke-dist.ts",
|
|
83
|
+
"site:prepare": "node www/scripts/sync-docs.ts",
|
|
84
|
+
"site:check": "node www/scripts/check.ts",
|
|
85
|
+
"samples:check": "node www/scripts/check-samples.ts",
|
|
86
|
+
"site:dev": "pnpm run site:prepare && vitepress dev www",
|
|
87
|
+
"site:build": "pnpm run site:prepare && vitepress build www && node www/scripts/check-built-links.ts",
|
|
88
|
+
"site:preview": "vitepress preview www",
|
|
79
89
|
"docs": "node scripts/gen-docs.ts",
|
|
80
90
|
"docs:check": "node scripts/gen-docs.ts && git add --intent-to-add -- docs/api && git diff --exit-code -- docs/api",
|
|
81
91
|
"constitution:check": "node scripts/check-constitution.ts",
|
|
82
92
|
"layering:check": "node scripts/check-layering.ts",
|
|
83
93
|
"entries:check": "node scripts/check-entries.ts",
|
|
94
|
+
"browser:check": "node scripts/check-browser-safe.ts",
|
|
84
95
|
"source-text:check": "node scripts/check-source-text.ts",
|
|
85
96
|
"chars:check": "charcheck",
|
|
86
|
-
"lint": "node node_modules/oxlint/bin/oxlint src scripts test tools charcheck.config.ts --type-aware --deny-warnings --report-unused-disable-directives",
|
|
97
|
+
"lint": "node node_modules/oxlint/bin/oxlint src scripts test tools www charcheck.config.ts --type-aware --deny-warnings --report-unused-disable-directives",
|
|
87
98
|
"lint:fix": "pnpm run lint --fix",
|
|
88
99
|
"format": "node scripts/format.ts --write",
|
|
89
100
|
"format:check": "node scripts/format.ts --check",
|
|
@@ -91,7 +102,9 @@
|
|
|
91
102
|
"typecheck:src": "tsc --noEmit -p tsconfig.json",
|
|
92
103
|
"typecheck:test": "tsc --noEmit -p tsconfig.test.json",
|
|
93
104
|
"typecheck:dist": "tsc --noEmit -p tsconfig.dist.json",
|
|
105
|
+
"typecheck:site": "tsc --noEmit -p www/tsconfig.json",
|
|
94
106
|
"test:src": "node --test \"src/**/*.test.ts\"",
|
|
107
|
+
"test:site": "node --test \"www/**/*.test.ts\"",
|
|
95
108
|
"coverage": "node scripts/coverage.ts",
|
|
96
109
|
"corpus": "node test/corpus/run.ts",
|
|
97
110
|
"corpus:dist": "node test/corpus/run.ts --target dist",
|
|
@@ -114,7 +127,10 @@
|
|
|
114
127
|
"oxfmt": "^0.64.0",
|
|
115
128
|
"oxlint": "^1.80.0",
|
|
116
129
|
"oxlint-tsgolint": "7.0.2001",
|
|
117
|
-
"
|
|
130
|
+
"shiki": "^4.4.3",
|
|
131
|
+
"typescript": "^7.0.2",
|
|
132
|
+
"vitepress": "^1.6.4",
|
|
133
|
+
"vue": "^3.5.41"
|
|
118
134
|
},
|
|
119
135
|
"engines": {
|
|
120
136
|
"node": ">=24"
|