@office-open/xml 0.3.0 → 0.3.2
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/_chunks/{utils-DlOOMr6B.d.mts → utils-BHmdH50s.d.mts} +7 -1
- package/dist/index.d.mts +12 -2
- package/dist/index.mjs +57 -61
- package/dist/utils.d.mts +2 -2
- package/dist/utils.mjs +15 -1
- package/package.json +1 -1
|
@@ -159,6 +159,12 @@ declare function attrNum(element: Element | undefined, name: string): number | u
|
|
|
159
159
|
* Get an attribute value as a boolean.
|
|
160
160
|
*/
|
|
161
161
|
declare function attrBool(element: Element | undefined, name: string): boolean | undefined;
|
|
162
|
+
/**
|
|
163
|
+
* Get a hex color attribute, handling nativeTypeValue coercion.
|
|
164
|
+
* nativeTypeAttributes converts "000000" → 0 (number); this recovers
|
|
165
|
+
* the original 6-digit hex string by zero-padding numeric values.
|
|
166
|
+
*/
|
|
167
|
+
declare function colorAttr(element: Element | undefined, name: string): string | undefined;
|
|
162
168
|
/**
|
|
163
169
|
* Check if an element has a specific child element.
|
|
164
170
|
*/
|
|
@@ -172,4 +178,4 @@ declare function findDeep(parent: Element | undefined, name: string): Element[];
|
|
|
172
178
|
*/
|
|
173
179
|
declare function childCount(parent: Element | undefined): number;
|
|
174
180
|
//#endregion
|
|
175
|
-
export {
|
|
181
|
+
export { XmlAttrs as C, XmlOption as D, XmlObject as E, XmlAtom as S, XmlDescArray as T, ElementCompact as _, childCount as a, Js2XmlOptions as b, collectText as c, findDeep as d, hasChild as f, Element as g, DeclarationAttributes as h, attrNum as i, colorAttr as l, Attributes as m, attr as n, childText as o, textOf as p, attrBool as r, children as s, allChildren as t, findChild as u, ElementObject as v, XmlDesc as w, Xml2JsOptions as x, IgnoreOptions as y };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as XmlAttrs, D as XmlOption, E as XmlObject, S as XmlAtom, T as XmlDescArray, _ as ElementCompact, a as childCount, b as Js2XmlOptions, c as collectText, d as findDeep, f as hasChild, g as Element, h as DeclarationAttributes, i as attrNum, l as colorAttr, m as Attributes, n as attr, o as childText, p as textOf, r as attrBool, s as children, t as allChildren, u as findChild, v as ElementObject, w as XmlDesc, x as Xml2JsOptions, y as IgnoreOptions } from "./_chunks/utils-BHmdH50s.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/serialize.d.ts
|
|
4
4
|
declare function xml(input: Record<string, any> | Record<string, any>[], options?: boolean | string | {
|
|
@@ -32,9 +32,19 @@ declare function escapeXml(str: string): string;
|
|
|
32
32
|
* Handles already-escaped entities to prevent double-escaping.
|
|
33
33
|
*/
|
|
34
34
|
declare function escapeAttributeValue(str: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Build an XML attribute string fragment from a record.
|
|
37
|
+
* `undefined` values are automatically skipped.
|
|
38
|
+
* String values are escaped via `escapeXml`.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* attrs({ id: 1, name: "foo", hidden: undefined })
|
|
42
|
+
* // => ' id="1" name="foo"'
|
|
43
|
+
*/
|
|
44
|
+
declare function attrs(record: Record<string, string | number | boolean | undefined>): string;
|
|
35
45
|
//#endregion
|
|
36
46
|
//#region src/json.d.ts
|
|
37
47
|
/** Convert XML string to JSON string — xml-js compatible export */
|
|
38
48
|
declare function xml2json(xml: string, options?: Xml2JsOptions): string;
|
|
39
49
|
//#endregion
|
|
40
|
-
export { Attributes, DeclarationAttributes, Element, ElementCompact, ElementObject, IgnoreOptions, Js2XmlOptions, Xml2JsOptions, XmlAtom, XmlAttrs, XmlDesc, XmlDescArray, XmlObject, XmlOption, allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, escapeAttributeValue, escapeXml, findChild, findDeep, hasChild, js2xml, json2xml, textOf, toElement, xml, xml2js, xml2json };
|
|
50
|
+
export { Attributes, DeclarationAttributes, Element, ElementCompact, ElementObject, IgnoreOptions, Js2XmlOptions, Xml2JsOptions, XmlAtom, XmlAttrs, XmlDesc, XmlDescArray, XmlObject, XmlOption, allChildren, attr, attrBool, attrNum, attrs, childCount, childText, children, collectText, colorAttr, escapeAttributeValue, escapeXml, findChild, findDeep, hasChild, js2xml, json2xml, textOf, toElement, xml, xml2js, xml2json };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, findChild, findDeep, hasChild, textOf } from "./utils.mjs";
|
|
1
|
+
import { allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, hasChild, textOf } from "./utils.mjs";
|
|
2
2
|
//#region src/escape.ts
|
|
3
3
|
const XML_CHAR_MAP = {
|
|
4
4
|
"&": "&",
|
|
@@ -19,6 +19,20 @@ function escapeXml(str) {
|
|
|
19
19
|
function escapeAttributeValue(str) {
|
|
20
20
|
return String(str).replace(/&(?!amp;|lt;|gt;|quot;|apos;)/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Build an XML attribute string fragment from a record.
|
|
24
|
+
* `undefined` values are automatically skipped.
|
|
25
|
+
* String values are escaped via `escapeXml`.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* attrs({ id: 1, name: "foo", hidden: undefined })
|
|
29
|
+
* // => ' id="1" name="foo"'
|
|
30
|
+
*/
|
|
31
|
+
function attrs(record) {
|
|
32
|
+
let s = "";
|
|
33
|
+
for (const [k, v] of Object.entries(record)) if (v !== void 0) s += ` ${k}="${typeof v === "string" ? escapeXml(v) : v}"`;
|
|
34
|
+
return s;
|
|
35
|
+
}
|
|
22
36
|
//#endregion
|
|
23
37
|
//#region src/serialize.ts
|
|
24
38
|
const DEFAULT_INDENT = " ";
|
|
@@ -37,7 +51,8 @@ function xml(input, options) {
|
|
|
37
51
|
}
|
|
38
52
|
const items = Array.isArray(input) ? input : [input];
|
|
39
53
|
for (let i = 0; i < items.length; i++) {
|
|
40
|
-
|
|
54
|
+
const keys = Object.keys(items[i]);
|
|
55
|
+
parts.push(formatElement(keys[0], items[i][keys[0]], opts.indent, 0));
|
|
41
56
|
if (opts.indent && i < items.length - 1) parts.push("\n");
|
|
42
57
|
}
|
|
43
58
|
return parts.join("");
|
|
@@ -51,69 +66,50 @@ function normalizeOptions$1(options) {
|
|
|
51
66
|
declaration: opts.declaration
|
|
52
67
|
};
|
|
53
68
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
};
|
|
67
|
-
switch (typeof values) {
|
|
68
|
-
case "object":
|
|
69
|
-
if (values._attr) for (const key of Object.keys(values._attr)) attributes.push(`${key}="${escapeXml(String(values._attr[key]))}"`);
|
|
70
|
-
if (values._cdata) {
|
|
71
|
-
const escaped = String(values._cdata).replace(/\]\]>/g, "]]]]><![CDATA[>");
|
|
72
|
-
content.push(`<![CDATA[${escaped}]]>`);
|
|
73
|
-
}
|
|
74
|
-
if (Array.isArray(values)) {
|
|
75
|
-
if (values.length === 0) return {
|
|
76
|
-
name,
|
|
77
|
-
attributes,
|
|
78
|
-
content,
|
|
79
|
-
indent,
|
|
80
|
-
depth,
|
|
81
|
-
emptyArray: true
|
|
82
|
-
};
|
|
83
|
-
for (const value of values) if (value && typeof value === "object" && "_attr" in value) for (const key of Object.keys(value._attr)) attributes.push(`${key}="${escapeXml(String(value._attr[key]))}"`);
|
|
84
|
-
else if (value && typeof value === "object") content.push(resolve(value, indent, depth + 1));
|
|
85
|
-
else if (value != null) content.push(escapeXml(String(value)));
|
|
86
|
-
}
|
|
87
|
-
break;
|
|
88
|
-
default: content.push(escapeXml(String(values)));
|
|
69
|
+
/**
|
|
70
|
+
* Single-pass XML formatter: directly converts IXmlableObject to string,
|
|
71
|
+
* eliminating the intermediate ResolvedElement tree.
|
|
72
|
+
*/
|
|
73
|
+
function formatElement(name, values, indent, depth) {
|
|
74
|
+
const attrParts = [];
|
|
75
|
+
const textParts = [];
|
|
76
|
+
const elemParts = [];
|
|
77
|
+
let emptyArray = false;
|
|
78
|
+
if (values == null) {
|
|
79
|
+
const attrStr = attrParts.length ? " " + attrParts.join(" ") : "";
|
|
80
|
+
return `${indent ? indent.repeat(depth) : ""}<${name}${attrStr}/>`;
|
|
89
81
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
82
|
+
if (typeof values === "object") {
|
|
83
|
+
if (values._attr) for (const key of Object.keys(values._attr)) attrParts.push(`${key}="${escapeXml(String(values._attr[key]))}"`);
|
|
84
|
+
if (values._attributes) for (const key of Object.keys(values._attributes)) attrParts.push(`${key}="${escapeXml(String(values._attributes[key]))}"`);
|
|
85
|
+
if (values._cdata) {
|
|
86
|
+
const escaped = String(values._cdata).replace(/\]\]>/g, "]]]]><![CDATA[>");
|
|
87
|
+
textParts.push(`<![CDATA[${escaped}]]>`);
|
|
88
|
+
}
|
|
89
|
+
if (Array.isArray(values)) {
|
|
90
|
+
if (values.length === 0) emptyArray = true;
|
|
91
|
+
else for (const value of values) if (value && typeof value === "object" && "_attr" in value) for (const key of Object.keys(value._attr)) attrParts.push(`${key}="${escapeXml(String(value._attr[key]))}"`);
|
|
92
|
+
else if (value && typeof value === "object" && "_attributes" in value) for (const key of Object.keys(value._attributes)) attrParts.push(`${key}="${escapeXml(String(value._attributes[key]))}"`);
|
|
93
|
+
else if (value && typeof value === "object") {
|
|
94
|
+
const childKeys = Object.keys(value);
|
|
95
|
+
elemParts.push(formatElement(childKeys[0], value[childKeys[0]], indent, depth + 1));
|
|
96
|
+
} else if (value != null) textParts.push(escapeXml(String(value)));
|
|
97
|
+
}
|
|
98
|
+
} else textParts.push(escapeXml(String(values)));
|
|
102
99
|
const ind = indent ? indent.repeat(depth) : "";
|
|
103
|
-
const attrStr =
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
return `${ind}<${name}${attrStr}/>`;
|
|
107
|
-
}
|
|
108
|
-
const textContent = content.length === 1 && typeof content[0] === "string" ? content[0] : null;
|
|
109
|
-
if (textContent !== null && !indent) return `<${name}${attrStr}>${textContent}</${name}>`;
|
|
110
|
-
if (textContent !== null) return `${ind}<${name}${attrStr}>${textContent}</${name}>`;
|
|
100
|
+
const attrStr = attrParts.length ? " " + attrParts.join(" ") : "";
|
|
101
|
+
if (textParts.length + elemParts.length === 0) return emptyArray ? `${ind}<${name}${attrStr}></${name}>` : `${ind}<${name}${attrStr}/>`;
|
|
102
|
+
if (elemParts.length === 0 && textParts.length === 1) return indent ? `${ind}<${name}${attrStr}>${textParts[0]}</${name}>` : `<${name}${attrStr}>${textParts[0]}</${name}>`;
|
|
111
103
|
const parts = [];
|
|
112
104
|
parts.push(`${ind}<${name}${attrStr}>`);
|
|
113
105
|
if (indent) parts.push("\n");
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
106
|
+
const childIndent = indent ? indent.repeat(depth + 1) : "";
|
|
107
|
+
for (const t of textParts) {
|
|
108
|
+
parts.push(`${childIndent}${t}`);
|
|
109
|
+
if (indent) parts.push("\n");
|
|
110
|
+
}
|
|
111
|
+
for (const e of elemParts) {
|
|
112
|
+
parts.push(e);
|
|
117
113
|
if (indent) parts.push("\n");
|
|
118
114
|
}
|
|
119
115
|
parts.push(`${ind}</${name}>`);
|
|
@@ -500,4 +496,4 @@ function xml2json(xml, options) {
|
|
|
500
496
|
return JSON.stringify(xml2js(xml, options));
|
|
501
497
|
}
|
|
502
498
|
//#endregion
|
|
503
|
-
export { allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, escapeAttributeValue, escapeXml, findChild, findDeep, hasChild, js2xml, json2xml, textOf, toElement, xml, xml2js, xml2json };
|
|
499
|
+
export { allChildren, attr, attrBool, attrNum, attrs, childCount, childText, children, collectText, colorAttr, escapeAttributeValue, escapeXml, findChild, findDeep, hasChild, js2xml, json2xml, textOf, toElement, xml, xml2js, xml2json };
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as childCount, c as collectText, d as
|
|
2
|
-
export { allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, findChild, findDeep, hasChild, textOf };
|
|
1
|
+
import { a as childCount, c as collectText, d as findDeep, f as hasChild, i as attrNum, l as colorAttr, n as attr, o as childText, p as textOf, r as attrBool, s as children, t as allChildren, u as findChild } from "./_chunks/utils-BHmdH50s.mjs";
|
|
2
|
+
export { allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, hasChild, textOf };
|
package/dist/utils.mjs
CHANGED
|
@@ -75,6 +75,20 @@ function attrBool(element, name) {
|
|
|
75
75
|
if (lower === "false" || lower === "0") return false;
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
|
+
* Get a hex color attribute, handling nativeTypeValue coercion.
|
|
79
|
+
* nativeTypeAttributes converts "000000" → 0 (number); this recovers
|
|
80
|
+
* the original 6-digit hex string by zero-padding numeric values.
|
|
81
|
+
*/
|
|
82
|
+
function colorAttr(element, name) {
|
|
83
|
+
const raw = element?.attributes?.[name];
|
|
84
|
+
if (raw === void 0 || raw === "") return void 0;
|
|
85
|
+
if (typeof raw === "boolean") return void 0;
|
|
86
|
+
if (typeof raw === "number") return String(raw).padStart(6, "0");
|
|
87
|
+
if (raw === "auto") return "auto";
|
|
88
|
+
if (/^[0-9A-Fa-f]{6}$/.test(raw)) return raw;
|
|
89
|
+
return raw;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
78
92
|
* Check if an element has a specific child element.
|
|
79
93
|
*/
|
|
80
94
|
function hasChild(parent, name) {
|
|
@@ -99,4 +113,4 @@ function childCount(parent) {
|
|
|
99
113
|
return parent?.elements?.length ?? 0;
|
|
100
114
|
}
|
|
101
115
|
//#endregion
|
|
102
|
-
export { allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, findChild, findDeep, hasChild, textOf };
|
|
116
|
+
export { allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, hasChild, textOf };
|