@office-open/xml 0.10.12 → 0.10.13

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.d.mts CHANGED
@@ -1,11 +1,6 @@
1
- import { C as Xml2JsOptions, D as XmlDescArray, E as XmlDesc, O as XmlObject, S as Js2XmlOptions, T as XmlAttrs, _ as DeclarationAttributes, a as attrNum, b as ElementObject, c as children, d as findChild, f as findDeep, g as Attributes, h as textOf, i as attrMeasure, k as XmlOption, l as collectText, m as hasChild, n as attr, o as childCount, p as findFirst, r as attrBool, s as childText, t as allChildren, u as colorAttr, v as Element, w as XmlAtom, x as IgnoreOptions, y as ElementCompact } from "./utils-t-_-N57p.mjs";
1
+ import { A as XmlObject, C as IgnoreOptions, D as XmlAttrs, E as XmlAtom, O as XmlDesc, S as ElementObject, T as Xml2JsOptions, _ as textOf, a as attrMeasure, b as Element, c as childText, d as colorAttr, f as findChild, g as isNonEmpty, h as hasChild, i as attrBool, j as XmlOption, k as XmlDescArray, l as children, m as findFirst, n as allChildren, o as attrNum, p as findDeep, r as attr, s as childCount, t as NonEmptyArray, u as collectText, v as Attributes, w as Js2XmlOptions, x as ElementCompact, y as DeclarationAttributes } from "./utils-BFKTfRa8.mjs";
2
2
 
3
3
  //#region src/serialize.d.ts
