@office-open/xml 0.6.5 → 0.6.7
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 +12 -12
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +60 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -103,31 +103,31 @@ Performance comparison against original `xml` (1.0.1) and `xml-js` (1.6.11) pack
|
|
|
103
103
|
|
|
104
104
|
| Scenario | @office-open/xml | xml | Speedup |
|
|
105
105
|
| ----------------------- | ---------------: | ---------: | --------: |
|
|
106
|
-
| Simple element |
|
|
107
|
-
| Nested element |
|
|
108
|
-
| Nested with declaration |
|
|
106
|
+
| Simple element | 5,177,260 hz | 788,296 hz | **6.57x** |
|
|
107
|
+
| Nested element | 931,473 hz | 283,093 hz | **3.29x** |
|
|
108
|
+
| Nested with declaration | 871,188 hz | 252,580 hz | **3.45x** |
|
|
109
109
|
|
|
110
110
|
### Parsing (xml2js)
|
|
111
111
|
|
|
112
|
-
| Scenario | @office-open/xml |
|
|
113
|
-
| ------------------ | ---------------: |
|
|
114
|
-
| Simple XML | 1,
|
|
115
|
-
| Complex OOXML |
|
|
116
|
-
| With captureSpaces |
|
|
112
|
+
| Scenario | @office-open/xml | xml-js | Speedup |
|
|
113
|
+
| ------------------ | ---------------: | --------: | ---------: |
|
|
114
|
+
| Simple XML | 1,007,094 hz | 91,782 hz | **10.97x** |
|
|
115
|
+
| Complex OOXML | 340,595 hz | 49,733 hz | **6.85x** |
|
|
116
|
+
| With captureSpaces | 314,648 hz | 44,190 hz | **7.12x** |
|
|
117
117
|
|
|
118
118
|
### Stringifying (js2xml)
|
|
119
119
|
|
|
120
120
|
| Scenario | @office-open/xml | xml-js | Speedup |
|
|
121
121
|
| -------------- | ---------------: | ---------: | --------: |
|
|
122
|
-
| Simple element |
|
|
123
|
-
| Complex OOXML |
|
|
122
|
+
| Simple element | 712,314 hz | 182,865 hz | **3.90x** |
|
|
123
|
+
| Complex OOXML | 333,739 hz | 125,132 hz | **2.67x** |
|
|
124
124
|
|
|
125
125
|
### Direct Conversion (toElement vs bridge)
|
|
126
126
|
|
|
127
127
|
| Scenario | toElement() | xml() + xml2js() bridge | Speedup |
|
|
128
128
|
| -------- | ------------: | ----------------------: | ---------: |
|
|
129
|
-
| Simple |
|
|
130
|
-
| Nested |
|
|
129
|
+
| Simple | 13,922,735 hz | 1,083,869 hz | **12.85x** |
|
|
130
|
+
| Nested | 3,799,372 hz | 436,241 hz | **8.71x** |
|
|
131
131
|
|
|
132
132
|
## Bundle Size
|
|
133
133
|
|
package/dist/index.d.mts
CHANGED
|
@@ -30,11 +30,6 @@ declare function toElement(xmlObject: Record<string, any>): Element;
|
|
|
30
30
|
//#region src/escape.d.ts
|
|
31
31
|
/** Escape text content for XML. Fast path returns original string when no special chars. */
|
|
32
32
|
declare function escapeXml(str: string): string;
|
|
33
|
-
/**
|
|
34
|
-
* Escape attribute value matching xml-js's js2xml behavior.
|
|
35
|
-
* Handles already-escaped entities to prevent double-escaping.
|
|
36
|
-
*/
|
|
37
|
-
declare function escapeAttributeValue(str: string): string;
|
|
38
33
|
/**
|
|
39
34
|
* Build an XML attribute string fragment from a record.
|
|
40
35
|
* `undefined` values are automatically skipped.
|
|
@@ -45,9 +40,14 @@ declare function escapeAttributeValue(str: string): string;
|
|
|
45
40
|
* // => ' id="1" name="foo"'
|
|
46
41
|
*/
|
|
47
42
|
declare function attrs(record: Record<string, string | number | boolean | undefined>): string;
|
|
43
|
+
/**
|
|
44
|
+
* Build a self-closing XML element: `<tag attrStr/>`.
|
|
45
|
+
* `attrStr` is a pre-serialized attribute string (from `attrs()`) or undefined.
|
|
46
|
+
*/
|
|
47
|
+
declare function selfCloseElement(tag: string, attrStr?: string): string;
|
|
48
48
|
//#endregion
|
|
49
49
|
//#region src/json.d.ts
|
|
50
50
|
/** Convert XML string to JSON string — xml-js compatible export */
|
|
51
51
|
declare function xml2json(xml: string, options?: Xml2JsOptions): string;
|
|
52
52
|
//#endregion
|
|
53
|
-
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,
|
|
53
|
+
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, escapeXml, findChild, findDeep, hasChild, js2xml, json2xml, nativeTypeValue, parseAttributes, selfCloseElement, textOf, toElement, unescapeXml, xml, xml2js, xml2json };
|
package/dist/index.mjs
CHANGED
|
@@ -1,29 +1,37 @@
|
|
|
1
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
|
-
const XML_CHAR_MAP = {
|
|
4
|
-
"&": "&",
|
|
5
|
-
"\"": """,
|
|
6
|
-
"'": "'",
|
|
7
|
-
"<": "<",
|
|
8
|
-
">": ">"
|
|
9
|
-
};
|
|
10
|
-
const XML_CHAR_PATTERN = /([&"<>'])/g;
|
|
11
3
|
/** Escape text content for XML. Fast path returns original string when no special chars. */
|
|
12
4
|
function escapeXml(str) {
|
|
13
5
|
for (let i = 0; i < str.length; i++) {
|
|
14
6
|
const c = str.charCodeAt(i);
|
|
15
|
-
if (c === 38 || c === 34 || c === 39 || c === 60 || c === 62)
|
|
7
|
+
if (c === 38 || c === 34 || c === 39 || c === 60 || c === 62) {
|
|
8
|
+
let s = "";
|
|
9
|
+
let last = 0;
|
|
10
|
+
for (let j = i; j < str.length; j++) {
|
|
11
|
+
const cj = str.charCodeAt(j);
|
|
12
|
+
if (cj === 38) {
|
|
13
|
+
s += str.slice(last, j) + "&";
|
|
14
|
+
last = j + 1;
|
|
15
|
+
} else if (cj === 34) {
|
|
16
|
+
s += str.slice(last, j) + """;
|
|
17
|
+
last = j + 1;
|
|
18
|
+
} else if (cj === 39) {
|
|
19
|
+
s += str.slice(last, j) + "'";
|
|
20
|
+
last = j + 1;
|
|
21
|
+
} else if (cj === 60) {
|
|
22
|
+
s += str.slice(last, j) + "<";
|
|
23
|
+
last = j + 1;
|
|
24
|
+
} else if (cj === 62) {
|
|
25
|
+
s += str.slice(last, j) + ">";
|
|
26
|
+
last = j + 1;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return s + str.slice(last);
|
|
30
|
+
}
|
|
16
31
|
}
|
|
17
32
|
return str;
|
|
18
33
|
}
|
|
19
34
|
/**
|
|
20
|
-
* Escape attribute value matching xml-js's js2xml behavior.
|
|
21
|
-
* Handles already-escaped entities to prevent double-escaping.
|
|
22
|
-
*/
|
|
23
|
-
function escapeAttributeValue(str) {
|
|
24
|
-
return String(str).replace(/&(?!amp;|lt;|gt;|quot;|apos;)/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
35
|
* Build an XML attribute string fragment from a record.
|
|
28
36
|
* `undefined` values are automatically skipped.
|
|
29
37
|
* String values are escaped via `escapeXml`.
|
|
@@ -34,9 +42,20 @@ function escapeAttributeValue(str) {
|
|
|
34
42
|
*/
|
|
35
43
|
function attrs(record) {
|
|
36
44
|
let s = "";
|
|
37
|
-
|
|
45
|
+
const keys = Object.keys(record);
|
|
46
|
+
for (let i = 0; i < keys.length; i++) {
|
|
47
|
+
const v = record[keys[i]];
|
|
48
|
+
if (v !== void 0) s += ` ${keys[i]}="${typeof v === "string" ? escapeXml(v) : v}"`;
|
|
49
|
+
}
|
|
38
50
|
return s;
|
|
39
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Build a self-closing XML element: `<tag attrStr/>`.
|
|
54
|
+
* `attrStr` is a pre-serialized attribute string (from `attrs()`) or undefined.
|
|
55
|
+
*/
|
|
56
|
+
function selfCloseElement(tag, attrStr) {
|
|
57
|
+
return attrStr ? `<${tag}${attrStr}/>` : `<${tag}/>`;
|
|
58
|
+
}
|
|
40
59
|
//#endregion
|
|
41
60
|
//#region src/serialize.ts
|
|
42
61
|
const DEFAULT_INDENT = " ";
|
|
@@ -435,7 +454,29 @@ function writeElements(elements, opts, depth, firstLine) {
|
|
|
435
454
|
}
|
|
436
455
|
function writeText(text) {
|
|
437
456
|
if (text == null) return "";
|
|
438
|
-
|
|
457
|
+
const str = String(text);
|
|
458
|
+
for (let i = 0; i < str.length; i++) {
|
|
459
|
+
const c = str.charCodeAt(i);
|
|
460
|
+
if (c === 38 || c === 60 || c === 62) {
|
|
461
|
+
let s = "";
|
|
462
|
+
let last = 0;
|
|
463
|
+
for (let j = i; j < str.length; j++) {
|
|
464
|
+
const cj = str.charCodeAt(j);
|
|
465
|
+
if (cj === 38) {
|
|
466
|
+
s += str.slice(last, j) + "&";
|
|
467
|
+
last = j + 1;
|
|
468
|
+
} else if (cj === 60) {
|
|
469
|
+
s += str.slice(last, j) + "<";
|
|
470
|
+
last = j + 1;
|
|
471
|
+
} else if (cj === 62) {
|
|
472
|
+
s += str.slice(last, j) + ">";
|
|
473
|
+
last = j + 1;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
return s + str.slice(last);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
return str;
|
|
439
480
|
}
|
|
440
481
|
function writeCdata(cdata) {
|
|
441
482
|
if (cdata == null) return "";
|
|
@@ -501,4 +542,4 @@ function xml2json(xml, options) {
|
|
|
501
542
|
return JSON.stringify(xml2js(xml, options));
|
|
502
543
|
}
|
|
503
544
|
//#endregion
|
|
504
|
-
export { allChildren, attr, attrBool, attrNum, attrs, childCount, childText, children, collectText, colorAttr,
|
|
545
|
+
export { allChildren, attr, attrBool, attrNum, attrs, childCount, childText, children, collectText, colorAttr, escapeXml, findChild, findDeep, hasChild, js2xml, json2xml, nativeTypeValue, parseAttributes, selfCloseElement, textOf, toElement, unescapeXml, xml, xml2js, xml2json };
|