@office-open/xml 0.1.0 → 0.3.1
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/_chunks/utils-BHmdH50s.d.mts +181 -0
- package/dist/index.d.mts +3 -124
- package/dist/index.mjs +4 -1
- package/dist/utils.d.mts +2 -0
- package/dist/utils.mjs +116 -0
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|

|
|
6
6
|

|
|
7
7
|
|
|
8
|
-
> XML parsing and serialization for Office Open XML. Zero dependencies, drop-in replacement for
|
|
8
|
+
> XML parsing and serialization for Office Open XML. Zero dependencies, drop-in replacement for xml + xml-js.
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
- **xml() Serialization** - Drop-in replacement for the `xml` package
|
|
14
14
|
- **xml2js() Parsing** - Drop-in replacement for `xml-js` XML parsing
|
|
15
15
|
- **js2xml() Stringifying** - Drop-in replacement for `xml-js` JS-to-XML conversion
|
|
16
|
-
- **toElement() Direct Convert** - Direct conversion from xml object format to xml-js Element,
|
|
16
|
+
- **toElement() Direct Convert** - Direct conversion from xml object format to xml-js Element, 10-19x faster than the xml→xml2js bridge
|
|
17
17
|
- **Complete Type Definitions** - Full type compatibility with `xml` and `xml-js`, import without changes
|
|
18
18
|
- **OOXML Optimized** - Implements all options needed for Office Open XML document generation
|
|
19
19
|
|
|
@@ -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 | 4,
|
|
107
|
-
| Nested element |
|
|
108
|
-
| Nested with declaration |
|
|
106
|
+
| Simple element | 4,023,269 hz | 742,728 hz | **5.42x** |
|
|
107
|
+
| Nested element | 1,030,612 hz | 322,801 hz | **3.19x** |
|
|
108
|
+
| Nested with declaration | 963,725 hz | 276,547 hz | **3.49x** |
|
|
109
109
|
|
|
110
110
|
### Parsing (xml2js)
|
|
111
111
|
|
|
112
112
|
| Scenario | @office-open/xml | xml-js | Speedup |
|
|
113
113
|
| ------------------ | ---------------: | --------: | ---------: |
|
|
114
|
-
| Simple XML | 1,
|
|
115
|
-
| Complex OOXML |
|
|
116
|
-
| With captureSpaces |
|
|
114
|
+
| Simple XML | 1,147,347 hz | 95,579 hz | **12.00x** |
|
|
115
|
+
| Complex OOXML | 401,553 hz | 52,327 hz | **7.67x** |
|
|
116
|
+
| With captureSpaces | 387,082 hz | 52,317 hz | **7.40x** |
|
|
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 | 778,368 hz | 197,520 hz | **3.94x** |
|
|
123
|
+
| Complex OOXML | 344,376 hz | 127,493 hz | **2.70x** |
|
|
124
124
|
|
|
125
125
|
### Direct Conversion (toElement vs bridge)
|
|
126
126
|
|
|
127
127
|
| Scenario | toElement() | xml() + xml2js() bridge | Speedup |
|
|
128
128
|
| -------- | ------------: | ----------------------: | ---------: |
|
|
129
|
-
| Simple | 14,
|
|
130
|
-
| Nested |
|
|
129
|
+
| Simple | 14,953,390 hz | 803,917 hz | **18.61x** |
|
|
130
|
+
| Nested | 4,530,626 hz | 466,126 hz | **9.72x** |
|
|
131
131
|
|
|
132
132
|
## Bundle Size
|
|
133
133
|
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
interface Attributes {
|
|
3
|
+
[key: string]: string | number | undefined;
|
|
4
|
+
}
|
|
5
|
+
interface DeclarationAttributes {
|
|
6
|
+
version?: string | number;
|
|
7
|
+
encoding?: string;
|
|
8
|
+
standalone?: string;
|
|
9
|
+
}
|
|
10
|
+
interface Element {
|
|
11
|
+
declaration?: {
|
|
12
|
+
attributes?: DeclarationAttributes;
|
|
13
|
+
};
|
|
14
|
+
instruction?: string;
|
|
15
|
+
attributes?: Attributes;
|
|
16
|
+
cdata?: string;
|
|
17
|
+
doctype?: string;
|
|
18
|
+
comment?: string;
|
|
19
|
+
text?: string | number | boolean;
|
|
20
|
+
type?: string;
|
|
21
|
+
name?: string;
|
|
22
|
+
elements?: Element[];
|
|
23
|
+
parent?: Element;
|
|
24
|
+
}
|
|
25
|
+
interface ElementCompact {
|
|
26
|
+
[key: string]: any;
|
|
27
|
+
_declaration?: {
|
|
28
|
+
_attributes?: DeclarationAttributes;
|
|
29
|
+
};
|
|
30
|
+
_instruction?: {
|
|
31
|
+
[key: string]: string;
|
|
32
|
+
};
|
|
33
|
+
_attributes?: Attributes;
|
|
34
|
+
_cdata?: string;
|
|
35
|
+
_doctype?: string;
|
|
36
|
+
_comment?: string;
|
|
37
|
+
_text?: string | number;
|
|
38
|
+
}
|
|
39
|
+
interface IgnoreOptions {
|
|
40
|
+
ignoreDeclaration?: boolean;
|
|
41
|
+
ignoreInstruction?: boolean;
|
|
42
|
+
ignoreAttributes?: boolean;
|
|
43
|
+
ignoreComment?: boolean;
|
|
44
|
+
ignoreCdata?: boolean;
|
|
45
|
+
ignoreDoctype?: boolean;
|
|
46
|
+
ignoreText?: boolean;
|
|
47
|
+
}
|
|
48
|
+
interface Xml2JsOptions extends IgnoreOptions {
|
|
49
|
+
compact?: boolean;
|
|
50
|
+
trim?: boolean;
|
|
51
|
+
sanitize?: boolean;
|
|
52
|
+
nativeType?: boolean;
|
|
53
|
+
nativeTypeAttributes?: boolean;
|
|
54
|
+
addParent?: boolean;
|
|
55
|
+
alwaysArray?: boolean | string[];
|
|
56
|
+
alwaysChildren?: boolean;
|
|
57
|
+
instructionHasAttributes?: boolean;
|
|
58
|
+
captureSpacesBetweenElements?: boolean;
|
|
59
|
+
doctypeFn?: (value: string, parentElement: object) => string;
|
|
60
|
+
instructionFn?: (value: string, instructionName: string, parentElement: string) => string;
|
|
61
|
+
cdataFn?: (value: string, parentElement: object) => string;
|
|
62
|
+
commentFn?: (value: string, parentElement: object) => string;
|
|
63
|
+
textFn?: (value: string, parentElement: object) => string;
|
|
64
|
+
instructionNameFn?: (instructionName: string, instructionValue: string, parentElement: string) => string;
|
|
65
|
+
elementNameFn?: (value: string, parentElement: object) => string;
|
|
66
|
+
attributeNameFn?: (attributeName: string, attributeValue: string, parentElement: string) => string;
|
|
67
|
+
attributeValueFn?: (attributeValue: string, attributeName: string, parentElement: string) => string;
|
|
68
|
+
attributesFn?: (value: Attributes, parentElement: string) => Attributes;
|
|
69
|
+
}
|
|
70
|
+
interface Js2XmlOptions extends IgnoreOptions {
|
|
71
|
+
spaces?: number | string;
|
|
72
|
+
compact?: boolean;
|
|
73
|
+
indentText?: boolean;
|
|
74
|
+
indentCdata?: boolean;
|
|
75
|
+
indentAttributes?: boolean;
|
|
76
|
+
indentInstruction?: boolean;
|
|
77
|
+
fullTagEmptyElement?: boolean;
|
|
78
|
+
noQuotesForNativeAttributes?: boolean;
|
|
79
|
+
doctypeFn?: (value: string, currentElementName: string, currentElementObj: object) => string;
|
|
80
|
+
instructionFn?: (instructionValue: string, instructionName: string, currentElementName: string, currentElementObj: object) => string;
|
|
81
|
+
cdataFn?: (value: string, currentElementName: string, currentElementObj: object) => string;
|
|
82
|
+
commentFn?: (value: string, currentElementName: string, currentElementObj: object) => string;
|
|
83
|
+
textFn?: (value: string, currentElementName: string, currentElementObj: object) => string;
|
|
84
|
+
instructionNameFn?: (instructionName: string, instructionValue: string, currentElementName: string, currentElementObj: object) => string;
|
|
85
|
+
elementNameFn?: (value: string, currentElementName: string, currentElementObj: object) => string;
|
|
86
|
+
attributeNameFn?: (attributeName: string, attributeValue: string, currentElementName: string, currentElementObj: object) => string;
|
|
87
|
+
attributeValueFn?: (attributeValue: string, attributeName: string, currentElementName: string, currentElementObj: object) => string;
|
|
88
|
+
attributesFn?: (value: Attributes, currentElementName: string, currentElementObj: object) => Attributes;
|
|
89
|
+
fullTagEmptyElementFn?: (currentElementName: string, currentElementObj: object) => boolean;
|
|
90
|
+
}
|
|
91
|
+
interface XmlOption {
|
|
92
|
+
indent?: string;
|
|
93
|
+
stream?: boolean;
|
|
94
|
+
declaration?: boolean | {
|
|
95
|
+
encoding?: string;
|
|
96
|
+
standalone?: string;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
interface XmlAttrs {
|
|
100
|
+
[attr: string]: XmlAtom;
|
|
101
|
+
}
|
|
102
|
+
type XmlAtom = string | number | boolean | null;
|
|
103
|
+
interface ElementObject {
|
|
104
|
+
push(xmlObject: XmlObject): void;
|
|
105
|
+
close(xmlObject?: XmlObject): void;
|
|
106
|
+
}
|
|
107
|
+
type XmlDesc = {
|
|
108
|
+
_attr: XmlAttrs;
|
|
109
|
+
} | {
|
|
110
|
+
_cdata: string;
|
|
111
|
+
} | {
|
|
112
|
+
_attr: XmlAttrs;
|
|
113
|
+
_cdata: string;
|
|
114
|
+
} | XmlAtom | XmlAtom[] | XmlDescArray;
|
|
115
|
+
interface XmlDescArray {
|
|
116
|
+
[index: number]: {
|
|
117
|
+
_attr: XmlAttrs;
|
|
118
|
+
} | XmlObject;
|
|
119
|
+
}
|
|
120
|
+
type XmlObject = {
|
|
121
|
+
[tag: string]: ElementObject | XmlDesc;
|
|
122
|
+
} | XmlDesc;
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/utils.d.ts
|
|
125
|
+
/**
|
|
126
|
+
* Find the first direct child element with the given name.
|
|
127
|
+
*/
|
|
128
|
+
declare function findChild(parent: Element | undefined, name: string): Element | undefined;
|
|
129
|
+
/**
|
|
130
|
+
* Get all direct child elements matching the given name.
|
|
131
|
+
*/
|
|
132
|
+
declare function children(parent: Element | undefined, name: string): Element[];
|
|
133
|
+
/**
|
|
134
|
+
* Get all direct child elements.
|
|
135
|
+
*/
|
|
136
|
+
declare function allChildren(parent: Element | undefined): Element[];
|
|
137
|
+
/**
|
|
138
|
+
* Get text content of the first child element with the given name.
|
|
139
|
+
*/
|
|
140
|
+
declare function childText(parent: Element | undefined, name: string): string;
|
|
141
|
+
/**
|
|
142
|
+
* Get text content of an element.
|
|
143
|
+
* Handles cases where text may be directly on .text or in a child element.
|
|
144
|
+
*/
|
|
145
|
+
declare function textOf(element: Element | undefined): string;
|
|
146
|
+
/**
|
|
147
|
+
* Collect text from all direct text nodes within an element.
|
|
148
|
+
*/
|
|
149
|
+
declare function collectText(element: Element | undefined): string;
|
|
150
|
+
/**
|
|
151
|
+
* Get an attribute value as a string.
|
|
152
|
+
*/
|
|
153
|
+
declare function attr(element: Element | undefined, name: string): string | undefined;
|
|
154
|
+
/**
|
|
155
|
+
* Get an attribute value as a number.
|
|
156
|
+
*/
|
|
157
|
+
declare function attrNum(element: Element | undefined, name: string): number | undefined;
|
|
158
|
+
/**
|
|
159
|
+
* Get an attribute value as a boolean.
|
|
160
|
+
*/
|
|
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;
|
|
168
|
+
/**
|
|
169
|
+
* Check if an element has a specific child element.
|
|
170
|
+
*/
|
|
171
|
+
declare function hasChild(parent: Element | undefined, name: string): boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Find deep descendant elements matching the given name.
|
|
174
|
+
*/
|
|
175
|
+
declare function findDeep(parent: Element | undefined, name: string): Element[];
|
|
176
|
+
/**
|
|
177
|
+
* Get the number of direct child elements.
|
|
178
|
+
*/
|
|
179
|
+
declare function childCount(parent: Element | undefined): number;
|
|
180
|
+
//#endregion
|
|
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,3 +1,5 @@
|
|
|
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
|
+
|
|
1
3
|
//#region src/serialize.d.ts
|
|
2
4
|
declare function xml(input: Record<string, any> | Record<string, any>[], options?: boolean | string | {
|
|
3
5
|
indent?: boolean | string;
|
|
@@ -7,129 +9,6 @@ declare function xml(input: Record<string, any> | Record<string, any>[], options
|
|
|
7
9
|
};
|
|
8
10
|
}): string;
|
|
9
11
|
//#endregion
|
|
10
|
-
//#region src/types.d.ts
|
|
11
|
-
interface Attributes {
|
|
12
|
-
[key: string]: string | number | undefined;
|
|
13
|
-
}
|
|
14
|
-
interface DeclarationAttributes {
|
|
15
|
-
version?: string | number;
|
|
16
|
-
encoding?: string;
|
|
17
|
-
standalone?: string;
|
|
18
|
-
}
|
|
19
|
-
interface Element {
|
|
20
|
-
declaration?: {
|
|
21
|
-
attributes?: DeclarationAttributes;
|
|
22
|
-
};
|
|
23
|
-
instruction?: string;
|
|
24
|
-
attributes?: Attributes;
|
|
25
|
-
cdata?: string;
|
|
26
|
-
doctype?: string;
|
|
27
|
-
comment?: string;
|
|
28
|
-
text?: string | number | boolean;
|
|
29
|
-
type?: string;
|
|
30
|
-
name?: string;
|
|
31
|
-
elements?: Element[];
|
|
32
|
-
parent?: Element;
|
|
33
|
-
}
|
|
34
|
-
interface ElementCompact {
|
|
35
|
-
[key: string]: any;
|
|
36
|
-
_declaration?: {
|
|
37
|
-
_attributes?: DeclarationAttributes;
|
|
38
|
-
};
|
|
39
|
-
_instruction?: {
|
|
40
|
-
[key: string]: string;
|
|
41
|
-
};
|
|
42
|
-
_attributes?: Attributes;
|
|
43
|
-
_cdata?: string;
|
|
44
|
-
_doctype?: string;
|
|
45
|
-
_comment?: string;
|
|
46
|
-
_text?: string | number;
|
|
47
|
-
}
|
|
48
|
-
interface IgnoreOptions {
|
|
49
|
-
ignoreDeclaration?: boolean;
|
|
50
|
-
ignoreInstruction?: boolean;
|
|
51
|
-
ignoreAttributes?: boolean;
|
|
52
|
-
ignoreComment?: boolean;
|
|
53
|
-
ignoreCdata?: boolean;
|
|
54
|
-
ignoreDoctype?: boolean;
|
|
55
|
-
ignoreText?: boolean;
|
|
56
|
-
}
|
|
57
|
-
interface Xml2JsOptions extends IgnoreOptions {
|
|
58
|
-
compact?: boolean;
|
|
59
|
-
trim?: boolean;
|
|
60
|
-
sanitize?: boolean;
|
|
61
|
-
nativeType?: boolean;
|
|
62
|
-
nativeTypeAttributes?: boolean;
|
|
63
|
-
addParent?: boolean;
|
|
64
|
-
alwaysArray?: boolean | string[];
|
|
65
|
-
alwaysChildren?: boolean;
|
|
66
|
-
instructionHasAttributes?: boolean;
|
|
67
|
-
captureSpacesBetweenElements?: boolean;
|
|
68
|
-
doctypeFn?: (value: string, parentElement: object) => string;
|
|
69
|
-
instructionFn?: (value: string, instructionName: string, parentElement: string) => string;
|
|
70
|
-
cdataFn?: (value: string, parentElement: object) => string;
|
|
71
|
-
commentFn?: (value: string, parentElement: object) => string;
|
|
72
|
-
textFn?: (value: string, parentElement: object) => string;
|
|
73
|
-
instructionNameFn?: (instructionName: string, instructionValue: string, parentElement: string) => string;
|
|
74
|
-
elementNameFn?: (value: string, parentElement: object) => string;
|
|
75
|
-
attributeNameFn?: (attributeName: string, attributeValue: string, parentElement: string) => string;
|
|
76
|
-
attributeValueFn?: (attributeValue: string, attributeName: string, parentElement: string) => string;
|
|
77
|
-
attributesFn?: (value: Attributes, parentElement: string) => Attributes;
|
|
78
|
-
}
|
|
79
|
-
interface Js2XmlOptions extends IgnoreOptions {
|
|
80
|
-
spaces?: number | string;
|
|
81
|
-
compact?: boolean;
|
|
82
|
-
indentText?: boolean;
|
|
83
|
-
indentCdata?: boolean;
|
|
84
|
-
indentAttributes?: boolean;
|
|
85
|
-
indentInstruction?: boolean;
|
|
86
|
-
fullTagEmptyElement?: boolean;
|
|
87
|
-
noQuotesForNativeAttributes?: boolean;
|
|
88
|
-
doctypeFn?: (value: string, currentElementName: string, currentElementObj: object) => string;
|
|
89
|
-
instructionFn?: (instructionValue: string, instructionName: string, currentElementName: string, currentElementObj: object) => string;
|
|
90
|
-
cdataFn?: (value: string, currentElementName: string, currentElementObj: object) => string;
|
|
91
|
-
commentFn?: (value: string, currentElementName: string, currentElementObj: object) => string;
|
|
92
|
-
textFn?: (value: string, currentElementName: string, currentElementObj: object) => string;
|
|
93
|
-
instructionNameFn?: (instructionName: string, instructionValue: string, currentElementName: string, currentElementObj: object) => string;
|
|
94
|
-
elementNameFn?: (value: string, currentElementName: string, currentElementObj: object) => string;
|
|
95
|
-
attributeNameFn?: (attributeName: string, attributeValue: string, currentElementName: string, currentElementObj: object) => string;
|
|
96
|
-
attributeValueFn?: (attributeValue: string, attributeName: string, currentElementName: string, currentElementObj: object) => string;
|
|
97
|
-
attributesFn?: (value: Attributes, currentElementName: string, currentElementObj: object) => Attributes;
|
|
98
|
-
fullTagEmptyElementFn?: (currentElementName: string, currentElementObj: object) => boolean;
|
|
99
|
-
}
|
|
100
|
-
interface XmlOption {
|
|
101
|
-
indent?: string;
|
|
102
|
-
stream?: boolean;
|
|
103
|
-
declaration?: boolean | {
|
|
104
|
-
encoding?: string;
|
|
105
|
-
standalone?: string;
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
interface XmlAttrs {
|
|
109
|
-
[attr: string]: XmlAtom;
|
|
110
|
-
}
|
|
111
|
-
type XmlAtom = string | number | boolean | null;
|
|
112
|
-
interface ElementObject {
|
|
113
|
-
push(xmlObject: XmlObject): void;
|
|
114
|
-
close(xmlObject?: XmlObject): void;
|
|
115
|
-
}
|
|
116
|
-
type XmlDesc = {
|
|
117
|
-
_attr: XmlAttrs;
|
|
118
|
-
} | {
|
|
119
|
-
_cdata: string;
|
|
120
|
-
} | {
|
|
121
|
-
_attr: XmlAttrs;
|
|
122
|
-
_cdata: string;
|
|
123
|
-
} | XmlAtom | XmlAtom[] | XmlDescArray;
|
|
124
|
-
interface XmlDescArray {
|
|
125
|
-
[index: number]: {
|
|
126
|
-
_attr: XmlAttrs;
|
|
127
|
-
} | XmlObject;
|
|
128
|
-
}
|
|
129
|
-
type XmlObject = {
|
|
130
|
-
[tag: string]: ElementObject | XmlDesc;
|
|
131
|
-
} | XmlDesc;
|
|
132
|
-
//#endregion
|
|
133
12
|
//#region src/parse.d.ts
|
|
134
13
|
declare function xml2js(xmlString: string, options?: Xml2JsOptions): Element;
|
|
135
14
|
//#endregion
|
|
@@ -158,4 +37,4 @@ declare function escapeAttributeValue(str: string): string;
|
|
|
158
37
|
/** Convert XML string to JSON string — xml-js compatible export */
|
|
159
38
|
declare function xml2json(xml: string, options?: Xml2JsOptions): string;
|
|
160
39
|
//#endregion
|
|
161
|
-
export { Attributes, DeclarationAttributes, Element, ElementCompact, ElementObject, IgnoreOptions, Js2XmlOptions, Xml2JsOptions, XmlAtom, XmlAttrs, XmlDesc, XmlDescArray, XmlObject, XmlOption, escapeAttributeValue, escapeXml, js2xml, json2xml, toElement, xml, xml2js, xml2json };
|
|
40
|
+
export { Attributes, DeclarationAttributes, Element, ElementCompact, ElementObject, IgnoreOptions, Js2XmlOptions, Xml2JsOptions, XmlAtom, XmlAttrs, XmlDesc, XmlDescArray, XmlObject, XmlOption, allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, colorAttr, escapeAttributeValue, escapeXml, findChild, findDeep, hasChild, js2xml, json2xml, textOf, toElement, xml, xml2js, xml2json };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, hasChild, textOf } from "./utils.mjs";
|
|
1
2
|
//#region src/escape.ts
|
|
2
3
|
const XML_CHAR_MAP = {
|
|
3
4
|
"&": "&",
|
|
@@ -66,6 +67,7 @@ function resolve(data, indent, depth) {
|
|
|
66
67
|
switch (typeof values) {
|
|
67
68
|
case "object":
|
|
68
69
|
if (values._attr) for (const key of Object.keys(values._attr)) attributes.push(`${key}="${escapeXml(String(values._attr[key]))}"`);
|
|
70
|
+
if (values._attributes) for (const key of Object.keys(values._attributes)) attributes.push(`${key}="${escapeXml(String(values._attributes[key]))}"`);
|
|
69
71
|
if (values._cdata) {
|
|
70
72
|
const escaped = String(values._cdata).replace(/\]\]>/g, "]]]]><![CDATA[>");
|
|
71
73
|
content.push(`<![CDATA[${escaped}]]>`);
|
|
@@ -80,6 +82,7 @@ function resolve(data, indent, depth) {
|
|
|
80
82
|
emptyArray: true
|
|
81
83
|
};
|
|
82
84
|
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]))}"`);
|
|
85
|
+
else if (value && typeof value === "object" && "_attributes" in value) for (const key of Object.keys(value._attributes)) attributes.push(`${key}="${escapeXml(String(value._attributes[key]))}"`);
|
|
83
86
|
else if (value && typeof value === "object") content.push(resolve(value, indent, depth + 1));
|
|
84
87
|
else if (value != null) content.push(escapeXml(String(value)));
|
|
85
88
|
}
|
|
@@ -499,4 +502,4 @@ function xml2json(xml, options) {
|
|
|
499
502
|
return JSON.stringify(xml2js(xml, options));
|
|
500
503
|
}
|
|
501
504
|
//#endregion
|
|
502
|
-
export { escapeAttributeValue, escapeXml, js2xml, json2xml, toElement, xml, xml2js, xml2json };
|
|
505
|
+
export { allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, colorAttr, escapeAttributeValue, escapeXml, findChild, findDeep, hasChild, js2xml, json2xml, textOf, toElement, xml, xml2js, xml2json };
|
package/dist/utils.d.mts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
//#region src/utils.ts
|
|
2
|
+
/**
|
|
3
|
+
* Find the first direct child element with the given name.
|
|
4
|
+
*/
|
|
5
|
+
function findChild(parent, name) {
|
|
6
|
+
return parent?.elements?.find((e) => e.name === name);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Get all direct child elements matching the given name.
|
|
10
|
+
*/
|
|
11
|
+
function children(parent, name) {
|
|
12
|
+
return parent?.elements?.filter((e) => e.name === name) ?? [];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get all direct child elements.
|
|
16
|
+
*/
|
|
17
|
+
function allChildren(parent) {
|
|
18
|
+
return parent?.elements ?? [];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get text content of the first child element with the given name.
|
|
22
|
+
*/
|
|
23
|
+
function childText(parent, name) {
|
|
24
|
+
return textOf(findChild(parent, name));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get text content of an element.
|
|
28
|
+
* Handles cases where text may be directly on .text or in a child element.
|
|
29
|
+
*/
|
|
30
|
+
function textOf(element) {
|
|
31
|
+
if (!element) return "";
|
|
32
|
+
if (element.text !== void 0 && typeof element.text === "string") return element.text;
|
|
33
|
+
if (element.elements && element.elements.length > 0) return element.elements.map((e) => typeof e.text === "string" ? e.text : "").join("");
|
|
34
|
+
return "";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Collect text from all direct text nodes within an element.
|
|
38
|
+
*/
|
|
39
|
+
function collectText(element) {
|
|
40
|
+
if (!element) return "";
|
|
41
|
+
const parts = [];
|
|
42
|
+
collectTextRecursive(element, parts);
|
|
43
|
+
return parts.join("");
|
|
44
|
+
}
|
|
45
|
+
function collectTextRecursive(element, parts) {
|
|
46
|
+
if (!element) return;
|
|
47
|
+
if (element.text !== void 0 && typeof element.text === "string") parts.push(element.text);
|
|
48
|
+
if (element.elements) for (const child of element.elements) collectTextRecursive(child, parts);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get an attribute value as a string.
|
|
52
|
+
*/
|
|
53
|
+
function attr(element, name) {
|
|
54
|
+
const v = element?.attributes?.[name];
|
|
55
|
+
return v !== void 0 ? String(v) : void 0;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get an attribute value as a number.
|
|
59
|
+
*/
|
|
60
|
+
function attrNum(element, name) {
|
|
61
|
+
const v = element?.attributes?.[name];
|
|
62
|
+
if (v === void 0) return void 0;
|
|
63
|
+
const n = Number(v);
|
|
64
|
+
return isNaN(n) ? void 0 : n;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get an attribute value as a boolean.
|
|
68
|
+
*/
|
|
69
|
+
function attrBool(element, name) {
|
|
70
|
+
const v = element?.attributes?.[name];
|
|
71
|
+
if (v === void 0) return void 0;
|
|
72
|
+
if (typeof v === "boolean") return v;
|
|
73
|
+
const lower = String(v).toLowerCase();
|
|
74
|
+
if (lower === "true" || lower === "1") return true;
|
|
75
|
+
if (lower === "false" || lower === "0") return false;
|
|
76
|
+
}
|
|
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
|
+
/**
|
|
92
|
+
* Check if an element has a specific child element.
|
|
93
|
+
*/
|
|
94
|
+
function hasChild(parent, name) {
|
|
95
|
+
return parent?.elements?.some((e) => e.name === name) ?? false;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Find deep descendant elements matching the given name.
|
|
99
|
+
*/
|
|
100
|
+
function findDeep(parent, name) {
|
|
101
|
+
const result = [];
|
|
102
|
+
if (!parent) return result;
|
|
103
|
+
for (const child of parent.elements ?? []) {
|
|
104
|
+
if (child.name === name) result.push(child);
|
|
105
|
+
result.push(...findDeep(child, name));
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get the number of direct child elements.
|
|
111
|
+
*/
|
|
112
|
+
function childCount(parent) {
|
|
113
|
+
return parent?.elements?.length ?? 0;
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
export { allChildren, attr, attrBool, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, hasChild, textOf };
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@office-open/xml",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "XML parsing and serialization,
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "XML parsing and serialization for Office Open XML. Zero dependencies, drop-in replacement for xml + xml-js.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"office-open",
|
|
7
7
|
"ooxml",
|
|
8
8
|
"parse",
|
|
9
9
|
"serialize",
|
|
10
|
-
"xml"
|
|
10
|
+
"xml",
|
|
11
|
+
"zero-dependencies"
|
|
11
12
|
],
|
|
12
13
|
"homepage": "https://github.com/DemoMacro/office-open#readme",
|
|
13
14
|
"bugs": {
|
|
@@ -33,6 +34,10 @@
|
|
|
33
34
|
".": {
|
|
34
35
|
"types": "./dist/index.d.mts",
|
|
35
36
|
"import": "./dist/index.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./utils": {
|
|
39
|
+
"types": "./dist/utils.d.mts",
|
|
40
|
+
"import": "./dist/utils.mjs"
|
|
36
41
|
}
|
|
37
42
|
},
|
|
38
43
|
"devDependencies": {
|