4
- /**
5
- * Serialize IXmlableObject to XML string.
6
- * @deprecated Use `stringify` (Element → string) instead. This IXmlableObject path
7
- * will be removed once the Descriptor migration is complete.
8
- */
9
4
  declare function xml(input: Record<string, unknown> | Record<string, unknown>[], options?: boolean | string | {
10
5
  indent?: boolean | string;
11
6
  declaration?: boolean | {
@@ -22,66 +17,20 @@ declare function parseAttributes(str: string): Record<string, string>;
22
17
  //#endregion
23
18
  //#region src/stringify.d.ts
24
19
  declare function stringify(js: Element, options?: Js2XmlOptions): string;
25
- /** @deprecated Use `stringify` instead. xml-js compatible alias. */
26
20
  declare function json2xml(json: Element, options?: Js2XmlOptions): string;
27
21
  //#endregion
28
22
  //#region src/convert.d.ts
29
- /**
30
- * Convert XmlObject (node-xml format) directly to Element (xml-js format).
31
- * Eliminates the redundant xml() → xml2js() bridge path.
32
- */
33
23
  declare function toElement(xmlObject: Record<string, unknown>): Element;
34
24
  //#endregion
35
25
  //#region src/escape.d.ts
36
- /** Escape text content for XML. Fast path returns original string when no special chars. */
37
26
  declare function escapeXml(str: string): string;
38
- /**
39
- * Build an XML attribute string fragment from a record.
40
- * `undefined` values are automatically skipped.
41
- * String values are escaped via `escapeXml`.
42
- *
43
- * @example
44
- * attrs({ id: 1, name: "foo", hidden: undefined })
45
- * // => ' id="1" name="foo"'
46
- */
47
27
  declare function attrs(record: Record<string, string | number | boolean | undefined>): string;
48
- /**
49
- * Build an XML attribute string without escaping.
50
- *
51
- * Same as `attrs()` but skips `typeof` checks and `escapeXml` — use only when
52
- * all values are known-safe (numbers, booleans, or strings free of `& " ' < >`).
53
- * Avoids per-call array and `Object.keys()` allocation in hot loops.
54
- *
55
- * @example
56
- * attrsRaw({ r: "A1", s: 5 })
57
- * // => ' r="A1" s="5"'
58
- */
59
28
  declare function attrsRaw(record: Record<string, string | number | boolean | undefined>): string;
60
- /**
61
- * Build a self-closing XML element: `<tag attrStr/>`.
62
- * `attrStr` is a pre-serialized attribute string (from `attrs()`) or undefined.
63
- */
64
29
  declare function selfCloseElement(tag: string, attrStr?: string): string;
65
- /**
66
- * Build a complete XML element string from name, optional attributes, and string children.
67
- *
68
- * Replaces `new BuilderElement({...})` + `.toXml()` / `.serialize()` with a
69
- * single function call returning a string — zero object allocation.
70
- *
71
- * @param name Element tag name (e.g. `"a:srgbClr"`)
72
- * @param attrRecord Optional flat attribute map; `undefined` values are skipped
73
- * @param children Optional pre-serialized child XML strings
74
- *
75
- * @example
76
- * ```ts
77
- * element("a:solidFill", undefined, [element("a:srgbClr", { val: "FF0000" })])
78
- * // => '<a:solidFill><a:srgbClr val="FF0000"/></a:solidFill>'
79
- * ```
80
- */
81
30
  declare function element(name: string, attrRecord?: Readonly<Record<string, string | number | boolean | undefined>>, children?: readonly string[]): string;
82
31
  //#endregion
83
32
  //#region src/json.d.ts
84
- /** Convert XML string to JSON string — xml-js compatible export */
85
33
  declare function xml2json(xml: string, options?: Xml2JsOptions): string;
86
34
  //#endregion
87
- export { type Attributes, type DeclarationAttributes, type Element, type ElementCompact, type ElementObject, type IgnoreOptions, type Js2XmlOptions, type Xml2JsOptions, type XmlAtom, type XmlAttrs, type XmlDesc, type XmlDescArray, type XmlObject, type XmlOption, allChildren, attr, attrBool, attrMeasure, attrNum, attrs, attrsRaw, childCount, childText, children, collectText, colorAttr, element, escapeXml, findChild, findDeep, findFirst, hasChild, stringify as js2xml, stringify, json2xml, nativeTypeValue, parse, parse as xml2js, parseAttributes, selfCloseElement, textOf, toElement, unescapeXml, xml, xml2json };
35
+ export { type Attributes, type DeclarationAttributes, type Element, type ElementCompact, type ElementObject, type IgnoreOptions, type Js2XmlOptions, NonEmptyArray, type Xml2JsOptions, type XmlAtom, type XmlAttrs, type XmlDesc, type XmlDescArray, type XmlObject, type XmlOption, allChildren, attr, attrBool, attrMeasure, attrNum, attrs, attrsRaw, childCount, childText, children, collectText, colorAttr, element, escapeXml, findChild, findDeep, findFirst, hasChild, isNonEmpty, stringify as js2xml, stringify, json2xml, nativeTypeValue, parse, parse as xml2js, parseAttributes, selfCloseElement, textOf, toElement, unescapeXml, xml, xml2json };
36
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/serialize.ts","../src/parse.ts","../src/stringify.ts","../src/convert.ts","../src/escape.ts","../src/json.ts"],"mappings":";;;iBASgB,GAAA,CACd,KAAA,EAAO,MAAA,oBAA0B,MAAM,qBACvC,OAAA;EAIM,MAAA;EACA,WAAA;IAA0B,QAAA;IAAmB,UAAA;EAAA;AAAA;;;iBCHrC,WAAA,CAAY,GAAW;AAAA,iBAWvB,eAAA,CAAgB,KAAa;AAAA,iBAa7B,KAAA,CAAM,SAAA,UAAmB,OAAA,GAAU,aAAA,GAAgB,OAAO;AAAA,iBAmN1D,eAAA,CAAgB,GAAA,WAAc,MAAM;;;iBCrPpC,SAAA,CAAU,EAAA,EAAI,OAAA,EAAS,OAAA,GAAU,aAAa;AAAA,iBAmB9C,QAAA,CAAS,IAAA,EAAM,OAAA,EAAS,OAAA,GAAU,aAAa;;;iBChB/C,SAAA,CAAU,SAAA,EAAW,MAAA,oBAA0B,OAAO;;;iBCLtD,SAAA,CAAU,GAAW;AAAA,iBA6CrB,KAAA,CAAM,MAA6D,EAArD,MAAM;AAAA,iBAqBpB,QAAA,CAAS,MAA6D,EAArD,MAAM;AAAA,iBAevB,gBAAA,CAAiB,GAAA,UAAa,OAAgB;AAAA,iBAoB9C,OAAA,CACd,IAAA,UACA,UAAA,GAAa,QAAQ,CAAC,MAAA,kDACtB,QAAA;;;iBCrGc,QAAA,CAAS,GAAA,UAAa,OAAA,GAAU,aAAa"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { allChildren, attr, attrBool, attrMeasure, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, findFirst, hasChild, textOf } from "./utils.mjs";
1
+ import { allChildren, attr, attrBool, attrMeasure, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, findFirst, hasChild, isNonEmpty, textOf } from "./utils.mjs";
2
2
  //#region src/escape.ts
3
3
  /** Escape text content for XML. Fast path returns original string when no special chars. */
4
4
  function escapeXml(str) {
@@ -42,11 +42,7 @@ function escapeXml(str) {
42
42
  */
43
43
  function attrs(record) {
44
44
  const parts = [];
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) parts.push(` ${keys[i]}="${typeof v === "string" ? escapeXml(v) : v}"`);
49
- }
45
+ for (const [key, v] of Object.entries(record)) if (v !== void 0) parts.push(` ${key}="${typeof v === "string" ? escapeXml(v) : v}"`);
50
46
  return parts.join("");
51
47
  }
52
48
  /**
@@ -101,8 +97,8 @@ function element(name, attrRecord, children) {
101
97
  //#region src/serialize.ts
102
98
  const DEFAULT_INDENT = " ";
103
99
  /**
104
- * Serialize IXmlableObject to XML string.
105
- * @deprecated Use `stringify` (Element → string) instead. This IXmlableObject path
100
+ * Serialize a Record-based XML object tree to an XML string.
101
+ * @deprecated Use `stringify` (Element → string) instead. This object-tree path
106
102
  * will be removed once the Descriptor migration is complete.
107
103
  */
108
104
  function xml(input, options) {
@@ -120,8 +116,11 @@ function xml(input, options) {
120
116
  }
121
117
  const items = Array.isArray(input) ? input : [input];
122
118
  for (let i = 0; i < items.length; i++) {
123
- const keys = Object.keys(items[i]);
124
- parts.push(formatElement(keys[0], items[i][keys[0]], opts.indent, 0));
119
+ const item = items[i];
120
+ if (!item) continue;
121
+ const key = Object.keys(item)[0];
122
+ if (!key) continue;
123
+ parts.push(formatElement(key, item[key], opts.indent, 0));
125
124
  if (opts.indent && i < items.length - 1) parts.push("\n");
126
125
  }
127
126
  return parts.join("");
@@ -136,7 +135,7 @@ function normalizeOptions$1(options) {
136
135
  };
137
136
  }
138
137
  /**
139
- * Single-pass XML formatter: directly converts IXmlableObject to string,
138
+ * Single-pass XML formatter: directly converts a Record-based XML object to string,
140
139
  * eliminating the intermediate ResolvedElement tree.
141
140
  */
142
141
  function formatElement(name, values, indent, depth) {
@@ -171,8 +170,8 @@ function formatElement(name, values, indent, depth) {
171
170
  const attr = value._attributes;
172
171
  for (const key of Object.keys(attr)) attrParts.push(`${key}="${escapeXml(String(attr[key]))}"`);
173
172
  } else if (value && typeof value === "object") {
174
- const childKeys = Object.keys(value);
175
- elemParts.push(formatElement(childKeys[0], value[childKeys[0]], indent, depth + 1));
173
+ const childKey = Object.keys(value)[0];
174
+ if (childKey) elemParts.push(formatElement(childKey, value[childKey], indent, depth + 1));
176
175
  } else if (value != null) textParts.push(escapeXml(String(value)));
177
176
  }
178
177
  } else textParts.push(escapeXml(String(values)));
@@ -243,7 +242,7 @@ function parse(xmlString, options) {
243
242
  if (trim) text = text.trim();
244
243
  if (ignoreText) continue;
245
244
  if (text.length > 0) {
246
- if (captureSpaces || text.trim().length > 0 || isPreserveContext(stack)) addField(stack[stack.length - 1], "text", text);
245
+ if (captureSpaces || text.trim().length > 0 || isPreserveContext(stack)) addField(peek(stack), "text", text);
247
246
  }
248
247
  continue;
249
248
  }
@@ -257,8 +256,8 @@ function parse(xmlString, options) {
257
256
  if (xmlMatch) {
258
257
  if (!ignoreDeclaration) {
259
258
  if (!result.declaration) result.declaration = {};
260
- const attrs = parseAttributes(xmlMatch[1]);
261
- if (nativeTypeAttributes) for (const key of Object.keys(attrs)) attrs[key] = nativeTypeValue(attrs[key]);
259
+ const attrs = parseAttributes(xmlMatch[1] ?? "");
260
+ if (nativeTypeAttributes) for (const key in attrs) attrs[key] = nativeTypeValue(attrs[key]);
262
261
  result.declaration.attributes = attrs;
263
262
  }
264
263
  }
@@ -269,8 +268,8 @@ function parse(xmlString, options) {
269
268
  if (end === -1) break;
270
269
  const comment = xmlString.slice(i + 3, end);
271
270
  i = end + 3;
272
- if (!ignoreComment) if (trim) addField(stack[stack.length - 1], "comment", comment.trim());
273
- else addField(stack[stack.length - 1], "comment", comment);
271
+ if (!ignoreComment) if (trim) addField(peek(stack), "comment", comment.trim());
272
+ else addField(peek(stack), "comment", comment);
274
273
  continue;
275
274
  }
276
275
  if (xmlString.charCodeAt(i) === 33 && xmlString.slice(i, i + 8) === "![CDATA[") {
@@ -278,8 +277,8 @@ function parse(xmlString, options) {
278
277
  if (end === -1) break;
279
278
  const cdata = xmlString.slice(i + 8, end);
280
279
  i = end + 3;
281
- if (!ignoreCdata) if (trim) addField(stack[stack.length - 1], "cdata", cdata.trim());
282
- else addField(stack[stack.length - 1], "cdata", cdata);
280
+ if (!ignoreCdata) if (trim) addField(peek(stack), "cdata", cdata.trim());
281
+ else addField(peek(stack), "cdata", cdata);
283
282
  continue;
284
283
  }
285
284
  if (xmlString.charCodeAt(i) === 33 && xmlString.slice(i, i + 9) === "!DOCTYPE") {
@@ -287,7 +286,7 @@ function parse(xmlString, options) {
287
286
  if (end === -1) break;
288
287
  const doctype = xmlString.slice(i + 9, end).trim();
289
288
  i = end + 1;
290
- if (!ignoreDoctype) addField(stack[stack.length - 1], "doctype", doctype);
289
+ if (!ignoreDoctype) addField(peek(stack), "doctype", doctype);
291
290
  continue;
292
291
  }
293
292
  if (xmlString.charCodeAt(i) === 47) {
@@ -302,7 +301,7 @@ function parse(xmlString, options) {
302
301
  let pos = tagNameEnd;
303
302
  const attributes = parseAttributesFromXml(xmlString, pos);
304
303
  pos = attributes.pos;
305
- if (nativeTypeAttributes) for (const key of Object.keys(attributes.attrs)) attributes.attrs[key] = nativeTypeValue(attributes.attrs[key]);
304
+ if (nativeTypeAttributes) for (const key in attributes.attrs) attributes.attrs[key] = nativeTypeValue(attributes.attrs[key]);
306
305
  const isSelfClosing = xmlString.charCodeAt(pos) === 47;
307
306
  if (isSelfClosing) pos += 2;
308
307
  else pos++;
@@ -311,7 +310,7 @@ function parse(xmlString, options) {
311
310
  name: tagName
312
311
  };
313
312
  if (Object.keys(attributes.attrs).length > 0) element.attributes = attributes.attrs;
314
- const parent = stack[stack.length - 1];
313
+ const parent = peek(stack);
315
314
  if (!parent.elements) parent.elements = [];
316
315
  parent.elements.push(element);
317
316
  if (!isSelfClosing) stack.push(element);
@@ -391,6 +390,17 @@ function parseAttributes(str) {
391
390
  }
392
391
  return result;
393
392
  }
393
+ /**
394
+ * Top of the parse stack. The stack is guaranteed non-empty — the result root
395
+ * is pushed at init and push/pop stay balanced across well-formed input — so
396
+ * this is a compile-time narrow (one non-null assertion) rather than a runtime
397
+ * check: it must not add a throw path that changes how `parse` surfaces
398
+ * malformed documents. Centralising the access keeps that single `!` off the
399
+ * read sites, matching the "wrap indexed access behind a helper" pattern.
400
+ */
401
+ function peek(stack) {
402
+ return stack[stack.length - 1];
403
+ }
394
404
  function addField(parent, type, value) {
395
405
  if (!parent.elements) parent.elements = [];
396
406
  if (type === "text" || type === "cdata") {
@@ -408,7 +418,9 @@ function addField(parent, type, value) {
408
418
  /** True when the nearest ancestor with an explicit xml:space sets "preserve". */
409
419
  function isPreserveContext(stack) {
410
420
  for (let i = stack.length - 1; i >= 0; i--) {
411
- const space = stack[i].attributes?.["xml:space"];
421
+ const node = stack[i];
422
+ if (!node) continue;
423
+ const space = node.attributes?.["xml:space"];
412
424
  if (space !== void 0) return space === "preserve";
413
425
  }
414
426
  return false;
@@ -495,6 +507,7 @@ function writeElements(elements, opts, depth, firstLine) {
495
507
  const parts = [];
496
508
  for (let i = 0; i < elements.length; i++) {
497
509
  const element = elements[i];
510
+ if (!element) continue;
498
511
  const isFirst = firstLine && i === 0;
499
512
  switch (element.type) {
500
513
  case "element":
@@ -572,6 +585,10 @@ function writeDoctype(doctype) {
572
585
  */
573
586
  function toElement(xmlObject) {
574
587
  const tagName = Object.keys(xmlObject)[0];
588
+ if (!tagName) return {
589
+ type: "element",
590
+ name: ""
591
+ };
575
592
  const value = xmlObject[tagName];
576
593
  const element = {
577
594
  type: "element",
@@ -617,4 +634,6 @@ function xml2json(xml, options) {
617
634
  return JSON.stringify(parse(xml, options));
618
635
  }
619
636
  //#endregion
620
- export { allChildren, attr, attrBool, attrMeasure, attrNum, attrs, attrsRaw, childCount, childText, children, collectText, colorAttr, element, escapeXml, findChild, findDeep, findFirst, hasChild, stringify as js2xml, stringify, json2xml, nativeTypeValue, parse, parse as xml2js, parseAttributes, selfCloseElement, textOf, toElement, unescapeXml, xml, xml2json };
637
+ export { allChildren, attr, attrBool, attrMeasure, attrNum, attrs, attrsRaw, childCount, childText, children, collectText, colorAttr, element, escapeXml, findChild, findDeep, findFirst, hasChild, isNonEmpty, stringify as js2xml, stringify, json2xml, nativeTypeValue, parse, parse as xml2js, parseAttributes, selfCloseElement, textOf, toElement, unescapeXml, xml, xml2json };
638
+
639
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["normalizeOptions","xml2js"],"sources":["../src/escape.ts","../src/serialize.ts","../src/parse.ts","../src/stringify.ts","../src/convert.ts","../src/json.ts"],"sourcesContent":["/** Escape text content for XML. Fast path returns original string when no special chars. */\nexport function escapeXml(str: string): string {\n // Fast path: most text content doesn't contain XML-special characters.\n // Manual scan avoids regex overhead; returning the original string reference\n // means zero allocation for the common case.\n for (let i = 0; i < str.length; i++) {\n const c = str.charCodeAt(i);\n if (c === 38 || c === 34 || c === 39 || c === 60 || c === 62) {\n // & \" ' < >\n // Slow path: slice-and-append avoids regex + temporary match objects.\n let s = \"\";\n let last = 0;\n for (let j = i; j < str.length; j++) {\n const cj = str.charCodeAt(j);\n if (cj === 38) {\n s += str.slice(last, j) + \"&amp;\";\n last = j + 1;\n } else if (cj === 34) {\n s += str.slice(last, j) + \"&quot;\";\n last = j + 1;\n } else if (cj === 39) {\n s += str.slice(last, j) + \"&apos;\";\n last = j + 1;\n } else if (cj === 60) {\n s += str.slice(last, j) + \"&lt;\";\n last = j + 1;\n } else if (cj === 62) {\n s += str.slice(last, j) + \"&gt;\";\n last = j + 1;\n }\n }\n return s + str.slice(last);\n }\n }\n return str;\n}\n\n/**\n * Build an XML attribute string fragment from a record.\n * `undefined` values are automatically skipped.\n * String values are escaped via `escapeXml`.\n *\n * @example\n * attrs({ id: 1, name: \"foo\", hidden: undefined })\n * // => ' id=\"1\" name=\"foo\"'\n */\nexport function attrs(record: Record<string, string | number | boolean | undefined>): string {\n const parts: string[] = [];\n for (const [key, v] of Object.entries(record)) {\n if (v !== undefined) {\n parts.push(` ${key}=\"${typeof v === \"string\" ? escapeXml(v) : v}\"`);\n }\n }\n return parts.join(\"\");\n}\n\n/**\n * Build an XML attribute string without escaping.\n *\n * Same as `attrs()` but skips `typeof` checks and `escapeXml` — use only when\n * all values are known-safe (numbers, booleans, or strings free of `& \" ' < >`).\n * Avoids per-call array and `Object.keys()` allocation in hot loops.\n *\n * @example\n * attrsRaw({ r: \"A1\", s: 5 })\n * // => ' r=\"A1\" s=\"5\"'\n */\nexport function attrsRaw(record: Record<string, string | number | boolean | undefined>): string {\n let s = \"\";\n for (const key in record) {\n const v = record[key];\n if (v !== undefined) {\n s += ` ${key}=\"${v}\"`;\n }\n }\n return s;\n}\n\n/**\n * Build a self-closing XML element: `<tag attrStr/>`.\n * `attrStr` is a pre-serialized attribute string (from `attrs()`) or undefined.\n */\nexport function selfCloseElement(tag: string, attrStr?: string): string {\n return attrStr ? `<${tag}${attrStr}/>` : `<${tag}/>`;\n}\n\n/**\n * Build a complete XML element string from name, optional attributes, and string children.\n *\n * Replaces `new BuilderElement({...})` + `.toXml()` / `.serialize()` with a\n * single function call returning a string — zero object allocation.\n *\n * @param name Element tag name (e.g. `\"a:srgbClr\"`)\n * @param attrRecord Optional flat attribute map; `undefined` values are skipped\n * @param children Optional pre-serialized child XML strings\n *\n * @example\n * ```ts\n * element(\"a:solidFill\", undefined, [element(\"a:srgbClr\", { val: \"FF0000\" })])\n * // => '<a:solidFill><a:srgbClr val=\"FF0000\"/></a:solidFill>'\n * ```\n */\nexport function element(\n name: string,\n attrRecord?: Readonly<Record<string, string | number | boolean | undefined>>,\n children?: readonly string[],\n): string {\n const attrStr = attrRecord ? attrs(attrRecord) : undefined;\n if (!children || children.length === 0) return selfCloseElement(name, attrStr);\n const body = children.join(\"\");\n return body.length === 0\n ? selfCloseElement(name, attrStr)\n : `<${name}${attrStr ?? \"\"}>${body}</${name}>`;\n}\n","import { escapeXml } from \"./escape\";\n\nconst DEFAULT_INDENT = \" \";\n\n/**\n * Serialize a Record-based XML object tree to an XML string.\n * @deprecated Use `stringify` (Element → string) instead. This object-tree path\n * will be removed once the Descriptor migration is complete.\n */\nexport function xml(\n input: Record<string, unknown> | Record<string, unknown>[],\n options?:\n | boolean\n | string\n | {\n indent?: boolean | string;\n declaration?: boolean | { encoding?: string; standalone?: string };\n },\n): string {\n const opts = normalizeOptions(options);\n const parts: string[] = [];\n\n if (opts.declaration) {\n const declOpts = opts.declaration === true ? {} : opts.declaration;\n const enc = declOpts.encoding || \"UTF-8\";\n const sa = declOpts.standalone;\n const declParts: string[] = [`<?xml version=\"1.0\" encoding=\"${enc}\"`];\n if (sa) declParts.push(` standalone=\"${sa}\"`);\n declParts.push(\"?>\");\n parts.push(declParts.join(\"\"));\n if (opts.indent) parts.push(\"\\n\");\n }\n\n const items = Array.isArray(input) ? input : [input];\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (!item) continue;\n const key = Object.keys(item)[0];\n if (!key) continue;\n parts.push(formatElement(key, item[key], opts.indent, 0));\n if (opts.indent && i < items.length - 1) parts.push(\"\\n\");\n }\n\n return parts.join(\"\");\n}\n\ntype XmlInputOptions = {\n indent?: boolean | string;\n declaration?: boolean | { encoding?: string; standalone?: string };\n};\n\nfunction normalizeOptions(options?: boolean | string | XmlInputOptions): {\n indent: string;\n declaration: XmlInputOptions[\"declaration\"];\n} {\n const opts =\n typeof options === \"object\" && !Array.isArray(options)\n ? options\n : { indent: options as boolean | string };\n let indent = \"\";\n if (opts.indent) {\n indent = opts.indent === true ? DEFAULT_INDENT : String(opts.indent);\n }\n return { indent, declaration: opts.declaration };\n}\n\n/**\n * Single-pass XML formatter: directly converts a Record-based XML object to string,\n * eliminating the intermediate ResolvedElement tree.\n */\nfunction formatElement(name: string, values: unknown, indent: string, depth: number): string {\n const attrParts: string[] = [];\n const textParts: string[] = [];\n const elemParts: string[] = [];\n let emptyArray = false;\n\n if (values == null) {\n const attrStr = attrParts.length ? \" \" + attrParts.join(\" \") : \"\";\n const ind = indent ? indent.repeat(depth) : \"\";\n return `${ind}<${name}${attrStr}/>`;\n }\n\n if (typeof values === \"object\") {\n const obj = values as Record<string, unknown>;\n if (obj._attr) {\n const attr = obj._attr as Record<string, unknown>;\n for (const key of Object.keys(attr)) {\n attrParts.push(`${key}=\"${escapeXml(String(attr[key]))}\"`);\n }\n }\n if (obj._attributes) {\n const attr = obj._attributes as Record<string, unknown>;\n for (const key of Object.keys(attr)) {\n attrParts.push(`${key}=\"${escapeXml(String(attr[key]))}\"`);\n }\n }\n if (obj._cdata) {\n const escaped = String(obj._cdata as string).replace(/\\]\\]>/g, \"]]]]><![CDATA[>\");\n textParts.push(`<![CDATA[${escaped}]]>`);\n }\n if (Array.isArray(values)) {\n if (values.length === 0) {\n emptyArray = true;\n } else {\n for (const value of values) {\n if (value && typeof value === \"object\" && \"_attr\" in value) {\n const attr = (value as Record<string, unknown>)._attr as Record<string, unknown>;\n for (const key of Object.keys(attr)) {\n attrParts.push(`${key}=\"${escapeXml(String(attr[key]))}\"`);\n }\n } else if (value && typeof value === \"object\" && \"_attributes\" in value) {\n const attr = (value as Record<string, unknown>)._attributes as Record<string, unknown>;\n for (const key of Object.keys(attr)) {\n attrParts.push(`${key}=\"${escapeXml(String(attr[key]))}\"`);\n }\n } else if (value && typeof value === \"object\") {\n const childKeys = Object.keys(value);\n const childKey = childKeys[0];\n if (childKey) {\n elemParts.push(\n formatElement(\n childKey,\n (value as Record<string, unknown>)[childKey],\n indent,\n depth + 1,\n ),\n );\n }\n } else if (value != null) {\n textParts.push(escapeXml(String(value)));\n }\n }\n }\n }\n } else {\n textParts.push(escapeXml(String(values as string | number | boolean)));\n }\n\n const ind = indent ? indent.repeat(depth) : \"\";\n const attrStr = attrParts.length ? \" \" + attrParts.join(\" \") : \"\";\n const totalParts = textParts.length + elemParts.length;\n\n if (totalParts === 0) {\n return emptyArray ? `${ind}<${name}${attrStr}></${name}>` : `${ind}<${name}${attrStr}/>`;\n }\n\n // Text-only optimization: single text child, no element children\n if (elemParts.length === 0 && textParts.length === 1) {\n return indent\n ? `${ind}<${name}${attrStr}>${textParts[0]}</${name}>`\n : `<${name}${attrStr}>${textParts[0]}</${name}>`;\n }\n\n // Mixed content\n const parts: string[] = [];\n parts.push(`${ind}<${name}${attrStr}>`);\n if (indent) parts.push(\"\\n\");\n const childIndent = indent ? indent.repeat(depth + 1) : \"\";\n for (const t of textParts) {\n parts.push(`${childIndent}${t}`);\n if (indent) parts.push(\"\\n\");\n }\n for (const e of elemParts) {\n parts.push(e);\n if (indent) parts.push(\"\\n\");\n }\n parts.push(`${ind}</${name}>`);\n return parts.join(\"\");\n}\n","import type { Element, Xml2JsOptions } from \"./types\";\n\nconst ENTITY_MAP: Record<string, string> = {\n \"&amp;\": \"&\",\n \"&lt;\": \"<\",\n \"&gt;\": \">\",\n \"&quot;\": '\"',\n \"&apos;\": \"'\",\n};\n// Matches the five named entities plus numeric character references\n// (&#65; decimal, &#x42; hex).\nconst ENTITY_PATTERN = /&(?:amp|lt|gt|quot|apos|#x[0-9a-fA-F]+|#[0-9]+);/g;\n\nexport function unescapeXml(str: string): string {\n return str.replace(ENTITY_PATTERN, (match) => {\n if (ENTITY_MAP[match] !== undefined) return ENTITY_MAP[match];\n // Numeric character reference: strip \"&#\" prefix and \";\" suffix.\n const body = match.slice(2, -1);\n const code =\n body[0] === \"x\" || body[0] === \"X\" ? parseInt(body.slice(1), 16) : parseInt(body, 10);\n return Number.isFinite(code) && code >= 0 ? String.fromCodePoint(code) : match;\n });\n}\n\nexport function nativeTypeValue(value: string): string | number | boolean {\n if (value === \"\") return value;\n const n = Number(value);\n // Only coerce when lossless: leading zeros (\"00992297\"), exponential\n // notation (\"1e5\"), and a leading sign (\"+5\") must stay strings so hex-like\n // values (rsid, color) survive parse → stringify round-trips byte-exact.\n if (!isNaN(n) && String(n) === value) return n;\n const lower = value.toLowerCase();\n if (lower === \"true\") return true;\n if (lower === \"false\") return false;\n return value;\n}\n\nexport function parse(xmlString: string, options?: Xml2JsOptions): Element {\n const captureSpaces = options?.captureSpacesBetweenElements ?? false;\n const trim = options?.trim ?? false;\n const ignoreDeclaration = options?.ignoreDeclaration ?? false;\n const ignoreText = options?.ignoreText ?? false;\n const ignoreComment = options?.ignoreComment ?? false;\n const ignoreCdata = options?.ignoreCdata ?? false;\n const ignoreDoctype = options?.ignoreDoctype ?? false;\n const nativeTypeAttributes = options?.nativeTypeAttributes ?? false;\n\n const result: Element = {};\n const stack: Element[] = [result];\n\n let i = 0;\n const len = xmlString.length;\n\n while (i < len) {\n // Text node: read up to the next '<'. Pure-whitespace nodes (indentation)\n // are dropped below unless captureSpaces is on, but leading/trailing\n // spaces of nodes that have content are preserved.\n if (xmlString.charCodeAt(i) !== 0x3c /* < */) {\n const start = i;\n while (i < len && xmlString.charCodeAt(i) !== 0x3c) i++;\n let text = unescapeXml(xmlString.slice(start, i));\n if (trim) text = text.trim();\n if (ignoreText) continue;\n if (text.length > 0) {\n if (captureSpaces || text.trim().length > 0 || isPreserveContext(stack)) {\n addField(peek(stack), \"text\", text);\n }\n }\n continue;\n }\n\n i++;\n\n // <? processing instruction / declaration\n if (xmlString.charCodeAt(i) === 0x3f /* ? */) {\n const end = xmlString.indexOf(\"?>\", i + 1);\n if (end === -1) break;\n const body = xmlString.slice(i + 1, end);\n i = end + 2;\n\n const xmlMatch = body.match(/^xml\\s+(.*)$/s);\n if (xmlMatch) {\n if (!ignoreDeclaration) {\n if (!result.declaration) {\n result.declaration = {};\n }\n const attrs = parseAttributes(xmlMatch[1] ?? \"\");\n if (nativeTypeAttributes) {\n for (const key in attrs) {\n attrs[key] = nativeTypeValue(attrs[key] as string) as string;\n }\n }\n result.declaration.attributes = attrs;\n }\n }\n continue;\n }\n\n // !-- comment\n if (xmlString.charCodeAt(i) === 0x21 && xmlString.slice(i, i + 3) === \"!--\") {\n const end = xmlString.indexOf(\"-->\", i + 3);\n if (end === -1) break;\n const comment = xmlString.slice(i + 3, end);\n i = end + 3;\n if (!ignoreComment) {\n if (trim) addField(peek(stack), \"comment\", comment.trim());\n else addField(peek(stack), \"comment\", comment);\n }\n continue;\n }\n\n // ![CDATA[\n if (xmlString.charCodeAt(i) === 0x21 && xmlString.slice(i, i + 8) === \"![CDATA[\") {\n const end = xmlString.indexOf(\"]]>\", i + 8);\n if (end === -1) break;\n const cdata = xmlString.slice(i + 8, end);\n i = end + 3;\n if (!ignoreCdata) {\n if (trim) addField(peek(stack), \"cdata\", cdata.trim());\n else addField(peek(stack), \"cdata\", cdata);\n }\n continue;\n }\n\n // <!DOCTYPE\n if (xmlString.charCodeAt(i) === 0x21 && xmlString.slice(i, i + 9) === \"!DOCTYPE\") {\n const end = xmlString.indexOf(\">\", i + 9);\n if (end === -1) break;\n const doctype = xmlString.slice(i + 9, end).trim();\n i = end + 1;\n if (!ignoreDoctype) {\n addField(peek(stack), \"doctype\", doctype);\n }\n continue;\n }\n\n // </ closing tag\n if (xmlString.charCodeAt(i) === 0x2f /* / */) {\n const end = xmlString.indexOf(\">\", i + 1);\n if (end === -1) break;\n i = end + 1;\n stack.pop();\n continue;\n }\n\n // < opening tag\n const tagNameEnd = findTagNameEnd(xmlString, i);\n const tagName = xmlString.slice(i, tagNameEnd);\n let pos = tagNameEnd;\n\n const attributes = parseAttributesFromXml(xmlString, pos);\n pos = attributes.pos;\n\n if (nativeTypeAttributes) {\n for (const key in attributes.attrs) {\n attributes.attrs[key] = nativeTypeValue(attributes.attrs[key] as string) as string;\n }\n }\n\n const isSelfClosing = xmlString.charCodeAt(pos) === 0x2f /* / */;\n if (isSelfClosing) pos += 2;\n else pos++;\n\n const element: Element = {\n type: \"element\",\n name: tagName,\n };\n if (Object.keys(attributes.attrs).length > 0) {\n element.attributes = attributes.attrs;\n }\n\n const parent = peek(stack);\n if (!parent.elements) {\n parent.elements = [];\n }\n parent.elements.push(element);\n\n if (!isSelfClosing) {\n stack.push(element);\n }\n\n i = pos;\n }\n\n if (result.elements) {\n const temp = result.elements;\n delete result.elements;\n result.elements = temp;\n delete result.text;\n }\n\n return result;\n}\n\nfunction findTagNameEnd(str: string, start: number): number {\n let i = start;\n const len = str.length;\n while (i < len) {\n const ch = str.charCodeAt(i);\n if (ch === 0x20 || ch === 0x09 || ch === 0x0a || ch === 0x0d || ch === 0x2f || ch === 0x3e) {\n return i;\n }\n i++;\n }\n return i;\n}\n\nfunction parseAttributesFromXml(\n str: string,\n start: number,\n): { attrs: Record<string, string>; pos: number } {\n const attrs: Record<string, string> = {};\n let i = start;\n const len = str.length;\n\n while (i < len) {\n while (i < len && isWhitespace(str.charCodeAt(i))) i++;\n if (i >= len || str.charCodeAt(i) === 0x3e || str.charCodeAt(i) === 0x2f) {\n break;\n }\n\n const nameStart = i;\n while (i < len && str.charCodeAt(i) !== 0x3d) {\n if (str.charCodeAt(i) === 0x3e || str.charCodeAt(i) === 0x2f) break;\n i++;\n }\n const name = str.slice(nameStart, i);\n\n if (str.charCodeAt(i) !== 0x3d) break;\n i++;\n\n while (i < len && isWhitespace(str.charCodeAt(i))) i++;\n\n const quote = str.charCodeAt(i);\n if (quote !== 0x22 && quote !== 0x27) break;\n i++;\n const valueStart = i;\n while (i < len && str.charCodeAt(i) !== quote) i++;\n attrs[name] = unescapeXml(str.slice(valueStart, i));\n i++;\n }\n\n return { attrs, pos: i };\n}\n\n/** @deprecated Use `parse` instead. xml-js compatible alias. */\nexport { parse as xml2js };\n\nexport function parseAttributes(str: string): Record<string, string> {\n const result: Record<string, string> = {};\n let i = 0;\n const len = str.length;\n\n while (i < len) {\n while (i < len && isWhitespace(str.charCodeAt(i))) i++;\n if (i >= len) break;\n\n const nameStart = i;\n while (i < len && str.charCodeAt(i) !== 0x3d) {\n if (isWhitespace(str.charCodeAt(i))) break;\n i++;\n }\n const name = str.slice(nameStart, i);\n\n while (i < len && isWhitespace(str.charCodeAt(i))) i++;\n if (i >= len || str.charCodeAt(i) !== 0x3d) break;\n i++;\n\n while (i < len && isWhitespace(str.charCodeAt(i))) i++;\n\n const quote = str.charCodeAt(i);\n if (quote !== 0x22 && quote !== 0x27) break;\n i++;\n const valueStart = i;\n while (i < len && str.charCodeAt(i) !== quote) i++;\n result[name] = unescapeXml(str.slice(valueStart, i));\n i++;\n }\n return result;\n}\n\n/**\n * Top of the parse stack. The stack is guaranteed non-empty — the result root\n * is pushed at init and push/pop stay balanced across well-formed input — so\n * this is a compile-time narrow (one non-null assertion) rather than a runtime\n * check: it must not add a throw path that changes how `parse` surfaces\n * malformed documents. Centralising the access keeps that single `!` off the\n * read sites, matching the \"wrap indexed access behind a helper\" pattern.\n */\nfunction peek(stack: Element[]): Element {\n return stack[stack.length - 1]!;\n}\n\nfunction addField(parent: Element, type: string, value: string) {\n if (!parent.elements) {\n parent.elements = [];\n }\n // Merge adjacent text/cdata nodes: a CDATA section containing the literal\n // `]]>` is serialized as two adjacent CDATA sections and must reassemble\n // into a single node on parse. Adjacent text nodes likewise merge.\n if (type === \"text\" || type === \"cdata\") {\n const last = parent.elements[parent.elements.length - 1];\n if (last && last.type === type) {\n const key = type as \"text\" | \"cdata\";\n last[key] = (last[key] as string) + value;\n return;\n }\n }\n const element: Element = { type };\n (element as Record<string, unknown>)[type] = value;\n parent.elements.push(element);\n}\n\n/** True when the nearest ancestor with an explicit xml:space sets \"preserve\". */\nfunction isPreserveContext(stack: Element[]): boolean {\n for (let i = stack.length - 1; i >= 0; i--) {\n const node = stack[i];\n if (!node) continue;\n const space = node.attributes?.[\"xml:space\"];\n if (space !== undefined) return space === \"preserve\";\n }\n return false;\n}\n\nfunction isWhitespace(ch: number): boolean {\n return ch === 0x20 || ch === 0x09 || ch === 0x0a || ch === 0x0d;\n}\n","import { escapeXml } from \"./escape\";\nimport type { Element, Js2XmlOptions } from \"./types\";\n\nexport function stringify(js: Element, options?: Js2XmlOptions): string {\n const opts = normalizeOptions(options);\n const parts: string[] = [];\n\n if (js.declaration && !opts.ignoreDeclaration) {\n parts.push(writeDeclaration(js.declaration));\n }\n\n if (js.elements?.length) {\n parts.push(writeElements(js.elements, opts, 0, !parts.length));\n }\n\n return parts.join(\"\");\n}\n\n/** @deprecated Use `stringify` instead. xml-js compatible alias. */\nexport { stringify as js2xml };\n\n/** @deprecated Use `stringify` instead. xml-js compatible alias. */\nexport function json2xml(json: Element, options?: Js2XmlOptions): string {\n return stringify(json, options);\n}\n\nfunction normalizeOptions(options?: Js2XmlOptions): {\n spaces: string;\n ignoreDeclaration: boolean;\n ignoreText: boolean;\n ignoreComment: boolean;\n ignoreCdata: boolean;\n ignoreDoctype: boolean;\n fullTagEmptyElement: boolean;\n indentText: boolean;\n indentCdata: boolean;\n attributeValueFn?: Js2XmlOptions[\"attributeValueFn\"];\n} {\n if (!options) {\n return {\n spaces: \"\",\n ignoreDeclaration: false,\n ignoreText: false,\n ignoreComment: false,\n ignoreCdata: false,\n ignoreDoctype: false,\n fullTagEmptyElement: false,\n indentText: false,\n indentCdata: false,\n };\n }\n let spaces = \"\";\n if (options.spaces != null) {\n spaces = typeof options.spaces === \"number\" ? \" \".repeat(options.spaces) : options.spaces;\n }\n return {\n spaces,\n ignoreDeclaration: options.ignoreDeclaration ?? false,\n ignoreText: options.ignoreText ?? false,\n ignoreComment: options.ignoreComment ?? false,\n ignoreCdata: options.ignoreCdata ?? false,\n ignoreDoctype: options.ignoreDoctype ?? false,\n fullTagEmptyElement: options.fullTagEmptyElement ?? false,\n indentText: options.indentText ?? false,\n indentCdata: options.indentCdata ?? false,\n attributeValueFn: options.attributeValueFn,\n };\n}\n\nfunction writeIndentation(spaces: string, depth: number, firstLine: boolean): string {\n return (!firstLine && spaces ? \"\\n\" : \"\") + spaces.repeat(depth);\n}\n\nfunction writeDeclaration(declaration: NonNullable<Element[\"declaration\"]>): string {\n const attrs = declaration.attributes;\n if (!attrs) return '<?xml version=\"1.0\"?>';\n\n const parts: string[] = [`<?xml version=\"1.0\"`];\n if (attrs.encoding) parts.push(` encoding=\"${attrs.encoding}\"`);\n if (attrs.standalone) parts.push(` standalone=\"${attrs.standalone}\"`);\n return parts.join(\"\") + \"?>\";\n}\n\nfunction writeAttributes(\n attributes: Record<string, string | number | undefined>,\n elementName: string,\n element: Element,\n attributeValueFn?: Js2XmlOptions[\"attributeValueFn\"],\n): string {\n const parts: string[] = [];\n for (const key of Object.keys(attributes)) {\n const value = attributes[key];\n if (value === null || value === undefined) continue;\n\n // attributeValueFn (xml-js hook) owns escaping when provided; otherwise\n // we escape all XML-special characters ourselves.\n const raw = String(value);\n const attr = attributeValueFn\n ? attributeValueFn(raw, key, elementName, element)\n : escapeXml(raw);\n parts.push(` ${key}=\"${attr}\"`);\n }\n return parts.join(\"\");\n}\n\nfunction writeElement(\n element: Element,\n opts: ReturnType<typeof normalizeOptions>,\n depth: number,\n): string {\n if (!element.name) return \"\";\n const name = element.name;\n const attrStr = element.attributes\n ? writeAttributes(element.attributes, name, element, opts.attributeValueFn)\n : \"\";\n const withClosingTag =\n (element.elements?.length ?? 0) > 0 ||\n element.attributes?.[\"xml:space\"] === \"preserve\" ||\n opts.fullTagEmptyElement;\n\n if (!withClosingTag) {\n return `<${name}${attrStr}/>`;\n }\n\n const parts: string[] = [];\n parts.push(`<${name}${attrStr}>`);\n const hasChildElements = element.elements?.some((e) => e.type === \"element\") ?? false;\n if (element.elements?.length) {\n parts.push(writeElements(element.elements, opts, depth + 1, false));\n }\n if (opts.spaces && hasChildElements) {\n parts.push(\"\\n\" + opts.spaces.repeat(depth));\n }\n parts.push(`</${name}>`);\n return parts.join(\"\");\n}\n\nfunction writeElements(\n elements: Element[],\n opts: ReturnType<typeof normalizeOptions>,\n depth: number,\n firstLine: boolean,\n): string {\n const parts: string[] = [];\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n if (!element) continue;\n const isFirst = firstLine && i === 0;\n switch (element.type) {\n case \"element\":\n parts.push(writeIndentation(opts.spaces, depth, isFirst));\n parts.push(writeElement(element, opts, depth));\n break;\n case \"text\":\n if (opts.ignoreText) continue;\n if (opts.indentText) parts.push(writeIndentation(opts.spaces, depth, isFirst));\n parts.push(writeText(element.text));\n break;\n case \"cdata\":\n if (opts.ignoreCdata) continue;\n if (opts.indentCdata) parts.push(writeIndentation(opts.spaces, depth, isFirst));\n parts.push(writeCdata(element.cdata));\n break;\n case \"comment\":\n if (opts.ignoreComment) continue;\n parts.push(writeIndentation(opts.spaces, depth, isFirst));\n parts.push(writeComment(element.comment));\n break;\n case \"doctype\":\n if (opts.ignoreDoctype) continue;\n parts.push(writeIndentation(opts.spaces, depth, isFirst));\n parts.push(writeDoctype(element.doctype));\n break;\n default:\n break;\n }\n }\n return parts.join(\"\");\n}\n\nfunction writeText(text: string | number | boolean | undefined | null): string {\n if (text == null) return \"\";\n const str = String(text);\n // Fast path: most text content doesn't contain XML-special characters.\n for (let i = 0; i < str.length; i++) {\n const c = str.charCodeAt(i);\n if (c === 38 || c === 60 || c === 62) {\n // & < >\n let s = \"\";\n let last = 0;\n for (let j = i; j < str.length; j++) {\n const cj = str.charCodeAt(j);\n if (cj === 38) {\n s += str.slice(last, j) + \"&amp;\";\n last = j + 1;\n } else if (cj === 60) {\n s += str.slice(last, j) + \"&lt;\";\n last = j + 1;\n } else if (cj === 62) {\n s += str.slice(last, j) + \"&gt;\";\n last = j + 1;\n }\n }\n return s + str.slice(last);\n }\n }\n return str;\n}\n\nfunction writeCdata(cdata: string | undefined | null): string {\n if (cdata == null) return \"\";\n const escaped = cdata.replace(/\\]\\]>/g, \"]]]]><![CDATA[>\");\n return `<![CDATA[${escaped}]]>`;\n}\n\nfunction writeComment(comment: string | undefined | null): string {\n if (comment == null) return \"\";\n return `<!--${comment}-->`;\n}\n\nfunction writeDoctype(doctype: string | undefined | null): string {\n if (doctype == null) return \"\";\n return `<!DOCTYPE ${doctype}>`;\n}\n\ntype NonNullable<T> = T extends null | undefined ? never : T;\n","import type { Element, Attributes } from \"./types\";\n\n/**\n * Convert XmlObject (node-xml format) directly to Element (xml-js format).\n * Eliminates the redundant xml() → xml2js() bridge path.\n */\nexport function toElement(xmlObject: Record<string, unknown>): Element {\n const tagName = Object.keys(xmlObject)[0];\n if (!tagName) {\n return { type: \"element\", name: \"\" };\n }\n const value = xmlObject[tagName];\n\n const element: Element = {\n type: \"element\",\n name: tagName,\n };\n\n if (value == null) {\n return element;\n }\n\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n element.elements = [{ type: \"text\", text: String(value) }];\n return element;\n }\n\n if (Array.isArray(value)) {\n const children: Element[] = [];\n for (const item of value) {\n if (item && typeof item === \"object\" && \"_attr\" in item) {\n element.attributes = item._attr as Attributes;\n } else if (item && typeof item === \"object\") {\n const childKeys = Object.keys(item);\n if (childKeys[0] === \"_cdata\") {\n children.push({ type: \"cdata\", cdata: String(item._cdata) });\n } else {\n children.push(toElement(item));\n }\n } else if (item != null) {\n children.push({ type: \"text\", text: String(item) });\n }\n }\n if (children.length > 0) {\n element.elements = children;\n }\n return element;\n }\n\n if (typeof value === \"object\" && value !== null) {\n const obj = value as { _attr?: Attributes; _cdata?: string };\n if (obj._attr) {\n element.attributes = obj._attr;\n }\n if (obj._cdata) {\n element.elements = [{ type: \"cdata\", cdata: String(obj._cdata) }];\n }\n }\n\n return element;\n}\n","import { xml2js } from \"./parse\";\nimport type { Xml2JsOptions } from \"./types\";\n\n/** Convert XML string to JSON string — xml-js compatible export */\nexport function xml2json(xml: string, options?: Xml2JsOptions): string {\n return JSON.stringify(xml2js(xml, options));\n}\n"],"mappings":"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"}
@@ -122,80 +122,23 @@ type XmlObject = {
122
122
  } | XmlDesc;
123
123
  //#endregion
124
124
  //#region src/utils.d.ts
125
- /**
126
- * Find the first direct child element with the given name.
127
- */
125
+ type NonEmptyArray<T> = readonly [T, ...ReadonlyArray<T>];
126
+ declare const isNonEmpty: <T>(arr: readonly T[]) => arr is NonEmptyArray<T>;
128
127
  declare function findChild(parent: Element | undefined, name: string): Element | undefined;
129
- /**
130
- * Get all direct child elements matching the given name.
131
- */
132
128
  declare function children(parent: Element | undefined, name: string): Element[];
133
- /**
134
- * Get all direct child elements.
135
- */
136
129
  declare function allChildren(parent: Element | undefined): Element[];
137
- /**
138
- * Get text content of the first child element with the given name.
139
- */
140
130
  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
131
  declare function textOf(element: Element | undefined): string;
146
- /**
147
- * Collect text from all direct text nodes within an element.
148
- */
149
132
  declare function collectText(element: Element | undefined): string;
150
- /**
151
- * Get an attribute value as a string.
152
- */
153
133
  declare function attr(element: Element | undefined, name: string): string | undefined;
154
- /**
155
- * Get an attribute value as a number.
156
- */
157
134
  declare function attrNum(element: Element | undefined, name: string): number | undefined;
158
- /**
159
- * Get a measurement attribute as a number or a verbatim measure/percent string.
160
- *
161
- * Counterpart to {@link attrNum} for XSD attribute unions of a decimal number
162
- * and UniversalMeasure/Percentage (ST_TwipsMeasure, ST_MeasurementOrPercent,
163
- * CT_TblWidth/@w, CT_Height/@val): a plain numeric token yields a number, while
164
- * UniversalMeasure ("5mm") and Percentage ("50%") stay verbatim so they
165
- * round-trip with the stringify-side value helpers in @office-open/core.
166
- *
167
- * For CT_TblWidth with type="pct", the fiftieths token ("5000" = 100%) is a
168
- * plain numeric token and is returned as the number 5000; the stringify side
169
- * emits it verbatim (never "5000%", which is a different XSD branch).
170
- */
171
135
  declare function attrMeasure(element: Element | undefined, name: string): number | string | undefined;
172
- /**
173
- * Get an attribute value as a boolean.
174
- */
175
136
  declare function attrBool(element: Element | undefined, name: string): boolean | undefined;
176
- /**
177
- * Get a hex color attribute, handling nativeTypeValue coercion.
178
- * nativeTypeAttributes converts "000000" → 0 (number); this recovers
179
- * the original 6-digit hex string by zero-padding numeric values.
180
- */
181
137
  declare function colorAttr(element: Element | undefined, name: string): string | undefined;
182
- /**
183
- * Check if an element has a specific child element.
184
- */
185
138
  declare function hasChild(parent: Element | undefined, name: string): boolean;
186
- /**
187
- * Find deep descendant elements matching the given name.
188
- */
189
139
  declare function findDeep(parent: Element | undefined, name: string): Element[];
190
- /**
191
- * Find the first descendant element with the given name (depth-first pre-order).
192
- * Short-circuits at the first match — prefer this over `findDeep(parent, name)[0]`
193
- * to avoid traversing the whole subtree and allocating the full results array.
194
- */
195
140
  declare function findFirst(parent: Element | undefined, name: string): Element | undefined;
196
- /**
197
- * Get the number of direct child elements.
198
- */
199
141
  declare function childCount(parent: Element | undefined): number;
200
142
  //#endregion
201
- export { Xml2JsOptions as C, XmlDescArray as D, XmlDesc as E, XmlObject as O, Js2XmlOptions as S, XmlAttrs as T, DeclarationAttributes as _, attrNum as a, ElementObject as b, children as c, findChild as d, findDeep as f, Attributes as g, textOf as h, attrMeasure as i, XmlOption as k, collectText as l, hasChild as m, attr as n, childCount as o, findFirst as p, attrBool as r, childText as s, allChildren as t, colorAttr as u, Element as v, XmlAtom as w, IgnoreOptions as x, ElementCompact as y };
143
+ export { XmlObject as A, IgnoreOptions as C, XmlAttrs as D, XmlAtom as E, XmlDesc as O, ElementObject as S, Xml2JsOptions as T, textOf as _, attrMeasure as a, Element as b, childText as c, colorAttr as d, findChild as f, isNonEmpty as g, hasChild as h, attrBool as i, XmlOption as j, XmlDescArray as k, children as l, findFirst as m, allChildren as n, attrNum as o, findDeep as p, attr as r, childCount as s, NonEmptyArray as t, collectText as u, Attributes as v, Js2XmlOptions as w, ElementCompact as x, DeclarationAttributes as y };
144
+ //# sourceMappingURL=utils-BFKTfRa8.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-BFKTfRa8.d.mts","names":[],"sources":["../src/types.ts","../src/utils.ts"],"mappings":"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"}
package/dist/utils.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as attrNum, c as children, d as findChild, f as findDeep, h as textOf, i as attrMeasure, l as collectText, m as hasChild, n as attr, o as childCount, p as findFirst, r as attrBool, s as childText, t as allChildren, u as colorAttr } from "./utils-t-_-N57p.mjs";
2
- export { allChildren, attr, attrBool, attrMeasure, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, findFirst, hasChild, textOf };
1
+ import { _ as textOf, a as attrMeasure, c as childText, d as colorAttr, f as findChild, g as isNonEmpty, h as hasChild, i as attrBool, l as children, m as findFirst, n as allChildren, o as attrNum, p as findDeep, r as attr, s as childCount, t as NonEmptyArray, u as collectText } from "./utils-BFKTfRa8.mjs";
2
+ export { NonEmptyArray, allChildren, attr, attrBool, attrMeasure, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, findFirst, hasChild, isNonEmpty, textOf };
package/dist/utils.mjs CHANGED
@@ -1,5 +1,11 @@
1
1
  //#region src/utils.ts
2
2
  /**
3
+ * User-defined type guard narrowing an array to {@link NonEmptyArray}.
4
+ * Prefer this over a bare `arr.length > 0` check, which TypeScript does
5
+ * not reliably narrow into a non-empty tuple at the read site.
6
+ */
7
+ const isNonEmpty = (arr) => arr.length > 0;
8
+ /**
3
9
  * Find the first direct child element with the given name.
4
10
  */
5
11
  function findChild(parent, name) {
@@ -30,7 +36,11 @@ function childText(parent, name) {
30
36
  function textOf(element) {
31
37
  if (!element) return "";
32
38
  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("");
39
+ if (element.elements && element.elements.length > 0) {
40
+ let text = "";
41
+ for (const e of element.elements) if (typeof e.text === "string") text += e.text;
42
+ return text;
43
+ }
34
44
  return "";
35
45
  }
36
46
  /**
@@ -119,12 +129,15 @@ function hasChild(parent, name) {
119
129
  */
120
130
  function findDeep(parent, name) {
121
131
  const result = [];
122
- if (!parent) return result;
132
+ collectDeep(parent, name, result);
133
+ return result;
134
+ }
135
+ function collectDeep(parent, name, result) {
136
+ if (!parent) return;
123
137
  for (const child of parent.elements ?? []) {
124
138
  if (child.name === name) result.push(child);
125
- for (const found of findDeep(child, name)) result.push(found);
139
+ collectDeep(child, name, result);
126
140
  }
127
- return result;
128
141
  }
129
142
  /**
130
143
  * Find the first descendant element with the given name (depth-first pre-order).
@@ -146,4 +159,6 @@ function childCount(parent) {
146
159
  return parent?.elements?.length ?? 0;
147
160
  }
148
161
  //#endregion
149
- export { allChildren, attr, attrBool, attrMeasure, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, findFirst, hasChild, textOf };
162
+ export { allChildren, attr, attrBool, attrMeasure, attrNum, childCount, childText, children, collectText, colorAttr, findChild, findDeep, findFirst, hasChild, isNonEmpty, textOf };
163
+
164
+ //# sourceMappingURL=utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.mjs","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import type { Element } from \"./types\";\n\n/**\n * A readonly array guaranteed to have at least one element. Use with\n * {@link isNonEmpty} to narrow `T[]` so indexed access (e.g. `arr[0]`)\n * returns `T` instead of `T | undefined` under `noUncheckedIndexedAccess`.\n */\nexport type NonEmptyArray<T> = readonly [T, ...ReadonlyArray<T>];\n\n/**\n * User-defined type guard narrowing an array to {@link NonEmptyArray}.\n * Prefer this over a bare `arr.length > 0` check, which TypeScript does\n * not reliably narrow into a non-empty tuple at the read site.\n */\nexport const isNonEmpty = <T>(arr: readonly T[]): arr is NonEmptyArray<T> => arr.length > 0;\n\n/**\n * Find the first direct child element with the given name.\n */\nexport function findChild(parent: Element | undefined, name: string): Element | undefined {\n return parent?.elements?.find((e) => e.name === name);\n}\n\n/**\n * Get all direct child elements matching the given name.\n */\nexport function children(parent: Element | undefined, name: string): Element[] {\n return parent?.elements?.filter((e) => e.name === name) ?? [];\n}\n\n/**\n * Get all direct child elements.\n */\nexport function allChildren(parent: Element | undefined): Element[] {\n return parent?.elements ?? [];\n}\n\n/**\n * Get text content of the first child element with the given name.\n */\nexport function childText(parent: Element | undefined, name: string): string {\n const child = findChild(parent, name);\n return textOf(child);\n}\n\n/**\n * Get text content of an element.\n * Handles cases where text may be directly on .text or in a child element.\n */\nexport function textOf(element: Element | undefined): string {\n if (!element) return \"\";\n if (element.text !== undefined && typeof element.text === \"string\") return element.text;\n if (element.elements && element.elements.length > 0) {\n let text = \"\";\n for (const e of element.elements) {\n if (typeof e.text === \"string\") text += e.text;\n }\n return text;\n }\n return \"\";\n}\n\n/**\n * Collect text from all direct text nodes within an element.\n */\nexport function collectText(element: Element | undefined): string {\n if (!element) return \"\";\n const parts: string[] = [];\n collectTextRecursive(element, parts);\n return parts.join(\"\");\n}\n\nfunction collectTextRecursive(element: Element | undefined, parts: string[]): void {\n if (!element) return;\n if (element.text !== undefined && typeof element.text === \"string\") {\n parts.push(element.text);\n }\n if (element.elements) {\n for (const child of element.elements) {\n collectTextRecursive(child, parts);\n }\n }\n}\n\n/**\n * Get an attribute value as a string.\n */\nexport function attr(element: Element | undefined, name: string): string | undefined {\n const v = element?.attributes?.[name];\n return v !== undefined ? String(v) : undefined;\n}\n\n/**\n * Get an attribute value as a number.\n */\nexport function attrNum(element: Element | undefined, name: string): number | undefined {\n const v = element?.attributes?.[name];\n if (v === undefined) return undefined;\n const n = Number(v);\n return isNaN(n) ? undefined : n;\n}\n\n/**\n * Get a measurement attribute as a number or a verbatim measure/percent string.\n *\n * Counterpart to {@link attrNum} for XSD attribute unions of a decimal number\n * and UniversalMeasure/Percentage (ST_TwipsMeasure, ST_MeasurementOrPercent,\n * CT_TblWidth/@w, CT_Height/@val): a plain numeric token yields a number, while\n * UniversalMeasure (\"5mm\") and Percentage (\"50%\") stay verbatim so they\n * round-trip with the stringify-side value helpers in @office-open/core.\n *\n * For CT_TblWidth with type=\"pct\", the fiftieths token (\"5000\" = 100%) is a\n * plain numeric token and is returned as the number 5000; the stringify side\n * emits it verbatim (never \"5000%\", which is a different XSD branch).\n */\nexport function attrMeasure(\n element: Element | undefined,\n name: string,\n): number | string | undefined {\n const v = element?.attributes?.[name];\n if (v === undefined) return undefined;\n const raw = String(v);\n const n = Number(raw);\n return Number.isNaN(n) ? raw : n;\n}\n\n/**\n * Get an attribute value as a boolean.\n */\nexport function attrBool(element: Element | undefined, name: string): boolean | undefined {\n const v = element?.attributes?.[name];\n if (v === undefined) return undefined;\n if (typeof v === \"boolean\") return v;\n const lower = String(v).toLowerCase();\n if (lower === \"true\" || lower === \"1\") return true;\n if (lower === \"false\" || lower === \"0\") return false;\n return undefined;\n}\n\n/**\n * Get a hex color attribute, handling nativeTypeValue coercion.\n * nativeTypeAttributes converts \"000000\" → 0 (number); this recovers\n * the original 6-digit hex string by zero-padding numeric values.\n */\nexport function colorAttr(element: Element | undefined, name: string): string | undefined {\n const raw = element?.attributes?.[name];\n if (raw === undefined || raw === \"\") return undefined;\n if (typeof raw === \"boolean\") return undefined;\n if (typeof raw === \"number\") {\n return String(raw).padStart(6, \"0\");\n }\n if (raw === \"auto\") return \"auto\";\n if (/^[0-9A-Fa-f]{6}$/.test(raw)) return raw;\n return raw;\n}\n\n/**\n * Check if an element has a specific child element.\n */\nexport function hasChild(parent: Element | undefined, name: string): boolean {\n return parent?.elements?.some((e) => e.name === name) ?? false;\n}\n\n/**\n * Find deep descendant elements matching the given name.\n */\nexport function findDeep(parent: Element | undefined, name: string): Element[] {\n const result: Element[] = [];\n collectDeep(parent, name, result);\n return result;\n}\n\nfunction collectDeep(parent: Element | undefined, name: string, result: Element[]): void {\n if (!parent) return;\n for (const child of parent.elements ?? []) {\n if (child.name === name) result.push(child);\n collectDeep(child, name, result);\n }\n}\n\n/**\n * Find the first descendant element with the given name (depth-first pre-order).\n * Short-circuits at the first match — prefer this over `findDeep(parent, name)[0]`\n * to avoid traversing the whole subtree and allocating the full results array.\n */\nexport function findFirst(parent: Element | undefined, name: string): Element | undefined {\n if (!parent) return undefined;\n for (const child of parent.elements ?? []) {\n if (child.name === name) return child;\n const found = findFirst(child, name);\n if (found) return found;\n }\n return undefined;\n}\n\n/**\n * Get the number of direct child elements.\n */\nexport function childCount(parent: Element | undefined): number {\n return parent?.elements?.length ?? 0;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@office-open/xml",
3
- "version": "0.10.12",
3
+ "version": "0.10.13",
4
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",
@@ -28,6 +28,7 @@
28
28
  "dist"
29
29
  ],
30
30
  "type": "module",
31
+ "sideEffects": false,
31
32
  "main": "dist/index.mjs",
32
33
  "types": "dist/index.d.mts",
33
34
  "exports": {