{"version":3,"file":"index.mjs","names":["stringifyChildren"],"sources":["../src/parse.ts","../src/escape.ts","../src/stringify.ts","../src/stringify-element.ts"],"sourcesContent":["import type { Element, ParseOptions } 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// \"Contains a non-whitespace character\" — same predicate as\n// `text.trim().length > 0` without allocating the trimmed copy.\nconst HAS_CONTENT = /\\S/;\n\nexport function unescapeXml(str: string): string {\n  // Fast path: entities all start with '&', and OOXML parts overwhelmingly\n  // contain none (a 63 MB worksheet measured zero occurrences). The regex\n  // scan + replace setup per call showed up to ~12% of large-file parse\n  // profiles, so gate it on the sentinel byte.\n  if (str.indexOf(\"&\") === -1) return str;\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  // Digit-only fast path — plain integers are the most common numeric shape\n  // in OOXML (row/column indexes, sizes, ids). At most 15 digits is always\n  // exact in float64, so the scan replaces the Number() + String(n)\n  // round-trip (the String(n) side allocates) without re-checking losslessness.\n  const neg = value.charCodeAt(0) === 0x2d; /* - */\n  const start = neg ? 1 : 0;\n  const digits = value.length - start;\n  if (digits > 0 && digits <= 15) {\n    // Leading zeros (\"00992297\") must stay strings; only a lone \"0\" passes.\n    // \"-0\" falls through too — Number coerces it to -0 whose String() is \"0\",\n    // so the slow path must keep it a string.\n    const head = value.charCodeAt(start);\n    if (head !== 0x30 || (!neg && digits === 1)) {\n      let n = 0;\n      let allDigits = true;\n      for (let i = start; i < value.length; i++) {\n        const c = value.charCodeAt(i);\n        if (c < 0x30 || c > 0x39) {\n          allDigits = false;\n          break;\n        }\n        n = n * 10 + (c - 0x30);\n      }\n      if (allDigits) return neg ? -n : n;\n    }\n  }\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  // Length gate before toLowerCase: every non-numeric attribute value paid\n  // two throwaway lowercase strings (cell refs, format names, ids …), which\n  // parse profiles attributed to GC pressure.\n  if (value.length === 4 || value.length === 5) {\n    const lower = value.toLowerCase();\n    if (lower === \"true\") return true;\n    if (lower === \"false\") return false;\n  }\n  return value;\n}\n\nexport function parse(xmlString: string, options?: ParseOptions): 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  // Lookup set for deferred elements (raw inner-XML capture). Undefined when\n  // the option is absent so the common path pays one truthiness check.\n  const deferSet =\n    options?.deferElements !== undefined && options.deferElements.length > 0\n      ? new Set(options.deferElements)\n      : undefined;\n\n  // Namespace normalization (see ParseOptions.normalizeNamespaces): in-scope\n  // prefix → canonical-prefix bindings, copy-on-write per element that carries\n  // xmlns declarations. `prefixes === undefined` means nothing is bound yet\n  // (the common subtree shares the root layer object untouched).\n  const nsTable =\n    options?.normalizeNamespaces !== undefined\n      ? new Map(Object.entries(options.normalizeNamespaces))\n      : undefined;\n  interface NsLayer {\n    prefixes: Map<string, string> | undefined;\n    /** Canonical form of the default namespace; undefined = none/unknown. */\n    defaultCanonical: string | undefined;\n  }\n  const nsRootLayer: NsLayer = { prefixes: undefined, defaultCanonical: undefined };\n  const nsStack: NsLayer[] = [nsRootLayer];\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      // Single-char indexOf runs as a native memchr scan — far faster than a\n      // JS byte-by-byte loop (the outer check already guarantees i is not '<').\n      const lt = xmlString.indexOf(\"<\", i);\n      i = lt === -1 ? len : lt;\n      let text = unescapeXml(xmlString.slice(start, i));\n      if (trim) text = text.trim();\n      if (ignoreText) continue;\n      if (text.length > 0) {\n        // trim mode already guarantees non-whitespace past the length gate;\n        // otherwise test natively instead of allocating a trimmed copy.\n        if (captureSpaces || (trim ? true : HAS_CONTENT.test(text)) || isPreserveContext(stack)) {\n          // Text-node hot path, inlined from addField(\"text\"): one lookup of\n          // the last child covers both the adjacent-merge case (same shape as\n          // addField — a split CDATA/text run must reassemble) and the fresh\n          // push. addField stays for the cold node types.\n          const parent = stack[stack.length - 1]!;\n          const elements = parent.elements;\n          const last = elements === undefined ? undefined : elements[elements.length - 1];\n          if (last !== undefined && last.type === \"text\") {\n            last.text = (last.text as string) + text;\n          } else {\n            const node: Element = { type: \"text\", text };\n            if (elements === undefined) {\n              parent.elements = [node];\n            } else {\n              elements.push(node);\n            }\n          }\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      if (nsTable !== undefined) nsStack.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    // Namespace bindings for this element: inherit the parent layer; the\n    // attribute scan clones it on the first xmlns declaration it meets.\n    const nsParent = nsTable !== undefined ? nsStack[nsStack.length - 1]! : undefined;\n    let nsPrefixes = nsParent?.prefixes;\n    let nsDefault = nsParent?.defaultCanonical;\n    let nsDeclared = false;\n\n    // Attribute scan, inlined from parseAttributesFromXml: called once per\n    // opening tag, the `{ attrs, pos }` wrapper was one allocation per element.\n    // `attrs` is allocated lazily on the first attribute — tags without\n    // attributes (the majority in data-heavy parts) must not pay a record\n    // allocation.\n    let attrs: Record<string, string> | undefined;\n    while (pos < len) {\n      while (pos < len && isWhitespace(xmlString.charCodeAt(pos))) pos++;\n      if (pos >= len || xmlString.charCodeAt(pos) === 0x3e || xmlString.charCodeAt(pos) === 0x2f) {\n        break;\n      }\n\n      const nameStart = pos;\n      while (pos < len && xmlString.charCodeAt(pos) !== 0x3d) {\n        if (xmlString.charCodeAt(pos) === 0x3e || xmlString.charCodeAt(pos) === 0x2f) break;\n        pos++;\n      }\n      // XML's Eq production allows whitespace around '='; trim it off the\n      // name so `Target = \"…\"` resolves like `Target=\"…\"`.\n      const name = xmlString.slice(nameStart, pos).trim();\n\n      if (xmlString.charCodeAt(pos) !== 0x3d) break;\n      pos++;\n\n      while (pos < len && isWhitespace(xmlString.charCodeAt(pos))) pos++;\n\n      const quote = xmlString.charCodeAt(pos);\n      if (quote !== 0x22 && quote !== 0x27) break;\n      pos++;\n      const valueStart = pos;\n      while (pos < len && xmlString.charCodeAt(pos) !== quote) pos++;\n      const value = unescapeXml(xmlString.slice(valueStart, pos));\n      pos++;\n\n      if (nsTable !== undefined && (name === \"xmlns\" || name.startsWith(\"xmlns:\"))) {\n        if (attrs === undefined) attrs = {};\n        const canonical = nsTable.get(value);\n        if (name === \"xmlns\") {\n          nsDefault = canonical;\n          if (canonical !== undefined && canonical !== \"\") {\n            // Known non-default canonical form: upgrade the declaration to a\n            // prefixed one (xmlns=\"uri\" → xmlns:w=\"uri\") so the rewritten\n            // element names stay declared.\n            attrs[`xmlns:${canonical}`] = value;\n          } else {\n            attrs[name] = value;\n          }\n        } else {\n          const prefix = name.slice(6);\n          if (canonical !== undefined && canonical !== \"\") {\n            attrs[`xmlns:${canonical}`] = value;\n          } else if (canonical === \"\" && !(\"xmlns\" in attrs)) {\n            // Canonical form is unprefixed: demote to a default declaration.\n            attrs.xmlns = value;\n          } else {\n            attrs[name] = value;\n          }\n          if (!nsDeclared) {\n            nsPrefixes = new Map(nsPrefixes ?? []);\n            nsDeclared = true;\n          }\n          // Unknown URI keeps the source prefix bound to itself, which the\n          // rewrite step treats as \"leave names as written\". Non-null: either\n          // just assigned above or already a Map from a prior nsDeclared pass.\n          nsPrefixes!.set(prefix, canonical ?? prefix);\n        }\n        continue;\n      }\n      if (attrs === undefined) attrs = {};\n      attrs[name] = value;\n    }\n\n    if (attrs && nativeTypeAttributes) {\n      for (const key in attrs) {\n        attrs[key] = nativeTypeValue(attrs[key] as string) as string;\n      }\n    }\n\n    // Namespace-normalize the element name and the non-declaration attribute\n    // names onto this element's effective bindings (its own declarations\n    // included — attributes see the element's in-scope bindings).\n    let finalName = tagName;\n    if (nsTable !== undefined) {\n      const colon = tagName.indexOf(\":\");\n      if (colon > 0) {\n        const p = tagName.slice(0, colon);\n        if (p !== \"xml\") {\n          const c = nsPrefixes?.get(p);\n          if (c !== undefined && c !== p) {\n            finalName = c === \"\" ? tagName.slice(colon + 1) : c + tagName.slice(colon);\n          }\n        }\n      } else if (colon < 0 && nsDefault !== undefined && nsDefault !== \"\") {\n        finalName = nsDefault + \":\" + tagName;\n      }\n      if (attrs !== undefined && nsPrefixes !== undefined) {\n        for (const key of Object.keys(attrs)) {\n          if (key === \"xmlns\" || key.startsWith(\"xmlns:\")) continue;\n          const kcolon = key.indexOf(\":\");\n          if (kcolon <= 0) continue;\n          const p = key.slice(0, kcolon);\n          if (p === \"xml\") continue;\n          const c = nsPrefixes.get(p);\n          if (c !== undefined && c !== p) {\n            const renamed = c === \"\" ? key.slice(kcolon + 1) : c + key.slice(kcolon);\n            const attrValue = attrs[key];\n            if (attrValue !== undefined) attrs[renamed] = attrValue;\n            delete attrs[key];\n          }\n        }\n      }\n    }\n\n    const isSelfClosing = xmlString.charCodeAt(pos) === 0x2f; /* / */\n    if (isSelfClosing) pos += 2;\n    else pos++;\n\n    // Constant shape: every element node carries all four fields (undefined\n    // placeholders included), so attribute/children assignment writes an\n    // existing slot instead of walking a hidden-class transition — element\n    // access sites stay monomorphic instead of 2-3 shapes deep.\n    const element: Element = {\n      type: \"element\",\n      name: finalName,\n      attributes: attrs,\n      elements: undefined,\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      if (deferSet !== undefined && deferSet.has(tagName)) {\n        // Deferred container: capture inner XML verbatim instead of parsing\n        // children. Scan to the matching close tag, counting same-name opens\n        // so nested occurrences (if any) don't end the capture early.\n        const closeTag = `</${tagName}>`;\n        let depth = 1;\n        let scan = pos;\n        let closeIdx = -1;\n        for (;;) {\n          closeIdx = xmlString.indexOf(closeTag, scan);\n          if (closeIdx === -1) break;\n          let p = scan;\n          for (;;) {\n            const openIdx = xmlString.indexOf(`<${tagName}`, p);\n            if (openIdx === -1 || openIdx >= closeIdx) break;\n            // Boundary check so `<rowx>` doesn't count as `<row`.\n            const after = xmlString.charCodeAt(openIdx + tagName.length + 1);\n            if (\n              after === 0x20 ||\n              after === 0x09 ||\n              after === 0x0a ||\n              after === 0x0d ||\n              after === 0x2f ||\n              after === 0x3e\n            ) {\n              depth++;\n            }\n            p = openIdx + tagName.length + 1;\n          }\n          scan = closeIdx + closeTag.length;\n          depth--;\n          if (depth === 0) break;\n        }\n        if (closeIdx === -1) {\n          element.raw = xmlString.slice(pos);\n          i = len;\n        } else {\n          element.raw = xmlString.slice(pos, closeIdx);\n          i = scan;\n        }\n        continue;\n      }\n      stack.push(element);\n      if (nsTable !== undefined) {\n        // Share the parent layer unless this element declared anything (a\n        // cloned prefix map, or a default declaration that can shadow one).\n        const layerChanged = nsDeclared || nsDefault !== nsParent!.defaultCanonical;\n        nsStack.push(\n          layerChanged ? { prefixes: nsPrefixes, defaultCanonical: nsDefault } : nsParent!,\n        );\n      }\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\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","// Non-global on purpose: a /g regex would carry stateful lastIndex across calls.\nconst XML_SPECIALS = /[&\"'<>]/;\n\n/** 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  // A character-class regex test beats a manual charCodeAt loop by ~10× (V8\n  // compiles it to a native SIMD scan); returning the original string\n  // reference means zero allocation for the common case.\n  if (!XML_SPECIALS.test(str)) return str;\n\n  // Chained native replaces: specials are sparse, so each pass after the\n  // first usually finds nothing and exits quickly. Raw /g literals carry no\n  // lastIndex state.\n  return str\n    .replace(/&/g, \"&amp;\")\n    .replace(/\"/g, \"&quot;\")\n    .replace(/'/g, \"&apos;\")\n    .replace(/</g, \"&lt;\")\n    .replace(/>/g, \"&gt;\");\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`. Booleans serialize as 0/1 —\n * the spelling Office itself writes for xsd:boolean attributes and\n * ST_OnOff unions alike.\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      const value = typeof v === \"string\" ? escapeXml(v) : typeof v === \"boolean\" ? (v ? 1 : 0) : v;\n      parts.push(` ${key}=\"${value}\"`);\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\";\nimport type { Element, StringifyOptions } from \"./types\";\n\n// Non-global on purpose: a /g regex would carry stateful lastIndex across calls.\n// Text content needs only the three markup delimiters — quotes are legal as-is.\nconst TEXT_SPECIALS = /[&<>]/;\n\nexport function stringify(js: Element, options?: StringifyOptions): 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\ninterface NormalizedOptions {\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?: StringifyOptions[\"attributeValueFn\"];\n}\n\n// Shared frozen defaults — the no-options call (the hot path) skips the\n// per-call object construction entirely.\nconst DEFAULT_OPTIONS: NormalizedOptions = {\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\nfunction normalizeOptions(options?: StringifyOptions): NormalizedOptions {\n  if (!options) return DEFAULT_OPTIONS;\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  if (!spaces) return \"\";\n  return (!firstLine ? \"\\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?: StringifyOptions[\"attributeValueFn\"],\n): string {\n  // Rope accumulation: attribute counts are small (1-3), a parts array + join\n  // would cost more than V8's cons-string +=. for-in over plain data records\n  // skips the Object.keys array allocation JSC penalizes (~1.3× on bun).\n  let s = \"\";\n  for (const key in 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    s += ` ${key}=\"${attr}\"`;\n  }\n  return s;\n}\n\nfunction writeElements(\n  elements: Element[],\n  opts: NormalizedOptions,\n  depth: number,\n  firstLine: boolean,\n): string {\n  // Rope accumulation — V8 cons-strings make += O(1) and skip the parts-array\n  // allocation the join-based form pays per level. The element body is inlined\n  // (no writeElement/writeElements mutual recursion): an ordered if-chain over\n  // the node type benchmarks ~1.6× faster than a switch plus a helper call\n  // per element under JSC, with V8 unchanged.\n  let s = \"\";\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    const type = element.type;\n    if (type === \"element\") {\n      const name = element.name;\n      if (!name) continue;\n      if (opts.spaces) s += writeIndentation(opts.spaces, depth, isFirst);\n      const attributes = element.attributes;\n      const attrStr = attributes\n        ? writeAttributes(attributes, name, element, opts.attributeValueFn)\n        : \"\";\n      // Deferred content: re-emit the captured inner XML verbatim — children\n      // were never parsed, and the bytes must survive a set/save round-trip.\n      if (element.raw !== undefined) {\n        s += `<${name}${attrStr}>${element.raw}</${name}>`;\n        continue;\n      }\n      const children = element.elements;\n      // The xml:space dictionary probe is deliberately last: it only matters\n      // for empty leaf elements, so child-bearing elements skip it.\n      const withClosingTag =\n        (children !== undefined && children.length > 0) ||\n        opts.fullTagEmptyElement ||\n        attributes?.[\"xml:space\"] === \"preserve\";\n      if (!withClosingTag) {\n        s += `<${name}${attrStr}/>`;\n        continue;\n      }\n      const open = `<${name}${attrStr}>`;\n      if (children !== undefined && children.length > 0) {\n        const inner = writeElements(children, opts, depth + 1, false);\n        // The child-element scan is only needed to pretty-print the closing\n        // tag — skip it entirely when not indenting.\n        if (opts.spaces && children.some((e) => e.type === \"element\")) {\n          s += open + inner + \"\\n\" + opts.spaces.repeat(depth) + `</${name}>`;\n        } else {\n          s += open + inner + `</${name}>`;\n        }\n      } else {\n        s += open + `</${name}>`;\n      }\n    } else if (type === \"text\") {\n      if (opts.ignoreText) continue;\n      if (opts.indentText && opts.spaces) s += writeIndentation(opts.spaces, depth, isFirst);\n      // Text escaping inline — fast path: most text content contains no\n      // markup delimiters, so a regex test (a native scan in V8/JSC, ~10× a\n      // charCodeAt loop) returns the original string reference with zero\n      // allocation. Chained replaces afterwards: specials are sparse, so each\n      // pass after the first usually finds nothing and exits quickly.\n      const text = element.text;\n      if (text == null) continue;\n      const str = String(text);\n      s += TEXT_SPECIALS.test(str)\n        ? str.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\")\n        : str;\n    } else if (type === \"cdata\") {\n      if (opts.ignoreCdata) continue;\n      if (opts.indentCdata && opts.spaces) s += writeIndentation(opts.spaces, depth, isFirst);\n      s += writeCdata(element.cdata);\n    } else if (type === \"comment\") {\n      if (opts.ignoreComment) continue;\n      if (opts.spaces) s += writeIndentation(opts.spaces, depth, isFirst);\n      s += writeComment(element.comment);\n    } else if (type === \"doctype\") {\n      if (opts.ignoreDoctype) continue;\n      if (opts.spaces) s += writeIndentation(opts.spaces, depth, isFirst);\n      s += writeDoctype(element.doctype);\n    }\n  }\n  return s;\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","/**\n * Serialize an Element including its own opening/closing tag.\n *\n * `stringify` serializes only an element's children (it treats its input as\n * a document root). Raw-XML round-trip of whole elements needs the element's\n * own tag wrapped around its serialized children.\n */\nimport { escapeXml } from \"./escape\";\nimport { stringify as stringifyChildren } from \"./stringify\";\nimport type { Element } from \"./types\";\n\nexport function stringifyElement(el: Element): string {\n  if (!el.name) return \"\";\n  let attrStr = \"\";\n  if (el.attributes) {\n    for (const key of Object.keys(el.attributes)) {\n      const v = el.attributes[key];\n      if (v === null || v === undefined) continue;\n      attrStr += ` ${key}=\"${escapeXml(String(v))}\"`;\n    }\n  }\n  const withClosingTag =\n    (el.elements?.length ?? 0) > 0 || el.attributes?.[\"xml:space\"] === \"preserve\";\n  if (!withClosingTag) return `<${el.name}${attrStr}/>`;\n  return `<${el.name}${attrStr}>${stringifyChildren(el)}</${el.name}>`;\n}\n"],"mappings":"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"}