@office-open/xml
Advanced tools
+28
-11
@@ -207,5 +207,10 @@ import { allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, hasChild, textOf } from "./utils.mjs"; | ||
| }; | ||
| const ENTITY_PATTERN = /&(amp|lt|gt|quot|apos);/g; | ||
| const ENTITY_PATTERN = /&(?:amp|lt|gt|quot|apos|#x[0-9a-fA-F]+|#[0-9]+);/g; | ||
| function unescapeXml(str) { | ||
| return str.replace(ENTITY_PATTERN, (match) => ENTITY_MAP[match]); | ||
| return str.replace(ENTITY_PATTERN, (match) => { | ||
| if (ENTITY_MAP[match] !== void 0) return ENTITY_MAP[match]; | ||
| const body = match.slice(2, -1); | ||
| const code = body[0] === "x" || body[0] === "X" ? parseInt(body.slice(1), 16) : parseInt(body, 10); | ||
| return Number.isFinite(code) && code >= 0 ? String.fromCodePoint(code) : match; | ||
| }); | ||
| } | ||
@@ -235,6 +240,2 @@ function nativeTypeValue(value) { | ||
| while (i < len) { | ||
| if (!captureSpaces && isWhitespace(xmlString.charCodeAt(i))) { | ||
| i++; | ||
| continue; | ||
| } | ||
| if (xmlString.charCodeAt(i) !== 60) { | ||
@@ -247,3 +248,3 @@ const start = i; | ||
| if (text.length > 0) { | ||
| if (captureSpaces || text.trim().length > 0) addField(stack[stack.length - 1], "text", text); | ||
| if (captureSpaces || text.trim().length > 0 || isPreserveContext(stack)) addField(stack[stack.length - 1], "text", text); | ||
| } | ||
@@ -361,3 +362,3 @@ continue; | ||
| while (i < len && str.charCodeAt(i) !== quote) i++; | ||
| attrs[name] = str.slice(valueStart, i); | ||
| attrs[name] = unescapeXml(str.slice(valueStart, i)); | ||
| i++; | ||
@@ -392,3 +393,3 @@ } | ||
| while (i < len && str.charCodeAt(i) !== quote) i++; | ||
| result[name] = str.slice(valueStart, i); | ||
| result[name] = unescapeXml(str.slice(valueStart, i)); | ||
| i++; | ||
@@ -400,2 +401,10 @@ } | ||
| if (!parent.elements) parent.elements = []; | ||
| if (type === "text" || type === "cdata") { | ||
| const last = parent.elements[parent.elements.length - 1]; | ||
| if (last && last.type === type) { | ||
| const key = type; | ||
| last[key] = last[key] + value; | ||
| return; | ||
| } | ||
| } | ||
| const element = { type }; | ||
@@ -405,2 +414,10 @@ element[type] = value; | ||
| } | ||
| /** True when the nearest ancestor with an explicit xml:space sets "preserve". */ | ||
| function isPreserveContext(stack) { | ||
| for (let i = stack.length - 1; i >= 0; i--) { | ||
| const space = stack[i].attributes?.["xml:space"]; | ||
| if (space !== void 0) return space === "preserve"; | ||
| } | ||
| return false; | ||
| } | ||
| function isWhitespace(ch) { | ||
@@ -465,4 +482,4 @@ return ch === 32 || ch === 9 || ch === 10 || ch === 13; | ||
| if (value === null || value === void 0) continue; | ||
| let attr = String(value).replace(/"/g, """); | ||
| if (attributeValueFn) attr = attributeValueFn(attr, key, elementName, element); | ||
| const raw = String(value); | ||
| const attr = attributeValueFn ? attributeValueFn(raw, key, elementName, element) : escapeXml(raw); | ||
| parts.push(` ${key}="${attr}"`); | ||
@@ -469,0 +486,0 @@ } |
+1
-1
| { | ||
| "name": "@office-open/xml", | ||
| "version": "0.9.3", | ||
| "version": "0.9.4", | ||
| "description": "XML parsing and serialization for Office Open XML. Zero dependencies, drop-in replacement for xml + xml-js.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
43462
1.77%736
2.36%