@shbernal/ts-xlsx 1.3.1 → 2.1.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 +72 -3
- package/dist/core/address.js +50 -10
- package/dist/core/autofilter.d.ts +13 -2
- package/dist/core/autofilter.js +35 -10
- package/dist/core/cell.d.ts +17 -16
- package/dist/core/cell.js +3 -7
- package/dist/core/color-resolution.d.ts +8 -8
- package/dist/core/color-resolution.js +7 -8
- package/dist/core/column.d.ts +8 -9
- package/dist/core/column.js +2 -4
- package/dist/core/comment-thread.d.ts +32 -23
- package/dist/core/comment-thread.js +4 -4
- package/dist/core/conditional-formatting-overlay.d.ts +6 -1
- package/dist/core/conditional-formatting-overlay.js +11 -0
- package/dist/core/conditional-formatting.d.ts +48 -8
- package/dist/core/conditional-formatting.js +88 -0
- package/dist/core/data-validation-overlay.d.ts +12 -1
- package/dist/core/data-validation-overlay.js +21 -2
- package/dist/core/data-validation.d.ts +12 -5
- package/dist/core/data-validation.js +34 -0
- package/dist/core/date.d.ts +3 -3
- package/dist/core/formula.d.ts +6 -6
- package/dist/core/grid-edits.d.ts +16 -0
- package/dist/core/grid-edits.js +29 -11
- package/dist/core/grid-shift.d.ts +19 -0
- package/dist/core/grid-shift.js +8 -0
- package/dist/core/image.d.ts +39 -2
- package/dist/core/image.js +10 -0
- package/dist/core/internal.d.ts +9 -1
- package/dist/core/limits.d.ts +4 -4
- package/dist/core/merge.d.ts +17 -12
- package/dist/core/merge.js +36 -5
- package/dist/core/page-setup.d.ts +20 -6
- package/dist/core/page-setup.js +8 -1
- package/dist/core/pivot-table.d.ts +4 -4
- package/dist/core/pivot-table.js +29 -20
- package/dist/core/preserved.d.ts +3 -3
- package/dist/core/protection.d.ts +7 -4
- package/dist/core/protection.js +20 -14
- package/dist/core/range.d.ts +16 -14
- package/dist/core/range.js +5 -5
- package/dist/core/row-input.d.ts +9 -8
- package/dist/core/row-input.js +12 -10
- package/dist/core/row.d.ts +7 -8
- package/dist/core/row.js +2 -4
- package/dist/core/style.d.ts +41 -14
- package/dist/core/style.js +82 -67
- package/dist/core/table-style.d.ts +9 -9
- package/dist/core/table-style.js +1 -1
- package/dist/core/table.d.ts +53 -51
- package/dist/core/table.js +83 -41
- package/dist/core/theme.d.ts +16 -44
- package/dist/core/theme.js +6 -148
- package/dist/core/value.d.ts +7 -7
- package/dist/core/workbook-protection.d.ts +2 -2
- package/dist/core/workbook-styles.d.ts +26 -0
- package/dist/core/workbook-styles.js +48 -0
- package/dist/core/workbook-theme.d.ts +25 -0
- package/dist/core/workbook-theme.js +49 -0
- package/dist/core/workbook-vba.d.ts +17 -0
- package/dist/core/workbook-vba.js +79 -0
- package/dist/core/workbook.d.ts +133 -87
- package/dist/core/workbook.js +74 -133
- package/dist/core/worksheet-comments.d.ts +17 -0
- package/dist/core/worksheet-comments.js +70 -0
- package/dist/core/worksheet-model.d.ts +4 -4
- package/dist/core/worksheet-model.js +1 -0
- package/dist/core/worksheet-pictures.d.ts +29 -0
- package/dist/core/worksheet-pictures.js +42 -0
- package/dist/core/worksheet.d.ts +100 -79
- package/dist/core/worksheet.js +63 -142
- package/dist/customui/errors.d.ts +1 -1
- package/dist/customui/ribbon.d.ts +3 -3
- package/dist/customui/ribbon.js +24 -23
- package/dist/entries/core.d.ts +7 -7
- package/dist/entries/core.js +1 -1
- 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/vba.d.ts +1 -1
- package/dist/entries/vba.js +1 -1
- package/dist/entries/xlsx.d.ts +1 -1
- package/dist/entries/xlsx.js +1 -1
- package/dist/errors.d.ts +12 -12
- package/dist/io/csv/read.js +2 -3
- package/dist/io/csv/write.d.ts +19 -4
- package/dist/io/csv/write.js +34 -4
- package/dist/io/opc/errors.d.ts +6 -6
- package/dist/io/opc/inflate.d.ts +1 -1
- package/dist/io/opc/inflate.js +2 -12
- package/dist/io/opc/namespaces.d.ts +1 -1
- package/dist/io/opc/read-opc.d.ts +19 -3
- package/dist/io/opc/read-opc.js +14 -8
- package/dist/io/opc/read-options.d.ts +2 -2
- package/dist/io/opc/rels.d.ts +11 -0
- package/dist/io/opc/rels.js +3 -2
- package/dist/io/opc/sniff-format.d.ts +2 -2
- package/dist/io/style/xf-style.d.ts +44 -7
- package/dist/io/style/xf-style.js +27 -0
- package/dist/io/xlsb/errors.d.ts +1 -1
- package/dist/io/xlsb/formula.d.ts +4 -4
- package/dist/io/xlsb/primitives.d.ts +8 -8
- package/dist/io/xlsb/ptg-functions.d.ts +1 -1
- package/dist/io/xlsb/read-styles.js +2 -20
- package/dist/io/xlsb/read.d.ts +2 -2
- package/dist/io/xlsx/cell-accumulator.d.ts +26 -9
- package/dist/io/xlsx/cell-accumulator.js +89 -46
- package/dist/io/xlsx/cell-value.d.ts +3 -3
- package/dist/io/xlsx/cell-value.js +9 -6
- package/dist/io/xlsx/color-xml.d.ts +1 -1
- package/dist/io/xlsx/color-xml.js +18 -23
- package/dist/io/xlsx/comments.d.ts +5 -5
- package/dist/io/xlsx/comments.js +17 -8
- package/dist/io/xlsx/conditional-formatting.d.ts +4 -4
- package/dist/io/xlsx/conditional-formatting.js +64 -58
- package/dist/io/xlsx/data-validation.d.ts +3 -3
- package/dist/io/xlsx/data-validation.js +35 -33
- package/dist/io/xlsx/errors.d.ts +3 -3
- package/dist/io/xlsx/hyperlinks.d.ts +4 -2
- package/dist/io/xlsx/hyperlinks.js +10 -18
- package/dist/io/xlsx/images.d.ts +1 -1
- package/dist/io/xlsx/images.js +25 -28
- package/dist/io/xlsx/namespaces.d.ts +2 -2
- package/dist/io/xlsx/package-plan.js +5 -2
- package/dist/io/xlsx/read-pivot.js +4 -13
- package/dist/io/xlsx/read-rows.d.ts +13 -13
- package/dist/io/xlsx/read-rows.js +19 -55
- package/dist/io/xlsx/read-shared-strings.js +7 -44
- package/dist/io/xlsx/read-styles.d.ts +3 -3
- package/dist/io/xlsx/read-styles.js +42 -66
- package/dist/io/xlsx/read-worksheet.js +73 -129
- package/dist/io/xlsx/read.d.ts +4 -6
- package/dist/io/xlsx/read.js +104 -142
- package/dist/io/xlsx/rich-runs.d.ts +41 -7
- package/dist/io/xlsx/rich-runs.js +94 -30
- package/dist/io/xlsx/rich-text.d.ts +1 -1
- package/dist/io/xlsx/shared-strings.d.ts +2 -2
- package/dist/io/xlsx/sheet-properties.d.ts +1 -1
- package/dist/io/xlsx/sheet-properties.js +14 -10
- package/dist/io/xlsx/styles.d.ts +9 -22
- package/dist/io/xlsx/styles.js +65 -89
- package/dist/io/xlsx/tables.d.ts +2 -2
- package/dist/io/xlsx/tables.js +20 -25
- package/dist/io/xlsx/theme-xml.d.ts +37 -0
- package/dist/io/xlsx/theme-xml.js +145 -0
- package/dist/io/xlsx/threaded-comments.d.ts +18 -27
- package/dist/io/xlsx/threaded-comments.js +26 -38
- package/dist/io/xlsx/workbook-xml.js +14 -8
- package/dist/io/xlsx/worksheet-xml.d.ts +2 -2
- package/dist/io/xlsx/worksheet-xml.js +40 -48
- package/dist/io/xlsx/write-stream.d.ts +23 -16
- package/dist/io/xlsx/write-stream.js +13 -14
- package/dist/io/xlsx/write.d.ts +8 -7
- package/dist/io/xlsx/write.js +6 -3
- package/dist/io/xlsx/x14-ext.d.ts +1 -1
- package/dist/sha512.d.ts +2 -0
- package/dist/sha512.js +146 -0
- package/dist/vba/bytes.d.ts +11 -0
- package/dist/vba/bytes.js +29 -0
- package/dist/vba/cfb-writer.d.ts +1 -1
- package/dist/vba/cfb.d.ts +1 -1
- package/dist/vba/cfb.js +15 -51
- package/dist/vba/codepage.d.ts +2 -2
- package/dist/vba/dir-records.d.ts +53 -0
- package/dist/vba/dir-records.js +28 -0
- package/dist/vba/errors.d.ts +2 -2
- package/dist/vba/index.d.ts +2 -2
- package/dist/vba/index.js +2 -2
- package/dist/vba/ms-ovba.d.ts +1 -1
- package/dist/vba/ms-ovba.js +1 -3
- package/dist/vba/project-editor.d.ts +9 -9
- package/dist/vba/project-editor.js +6 -44
- package/dist/vba/project.d.ts +5 -5
- package/dist/vba/project.js +3 -28
- package/dist/vba/vba-encoding.d.ts +1 -1
- package/dist/xml/errors.d.ts +1 -1
- package/dist/xml/xml-read.d.ts +98 -9
- package/dist/xml/xml-read.js +70 -0
- package/dist/xml/xml.d.ts +74 -10
- package/dist/xml/xml.js +39 -7
- package/package.json +59 -36
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { boolStrict, coerceNumericLiteral, localName, parseXml } from '../../xml/xml-read.js';
|
|
1
|
+
import { isCfValueObjectType, isConditionalFormattingOperator, isConditionalFormattingType, isIconSetType, isCfTimePeriod, } from '../../core/conditional-formatting.js';
|
|
2
|
+
import { boolPresent, boolStrict, coerceNumericLiteral, enumToken, localName, numFinite, numInteger, parseXml, TextCapture, } from '../../xml/xml-read.js';
|
|
3
|
+
import { boolAttr, checkedToken, escapeAttr, escapeText, numberText, stripFormulaEquals, textAttr, } from '../../xml/xml.js';
|
|
3
4
|
import { colorAttrs, parseColor } from './color-xml.js';
|
|
4
5
|
import { CF_EXT_URI, DATABAR_LINK_EXT_URI, XM_NS } from './namespaces.js';
|
|
5
6
|
import { x14Ext } from './x14-ext.js';
|
|
@@ -61,7 +62,7 @@ function x14DataBarXml(ref, rule, guid) {
|
|
|
61
62
|
`</x14:cfRule><xm:sqref>${escapeText(ref)}</xm:sqref></x14:conditionalFormatting>`);
|
|
62
63
|
}
|
|
63
64
|
function x14CfvoXml(cfvo) {
|
|
64
|
-
const type =
|
|
65
|
+
const type = checkedToken(cfvo.type, isCfValueObjectType, 'conditional format value type');
|
|
65
66
|
if (cfvo.value === undefined)
|
|
66
67
|
return `<x14:cfvo type="${type}"/>`;
|
|
67
68
|
return `<x14:cfvo type="${type}"><xm:f>${escapeText(String(cfvo.value))}</xm:f></x14:cfvo>`;
|
|
@@ -71,12 +72,16 @@ function cfRuleExtLinkXml(guid) {
|
|
|
71
72
|
}
|
|
72
73
|
function blockXml(cf, styles, priority, extLinks) {
|
|
73
74
|
const rules = cf.rules.map((rule) => ruleXml(rule, styles, priority, extLinks)).join('');
|
|
75
|
+
if (rules === '')
|
|
76
|
+
return '';
|
|
74
77
|
return `<conditionalFormatting sqref="${escapeAttr(cf.ref)}">${rules}</conditionalFormatting>`;
|
|
75
78
|
}
|
|
76
79
|
function ruleXml(rule, styles, priority, extLinks) {
|
|
77
80
|
const p = rule.priority ?? priority.next;
|
|
78
81
|
priority.next = Math.max(priority.next, p) + 1;
|
|
79
|
-
const attrs = [
|
|
82
|
+
const attrs = [
|
|
83
|
+
`type="${checkedToken(rule.type, isConditionalFormattingType, 'conditional formatting type')}"`,
|
|
84
|
+
];
|
|
80
85
|
const dxfId = resolveDxfId(rule, styles);
|
|
81
86
|
if (dxfId !== undefined)
|
|
82
87
|
attrs.push(`dxfId="${dxfId}"`);
|
|
@@ -91,16 +96,18 @@ function ruleXml(rule, styles, priority, extLinks) {
|
|
|
91
96
|
attrs.push('bottom="1"');
|
|
92
97
|
if (rule.percent)
|
|
93
98
|
attrs.push('percent="1"');
|
|
94
|
-
if (rule.operator !== undefined)
|
|
95
|
-
attrs.push(`operator="${
|
|
99
|
+
if (rule.operator !== undefined) {
|
|
100
|
+
attrs.push(`operator="${checkedToken(rule.operator, isConditionalFormattingOperator, 'conditional formatting operator')}"`);
|
|
101
|
+
}
|
|
96
102
|
if (rule.text !== undefined)
|
|
97
103
|
attrs.push(`text="${escapeAttr(rule.text)}"`);
|
|
98
|
-
if (rule.timePeriod !== undefined)
|
|
99
|
-
attrs.push(`timePeriod="${
|
|
104
|
+
if (rule.timePeriod !== undefined) {
|
|
105
|
+
attrs.push(`timePeriod="${checkedToken(rule.timePeriod, isCfTimePeriod, 'time period')}"`);
|
|
106
|
+
}
|
|
100
107
|
if (rule.rank !== undefined)
|
|
101
|
-
attrs.push(`rank="${rule.rank}"`);
|
|
108
|
+
attrs.push(`rank="${numberText(rule.rank)}"`);
|
|
102
109
|
if (rule.stdDev !== undefined)
|
|
103
|
-
attrs.push(`stdDev="${rule.stdDev}"`);
|
|
110
|
+
attrs.push(`stdDev="${numberText(rule.stdDev)}"`);
|
|
104
111
|
let body = SCALE_TYPES.has(rule.type) ? scaleXml(rule) : formulaeXml(rule.formulae);
|
|
105
112
|
const extGuid = extLinks.get(rule);
|
|
106
113
|
if (extGuid !== undefined)
|
|
@@ -112,8 +119,9 @@ function ruleXml(rule, styles, priority, extLinks) {
|
|
|
112
119
|
function resolveDxfId(rule, styles) {
|
|
113
120
|
if (SCALE_TYPES.has(rule.type))
|
|
114
121
|
return undefined;
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
const preserved = dxfIndex(rule.dxfId);
|
|
123
|
+
if (preserved !== undefined)
|
|
124
|
+
return preserved;
|
|
117
125
|
if (rule.style !== undefined)
|
|
118
126
|
return styles.differentialStyleId(rule.style);
|
|
119
127
|
return undefined;
|
|
@@ -142,41 +150,41 @@ function colorScaleXml(rule) {
|
|
|
142
150
|
return `<colorScale>${anchors}${colors}</colorScale>`;
|
|
143
151
|
}
|
|
144
152
|
function iconSetXml(rule) {
|
|
145
|
-
const name = rule.iconSet
|
|
153
|
+
const name = rule.iconSet === undefined
|
|
154
|
+
? ''
|
|
155
|
+
: ` iconSet="${checkedToken(rule.iconSet, isIconSetType, 'icon set')}"`;
|
|
146
156
|
const anchors = (rule.cfvo ?? []).map(cfvoXml).join('');
|
|
147
157
|
return `<iconSet${name}>${anchors}</iconSet>`;
|
|
148
158
|
}
|
|
149
159
|
function cfvoXml(cfvo) {
|
|
150
|
-
const
|
|
151
|
-
|
|
160
|
+
const type = checkedToken(cfvo.type, isCfValueObjectType, 'conditional format value type');
|
|
161
|
+
const val = cfvo.value === undefined ? '' : textAttr('val', String(cfvo.value));
|
|
162
|
+
return `<cfvo type="${type}"${val}/>`;
|
|
152
163
|
}
|
|
153
164
|
export function parseConditionalFormattings(xml) {
|
|
154
165
|
const blocks = [];
|
|
155
166
|
let block;
|
|
156
167
|
let draft;
|
|
157
168
|
let scale;
|
|
158
|
-
|
|
159
|
-
let formulaText = '';
|
|
169
|
+
const formulaCapture = new TextCapture('formula');
|
|
160
170
|
const linked = [];
|
|
161
171
|
const extById = new Map();
|
|
162
172
|
let x14Ext;
|
|
163
173
|
let x14ExtId;
|
|
164
|
-
|
|
165
|
-
let x14IdText = '';
|
|
174
|
+
const x14IdCapture = new TextCapture('id');
|
|
166
175
|
parseXml(xml, {
|
|
167
176
|
onOpen(name, attrs, selfClosing) {
|
|
168
177
|
const ln = localName(name);
|
|
169
178
|
if (name.includes(':')) {
|
|
170
179
|
if (ln === 'id' && draft !== undefined) {
|
|
171
|
-
|
|
172
|
-
x14IdText = '';
|
|
180
|
+
x14IdCapture.open(ln, selfClosing);
|
|
173
181
|
}
|
|
174
182
|
else if (ln === 'cfRule') {
|
|
175
183
|
x14Ext = attrs.type === 'dataBar' && attrs.id !== undefined ? emptyExt() : undefined;
|
|
176
184
|
x14ExtId = attrs.id;
|
|
177
185
|
}
|
|
178
186
|
else if (x14Ext !== undefined && ln === 'dataBar') {
|
|
179
|
-
x14Ext.gradient = attrs.gradient
|
|
187
|
+
x14Ext.gradient = boolPresent(attrs.gradient);
|
|
180
188
|
}
|
|
181
189
|
else if (x14Ext !== undefined && ln === 'negativeFillColor') {
|
|
182
190
|
x14Ext.negativeFillColor = parseColor(attrs);
|
|
@@ -191,7 +199,9 @@ export function parseConditionalFormattings(xml) {
|
|
|
191
199
|
}
|
|
192
200
|
else if (ln === 'cfRule' && block !== undefined) {
|
|
193
201
|
if (selfClosing) {
|
|
194
|
-
|
|
202
|
+
const rule = finalizeRule(newDraft(attrs));
|
|
203
|
+
if (rule !== undefined)
|
|
204
|
+
block.rules.push(rule);
|
|
195
205
|
}
|
|
196
206
|
else {
|
|
197
207
|
draft = newDraft(attrs);
|
|
@@ -201,8 +211,8 @@ export function parseConditionalFormattings(xml) {
|
|
|
201
211
|
else if (draft !== undefined &&
|
|
202
212
|
(ln === 'dataBar' || ln === 'colorScale' || ln === 'iconSet')) {
|
|
203
213
|
scale = ln;
|
|
204
|
-
if (ln === 'iconSet'
|
|
205
|
-
draft.iconSet = attrs.iconSet;
|
|
214
|
+
if (ln === 'iconSet')
|
|
215
|
+
draft.iconSet = enumToken(attrs.iconSet, isIconSetType);
|
|
206
216
|
}
|
|
207
217
|
else if (draft !== undefined && ln === 'cfvo') {
|
|
208
218
|
draft.cfvo.push(parseCfvo(attrs));
|
|
@@ -215,23 +225,20 @@ export function parseConditionalFormattings(xml) {
|
|
|
215
225
|
draft.colors.push(color);
|
|
216
226
|
}
|
|
217
227
|
else if (draft !== undefined && ln === 'formula') {
|
|
218
|
-
|
|
219
|
-
formulaText = '';
|
|
228
|
+
formulaCapture.open(ln, selfClosing);
|
|
220
229
|
}
|
|
221
230
|
},
|
|
222
231
|
onText(chunk) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (capturingX14Id)
|
|
226
|
-
x14IdText += chunk;
|
|
232
|
+
formulaCapture.text(chunk);
|
|
233
|
+
x14IdCapture.text(chunk);
|
|
227
234
|
},
|
|
228
235
|
onClose(name) {
|
|
229
236
|
const ln = localName(name);
|
|
230
237
|
if (name.includes(':')) {
|
|
231
|
-
|
|
238
|
+
const id = x14IdCapture.close(ln);
|
|
239
|
+
if (id !== undefined) {
|
|
232
240
|
if (draft !== undefined)
|
|
233
|
-
draft.x14Id =
|
|
234
|
-
capturingX14Id = false;
|
|
241
|
+
draft.x14Id = id;
|
|
235
242
|
}
|
|
236
243
|
else if (ln === 'cfRule' && x14Ext !== undefined && x14ExtId !== undefined) {
|
|
237
244
|
extById.set(x14ExtId, x14Ext);
|
|
@@ -240,20 +247,22 @@ export function parseConditionalFormattings(xml) {
|
|
|
240
247
|
}
|
|
241
248
|
return;
|
|
242
249
|
}
|
|
243
|
-
|
|
250
|
+
const formula = formulaCapture.close(ln);
|
|
251
|
+
if (formula !== undefined) {
|
|
244
252
|
if (draft !== undefined)
|
|
245
|
-
draft.formulae.push(coerceNumericLiteral(
|
|
246
|
-
capturingFormula = false;
|
|
253
|
+
draft.formulae.push(coerceNumericLiteral(formula));
|
|
247
254
|
}
|
|
248
255
|
else if (ln === 'dataBar' || ln === 'colorScale' || ln === 'iconSet') {
|
|
249
256
|
scale = undefined;
|
|
250
257
|
}
|
|
251
258
|
else if (ln === 'cfRule' && draft !== undefined) {
|
|
252
259
|
const rule = finalizeRule(draft);
|
|
253
|
-
if (
|
|
254
|
-
block
|
|
255
|
-
|
|
256
|
-
|
|
260
|
+
if (rule !== undefined) {
|
|
261
|
+
if (block !== undefined)
|
|
262
|
+
block.rules.push(rule);
|
|
263
|
+
if (draft.x14Id !== undefined)
|
|
264
|
+
linked.push({ rule, id: draft.x14Id });
|
|
265
|
+
}
|
|
257
266
|
draft = undefined;
|
|
258
267
|
}
|
|
259
268
|
else if (ln === 'conditionalFormatting' && block !== undefined) {
|
|
@@ -287,17 +296,17 @@ export function parseDxfs(stylesXml) {
|
|
|
287
296
|
}
|
|
288
297
|
function newDraft(attrs) {
|
|
289
298
|
return {
|
|
290
|
-
type: attrs.type
|
|
291
|
-
priority:
|
|
299
|
+
type: enumToken(attrs.type, isConditionalFormattingType),
|
|
300
|
+
priority: numFinite(attrs.priority),
|
|
292
301
|
stopIfTrue: boolStrict(attrs.stopIfTrue),
|
|
293
|
-
operator: attrs.operator,
|
|
302
|
+
operator: enumToken(attrs.operator, isConditionalFormattingOperator),
|
|
294
303
|
text: attrs.text,
|
|
295
|
-
timePeriod: attrs.timePeriod,
|
|
296
|
-
rank:
|
|
297
|
-
stdDev:
|
|
304
|
+
timePeriod: enumToken(attrs.timePeriod, isCfTimePeriod),
|
|
305
|
+
rank: numFinite(attrs.rank),
|
|
306
|
+
stdDev: numFinite(attrs.stdDev),
|
|
298
307
|
percent: boolStrict(attrs.percent),
|
|
299
308
|
bottom: boolStrict(attrs.bottom),
|
|
300
|
-
aboveAverage: attrs.aboveAverage === undefined ? undefined : attrs.aboveAverage
|
|
309
|
+
aboveAverage: attrs.aboveAverage === undefined ? undefined : boolPresent(attrs.aboveAverage),
|
|
301
310
|
equalAverage: boolStrict(attrs.equalAverage),
|
|
302
311
|
dxfId: parseIndexAttr(attrs.dxfId),
|
|
303
312
|
iconSet: undefined,
|
|
@@ -308,19 +317,15 @@ function newDraft(attrs) {
|
|
|
308
317
|
x14Id: undefined,
|
|
309
318
|
};
|
|
310
319
|
}
|
|
311
|
-
function
|
|
312
|
-
|
|
313
|
-
return undefined;
|
|
314
|
-
const n = Number(value);
|
|
315
|
-
return Number.isFinite(n) ? n : undefined;
|
|
320
|
+
function dxfIndex(value) {
|
|
321
|
+
return numInteger(value, 0);
|
|
316
322
|
}
|
|
317
323
|
function parseIndexAttr(value) {
|
|
318
|
-
|
|
319
|
-
return undefined;
|
|
320
|
-
const n = Number(value);
|
|
321
|
-
return Number.isInteger(n) && n >= 0 ? value : undefined;
|
|
324
|
+
return dxfIndex(value) === undefined ? undefined : value;
|
|
322
325
|
}
|
|
323
326
|
function finalizeRule(draft) {
|
|
327
|
+
if (draft.type === undefined)
|
|
328
|
+
return undefined;
|
|
324
329
|
const rule = { type: draft.type };
|
|
325
330
|
if (draft.priority !== undefined)
|
|
326
331
|
rule.priority = draft.priority;
|
|
@@ -359,7 +364,8 @@ function finalizeRule(draft) {
|
|
|
359
364
|
return rule;
|
|
360
365
|
}
|
|
361
366
|
function parseCfvo(attrs) {
|
|
362
|
-
const
|
|
367
|
+
const raw = attrs.type;
|
|
368
|
+
const type = raw !== undefined && isCfValueObjectType(raw) ? raw : 'num';
|
|
363
369
|
const cfvo = { type };
|
|
364
370
|
if (attrs.val !== undefined) {
|
|
365
371
|
cfvo.value = type === 'formula' ? attrs.val : coerceNumericLiteral(attrs.val);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type DataValidationEntry } from '../../core/data-validation.ts';
|
|
2
2
|
import type { Worksheet } from '../../core/worksheet.ts';
|
|
3
3
|
/** The standard `<dataValidations>` element for the rules stored in the legacy form, or '' when the
|
|
4
|
-
* sheet has none of them
|
|
4
|
+
* sheet has none of them, so a sheet with only extended (or no) validations stays byte-clean here.
|
|
5
5
|
* The extended rules are emitted separately by {@link dataValidationsExtXml}. */
|
|
6
6
|
export declare function dataValidationsXml(entries: readonly DataValidationEntry[]): string;
|
|
7
7
|
/** The `<ext>` carrying the extended (`<x14:dataValidation>`) rules, or '' when the sheet declares
|
|
8
8
|
* none. Emitted bare (no `<extLst>` wrapper) so the worksheet serialiser can gather it into a single
|
|
9
|
-
* `<extLst>` beside the conditional-formatting extension
|
|
9
|
+
* `<extLst>` beside the conditional-formatting extension: a worksheet may carry at most one. */
|
|
10
10
|
export declare function dataValidationsExtXml(entries: readonly DataValidationEntry[]): string;
|
|
11
11
|
/** Parse every standard `<dataValidation>` out of a worksheet part into range-bound rules. */
|
|
12
12
|
export declare function parseDataValidations(xml: string): DataValidationEntry[];
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { isDataValidationErrorStyle, isDataValidationOperator, isDataValidationType, } from '../../core/data-validation.js';
|
|
2
|
+
import { decodeSqrefRects } from '../../core/merge.js';
|
|
3
|
+
import { boolStrict, coerceNumericLiteral, localName, parseXml, TextCapture, } from '../../xml/xml-read.js';
|
|
4
|
+
import { checkedToken, escapeAttr, escapeText, stripFormulaEquals, textAttr } from '../../xml/xml.js';
|
|
3
5
|
import { DATA_VALIDATION_EXT_URI, XM_NS } from './namespaces.js';
|
|
4
6
|
import { x14Ext } from './x14-ext.js';
|
|
5
7
|
const TYPED = new Set(['whole', 'decimal', 'date', 'time', 'textLength']);
|
|
@@ -18,16 +20,20 @@ export function dataValidationsExtXml(entries) {
|
|
|
18
20
|
return x14Ext(DATA_VALIDATION_EXT_URI, `<x14:dataValidations count="${extended.length}" xmlns:xm="${XM_NS}">${items}</x14:dataValidations>`);
|
|
19
21
|
}
|
|
20
22
|
function ruleAttrs(rule) {
|
|
21
|
-
return (` type="${rule.type}"` +
|
|
22
|
-
(rule.errorStyle
|
|
23
|
-
|
|
23
|
+
return (` type="${checkedToken(rule.type, isDataValidationType, 'data validation type')}"` +
|
|
24
|
+
(rule.errorStyle === undefined
|
|
25
|
+
? ''
|
|
26
|
+
: ` errorStyle="${checkedToken(rule.errorStyle, isDataValidationErrorStyle, 'data validation error style')}"`) +
|
|
27
|
+
(rule.operator === undefined
|
|
28
|
+
? ''
|
|
29
|
+
: ` operator="${checkedToken(rule.operator, isDataValidationOperator, 'data validation operator')}"`) +
|
|
24
30
|
(rule.allowBlank ? ' allowBlank="1"' : '') +
|
|
25
31
|
(rule.showInputMessage ? ' showInputMessage="1"' : '') +
|
|
26
32
|
(rule.showErrorMessage ? ' showErrorMessage="1"' : '') +
|
|
27
|
-
(
|
|
28
|
-
(
|
|
29
|
-
(
|
|
30
|
-
(
|
|
33
|
+
textAttr('errorTitle', rule.errorTitle) +
|
|
34
|
+
textAttr('error', rule.error) +
|
|
35
|
+
textAttr('promptTitle', rule.promptTitle) +
|
|
36
|
+
textAttr('prompt', rule.prompt));
|
|
31
37
|
}
|
|
32
38
|
function dataValidationXml(sqref, rule) {
|
|
33
39
|
const [f1, f2] = operands(rule);
|
|
@@ -100,11 +106,12 @@ function buildEntry(attrs, formulae) {
|
|
|
100
106
|
}
|
|
101
107
|
function buildRule(attrs, formulae) {
|
|
102
108
|
const { type } = attrs;
|
|
103
|
-
if (type === undefined)
|
|
109
|
+
if (type === undefined || !isDataValidationType(type))
|
|
104
110
|
return undefined;
|
|
105
|
-
const rule = { type
|
|
111
|
+
const rule = { type };
|
|
106
112
|
if (attrs.operator !== undefined) {
|
|
107
|
-
|
|
113
|
+
if (isDataValidationOperator(attrs.operator))
|
|
114
|
+
rule.operator = attrs.operator;
|
|
108
115
|
}
|
|
109
116
|
else if (TYPED.has(type)) {
|
|
110
117
|
rule.operator = 'between';
|
|
@@ -115,7 +122,7 @@ function buildRule(attrs, formulae) {
|
|
|
115
122
|
rule.showInputMessage = true;
|
|
116
123
|
if (boolStrict(attrs.showErrorMessage))
|
|
117
124
|
rule.showErrorMessage = true;
|
|
118
|
-
if (attrs.errorStyle !== undefined)
|
|
125
|
+
if (attrs.errorStyle !== undefined && isDataValidationErrorStyle(attrs.errorStyle))
|
|
119
126
|
rule.errorStyle = attrs.errorStyle;
|
|
120
127
|
if (attrs.error !== undefined)
|
|
121
128
|
rule.error = attrs.error;
|
|
@@ -136,10 +143,9 @@ export function parseExtendedDataValidations(xml) {
|
|
|
136
143
|
const entries = [];
|
|
137
144
|
let current;
|
|
138
145
|
let slot;
|
|
139
|
-
|
|
140
|
-
let text = '';
|
|
146
|
+
const capture = new TextCapture(['f', 'sqref']);
|
|
141
147
|
parseXml(xml, {
|
|
142
|
-
onOpen(name, attrs) {
|
|
148
|
+
onOpen(name, attrs, selfClosing) {
|
|
143
149
|
const ln = localName(name);
|
|
144
150
|
const prefixed = name.includes(':');
|
|
145
151
|
if (ln === 'dataValidation' && prefixed) {
|
|
@@ -151,30 +157,24 @@ export function parseExtendedDataValidations(xml) {
|
|
|
151
157
|
else if (current !== undefined && prefixed && ln === 'formula2') {
|
|
152
158
|
slot = 1;
|
|
153
159
|
}
|
|
154
|
-
else if (current !== undefined
|
|
155
|
-
capture
|
|
156
|
-
text = '';
|
|
157
|
-
}
|
|
158
|
-
else if (current !== undefined && ln === 'sqref') {
|
|
159
|
-
capture = 'sqref';
|
|
160
|
-
text = '';
|
|
160
|
+
else if (current !== undefined) {
|
|
161
|
+
capture.open(ln, selfClosing);
|
|
161
162
|
}
|
|
162
163
|
},
|
|
163
164
|
onText(chunk) {
|
|
164
|
-
|
|
165
|
-
text += chunk;
|
|
165
|
+
capture.text(chunk);
|
|
166
166
|
},
|
|
167
167
|
onClose(name) {
|
|
168
168
|
const ln = localName(name);
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
if (current !== undefined)
|
|
169
|
+
const text = capture.close(ln);
|
|
170
|
+
if (text !== undefined) {
|
|
171
|
+
if (ln === 'f') {
|
|
172
|
+
if (current !== undefined && slot !== undefined)
|
|
173
|
+
current.formulae[slot] = text;
|
|
174
|
+
}
|
|
175
|
+
else if (current !== undefined) {
|
|
176
176
|
current.sqref = text;
|
|
177
|
-
|
|
177
|
+
}
|
|
178
178
|
}
|
|
179
179
|
else if ((ln === 'formula1' || ln === 'formula2') && name.includes(':')) {
|
|
180
180
|
slot = undefined;
|
|
@@ -197,6 +197,8 @@ function buildExtendedEntry(attrs, formulae, sqref) {
|
|
|
197
197
|
}
|
|
198
198
|
export function applyDataValidations(sheet, entries) {
|
|
199
199
|
for (const { sqref, rule, extended } of entries) {
|
|
200
|
+
if (decodeSqrefRects(sqref).length === 0)
|
|
201
|
+
continue;
|
|
200
202
|
sheet.addDataValidation(sqref, rule, extended ? { extended: true } : {});
|
|
201
203
|
}
|
|
202
204
|
}
|
package/dist/io/xlsx/errors.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { XlsxError } from '../../errors.ts';
|
|
2
2
|
/**
|
|
3
3
|
* Thrown when an `.xlsx` package's XML content is well-formed but does not describe a workbook this
|
|
4
|
-
* library can act on
|
|
4
|
+
* library can act on: a `xl/workbook.xml` that declares no worksheets, say.
|
|
5
5
|
*
|
|
6
6
|
* It sits between two neighbours. {@link XmlParseError} reports that the *markup* did not parse;
|
|
7
7
|
* {@link UnsupportedFormatError} reports that the *container* is not one we read at all. This one
|
|
8
8
|
* fires when both of those were fine and the document itself is nonetheless not a workbook.
|
|
9
9
|
*
|
|
10
|
-
* The reader is deliberately lenient about content it does not recognise
|
|
11
|
-
* skipped, not fatal
|
|
10
|
+
* The reader is deliberately lenient about content it does not recognise (an unknown element is
|
|
11
|
+
* skipped, not fatal) so this is rare by design, and reaching it means something a workbook cannot
|
|
12
12
|
* do without being corrupt.
|
|
13
13
|
*/
|
|
14
14
|
export declare class XlsxParseError extends XlsxError {
|
|
@@ -37,6 +37,8 @@ interface ParsedHyperlink {
|
|
|
37
37
|
/** Parse every `<hyperlink>` element out of a worksheet part. */
|
|
38
38
|
export declare function parseSheetHyperlinks(xml: string): ParsedHyperlink[];
|
|
39
39
|
/** Fold parsed hyperlinks onto a sheet's cells, wrapping each cell's existing value (its visible
|
|
40
|
-
* label) into a {@link HyperlinkValue}. `
|
|
41
|
-
|
|
40
|
+
* label) into a {@link HyperlinkValue}. `targetOf` resolves a relationship id to its raw Target: a
|
|
41
|
+
* URL for the external links hyperlinks almost always are, so it must stay unresolved against the
|
|
42
|
+
* package rather than being handed over as a part path. */
|
|
43
|
+
export declare function applyHyperlinks(sheet: Worksheet, links: readonly ParsedHyperlink[], targetOf: (relId: string) => string | undefined): void;
|
|
42
44
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { tryDecodeRange } from '../../core/address.js';
|
|
2
2
|
import { isHyperlinkValue, isRichTextValue } from '../../core/value.js';
|
|
3
|
-
import { escapeAttr } from '../../xml/xml.js';
|
|
4
3
|
import { localName, parseXml } from '../../xml/xml-read.js';
|
|
4
|
+
import { escapeAttr, textAttr } from '../../xml/xml.js';
|
|
5
5
|
export function collectHyperlinks(sheet) {
|
|
6
6
|
const links = [];
|
|
7
7
|
for (const { cells } of sheet.rows()) {
|
|
@@ -33,8 +33,8 @@ export function hyperlinksXml(links) {
|
|
|
33
33
|
const items = links
|
|
34
34
|
.map((link) => {
|
|
35
35
|
const rid = link.relId !== undefined ? ` r:id="${link.relId}"` : '';
|
|
36
|
-
const location =
|
|
37
|
-
const tooltip =
|
|
36
|
+
const location = textAttr('location', link.location);
|
|
37
|
+
const tooltip = textAttr('tooltip', link.tooltip);
|
|
38
38
|
return `<hyperlink ref="${escapeAttr(link.ref)}"${rid}${location}${tooltip}/>`;
|
|
39
39
|
})
|
|
40
40
|
.join('');
|
|
@@ -59,13 +59,13 @@ export function parseSheetHyperlinks(xml) {
|
|
|
59
59
|
});
|
|
60
60
|
return links;
|
|
61
61
|
}
|
|
62
|
-
export function applyHyperlinks(sheet, links,
|
|
62
|
+
export function applyHyperlinks(sheet, links, targetOf) {
|
|
63
63
|
for (const link of links) {
|
|
64
|
-
const target = resolveTarget(link,
|
|
64
|
+
const target = resolveTarget(link, targetOf);
|
|
65
65
|
if (target === undefined)
|
|
66
66
|
continue;
|
|
67
|
-
const decoded =
|
|
68
|
-
if (decoded === undefined)
|
|
67
|
+
const decoded = tryDecodeRange(link.ref);
|
|
68
|
+
if (decoded === undefined || decoded.tl.col === undefined || decoded.tl.row === undefined)
|
|
69
69
|
continue;
|
|
70
70
|
const cell = sheet.getCell(decoded.tl.address);
|
|
71
71
|
const cellValue = cell.value;
|
|
@@ -80,17 +80,9 @@ export function applyHyperlinks(sheet, links, rels) {
|
|
|
80
80
|
cell.value = value;
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
function
|
|
84
|
-
try {
|
|
85
|
-
return decodeRange(ref);
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
function resolveTarget(link, rels) {
|
|
83
|
+
function resolveTarget(link, targetOf) {
|
|
92
84
|
if (link.rid !== undefined) {
|
|
93
|
-
const base =
|
|
85
|
+
const base = targetOf(link.rid);
|
|
94
86
|
if (base === undefined)
|
|
95
87
|
return undefined;
|
|
96
88
|
return link.location !== undefined ? `${base}#${link.location}` : base;
|
package/dist/io/xlsx/images.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export interface ParsedImageAnchor {
|
|
|
27
27
|
* Anchors that are not pictures (a chart, a shape) carry no `<a:blip r:embed>` and are skipped, so a
|
|
28
28
|
* mixed drawing yields only its images. */
|
|
29
29
|
export declare function parseDrawing(xml: string): ParsedImageAnchor[];
|
|
30
|
-
/** Whether a drawing part holds anchor content beyond plain pictures
|
|
30
|
+
/** Whether a drawing part holds anchor content beyond plain pictures: a chart, shape, connector, or
|
|
31
31
|
* group. Excel packs every one of a sheet's anchors into a single drawing part, so a sheet with both a
|
|
32
32
|
* picture and a chart yields a mixed drawing; modeling only its pictures and re-serialising from them
|
|
33
33
|
* would drop the chart. The reader uses this to fall back to whole-drawing byte-preservation instead. */
|
package/dist/io/xlsx/images.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { isOneCellAnchor, } from '../../core/image.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { isImageEditAs, isOneCellAnchor, } from '../../core/image.js';
|
|
2
|
+
import { enumToken, localName, numFinite, parseXml, TextCapture } from '../../xml/xml-read.js';
|
|
3
|
+
import { checkedToken, numAttr, numberText, XML_DECLARATION } from '../../xml/xml.js';
|
|
4
4
|
import { RELATIONSHIPS_NS } from '../opc/namespaces.js';
|
|
5
5
|
import { relationship, relationshipsPart } from '../opc/rels.js';
|
|
6
6
|
import { DRAWINGML_NS, XDR_NS } from './namespaces.js';
|
|
@@ -35,7 +35,7 @@ function anchorXml(image, id) {
|
|
|
35
35
|
: twoCellAnchorXml(anchor.from, anchor.to, anchor.editAs ?? 'oneCell', anchor.rotation, image.embedId, id);
|
|
36
36
|
}
|
|
37
37
|
function twoCellAnchorXml(from, to, editAs, rotation, embedId, id) {
|
|
38
|
-
return (`<xdr:twoCellAnchor editAs="${editAs}">` +
|
|
38
|
+
return (`<xdr:twoCellAnchor editAs="${checkedToken(editAs, isImageEditAs, 'image anchor edit mode')}">` +
|
|
39
39
|
`<xdr:from>${anchorPointXml(from)}</xdr:from>` +
|
|
40
40
|
`<xdr:to>${anchorPointXml(to)}</xdr:to>` +
|
|
41
41
|
picXml(embedId, id, rotation) +
|
|
@@ -45,13 +45,13 @@ function twoCellAnchorXml(from, to, editAs, rotation, embedId, id) {
|
|
|
45
45
|
function oneCellAnchorXml(from, ext, rotation, embedId, id) {
|
|
46
46
|
return ('<xdr:oneCellAnchor>' +
|
|
47
47
|
`<xdr:from>${anchorPointXml(from)}</xdr:from>` +
|
|
48
|
-
`<xdr:ext
|
|
48
|
+
`<xdr:ext${numAttr('cx', ext.cx)}${numAttr('cy', ext.cy)}/>` +
|
|
49
49
|
picXml(embedId, id, rotation) +
|
|
50
50
|
'<xdr:clientData/>' +
|
|
51
51
|
'</xdr:oneCellAnchor>');
|
|
52
52
|
}
|
|
53
53
|
function picXml(embedId, id, rotation) {
|
|
54
|
-
const xfrm = rotation !== undefined ? `<a:xfrm
|
|
54
|
+
const xfrm = rotation !== undefined ? `<a:xfrm${numAttr('rot', rotation)}/>` : '';
|
|
55
55
|
return ('<xdr:pic>' +
|
|
56
56
|
`<xdr:nvPicPr><xdr:cNvPr id="${id}" name="Picture ${id}"/>` +
|
|
57
57
|
'<xdr:cNvPicPr><a:picLocks noChangeAspect="1"/></xdr:cNvPicPr></xdr:nvPicPr>' +
|
|
@@ -61,8 +61,10 @@ function picXml(embedId, id, rotation) {
|
|
|
61
61
|
'</xdr:pic>');
|
|
62
62
|
}
|
|
63
63
|
function anchorPointXml(point) {
|
|
64
|
-
return (`<xdr:col>${point.col}</xdr:col
|
|
65
|
-
`<xdr:
|
|
64
|
+
return (`<xdr:col>${numberText(point.col)}</xdr:col>` +
|
|
65
|
+
`<xdr:colOff>${numberText(point.colOff ?? 0)}</xdr:colOff>` +
|
|
66
|
+
`<xdr:row>${numberText(point.row)}</xdr:row>` +
|
|
67
|
+
`<xdr:rowOff>${numberText(point.rowOff ?? 0)}</xdr:rowOff>`);
|
|
66
68
|
}
|
|
67
69
|
export function drawingRelsXml(mediaTargets) {
|
|
68
70
|
return relationshipsPart(mediaTargets.map((target, i) => relationship(`rId${i + 1}`, IMAGE_REL_TYPE, target)));
|
|
@@ -70,7 +72,6 @@ export function drawingRelsXml(mediaTargets) {
|
|
|
70
72
|
function blankPoint() {
|
|
71
73
|
return { col: 0, row: 0, colOff: 0, rowOff: 0 };
|
|
72
74
|
}
|
|
73
|
-
const EDIT_AS = new Set(['oneCell', 'twoCell', 'absolute']);
|
|
74
75
|
export function parseDrawing(xml) {
|
|
75
76
|
const anchors = [];
|
|
76
77
|
let from = null;
|
|
@@ -81,10 +82,9 @@ export function parseDrawing(xml) {
|
|
|
81
82
|
let embed;
|
|
82
83
|
let target = null;
|
|
83
84
|
let picDepth = 0;
|
|
84
|
-
|
|
85
|
-
let text = '';
|
|
85
|
+
const coord = new TextCapture(COORDINATES);
|
|
86
86
|
parseXml(xml, {
|
|
87
|
-
onOpen(name, attrs) {
|
|
87
|
+
onOpen(name, attrs, selfClosing) {
|
|
88
88
|
const local = localName(name);
|
|
89
89
|
if (local === 'twoCellAnchor' || local === 'oneCellAnchor') {
|
|
90
90
|
from = blankPoint();
|
|
@@ -92,15 +92,14 @@ export function parseDrawing(xml) {
|
|
|
92
92
|
ext = undefined;
|
|
93
93
|
rotation = undefined;
|
|
94
94
|
embed = undefined;
|
|
95
|
-
|
|
96
|
-
editAs = mode !== undefined && EDIT_AS.has(mode) ? mode : undefined;
|
|
95
|
+
editAs = enumToken(attrs.editAs, isImageEditAs);
|
|
97
96
|
}
|
|
98
97
|
else if (local === 'pic') {
|
|
99
98
|
picDepth++;
|
|
100
99
|
}
|
|
101
100
|
else if (local === 'xfrm' && picDepth > 0) {
|
|
102
|
-
const rot =
|
|
103
|
-
if (
|
|
101
|
+
const rot = numFinite(attrs.rot);
|
|
102
|
+
if (rot !== undefined && rot !== 0)
|
|
104
103
|
rotation = rot;
|
|
105
104
|
}
|
|
106
105
|
else if (local === 'from') {
|
|
@@ -110,9 +109,9 @@ export function parseDrawing(xml) {
|
|
|
110
109
|
target = to;
|
|
111
110
|
}
|
|
112
111
|
else if (local === 'ext' && picDepth === 0) {
|
|
113
|
-
const cx =
|
|
114
|
-
const cy =
|
|
115
|
-
if (
|
|
112
|
+
const cx = numFinite(attrs.cx, 0);
|
|
113
|
+
const cy = numFinite(attrs.cy, 0);
|
|
114
|
+
if (cx !== undefined && cy !== undefined)
|
|
116
115
|
ext = { cx, cy };
|
|
117
116
|
}
|
|
118
117
|
else if (local === 'blip') {
|
|
@@ -120,22 +119,20 @@ export function parseDrawing(xml) {
|
|
|
120
119
|
if (value !== undefined)
|
|
121
120
|
embed = value;
|
|
122
121
|
}
|
|
123
|
-
else if (target !== null
|
|
124
|
-
coord
|
|
125
|
-
text = '';
|
|
122
|
+
else if (target !== null) {
|
|
123
|
+
coord.open(local, selfClosing);
|
|
126
124
|
}
|
|
127
125
|
},
|
|
128
126
|
onText(chunk) {
|
|
129
|
-
|
|
130
|
-
text += chunk;
|
|
127
|
+
coord.text(chunk);
|
|
131
128
|
},
|
|
132
129
|
onClose(name) {
|
|
133
130
|
const local = localName(name);
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
131
|
+
const text = coord.close(local);
|
|
132
|
+
if (text !== undefined) {
|
|
133
|
+
const value = numFinite(text);
|
|
134
|
+
if (target !== null && value !== undefined)
|
|
137
135
|
setCoordinate(target, local, value);
|
|
138
|
-
coord = '';
|
|
139
136
|
}
|
|
140
137
|
else if (local === 'from' || local === 'to') {
|
|
141
138
|
target = null;
|