@office-open/xml 0.9.3 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +28 -11
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -204,9 +204,14 @@ const ENTITY_MAP = {
|
|
|
204
204
|
""": "\"",
|
|
205
205
|
"'": "'"
|
|
206
206
|
};
|
|
207
|
-
const ENTITY_PATTERN = /&(amp|lt|gt|quot|apos);/g;
|
|
207
|
+
const ENTITY_PATTERN = /&(?:amp|lt|gt|quot|apos|#x[0-9a-fA-F]+|#[0-9]+);/g;
|
|
208
208
|
function unescapeXml(str) {
|
|
209
|
-
return str.replace(ENTITY_PATTERN, (match) =>
|
|
209
|
+
return str.replace(ENTITY_PATTERN, (match) => {
|
|
210
|
+
if (ENTITY_MAP[match] !== void 0) return ENTITY_MAP[match];
|
|
211
|
+
const body = match.slice(2, -1);
|
|
212
|
+
const code = body[0] === "x" || body[0] === "X" ? parseInt(body.slice(1), 16) : parseInt(body, 10);
|
|
213
|
+
return Number.isFinite(code) && code >= 0 ? String.fromCodePoint(code) : match;
|
|
214
|
+
});
|
|
210
215
|
}
|
|
211
216
|
function nativeTypeValue(value) {
|
|
212
217
|
if (value === "") return value;
|
|
@@ -231,10 +236,6 @@ function parse(xmlString, options) {
|
|
|
231
236
|
let i = 0;
|
|
232
237
|
const len = xmlString.length;
|
|
233
238
|
while (i < len) {
|
|
234
|
-
if (!captureSpaces && isWhitespace(xmlString.charCodeAt(i))) {
|
|
235
|
-
i++;
|
|
236
|
-
continue;
|
|
237
|
-
}
|
|
238
239
|
if (xmlString.charCodeAt(i) !== 60) {
|
|
239
240
|
const start = i;
|
|
240
241
|
while (i < len && xmlString.charCodeAt(i) !== 60) i++;
|
|
@@ -242,7 +243,7 @@ function parse(xmlString, options) {
|
|
|
242
243
|
if (trim) text = text.trim();
|
|
243
244
|
if (ignoreText) continue;
|
|
244
245
|
if (text.length > 0) {
|
|
245
|
-
if (captureSpaces || text.trim().length > 0) addField(stack[stack.length - 1], "text", text);
|
|
246
|
+
if (captureSpaces || text.trim().length > 0 || isPreserveContext(stack)) addField(stack[stack.length - 1], "text", text);
|
|
246
247
|
}
|
|
247
248
|
continue;
|
|
248
249
|
}
|
|
@@ -355,7 +356,7 @@ function parseAttributesFromXml(str, start) {
|
|
|
355
356
|
i++;
|
|
356
357
|
const valueStart = i;
|
|
357
358
|
while (i < len && str.charCodeAt(i) !== quote) i++;
|
|
358
|
-
attrs[name] = str.slice(valueStart, i);
|
|
359
|
+
attrs[name] = unescapeXml(str.slice(valueStart, i));
|
|
359
360
|
i++;
|
|
360
361
|
}
|
|
361
362
|
return {
|
|
@@ -385,17 +386,33 @@ function parseAttributes(str) {
|
|
|
385
386
|
i++;
|
|
386
387
|
const valueStart = i;
|
|
387
388
|
while (i < len && str.charCodeAt(i) !== quote) i++;
|
|
388
|
-
result[name] = str.slice(valueStart, i);
|
|
389
|
+
result[name] = unescapeXml(str.slice(valueStart, i));
|
|
389
390
|
i++;
|
|
390
391
|
}
|
|
391
392
|
return result;
|
|
392
393
|
}
|
|
393
394
|
function addField(parent, type, value) {
|
|
394
395
|
if (!parent.elements) parent.elements = [];
|
|
396
|
+
if (type === "text" || type === "cdata") {
|
|
397
|
+
const last = parent.elements[parent.elements.length - 1];
|
|
398
|
+
if (last && last.type === type) {
|
|
399
|
+
const key = type;
|
|
400
|
+
last[key] = last[key] + value;
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
395
404
|
const element = { type };
|
|
396
405
|
element[type] = value;
|
|
397
406
|
parent.elements.push(element);
|
|
398
407
|
}
|
|
408
|
+
/** True when the nearest ancestor with an explicit xml:space sets "preserve". */
|
|
409
|
+
function isPreserveContext(stack) {
|
|
410
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
411
|
+
const space = stack[i].attributes?.["xml:space"];
|
|
412
|
+
if (space !== void 0) return space === "preserve";
|
|
413
|
+
}
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
399
416
|
function isWhitespace(ch) {
|
|
400
417
|
return ch === 32 || ch === 9 || ch === 10 || ch === 13;
|
|
401
418
|
}
|
|
@@ -455,8 +472,8 @@ function writeAttributes(attributes, elementName, element, attributeValueFn) {
|
|
|
455
472
|
for (const key of Object.keys(attributes)) {
|
|
456
473
|
const value = attributes[key];
|
|
457
474
|
if (value === null || value === void 0) continue;
|
|
458
|
-
|
|
459
|
-
|
|
475
|
+
const raw = String(value);
|
|
476
|
+
const attr = attributeValueFn ? attributeValueFn(raw, key, elementName, element) : escapeXml(raw);
|
|
460
477
|
parts.push(` ${key}="${attr}"`);
|
|
461
478
|
}
|
|
462
479
|
return parts.join("");
|