@office-kit/xlsx 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +7 -0
  2. package/dist/cell/cell.d.ts +1 -1
  3. package/dist/cell/index.d.ts +4 -4
  4. package/dist/cell/rich-text.d.ts +1 -1
  5. package/dist/cell-BucgGwl3.mjs.map +1 -1
  6. package/dist/cell-style-DuvS_Lsg.mjs.map +1 -1
  7. package/dist/chart/chart-xml.d.ts +1 -1
  8. package/dist/chart/chart.d.ts +3 -3
  9. package/dist/chart/cx/chartex-xml.d.ts +1 -1
  10. package/dist/chart/cx/chartex.d.ts +2 -2
  11. package/dist/chart/index.d.ts +6 -6
  12. package/dist/chart/user-shapes-xml.d.ts +1 -1
  13. package/dist/chart/user-shapes.d.ts +2 -2
  14. package/dist/chart.mjs.map +1 -1
  15. package/dist/chartsheet/chartsheet-xml.d.ts +1 -1
  16. package/dist/chartsheet/chartsheet.d.ts +4 -4
  17. package/dist/chartsheet/index.d.ts +2 -2
  18. package/dist/chartsheet-C3-tqkPy.mjs.map +1 -1
  19. package/dist/coordinate-96Ecci4d.mjs.map +1 -1
  20. package/dist/datetime-B2ySVlXt.mjs.map +1 -1
  21. package/dist/defined-names-CviWmtQg.mjs.map +1 -1
  22. package/dist/differential-DvKU8fJt.mjs.map +1 -1
  23. package/dist/drawing/dml/dml-xml.d.ts +8 -8
  24. package/dist/drawing/dml/effect.d.ts +2 -2
  25. package/dist/drawing/dml/fill.d.ts +1 -1
  26. package/dist/drawing/dml/geometry.d.ts +1 -1
  27. package/dist/drawing/dml/line.d.ts +1 -1
  28. package/dist/drawing/dml/shape-properties.d.ts +5 -5
  29. package/dist/drawing/dml/text.d.ts +4 -4
  30. package/dist/drawing/drawing-xml.d.ts +1 -1
  31. package/dist/drawing/drawing.d.ts +9 -9
  32. package/dist/drawing/index.d.ts +14 -14
  33. package/dist/drawing-BxzLuryn.mjs.map +1 -1
  34. package/dist/drawing.mjs.map +1 -1
  35. package/dist/{escape-DFTE7ZJc.mjs → escape-rnWSPpWY.mjs} +4 -6
  36. package/dist/{escape-DFTE7ZJc.mjs.map → escape-rnWSPpWY.mjs.map} +1 -1
  37. package/dist/formula/tokenizer.d.ts +1 -1
  38. package/dist/formula/translate.d.ts +2 -2
  39. package/dist/io/browser.d.ts +2 -2
  40. package/dist/io/index.d.ts +7 -7
  41. package/dist/io/load.d.ts +4 -4
  42. package/dist/io/node-fs.d.ts +2 -2
  43. package/dist/io/node-save.d.ts +2 -2
  44. package/dist/io/node.d.ts +2 -2
  45. package/dist/io/save.d.ts +2 -2
  46. package/dist/io.mjs +2 -2
  47. package/dist/io.mjs.map +1 -1
  48. package/dist/{load-MyOIjtrU.mjs → load-Bghb1YHY.mjs} +5 -5
  49. package/dist/load-Bghb1YHY.mjs.map +1 -0
  50. package/dist/{manifest-Cm9K7D62.mjs → manifest-pLmx7KYh.mjs} +3 -3
  51. package/dist/manifest-pLmx7KYh.mjs.map +1 -0
  52. package/dist/node.d.ts +3 -3
  53. package/dist/node.mjs +1 -1
  54. package/dist/node.mjs.map +1 -1
  55. package/dist/packaging/core.d.ts +1 -1
  56. package/dist/packaging/custom.d.ts +2 -2
  57. package/dist/packaging/extended.d.ts +2 -2
  58. package/dist/packaging/index.d.ts +10 -10
  59. package/dist/packaging.mjs +1 -1
  60. package/dist/{parser-D3SLaOFe.mjs → parser-By6RWZVW.mjs} +39 -10
  61. package/dist/parser-By6RWZVW.mjs.map +1 -0
  62. package/dist/reader-BNaUTVCy.mjs.map +1 -1
  63. package/dist/{save-2moCT3Af.mjs → save-Bqcf8w3g.mjs} +6 -6
  64. package/dist/save-Bqcf8w3g.mjs.map +1 -0
  65. package/dist/schema/core.d.ts +1 -1
  66. package/dist/schema/index.d.ts +3 -3
  67. package/dist/schema/serialize.d.ts +2 -2
  68. package/dist/serialize-BC2Wu3bR.mjs.map +1 -1
  69. package/dist/{serializer-BtO2TrI7.mjs → serializer-C6nm0mRJ.mjs} +2 -2
  70. package/dist/serializer-C6nm0mRJ.mjs.map +1 -0
  71. package/dist/streaming/index.d.ts +2 -2
  72. package/dist/streaming/read-only.d.ts +4 -4
  73. package/dist/streaming/write-only.d.ts +7 -7
  74. package/dist/streaming.mjs +6 -6
  75. package/dist/streaming.mjs.map +1 -1
  76. package/dist/styles/alignment.schema.d.ts +2 -2
  77. package/dist/styles/borders.d.ts +1 -1
  78. package/dist/styles/borders.schema.d.ts +2 -2
  79. package/dist/styles/cell-style.d.ts +9 -9
  80. package/dist/styles/colors.schema.d.ts +2 -2
  81. package/dist/styles/differential.d.ts +7 -7
  82. package/dist/styles/fills.d.ts +1 -1
  83. package/dist/styles/fills.schema.d.ts +2 -2
  84. package/dist/styles/fonts.d.ts +1 -1
  85. package/dist/styles/fonts.schema.d.ts +2 -2
  86. package/dist/styles/index.d.ts +21 -21
  87. package/dist/styles/named-styles.d.ts +6 -6
  88. package/dist/styles/numbers.schema.d.ts +2 -2
  89. package/dist/styles/protection.schema.d.ts +2 -2
  90. package/dist/styles/stylesheet-reader.d.ts +1 -1
  91. package/dist/styles/stylesheet-writer.d.ts +1 -1
  92. package/dist/styles/stylesheet.d.ts +8 -8
  93. package/dist/{stylesheet-writer-BrOw4jMY.mjs → stylesheet-writer-HxaX7bGy.mjs} +6 -6
  94. package/dist/stylesheet-writer-HxaX7bGy.mjs.map +1 -0
  95. package/dist/table-1P8we2gS.mjs.map +1 -1
  96. package/dist/tree-BX-sRRVp.mjs.map +1 -1
  97. package/dist/user-shapes-DfmCGKB0.mjs.map +1 -1
  98. package/dist/utf8-Tn3nzyik.mjs.map +1 -1
  99. package/dist/utils/escape.d.ts +3 -5
  100. package/dist/utils/index.d.ts +11 -11
  101. package/dist/utils.mjs +1 -1
  102. package/dist/workbook/calc-properties.d.ts +1 -1
  103. package/dist/workbook/defined-names.d.ts +3 -3
  104. package/dist/workbook/index.d.ts +24 -24
  105. package/dist/workbook/protection.d.ts +1 -1
  106. package/dist/workbook/shared-strings.d.ts +2 -2
  107. package/dist/workbook/views.d.ts +1 -1
  108. package/dist/workbook/workbook-properties.d.ts +1 -1
  109. package/dist/workbook/workbook.d.ts +46 -46
  110. package/dist/{workbook-CARZS94U.mjs → workbook-BlZVXiyG.mjs} +3 -3
  111. package/dist/workbook-BlZVXiyG.mjs.map +1 -0
  112. package/dist/workbook.mjs +1 -1
  113. package/dist/workbook.mjs.map +1 -1
  114. package/dist/worksheet/auto-filter.d.ts +1 -1
  115. package/dist/worksheet/cell-range.d.ts +2 -2
  116. package/dist/worksheet/comments-xml.d.ts +1 -1
  117. package/dist/worksheet/conditional-formatting.d.ts +2 -2
  118. package/dist/worksheet/custom-sheet-views.d.ts +2 -2
  119. package/dist/worksheet/data-validations.d.ts +2 -2
  120. package/dist/worksheet/errors.d.ts +1 -1
  121. package/dist/worksheet/hyperlinks.d.ts +1 -1
  122. package/dist/worksheet/index.d.ts +46 -46
  123. package/dist/worksheet/ole-objects.d.ts +1 -1
  124. package/dist/worksheet/page-setup.d.ts +1 -1
  125. package/dist/worksheet/properties.d.ts +1 -1
  126. package/dist/worksheet/protected-ranges.d.ts +1 -1
  127. package/dist/worksheet/protection.d.ts +1 -1
  128. package/dist/worksheet/reader.d.ts +9 -9
  129. package/dist/worksheet/scenarios.d.ts +1 -1
  130. package/dist/worksheet/table-xml.d.ts +1 -1
  131. package/dist/worksheet/table.d.ts +3 -3
  132. package/dist/worksheet/worksheet.d.ts +31 -31
  133. package/dist/worksheet/writer.d.ts +9 -9
  134. package/dist/worksheet-C5Ensf_j.mjs.map +1 -1
  135. package/dist/worksheet.mjs.map +1 -1
  136. package/dist/writer-IyFccCRJ.mjs.map +1 -1
  137. package/dist/xml/index.d.ts +10 -10
  138. package/dist/xml/parser.d.ts +1 -1
  139. package/dist/xml/serializer.d.ts +1 -1
  140. package/dist/xml/stream-writer.d.ts +1 -1
  141. package/dist/xml.mjs +3 -3
  142. package/dist/xml.mjs.map +1 -1
  143. package/dist/zip/decompression-guard.d.ts +1 -1
  144. package/dist/zip/index.d.ts +6 -6
  145. package/dist/zip/random-access-reader.d.ts +2 -2
  146. package/dist/zip/reader.d.ts +2 -2
  147. package/dist/zip/writer.d.ts +1 -1
  148. package/package.json +4 -1
  149. package/dist/load-MyOIjtrU.mjs.map +0 -1
  150. package/dist/manifest-Cm9K7D62.mjs.map +0 -1
  151. package/dist/parser-D3SLaOFe.mjs.map +0 -1
  152. package/dist/save-2moCT3Af.mjs.map +0 -1
  153. package/dist/serializer-BtO2TrI7.mjs.map +0 -1
  154. package/dist/stylesheet-writer-BrOw4jMY.mjs.map +0 -1
  155. package/dist/workbook-CARZS94U.mjs.map +0 -1
@@ -1,3 +1,3 @@
1
- export type { AttrDef, ElementDef, Primitive, Schema } from './core';
2
- export { defineSchema } from './core';
3
- export { fromTree, toTree } from './serialize';
1
+ export type { AttrDef, ElementDef, Primitive, Schema } from './core.js';
2
+ export { defineSchema } from './core.js';
3
+ export { fromTree, toTree } from './serialize.js';
@@ -1,5 +1,5 @@
1
- import { type XmlNode } from '../xml/tree';
2
- import type { Schema } from './core';
1
+ import { type XmlNode } from '../xml/tree.js';
2
+ import type { Schema } from './core.js';
3
3
  /** Serialise a value of `T` into an {@link XmlNode} per the supplied schema. */
4
4
  export declare function toTree<T>(value: T, schema: Schema<T>): XmlNode;
5
5
  /** Materialise a value of `T` from an {@link XmlNode} per the supplied schema. */
@@ -1 +1 @@
1
- {"version":3,"file":"serialize-BC2Wu3bR.mjs","names":[],"sources":["../src/schema/core.ts","../src/schema/serialize.ts"],"sourcesContent":["// Schema layer types — pure data, zero classes.\n//\n// A Schema<T> describes how a plain `T` is mapped to and from an XmlNode. The\n// runtime serialiser (src/schema/serialize.ts) is a single switch-on-kind walk\n// that needs nothing beyond these tables; bundlers can drop schemas a build\n// path never imports because each lives in its own const.\n//\n// Lazy element schemas (`schema: () => SideSchema`) are how circular references\n// — Border has Sides, Side has its own Color, etc. — stay expressible without\n// hoisting hazards at module load.\n\n/** Primitive coercion kinds attribute values may declare. */\nexport type Primitive = 'string' | 'int' | 'float' | 'bool';\n\nexport interface AttrDef {\n kind: Primitive | 'enum';\n /** Allowed values when kind === 'enum'. */\n values?: readonly string[];\n /** Treat the attribute as optional; missing → undefined. */\n optional?: boolean;\n /**\n * Default applied during fromTree when the attribute is absent. Never\n * auto-stripped during toTree — round-trip equivalence is the primary\n * concern; explicit emitters decide when to omit.\n */\n default?: unknown;\n /** Numeric range bounds for kind in {'int', 'float'}. */\n min?: number;\n max?: number;\n /** XML attribute name when it differs from the property key on T. */\n xmlName?: string;\n /** Namespace URI for the XML attribute. Empty / undefined = no namespace. */\n xmlNs?: string;\n}\n\n/**\n * Discriminated union of element shapes a schema can declare. Names are\n * unprefixed (`xmlNs` carries the namespace); the serialiser pairs them into\n * Clark names internally.\n */\nexport type ElementDef =\n | {\n kind: 'text';\n /** Property key on T — the value lands at `T[key]`. */\n key: string;\n /** XML element local name. Defaults to `key` when omitted. */\n name?: string;\n xmlNs?: string;\n primitive: Primitive;\n optional?: boolean;\n default?: unknown;\n /**\n * Fixed attributes always emitted on this element. Keys in Clark\n * notation. On parse, attributes other than these are ignored; keep the\n * schema strict only for the value (text content).\n *\n * Used for the `xsi:type=\"dcterms:W3CDTF\"` marker that docProps/core.xml\n * emits on its <dcterms:created> / <dcterms:modified> children, and\n * similar fixed-marker patterns.\n */\n attrs?: Record<string, string>;\n }\n | {\n kind: 'object';\n key: string;\n name?: string;\n xmlNs?: string;\n // Schema is contravariant in T at the element boundary; named types\n // come back via T anyway. The `any` is intentional — `unknown` would\n // force a cast in every concrete schema definition with no extra safety.\n // oxlint-disable-next-line typescript/no-explicit-any\n schema: () => Schema<any>;\n optional?: boolean;\n }\n | {\n kind: 'sequence';\n key: string;\n /** Local name of the repeated child element. */\n itemName: string;\n itemNs?: string;\n // See ElementDef.kind === 'object' for why `any` survives here.\n // oxlint-disable-next-line typescript/no-explicit-any\n itemSchema: () => Schema<any>;\n /** Optional wrapper element holding the items. */\n container?: { name: string; xmlNs?: string; count?: boolean };\n }\n | {\n /**\n * Empty marker element — `<key/>` whose presence sets `T[key] = true`,\n * absence leaves it `undefined`. Used by Font's `<b/>`, `<i/>`, etc.\n */\n kind: 'empty';\n key: string;\n name?: string;\n xmlNs?: string;\n }\n | {\n /**\n * `<key val=\"value\"/>` style child carrying a single primitive value via\n * an attribute (default `val`). This is openpyxl's NestedString /\n * NestedFloat / NestedInteger / NestedBool / NestedNoneSet pattern; it\n * shows up across Font, NumberFormat children and several chart\n * sub-elements.\n */\n kind: 'nested';\n key: string;\n name?: string;\n xmlNs?: string;\n primitive: Primitive | 'enum';\n /** Allowed values when primitive === 'enum'. */\n values?: readonly string[];\n /** Attribute name carrying the value. Defaults to \"val\". */\n valAttr?: string;\n /** Numeric range bounds (int / float). */\n min?: number;\n max?: number;\n optional?: boolean;\n default?: unknown;\n }\n | {\n /**\n * Opaque round-trip slot — fromTree stores the matched child as a raw\n * `XmlNode`, toTree splices it back verbatim. Used for subtrees we don't\n * want to model in detail (e.g. the vt:vector content under app.xml's\n * HeadingPairs / TitlesOfParts) but still need to preserve byte-for-byte\n * through edits.\n */\n kind: 'raw';\n key: string;\n name?: string;\n xmlNs?: string;\n optional?: boolean;\n };\n\nexport interface Schema<T> {\n /** Local element name. */\n tagname: string;\n /** Namespace URI of this element. */\n xmlNs?: string;\n /** Attribute table keyed by property name on T. */\n attrs: { readonly [K in keyof T & string]?: AttrDef };\n /** Child elements in declaration / emission order. */\n elements: ReadonlyArray<ElementDef>;\n /** Hook to normalise the parsed object (e.g., infer derived fields). */\n postParse?: (value: T, node: import('../xml/tree').XmlNode) => T;\n /** Hook to normalise the value before serialisation. */\n preSerialize?: (value: T) => T;\n}\n\n/**\n * Identity helper that pins inference to the supplied `T`. The runtime is just\n * `s => s`; the value matters only for the call-site type.\n */\nexport function defineSchema<T>(s: Schema<T>): Schema<T> {\n return s;\n}\n","// Schema-driven (de)serialisation. One switch-on-kind walk in each direction;\n// the schema does the work, no class-based descriptors.\n//\n// `toTree` and `fromTree` are pure functions over plain data. They run the same\n// on the schema layer's own types and on user types in the styles / chart /\n// drawing modules.\n\nimport { OpenXmlSchemaError } from '../utils/exceptions';\nimport { qname } from '../xml/namespaces';\nimport { el, type XmlNode } from '../xml/tree';\nimport type { AttrDef, ElementDef, Primitive, Schema } from './core';\n\n// ---- coercion helpers -------------------------------------------------------\n\nconst coerceFromString = (raw: string, kind: Primitive | 'enum', def: AttrDef): unknown => {\n switch (kind) {\n case 'string':\n return raw;\n case 'int': {\n const n = Number.parseInt(raw, 10);\n if (!Number.isFinite(n)) throw new OpenXmlSchemaError(`expected an integer, got \"${raw}\"`);\n if (def.min !== undefined && n < def.min) throw new OpenXmlSchemaError(`int \"${n}\" is below min ${def.min}`);\n if (def.max !== undefined && n > def.max) throw new OpenXmlSchemaError(`int \"${n}\" is above max ${def.max}`);\n return n;\n }\n case 'float': {\n const n = Number.parseFloat(raw);\n if (!Number.isFinite(n)) throw new OpenXmlSchemaError(`expected a number, got \"${raw}\"`);\n if (def.min !== undefined && n < def.min) throw new OpenXmlSchemaError(`float \"${n}\" is below min ${def.min}`);\n if (def.max !== undefined && n > def.max) throw new OpenXmlSchemaError(`float \"${n}\" is above max ${def.max}`);\n return n;\n }\n case 'bool': {\n // openpyxl accepts 'true'/'t'/'1' or 'false'/'f'/'0' (case-insensitive).\n const v = raw.toLowerCase();\n if (v === 'true' || v === 't' || v === '1') return true;\n if (v === 'false' || v === 'f' || v === '0') return false;\n throw new OpenXmlSchemaError(`expected a boolean, got \"${raw}\"`);\n }\n case 'enum': {\n if (!def.values?.includes(raw)) {\n throw new OpenXmlSchemaError(`expected one of [${def.values?.join(', ') ?? ''}], got \"${raw}\"`);\n }\n return raw;\n }\n }\n};\n\nconst coerceToString = (value: unknown, kind: Primitive | 'enum', def: AttrDef): string => {\n switch (kind) {\n case 'string':\n if (typeof value !== 'string') throw new OpenXmlSchemaError(`expected a string, got ${typeof value}`);\n return value;\n case 'int': {\n if (typeof value !== 'number' || !Number.isFinite(value) || !Number.isInteger(value)) {\n throw new OpenXmlSchemaError(`expected an integer, got ${String(value)}`);\n }\n return String(value);\n }\n case 'float': {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new OpenXmlSchemaError(`expected a number, got ${String(value)}`);\n }\n return String(value);\n }\n case 'bool': {\n if (typeof value !== 'boolean') throw new OpenXmlSchemaError(`expected a boolean, got ${typeof value}`);\n // OOXML convention: '1' / '0'.\n return value ? '1' : '0';\n }\n case 'enum': {\n if (typeof value !== 'string' || !def.values || !def.values.includes(value)) {\n throw new OpenXmlSchemaError(`enum value out of range: ${String(value)}`);\n }\n return value;\n }\n }\n};\n\nconst attrXmlKey = (key: string, def: AttrDef): string => qname(def.xmlNs ?? '', def.xmlName ?? key);\nconst elementXmlName = (def: ElementDef, fallbackNs: string | undefined): string => {\n const local = def.kind === 'sequence' ? (def.container?.name ?? def.itemName) : (def.name ?? def.key);\n const ns = def.kind === 'sequence' ? (def.container?.xmlNs ?? def.itemNs ?? fallbackNs) : (def.xmlNs ?? fallbackNs);\n return qname(ns ?? '', local);\n};\n\n// ---- toTree -----------------------------------------------------------------\n\n/** Serialise a value of `T` into an {@link XmlNode} per the supplied schema. */\nexport function toTree<T>(value: T, schema: Schema<T>): XmlNode {\n const v = (schema.preSerialize ? schema.preSerialize(value) : value) as Record<string, unknown>;\n const node = el(qname(schema.xmlNs ?? '', schema.tagname));\n\n for (const [key, def] of Object.entries(schema.attrs) as Array<[string, AttrDef | undefined]>) {\n if (def === undefined) continue;\n const raw = v[key];\n if (raw === undefined) {\n if (def.optional) continue;\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required attribute \"${key}\" is missing`);\n }\n node.attrs[attrXmlKey(key, def)] = coerceToString(raw, def.kind, def);\n }\n\n for (const def of schema.elements) {\n const raw = v[def.key];\n if (raw === undefined) {\n // 'empty' has no `optional`; presence is binary on the value itself.\n // 'sequence' is implicitly optional (undefined / [] = no items). 'raw'\n // uses the same optional flag as text/object.\n if ((def.kind === 'text' || def.kind === 'object' || def.kind === 'raw') && !def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required element \"${def.key}\" is missing`);\n }\n continue;\n }\n switch (def.kind) {\n case 'text': {\n const text = coerceToString(raw, def.primitive, { kind: def.primitive });\n node.children.push(el(elementXmlName(def, schema.xmlNs), def.attrs ?? {}, [], text));\n break;\n }\n case 'empty': {\n if (raw === true) node.children.push(el(elementXmlName(def, schema.xmlNs), {}, []));\n break;\n }\n case 'nested': {\n const valAttr = def.valAttr ?? 'val';\n const fakeAttrDef: AttrDef = {\n kind: def.primitive,\n ...(def.values !== undefined ? { values: def.values } : {}),\n ...(def.min !== undefined ? { min: def.min } : {}),\n ...(def.max !== undefined ? { max: def.max } : {}),\n };\n const text = coerceToString(raw, def.primitive, fakeAttrDef);\n node.children.push(el(elementXmlName(def, schema.xmlNs), { [valAttr]: text }, []));\n break;\n }\n case 'object': {\n const sub = toTree(raw as Record<string, unknown>, def.schema());\n // Allow the schema to declare its own tagname OR be addressed by the\n // parent under a different element name. We honour the schema's tagname\n // (it's the canonical identity for that type).\n if (def.name !== undefined && sub.name !== qname(def.xmlNs ?? schema.xmlNs ?? '', def.name)) {\n // Re-tag the produced element to the parent-defined name.\n sub.name = qname(def.xmlNs ?? schema.xmlNs ?? '', def.name);\n } else if (def.name === undefined && def.key !== sub.name.replace(/^\\{[^}]*\\}/, '')) {\n // No explicit `name` — use the property key as the local name.\n sub.name = qname(def.xmlNs ?? schema.xmlNs ?? '', def.key);\n }\n node.children.push(sub);\n break;\n }\n case 'raw': {\n // Splice the stored XmlNode back verbatim, but realign its name to the\n // schema-declared position so the output is well-formed even when the\n // caller mutates `name`.\n const sub = raw as XmlNode;\n const expected = elementXmlName(def, schema.xmlNs);\n if (sub.name !== expected) {\n node.children.push({ ...sub, name: expected });\n } else {\n node.children.push(sub);\n }\n break;\n }\n case 'sequence': {\n const items = raw as ReadonlyArray<Record<string, unknown>>;\n const itemSchema = def.itemSchema();\n const built = items.map((item) => {\n const sub = toTree(item, itemSchema);\n // Re-tag to the declared itemName / itemNs.\n sub.name = qname(def.itemNs ?? itemSchema.xmlNs ?? '', def.itemName);\n return sub;\n });\n if (def.container !== undefined) {\n const containerAttrs: Record<string, string> = {};\n if (def.container.count) containerAttrs['count'] = String(items.length);\n node.children.push(el(elementXmlName(def, schema.xmlNs), containerAttrs, built));\n } else {\n for (const c of built) node.children.push(c);\n }\n break;\n }\n }\n }\n\n return node;\n}\n\n// ---- fromTree ---------------------------------------------------------------\n\nconst childByName = (node: XmlNode, fullName: string): XmlNode | undefined => {\n for (const c of node.children) if (c.name === fullName) return c;\n return undefined;\n};\n\nconst childrenByName = (node: XmlNode, fullName: string): XmlNode[] => {\n const out: XmlNode[] = [];\n for (const c of node.children) if (c.name === fullName) out.push(c);\n return out;\n};\n\n/** Materialise a value of `T` from an {@link XmlNode} per the supplied schema. */\nexport function fromTree<T>(node: XmlNode, schema: Schema<T>): T {\n const out: Record<string, unknown> = {};\n const expectedTag = qname(schema.xmlNs ?? '', schema.tagname);\n if (node.name !== expectedTag) {\n throw new OpenXmlSchemaError(`fromTree: expected <${schema.tagname}> (Clark \"${expectedTag}\"), got \"${node.name}\"`);\n }\n\n for (const [key, def] of Object.entries(schema.attrs) as Array<[string, AttrDef | undefined]>) {\n if (def === undefined) continue;\n const xmlKey = attrXmlKey(key, def);\n const raw = node.attrs[xmlKey];\n if (raw === undefined) {\n if (def.default !== undefined) out[key] = def.default;\n else if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required attribute \"${key}\" is missing`);\n }\n continue;\n }\n out[key] = coerceFromString(raw, def.kind, def);\n }\n\n for (const def of schema.elements) {\n const fullName = elementXmlName(def, schema.xmlNs);\n switch (def.kind) {\n case 'text': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n if (def.default !== undefined) out[def.key] = def.default;\n else if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required text element \"${def.key}\" is missing`);\n }\n break;\n }\n out[def.key] = coerceFromString(child.text ?? '', def.primitive, { kind: def.primitive });\n break;\n }\n case 'empty': {\n const child = childByName(node, fullName);\n if (child !== undefined) out[def.key] = true;\n // Absent → leave key unset so the value compares equal to the\n // round-trip-emitting input that omitted it.\n break;\n }\n case 'nested': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n // The element itself was omitted: leave the field unset for optional\n // nested elements, regardless of `default`. `default` here governs\n // the \"child present but @val omitted\" case (e.g. <u/> meaning\n // underline=single per ECMA-376 §18.4.13), not \"child entirely\n // absent\".\n if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required nested element \"${def.key}\" is missing`);\n }\n break;\n }\n const valAttr = def.valAttr ?? 'val';\n const raw = child.attrs[valAttr];\n if (raw === undefined) {\n if (def.default !== undefined) {\n out[def.key] = def.default;\n break;\n }\n throw new OpenXmlSchemaError(\n `<${schema.tagname}>: nested element \"${def.key}\" missing attribute \"${valAttr}\"`,\n );\n }\n out[def.key] = coerceFromString(raw, def.primitive, {\n kind: def.primitive,\n ...(def.values !== undefined ? { values: def.values } : {}),\n ...(def.min !== undefined ? { min: def.min } : {}),\n ...(def.max !== undefined ? { max: def.max } : {}),\n });\n break;\n }\n case 'raw': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required raw element \"${def.key}\" is missing`);\n }\n break;\n }\n out[def.key] = child;\n break;\n }\n case 'object': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required element \"${def.key}\" is missing`);\n }\n break;\n }\n const itemSchema = def.schema();\n // Address the child by the parent-declared name even if the child\n // schema names itself differently.\n const renamed: XmlNode =\n child.name === qname(itemSchema.xmlNs ?? '', itemSchema.tagname)\n ? child\n : { ...child, name: qname(itemSchema.xmlNs ?? '', itemSchema.tagname) };\n out[def.key] = fromTree(renamed, itemSchema);\n break;\n }\n case 'sequence': {\n const itemSchema = def.itemSchema();\n const itemFullName = qname(def.itemNs ?? itemSchema.xmlNs ?? '', def.itemName);\n const itemSchemaName = qname(itemSchema.xmlNs ?? '', itemSchema.tagname);\n const containerNode = def.container !== undefined ? childByName(node, fullName) : node;\n const items: unknown[] = [];\n if (containerNode !== undefined) {\n const matches = childrenByName(containerNode, itemFullName);\n for (const m of matches) {\n const renamed: XmlNode = m.name === itemSchemaName ? m : { ...m, name: itemSchemaName };\n items.push(fromTree(renamed, itemSchema));\n }\n }\n out[def.key] = items;\n break;\n }\n }\n }\n\n const built = out as unknown as T;\n return schema.postParse ? schema.postParse(built, node) : built;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"serialize-BC2Wu3bR.mjs","names":[],"sources":["../src/schema/core.ts","../src/schema/serialize.ts"],"sourcesContent":["// Schema layer types — pure data, zero classes.\n//\n// A Schema<T> describes how a plain `T` is mapped to and from an XmlNode. The\n// runtime serialiser (src/schema/serialize.ts) is a single switch-on-kind walk\n// that needs nothing beyond these tables; bundlers can drop schemas a build\n// path never imports because each lives in its own const.\n//\n// Lazy element schemas (`schema: () => SideSchema`) are how circular references\n// — Border has Sides, Side has its own Color, etc. — stay expressible without\n// hoisting hazards at module load.\n\n/** Primitive coercion kinds attribute values may declare. */\nexport type Primitive = 'string' | 'int' | 'float' | 'bool';\n\nexport interface AttrDef {\n kind: Primitive | 'enum';\n /** Allowed values when kind === 'enum'. */\n values?: readonly string[];\n /** Treat the attribute as optional; missing → undefined. */\n optional?: boolean;\n /**\n * Default applied during fromTree when the attribute is absent. Never\n * auto-stripped during toTree — round-trip equivalence is the primary\n * concern; explicit emitters decide when to omit.\n */\n default?: unknown;\n /** Numeric range bounds for kind in {'int', 'float'}. */\n min?: number;\n max?: number;\n /** XML attribute name when it differs from the property key on T. */\n xmlName?: string;\n /** Namespace URI for the XML attribute. Empty / undefined = no namespace. */\n xmlNs?: string;\n}\n\n/**\n * Discriminated union of element shapes a schema can declare. Names are\n * unprefixed (`xmlNs` carries the namespace); the serialiser pairs them into\n * Clark names internally.\n */\nexport type ElementDef =\n | {\n kind: 'text';\n /** Property key on T — the value lands at `T[key]`. */\n key: string;\n /** XML element local name. Defaults to `key` when omitted. */\n name?: string;\n xmlNs?: string;\n primitive: Primitive;\n optional?: boolean;\n default?: unknown;\n /**\n * Fixed attributes always emitted on this element. Keys in Clark\n * notation. On parse, attributes other than these are ignored; keep the\n * schema strict only for the value (text content).\n *\n * Used for the `xsi:type=\"dcterms:W3CDTF\"` marker that docProps/core.xml\n * emits on its <dcterms:created> / <dcterms:modified> children, and\n * similar fixed-marker patterns.\n */\n attrs?: Record<string, string>;\n }\n | {\n kind: 'object';\n key: string;\n name?: string;\n xmlNs?: string;\n // Schema is contravariant in T at the element boundary; named types\n // come back via T anyway. The `any` is intentional — `unknown` would\n // force a cast in every concrete schema definition with no extra safety.\n // oxlint-disable-next-line typescript/no-explicit-any\n schema: () => Schema<any>;\n optional?: boolean;\n }\n | {\n kind: 'sequence';\n key: string;\n /** Local name of the repeated child element. */\n itemName: string;\n itemNs?: string;\n // See ElementDef.kind === 'object' for why `any` survives here.\n // oxlint-disable-next-line typescript/no-explicit-any\n itemSchema: () => Schema<any>;\n /** Optional wrapper element holding the items. */\n container?: { name: string; xmlNs?: string; count?: boolean };\n }\n | {\n /**\n * Empty marker element — `<key/>` whose presence sets `T[key] = true`,\n * absence leaves it `undefined`. Used by Font's `<b/>`, `<i/>`, etc.\n */\n kind: 'empty';\n key: string;\n name?: string;\n xmlNs?: string;\n }\n | {\n /**\n * `<key val=\"value\"/>` style child carrying a single primitive value via\n * an attribute (default `val`). This is openpyxl's NestedString /\n * NestedFloat / NestedInteger / NestedBool / NestedNoneSet pattern; it\n * shows up across Font, NumberFormat children and several chart\n * sub-elements.\n */\n kind: 'nested';\n key: string;\n name?: string;\n xmlNs?: string;\n primitive: Primitive | 'enum';\n /** Allowed values when primitive === 'enum'. */\n values?: readonly string[];\n /** Attribute name carrying the value. Defaults to \"val\". */\n valAttr?: string;\n /** Numeric range bounds (int / float). */\n min?: number;\n max?: number;\n optional?: boolean;\n default?: unknown;\n }\n | {\n /**\n * Opaque round-trip slot — fromTree stores the matched child as a raw\n * `XmlNode`, toTree splices it back verbatim. Used for subtrees we don't\n * want to model in detail (e.g. the vt:vector content under app.xml's\n * HeadingPairs / TitlesOfParts) but still need to preserve byte-for-byte\n * through edits.\n */\n kind: 'raw';\n key: string;\n name?: string;\n xmlNs?: string;\n optional?: boolean;\n };\n\nexport interface Schema<T> {\n /** Local element name. */\n tagname: string;\n /** Namespace URI of this element. */\n xmlNs?: string;\n /** Attribute table keyed by property name on T. */\n attrs: { readonly [K in keyof T & string]?: AttrDef };\n /** Child elements in declaration / emission order. */\n elements: ReadonlyArray<ElementDef>;\n /** Hook to normalise the parsed object (e.g., infer derived fields). */\n postParse?: (value: T, node: import('../xml/tree.js').XmlNode) => T;\n /** Hook to normalise the value before serialisation. */\n preSerialize?: (value: T) => T;\n}\n\n/**\n * Identity helper that pins inference to the supplied `T`. The runtime is just\n * `s => s`; the value matters only for the call-site type.\n */\nexport function defineSchema<T>(s: Schema<T>): Schema<T> {\n return s;\n}\n","// Schema-driven (de)serialisation. One switch-on-kind walk in each direction;\n// the schema does the work, no class-based descriptors.\n//\n// `toTree` and `fromTree` are pure functions over plain data. They run the same\n// on the schema layer's own types and on user types in the styles / chart /\n// drawing modules.\n\nimport { OpenXmlSchemaError } from '../utils/exceptions.js';\nimport { qname } from '../xml/namespaces.js';\nimport { el, type XmlNode } from '../xml/tree.js';\nimport type { AttrDef, ElementDef, Primitive, Schema } from './core.js';\n\n// ---- coercion helpers -------------------------------------------------------\n\nconst coerceFromString = (raw: string, kind: Primitive | 'enum', def: AttrDef): unknown => {\n switch (kind) {\n case 'string':\n return raw;\n case 'int': {\n const n = Number.parseInt(raw, 10);\n if (!Number.isFinite(n)) throw new OpenXmlSchemaError(`expected an integer, got \"${raw}\"`);\n if (def.min !== undefined && n < def.min) throw new OpenXmlSchemaError(`int \"${n}\" is below min ${def.min}`);\n if (def.max !== undefined && n > def.max) throw new OpenXmlSchemaError(`int \"${n}\" is above max ${def.max}`);\n return n;\n }\n case 'float': {\n const n = Number.parseFloat(raw);\n if (!Number.isFinite(n)) throw new OpenXmlSchemaError(`expected a number, got \"${raw}\"`);\n if (def.min !== undefined && n < def.min) throw new OpenXmlSchemaError(`float \"${n}\" is below min ${def.min}`);\n if (def.max !== undefined && n > def.max) throw new OpenXmlSchemaError(`float \"${n}\" is above max ${def.max}`);\n return n;\n }\n case 'bool': {\n // openpyxl accepts 'true'/'t'/'1' or 'false'/'f'/'0' (case-insensitive).\n const v = raw.toLowerCase();\n if (v === 'true' || v === 't' || v === '1') return true;\n if (v === 'false' || v === 'f' || v === '0') return false;\n throw new OpenXmlSchemaError(`expected a boolean, got \"${raw}\"`);\n }\n case 'enum': {\n if (!def.values?.includes(raw)) {\n throw new OpenXmlSchemaError(`expected one of [${def.values?.join(', ') ?? ''}], got \"${raw}\"`);\n }\n return raw;\n }\n }\n};\n\nconst coerceToString = (value: unknown, kind: Primitive | 'enum', def: AttrDef): string => {\n switch (kind) {\n case 'string':\n if (typeof value !== 'string') throw new OpenXmlSchemaError(`expected a string, got ${typeof value}`);\n return value;\n case 'int': {\n if (typeof value !== 'number' || !Number.isFinite(value) || !Number.isInteger(value)) {\n throw new OpenXmlSchemaError(`expected an integer, got ${String(value)}`);\n }\n return String(value);\n }\n case 'float': {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new OpenXmlSchemaError(`expected a number, got ${String(value)}`);\n }\n return String(value);\n }\n case 'bool': {\n if (typeof value !== 'boolean') throw new OpenXmlSchemaError(`expected a boolean, got ${typeof value}`);\n // OOXML convention: '1' / '0'.\n return value ? '1' : '0';\n }\n case 'enum': {\n if (typeof value !== 'string' || !def.values || !def.values.includes(value)) {\n throw new OpenXmlSchemaError(`enum value out of range: ${String(value)}`);\n }\n return value;\n }\n }\n};\n\nconst attrXmlKey = (key: string, def: AttrDef): string => qname(def.xmlNs ?? '', def.xmlName ?? key);\nconst elementXmlName = (def: ElementDef, fallbackNs: string | undefined): string => {\n const local = def.kind === 'sequence' ? (def.container?.name ?? def.itemName) : (def.name ?? def.key);\n const ns = def.kind === 'sequence' ? (def.container?.xmlNs ?? def.itemNs ?? fallbackNs) : (def.xmlNs ?? fallbackNs);\n return qname(ns ?? '', local);\n};\n\n// ---- toTree -----------------------------------------------------------------\n\n/** Serialise a value of `T` into an {@link XmlNode} per the supplied schema. */\nexport function toTree<T>(value: T, schema: Schema<T>): XmlNode {\n const v = (schema.preSerialize ? schema.preSerialize(value) : value) as Record<string, unknown>;\n const node = el(qname(schema.xmlNs ?? '', schema.tagname));\n\n for (const [key, def] of Object.entries(schema.attrs) as Array<[string, AttrDef | undefined]>) {\n if (def === undefined) continue;\n const raw = v[key];\n if (raw === undefined) {\n if (def.optional) continue;\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required attribute \"${key}\" is missing`);\n }\n node.attrs[attrXmlKey(key, def)] = coerceToString(raw, def.kind, def);\n }\n\n for (const def of schema.elements) {\n const raw = v[def.key];\n if (raw === undefined) {\n // 'empty' has no `optional`; presence is binary on the value itself.\n // 'sequence' is implicitly optional (undefined / [] = no items). 'raw'\n // uses the same optional flag as text/object.\n if ((def.kind === 'text' || def.kind === 'object' || def.kind === 'raw') && !def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required element \"${def.key}\" is missing`);\n }\n continue;\n }\n switch (def.kind) {\n case 'text': {\n const text = coerceToString(raw, def.primitive, { kind: def.primitive });\n node.children.push(el(elementXmlName(def, schema.xmlNs), def.attrs ?? {}, [], text));\n break;\n }\n case 'empty': {\n if (raw === true) node.children.push(el(elementXmlName(def, schema.xmlNs), {}, []));\n break;\n }\n case 'nested': {\n const valAttr = def.valAttr ?? 'val';\n const fakeAttrDef: AttrDef = {\n kind: def.primitive,\n ...(def.values !== undefined ? { values: def.values } : {}),\n ...(def.min !== undefined ? { min: def.min } : {}),\n ...(def.max !== undefined ? { max: def.max } : {}),\n };\n const text = coerceToString(raw, def.primitive, fakeAttrDef);\n node.children.push(el(elementXmlName(def, schema.xmlNs), { [valAttr]: text }, []));\n break;\n }\n case 'object': {\n const sub = toTree(raw as Record<string, unknown>, def.schema());\n // Allow the schema to declare its own tagname OR be addressed by the\n // parent under a different element name. We honour the schema's tagname\n // (it's the canonical identity for that type).\n if (def.name !== undefined && sub.name !== qname(def.xmlNs ?? schema.xmlNs ?? '', def.name)) {\n // Re-tag the produced element to the parent-defined name.\n sub.name = qname(def.xmlNs ?? schema.xmlNs ?? '', def.name);\n } else if (def.name === undefined && def.key !== sub.name.replace(/^\\{[^}]*\\}/, '')) {\n // No explicit `name` — use the property key as the local name.\n sub.name = qname(def.xmlNs ?? schema.xmlNs ?? '', def.key);\n }\n node.children.push(sub);\n break;\n }\n case 'raw': {\n // Splice the stored XmlNode back verbatim, but realign its name to the\n // schema-declared position so the output is well-formed even when the\n // caller mutates `name`.\n const sub = raw as XmlNode;\n const expected = elementXmlName(def, schema.xmlNs);\n if (sub.name !== expected) {\n node.children.push({ ...sub, name: expected });\n } else {\n node.children.push(sub);\n }\n break;\n }\n case 'sequence': {\n const items = raw as ReadonlyArray<Record<string, unknown>>;\n const itemSchema = def.itemSchema();\n const built = items.map((item) => {\n const sub = toTree(item, itemSchema);\n // Re-tag to the declared itemName / itemNs.\n sub.name = qname(def.itemNs ?? itemSchema.xmlNs ?? '', def.itemName);\n return sub;\n });\n if (def.container !== undefined) {\n const containerAttrs: Record<string, string> = {};\n if (def.container.count) containerAttrs['count'] = String(items.length);\n node.children.push(el(elementXmlName(def, schema.xmlNs), containerAttrs, built));\n } else {\n for (const c of built) node.children.push(c);\n }\n break;\n }\n }\n }\n\n return node;\n}\n\n// ---- fromTree ---------------------------------------------------------------\n\nconst childByName = (node: XmlNode, fullName: string): XmlNode | undefined => {\n for (const c of node.children) if (c.name === fullName) return c;\n return undefined;\n};\n\nconst childrenByName = (node: XmlNode, fullName: string): XmlNode[] => {\n const out: XmlNode[] = [];\n for (const c of node.children) if (c.name === fullName) out.push(c);\n return out;\n};\n\n/** Materialise a value of `T` from an {@link XmlNode} per the supplied schema. */\nexport function fromTree<T>(node: XmlNode, schema: Schema<T>): T {\n const out: Record<string, unknown> = {};\n const expectedTag = qname(schema.xmlNs ?? '', schema.tagname);\n if (node.name !== expectedTag) {\n throw new OpenXmlSchemaError(`fromTree: expected <${schema.tagname}> (Clark \"${expectedTag}\"), got \"${node.name}\"`);\n }\n\n for (const [key, def] of Object.entries(schema.attrs) as Array<[string, AttrDef | undefined]>) {\n if (def === undefined) continue;\n const xmlKey = attrXmlKey(key, def);\n const raw = node.attrs[xmlKey];\n if (raw === undefined) {\n if (def.default !== undefined) out[key] = def.default;\n else if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required attribute \"${key}\" is missing`);\n }\n continue;\n }\n out[key] = coerceFromString(raw, def.kind, def);\n }\n\n for (const def of schema.elements) {\n const fullName = elementXmlName(def, schema.xmlNs);\n switch (def.kind) {\n case 'text': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n if (def.default !== undefined) out[def.key] = def.default;\n else if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required text element \"${def.key}\" is missing`);\n }\n break;\n }\n out[def.key] = coerceFromString(child.text ?? '', def.primitive, { kind: def.primitive });\n break;\n }\n case 'empty': {\n const child = childByName(node, fullName);\n if (child !== undefined) out[def.key] = true;\n // Absent → leave key unset so the value compares equal to the\n // round-trip-emitting input that omitted it.\n break;\n }\n case 'nested': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n // The element itself was omitted: leave the field unset for optional\n // nested elements, regardless of `default`. `default` here governs\n // the \"child present but @val omitted\" case (e.g. <u/> meaning\n // underline=single per ECMA-376 §18.4.13), not \"child entirely\n // absent\".\n if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required nested element \"${def.key}\" is missing`);\n }\n break;\n }\n const valAttr = def.valAttr ?? 'val';\n const raw = child.attrs[valAttr];\n if (raw === undefined) {\n if (def.default !== undefined) {\n out[def.key] = def.default;\n break;\n }\n throw new OpenXmlSchemaError(\n `<${schema.tagname}>: nested element \"${def.key}\" missing attribute \"${valAttr}\"`,\n );\n }\n out[def.key] = coerceFromString(raw, def.primitive, {\n kind: def.primitive,\n ...(def.values !== undefined ? { values: def.values } : {}),\n ...(def.min !== undefined ? { min: def.min } : {}),\n ...(def.max !== undefined ? { max: def.max } : {}),\n });\n break;\n }\n case 'raw': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required raw element \"${def.key}\" is missing`);\n }\n break;\n }\n out[def.key] = child;\n break;\n }\n case 'object': {\n const child = childByName(node, fullName);\n if (child === undefined) {\n if (!def.optional) {\n throw new OpenXmlSchemaError(`<${schema.tagname}>: required element \"${def.key}\" is missing`);\n }\n break;\n }\n const itemSchema = def.schema();\n // Address the child by the parent-declared name even if the child\n // schema names itself differently.\n const renamed: XmlNode =\n child.name === qname(itemSchema.xmlNs ?? '', itemSchema.tagname)\n ? child\n : { ...child, name: qname(itemSchema.xmlNs ?? '', itemSchema.tagname) };\n out[def.key] = fromTree(renamed, itemSchema);\n break;\n }\n case 'sequence': {\n const itemSchema = def.itemSchema();\n const itemFullName = qname(def.itemNs ?? itemSchema.xmlNs ?? '', def.itemName);\n const itemSchemaName = qname(itemSchema.xmlNs ?? '', itemSchema.tagname);\n const containerNode = def.container !== undefined ? childByName(node, fullName) : node;\n const items: unknown[] = [];\n if (containerNode !== undefined) {\n const matches = childrenByName(containerNode, itemFullName);\n for (const m of matches) {\n const renamed: XmlNode = m.name === itemSchemaName ? m : { ...m, name: itemSchemaName };\n items.push(fromTree(renamed, itemSchema));\n }\n }\n out[def.key] = items;\n break;\n }\n }\n }\n\n const built = out as unknown as T;\n return schema.postParse ? schema.postParse(built, node) : built;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { n as escapeXmlAttr, r as escapeXmlText } from "./escape-DFTE7ZJc.mjs";
1
+ import { n as escapeXmlAttr, r as escapeXmlText } from "./escape-rnWSPpWY.mjs";
2
2
  import { At as parseQName, Dt as XML_NS, V as DEFAULT_PREFIXES } from "./tree-BX-sRRVp.mjs";
3
3
  //#region src/xml/serializer.ts
4
4
  /**
@@ -125,4 +125,4 @@ const emit = (out, node, allocation, isRoot) => {
125
125
  //#endregion
126
126
  export { serializeXml as t };
127
127
 
128
- //# sourceMappingURL=serializer-BtO2TrI7.mjs.map
128
+ //# sourceMappingURL=serializer-C6nm0mRJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializer-C6nm0mRJ.mjs","names":[],"sources":["../src/xml/serializer.ts"],"sourcesContent":["// DOM-style XML serializer. Inverse of src/xml/parser.ts.\n//\n// XmlNode trees use Clark-notation names (`{ns}local`); the serializer\n// rebuilds prefix mappings and emits a single UTF-8 byte payload.\n//\n// Algorithm:\n// 1. walk the tree once, collecting every namespace URI used by\n// elements or attributes;\n// 2. assign each URI a prefix — DEFAULT_PREFIXES first, then\n// auto-generated `ns{N}` — and decide which (if any) becomes the\n// default (xmlns=\"…\") namespace by reusing the root element's NS;\n// 3. emit the XML declaration, root open tag with all xmlns / xmlns:*\n// declarations, then a recursive children walk that escapes text\n// and attribute values.\n//\n// Output style matches openpyxl/Excel: no whitespace between elements,\n// `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` on its own\n// line, attribute values quoted with `\"`.\n\nimport { escapeXmlAttr, escapeXmlText } from '../utils/escape.js';\nimport { DEFAULT_PREFIXES, parseQName, XML_NS } from './namespaces.js';\nimport type { XmlNode } from './tree.js';\n\nexport interface SerializeOptions {\n /** Emit `<?xml … ?>` declaration. Defaults to true. */\n xmlDeclaration?: boolean;\n /** `standalone` attribute on the declaration. Defaults to 'yes'. */\n standalone?: 'yes' | 'no' | 'omit';\n /**\n * Namespace URI → prefix already bound by an ancestor, for a fragment being\n * spliced into a larger document. Those bindings are reused and not\n * redeclared on the fragment's own root. `''` means the ancestor's default\n * namespace — attributes never inherit a default binding, so only use it for\n * a namespace whose attributes are unqualified (every SpreadsheetML part).\n */\n inScopePrefixes?: Readonly<Record<string, string>>;\n}\n\n/**\n * Serialize an {@link XmlNode} tree into a UTF-8 byte payload. The\n * inverse of {@link parseXml}: `parseXml(serializeXml(n))` yields a\n * tree structurally equivalent to `n` modulo attribute insertion order\n * (which both directions preserve on Node 18+ / V8).\n */\nexport function serializeXml(root: XmlNode, opts: SerializeOptions = {}): Uint8Array {\n const { xmlDeclaration = true, standalone = 'yes', inScopePrefixes } = opts;\n\n const allocation = allocatePrefixes(root, inScopePrefixes);\n const out: string[] = [];\n\n if (xmlDeclaration) {\n out.push('<?xml version=\"1.0\" encoding=\"UTF-8\"');\n if (standalone !== 'omit') out.push(` standalone=\"${standalone}\"`);\n out.push('?>\\n');\n }\n\n emit(out, root, allocation, /* isRoot */ true);\n\n return new TextEncoder().encode(out.join(''));\n}\n\n// ---- prefix allocation ------------------------------------------------------\n\ninterface Allocation {\n /** ns URI → prefix ('' = default namespace) */\n prefixOf: Map<string, string>;\n /** prefix declarations to emit on the root element, in deterministic order */\n declarations: Array<{ prefix: string; ns: string }>;\n}\n\nconst allocatePrefixes = (root: XmlNode, inScope?: Readonly<Record<string, string>>): Allocation => {\n const used = new Set<string>();\n collectNamespaces(root, used, /* attrsToo */ true);\n used.delete(''); // empty NS = unprefixed names; not emitted as xmlns\n\n const prefixOf = new Map<string, string>();\n // Bindings an ancestor already declared: reuse them, and leave them out of\n // this fragment's own declarations.\n const inherited = new Set<string>();\n for (const [ns, prefix] of Object.entries(inScope ?? {})) {\n if (ns === '' || prefixOf.has(ns)) continue;\n prefixOf.set(ns, prefix);\n inherited.add(ns);\n }\n\n // Decide the default namespace. Prefer the root element's NS if its\n // canonical prefix in DEFAULT_PREFIXES is empty (i.e. designed to live\n // as a default), so the bulk of the root subtree stays unprefixed — unless\n // an ancestor already bound that namespace, in which case its binding wins.\n const rootNs = parseQName(root.name).ns;\n let defaultNs = '';\n if (rootNs && DEFAULT_PREFIXES[rootNs] === '' && !prefixOf.has(rootNs)) {\n defaultNs = rootNs;\n prefixOf.set(defaultNs, '');\n }\n // `xml` and `xmlns` are reserved by the XMLNS spec; xml ↔ XML_NS is\n // predefined and must NOT be redeclared via xmlns:xml=\"…\".\n prefixOf.set(XML_NS, 'xml');\n\n // Pass 1: respect DEFAULT_PREFIXES for namespaces that have a\n // canonical short prefix.\n let auto = 0;\n const usedPrefixes = new Set<string>(['', 'xml', 'xmlns', ...prefixOf.values()]);\n const ordered = Array.from(used).sort();\n for (const ns of ordered) {\n if (prefixOf.has(ns)) continue;\n const preferred = DEFAULT_PREFIXES[ns];\n if (preferred !== undefined && preferred !== '' && !usedPrefixes.has(preferred)) {\n prefixOf.set(ns, preferred);\n usedPrefixes.add(preferred);\n }\n }\n // Pass 2: auto-allocate for the remainder.\n for (const ns of ordered) {\n if (prefixOf.has(ns)) continue;\n let prefix = `ns${auto++}`;\n while (usedPrefixes.has(prefix)) prefix = `ns${auto++}`;\n prefixOf.set(ns, prefix);\n usedPrefixes.add(prefix);\n }\n\n // Emission order: default first, then other prefixes alphabetically by ns\n // URI for determinism. XML_NS is reserved and never declared.\n const declarations: Array<{ prefix: string; ns: string }> = [];\n if (defaultNs !== '') declarations.push({ prefix: '', ns: defaultNs });\n const inheritedDefault = [...inherited].find((ns) => prefixOf.get(ns) === '');\n for (const ns of ordered) {\n if (ns === defaultNs) continue;\n if (ns === inheritedDefault) continue;\n if (ns === XML_NS) continue;\n if (inherited.has(ns)) continue;\n const prefix = prefixOf.get(ns);\n if (prefix === undefined) continue;\n declarations.push({ prefix, ns });\n }\n\n return { prefixOf, declarations };\n};\n\nconst collectNamespaces = (node: XmlNode, into: Set<string>, attrsToo: boolean): void => {\n into.add(parseQName(node.name).ns);\n if (attrsToo) {\n for (const attrName of Object.keys(node.attrs)) {\n into.add(parseQName(attrName).ns);\n }\n }\n for (const c of node.children) collectNamespaces(c, into, attrsToo);\n};\n\n// ---- emission ---------------------------------------------------------------\n\nconst buildElementPrefix = (name: string, prefixOf: Map<string, string>): string => {\n const { ns, local } = parseQName(name);\n if (ns === '') return local;\n const prefix = prefixOf.get(ns);\n if (prefix === undefined || prefix === '') return local;\n return `${prefix}:${local}`;\n};\n\nconst buildAttrPrefix = (name: string, prefixOf: Map<string, string>): string => {\n const { ns, local } = parseQName(name);\n if (ns === '') return local;\n // Attributes never inherit the default namespace; if the namespace is\n // mapped to the default prefix, they still need an explicit prefix.\n const prefix = prefixOf.get(ns);\n if (prefix === undefined || prefix === '') {\n // Attribute lives in a namespace that we marked as default-only;\n // fall through to no prefix (the namespace must already be declared\n // by ancestor walk, but for default-namespace attrs that's invalid\n // XML — we keep it bare anyway since OOXML never produces this).\n return local;\n }\n return `${prefix}:${local}`;\n};\n\nconst emit = (out: string[], node: XmlNode, allocation: Allocation, isRoot: boolean): void => {\n const tag = buildElementPrefix(node.name, allocation.prefixOf);\n out.push('<', tag);\n\n if (isRoot) {\n for (const { prefix, ns } of allocation.declarations) {\n out.push(prefix === '' ? ` xmlns=\"${escapeXmlAttr(ns)}\"` : ` xmlns:${prefix}=\"${escapeXmlAttr(ns)}\"`);\n }\n }\n\n for (const [name, value] of Object.entries(node.attrs)) {\n const attrName = buildAttrPrefix(name, allocation.prefixOf);\n out.push(' ', attrName, '=\"', escapeXmlAttr(value), '\"');\n }\n\n const text = node.text;\n const hasText = text !== undefined && text !== '';\n const hasChildren = node.children.length > 0;\n if (!hasText && !hasChildren) {\n out.push('/>');\n return;\n }\n\n out.push('>');\n if (hasText) out.push(escapeXmlText(text));\n for (const c of node.children) emit(out, c, allocation, /* isRoot */ false);\n out.push('</', tag, '>');\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export { loadWorkbookStream, type IterRowsOptions, type LoadWorkbookStreamOptions, type ReadOnlyCell, type ReadOnlyWorkbook, type ReadOnlyWorksheet, } from './read-only';
2
- export { createWriteOnlyWorkbook, type WriteOnlyOptions, type WriteOnlyRowItem, type WriteOnlyStyle, type WriteOnlyWorkbook, type WriteOnlyWorksheet, } from './write-only';
1
+ export { loadWorkbookStream, type IterRowsOptions, type LoadWorkbookStreamOptions, type ReadOnlyCell, type ReadOnlyWorkbook, type ReadOnlyWorksheet, } from './read-only.js';
2
+ export { createWriteOnlyWorkbook, type WriteOnlyOptions, type WriteOnlyRowItem, type WriteOnlyStyle, type WriteOnlyWorkbook, type WriteOnlyWorksheet, } from './write-only.js';
@@ -1,7 +1,7 @@
1
- import type { DecompressionLimits } from '../zip/decompression-guard';
2
- import type { CellValue } from '../cell/cell';
3
- import type { XlsxSource } from '../io/source';
4
- import { type Stylesheet } from '../styles/stylesheet';
1
+ import type { DecompressionLimits } from '../zip/decompression-guard.js';
2
+ import type { CellValue } from '../cell/cell.js';
3
+ import type { XlsxSource } from '../io/source.js';
4
+ import { type Stylesheet } from '../styles/stylesheet.js';
5
5
  export interface IterRowsOptions {
6
6
  minRow?: number;
7
7
  maxRow?: number;
@@ -1,10 +1,10 @@
1
- import type { CellValue } from '../cell/cell';
2
- import type { XlsxSink } from '../io/sink';
3
- import type { Alignment } from '../styles/alignment';
4
- import type { Border } from '../styles/borders';
5
- import type { Fill } from '../styles/fills';
6
- import type { Font } from '../styles/fonts';
7
- import type { Protection } from '../styles/protection';
1
+ import type { CellValue } from '../cell/cell.js';
2
+ import type { XlsxSink } from '../io/sink.js';
3
+ import type { Alignment } from '../styles/alignment.js';
4
+ import type { Border } from '../styles/borders.js';
5
+ import type { Fill } from '../styles/fills.js';
6
+ import type { Font } from '../styles/fonts.js';
7
+ import type { Protection } from '../styles/protection.js';
8
8
  export interface WriteOnlyOptions {
9
9
  /** Reserved — currently ignored (the buffered backend doesn't honour it). */
10
10
  estimatedMaxRow?: number;
@@ -1,14 +1,14 @@
1
1
  import { i as OpenXmlIoError, o as OpenXmlSchemaError } from "./exceptions-D-CFwxgm.mjs";
2
2
  import { s as coordinateToTuple } from "./coordinate-96Ecci4d.mjs";
3
3
  import { t as ERROR_CODES } from "./inference-BrI9uIY4.mjs";
4
- import { n as escapeXmlAttr } from "./escape-DFTE7ZJc.mjs";
4
+ import { n as escapeXmlAttr } from "./escape-rnWSPpWY.mjs";
5
5
  import { _ as ARC_WORKBOOK_RELS, a as findChildren, c as ARC_CONTENT_TYPES, f as ARC_ROOT_RELS, ft as SHEET_MAIN_NS, g as ARC_WORKBOOK, i as findChild, lt as REL_NS, m as ARC_STYLE, p as ARC_SHARED_STRINGS, pt as STYLES_TYPE, ut as SHARED_STRINGS_TYPE, wt as XLSX_TYPE, yt as WORKSHEET_TYPE } from "./tree-BX-sRRVp.mjs";
6
- import { t as stylesheetToBytes, v as serializeCell } from "./stylesheet-writer-BrOw4jMY.mjs";
7
- import { t as parseXml } from "./parser-D3SLaOFe.mjs";
8
- import { Q as findById, a as makeManifest, n as addOverride, nt as relsFromBytes, o as manifestFromBytes, rt as relsToBytes, s as manifestToBytes, t as addDefault, tt as makeRelationships } from "./manifest-Cm9K7D62.mjs";
6
+ import { t as stylesheetToBytes, v as serializeCell } from "./stylesheet-writer-HxaX7bGy.mjs";
7
+ import { t as parseXml } from "./parser-By6RWZVW.mjs";
8
+ import { Q as findById, a as makeManifest, n as addOverride, nt as relsFromBytes, o as manifestFromBytes, rt as relsToBytes, s as manifestToBytes, t as addDefault, tt as makeRelationships } from "./manifest-pLmx7KYh.mjs";
9
9
  import { at as addNumFmt, et as addBorder, ft as makeStylesheet, it as addFont, nt as addCellXf, ot as defaultCellXf, rt as addFill } from "./cell-style-DuvS_Lsg.mjs";
10
- import { D as makeSharedStrings, S as validateSheetTitle, j as sharedStringsToBytes, k as parseSharedStringsXml } from "./workbook-CARZS94U.mjs";
11
- import { i as parseStylesheetXml, n as parseDate1904, r as resolveRelTarget } from "./load-MyOIjtrU.mjs";
10
+ import { D as makeSharedStrings, S as validateSheetTitle, j as sharedStringsToBytes, k as parseSharedStringsXml } from "./workbook-BlZVXiyG.mjs";
11
+ import { i as parseStylesheetXml, n as parseDate1904, r as resolveRelTarget } from "./load-Bghb1YHY.mjs";
12
12
  import { t as openZip } from "./reader-BNaUTVCy.mjs";
13
13
  import { t as createZipWriter } from "./writer-IyFccCRJ.mjs";
14
14
  import { n as iterParse, t as utf8ByteLength } from "./utf8-Tn3nzyik.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"streaming.mjs","names":[],"sources":["../src/streaming/read-only.ts","../src/streaming/write-only.ts"],"sourcesContent":["// Streaming read-only workbook.\n//\n// `loadWorkbookStream` opens the zip + parses workbook.xml / sharedStrings.xml\n// / styles.xml metadata up front (small even on million-row archives), then\n// exposes a lazy `openWorksheet(name)` that SAX-iterates the sheet body via\n// `iterParse`. The iterator streams rows without materialising the full sheet\n// in memory.\n\nimport { makeSharedStrings, parseSharedStringsXml, type SharedStringsTable } from '../workbook/shared-strings';\nimport { ARC_CONTENT_TYPES, ARC_ROOT_RELS, ARC_SHARED_STRINGS, ARC_STYLE, REL_NS, SHEET_MAIN_NS } from '../xml/namespaces';\nimport { findById, relsFromBytes } from '../packaging/relationships';\nimport { manifestFromBytes } from '../packaging/manifest';\nimport { OpenXmlSchemaError } from '../utils/exceptions';\nimport type { DecompressionLimits } from '../zip/decompression-guard';\nimport { type ZipArchive, openZip } from '../zip/reader';\nimport type { CellValue, ExcelErrorCode } from '../cell/cell';\nimport { ERROR_CODES } from '../utils/inference';\nimport { iterParse, type SaxEvent, type SaxInput } from '../xml/iterparse';\nimport { parseXml } from '../xml/parser';\nimport { findChild, findChildren, type XmlNode } from '../xml/tree';\nimport type { XlsxSource } from '../io/source';\nimport { coordinateToTuple } from '../utils/coordinate';\nimport { type Stylesheet, makeStylesheet } from '../styles/stylesheet';\nimport { parseStylesheetXml } from '../styles/stylesheet-reader';\nimport { parseDate1904, resolveRelTarget } from '../io/load';\n\nconst SHEET_TAG = `{${SHEET_MAIN_NS}}sheet`;\nconst SHEETS_TAG = `{${SHEET_MAIN_NS}}sheets`;\n\nexport interface IterRowsOptions {\n minRow?: number;\n maxRow?: number;\n minCol?: number;\n maxCol?: number;\n}\n\nexport interface ReadOnlyCell {\n readonly row: number;\n readonly col: number;\n readonly value: CellValue;\n readonly styleId: number;\n}\n\nexport interface ReadOnlyWorksheet {\n title: string;\n iterRows(opts?: IterRowsOptions): AsyncIterableIterator<ReadOnlyCell[]>;\n iterValues(opts?: IterRowsOptions): AsyncIterableIterator<CellValue[]>;\n}\n\nexport interface ReadOnlyWorkbook {\n sheetNames: string[];\n styles: Stylesheet;\n /** Date1904 mode toggles between Excel's two epoch systems. */\n date1904: boolean;\n openWorksheet(name: string): ReadOnlyWorksheet;\n close(): Promise<void>;\n}\n\ninterface SheetEntry {\n name: string;\n rId: string;\n partPath: string;\n}\n\nconst parseSheetList = (root: XmlNode, workbookPath: string, archive: ZipArchive): SheetEntry[] => {\n const sheetsEl = findChild(root, SHEETS_TAG);\n if (!sheetsEl) return [];\n const wbRelsPath = relsPathFor(workbookPath);\n const wbRels = archive.has(wbRelsPath) ? relsFromBytes(archive.read(wbRelsPath)) : { rels: [] };\n const out: SheetEntry[] = [];\n for (const sheet of findChildren(sheetsEl, SHEET_TAG)) {\n const name = sheet.attrs['name'];\n const rId = sheet.attrs[`{${REL_NS}}id`];\n if (!name || !rId) continue;\n const rel = findById(wbRels, rId);\n if (!rel) continue;\n const partPath = resolveRelTarget(workbookPath, rel.target);\n out.push({ name, rId, partPath });\n }\n return out;\n};\n\nconst relsPathFor = (partPath: string): string => {\n const i = partPath.lastIndexOf('/');\n if (i < 0) return `_rels/${partPath}.rels`;\n return `${partPath.slice(0, i)}/_rels/${partPath.slice(i + 1)}.rels`;\n};\n\nconst localName = (qname: string): string => {\n const i = qname.lastIndexOf('}');\n return i < 0 ? qname : qname.slice(i + 1);\n};\n\nconst decodeCellValue = (\n t: string,\n vText: string | undefined,\n inlineText: string | undefined,\n sst: ReadonlyArray<string>,\n): CellValue => {\n switch (t) {\n case 'n':\n return vText !== undefined && vText !== '' ? Number.parseFloat(vText) : null;\n case 's': {\n if (vText === undefined) return null;\n const idx = Number.parseInt(vText, 10);\n if (!Number.isInteger(idx) || idx < 0 || idx >= sst.length) return null;\n return sst[idx] ?? null;\n }\n case 'b':\n return vText === '1';\n case 'e': {\n if (!vText || !ERROR_CODES.has(vText)) return null;\n return { kind: 'error', code: vText as ExcelErrorCode };\n }\n case 'str':\n return vText ?? '';\n case 'inlineStr':\n return inlineText ?? '';\n default:\n return vText !== undefined && vText !== '' ? Number.parseFloat(vText) : null;\n }\n};\n\n/**\n * SAX-iterate `<sheetData>/<row>/<c>` events out of the worksheet bytes (or a\n * stream that yields them), yielding one `ReadOnlyCell[]` per row that matches\n * `opts`.\n */\nasync function* iterSheetRows(\n sheetInput: SaxInput,\n sst: ReadonlyArray<string>,\n opts: IterRowsOptions,\n): AsyncIterableIterator<ReadOnlyCell[]> {\n const minRow = opts.minRow ?? 1;\n const maxRow = opts.maxRow ?? Number.POSITIVE_INFINITY;\n const minCol = opts.minCol ?? 1;\n const maxCol = opts.maxCol ?? Number.POSITIVE_INFINITY;\n\n let inSheetData = false;\n let currentRow = -1;\n let currentRowAttrs: Record<string, string> | null = null;\n let currentCells: ReadOnlyCell[] = [];\n\n // Per-cell state. Reset when each <c> starts.\n let cellOpen = false;\n let cellRow = 0;\n let cellCol = 0;\n let cellType = 'n';\n let cellStyleId = 0;\n let inV = false;\n let vText = '';\n let inIs = false;\n let inIsT = false;\n let isText = '';\n\n for await (const ev of iterParse(sheetInput)) {\n const e = ev as SaxEvent;\n if (e.kind === 'start') {\n const local = localName(e.name);\n if (!inSheetData) {\n if (local === 'sheetData') inSheetData = true;\n continue;\n }\n switch (local) {\n case 'row': {\n currentRowAttrs = e.attrs;\n const rRaw = e.attrs['r'];\n currentRow = rRaw ? Number.parseInt(rRaw, 10) : currentRow + 1;\n currentCells = [];\n break;\n }\n case 'c': {\n if (currentRow < 0) break;\n // Skip cell-attr parsing entirely when the row is outside the\n // requested band — saves the parseInt + coordinateToTuple hit on\n // every cell of every excluded row.\n if (currentRow < minRow || currentRow > maxRow) break;\n cellOpen = true;\n cellType = e.attrs['t'] ?? 'n';\n const sRaw = e.attrs['s'];\n cellStyleId = sRaw ? Number.parseInt(sRaw, 10) || 0 : 0;\n const ref = e.attrs['r'];\n if (ref) {\n const tup = coordinateToTuple(ref);\n cellRow = tup.row;\n cellCol = tup.col;\n } else {\n cellRow = currentRow;\n cellCol = (currentCells[currentCells.length - 1]?.col ?? 0) + 1;\n }\n vText = '';\n isText = '';\n break;\n }\n case 'v':\n if (cellOpen) inV = true;\n break;\n case 'is':\n if (cellOpen) inIs = true;\n break;\n case 't':\n if (inIs) inIsT = true;\n break;\n default:\n break;\n }\n continue;\n }\n if (e.kind === 'text') {\n if (inV) vText += e.text;\n else if (inIsT) isText += e.text;\n continue;\n }\n // end\n const local = localName(e.name);\n if (!inSheetData) continue;\n switch (local) {\n case 'sheetData':\n inSheetData = false;\n return;\n case 'row': {\n if (currentRow >= minRow && currentRow <= maxRow && currentCells.length > 0) {\n yield currentCells;\n }\n // Once we've crossed maxRow there are no more rows to yield — every\n // subsequent <row> would just be parsed and dropped. Stop iterating\n // early. ECMA-376 emits rows in ascending order.\n if (currentRow > maxRow) {\n inSheetData = false;\n return;\n }\n currentRow = -1;\n currentRowAttrs = null;\n currentCells = [];\n break;\n }\n case 'c': {\n if (cellOpen && cellCol >= minCol && cellCol <= maxCol && cellRow >= minRow && cellRow <= maxRow) {\n const value = decodeCellValue(cellType, vText, isText, sst);\n currentCells.push({ row: cellRow, col: cellCol, value, styleId: cellStyleId });\n }\n cellOpen = false;\n break;\n }\n case 'v':\n inV = false;\n break;\n case 'is':\n inIs = false;\n break;\n case 't':\n if (inIs) inIsT = false;\n break;\n default:\n break;\n }\n }\n // Avoid unused-var lint when row attrs never touched.\n void currentRowAttrs;\n}\n\n/**\n * Build a sorted `[rowNum, byteOffset]` index for every `<row r=\"N\">`\n * occurrence in a worksheet's bytes. Pure byte-level scan (no SAX), cheap\n * relative to the per-cell SAX walk: ~50 ns per row on M-series Node 22.\n *\n * `sheetDataEnd` is the byte offset of `</sheetData>` so callers can clip the\n * slice that gets handed to saxes.\n */\nconst buildRowOffsetIndex = (\n bytes: Uint8Array,\n): { index: ReadonlyArray<{ row: number; offset: number }>; sheetDataEnd: number } => {\n const out: Array<{ row: number; offset: number }> = [];\n let sheetDataEnd = -1;\n let i = 0;\n while (i < bytes.length) {\n if (bytes[i] !== 0x3c /* '<' */) {\n i++;\n continue;\n }\n // Detect `</sheetData>` once — used to clip the slice fed to saxes.\n if (\n sheetDataEnd < 0 &&\n bytes[i + 1] === 0x2f /* '/' */ &&\n bytes[i + 2] === 0x73 /* 's' */ &&\n bytes[i + 3] === 0x68 /* 'h' */ &&\n bytes[i + 4] === 0x65 /* 'e' */ &&\n bytes[i + 5] === 0x65 /* 'e' */ &&\n bytes[i + 6] === 0x74 /* 't' */ &&\n bytes[i + 7] === 0x44 /* 'D' */ &&\n bytes[i + 8] === 0x61 /* 'a' */ &&\n bytes[i + 9] === 0x74 /* 't' */ &&\n bytes[i + 10] === 0x61 /* 'a' */ &&\n bytes[i + 11] === 0x3e /* '>' */\n ) {\n sheetDataEnd = i;\n break;\n }\n // Match `<row` followed by ASCII whitespace or '>'.\n if (\n bytes[i + 1] !== 0x72 /* 'r' */ ||\n bytes[i + 2] !== 0x6f /* 'o' */ ||\n bytes[i + 3] !== 0x77 /* 'w' */\n ) {\n i++;\n continue;\n }\n const next = bytes[i + 4];\n if (\n next !== 0x20 /* sp */ &&\n next !== 0x09 /* tab */ &&\n next !== 0x0a /* lf */ &&\n next !== 0x0d /* cr */ &&\n next !== 0x3e /* > */ &&\n next !== 0x2f /* / */\n ) {\n i++;\n continue;\n }\n // Walk to the closing '>'; the attrs region carries `r=\"N\"`.\n const start = i;\n let j = i + 4;\n while (j < bytes.length && bytes[j] !== 0x3e) j++;\n if (j >= bytes.length) break;\n const attrsBuf = bytes.subarray(start + 4, j);\n const attrs = new TextDecoder('ascii', { fatal: false }).decode(attrsBuf);\n const m = /\\sr=\"(\\d+)\"/.exec(attrs);\n if (m?.[1]) {\n const row = Number.parseInt(m[1], 10);\n if (Number.isInteger(row)) out.push({ row, offset: start });\n }\n i = j + 1;\n }\n if (sheetDataEnd < 0) sheetDataEnd = bytes.length;\n return { index: out, sheetDataEnd };\n};\n\n/**\n * Binary-search the row index for the first entry with `row >= target`. Returns\n * -1 when every recorded row is below the target.\n */\nconst firstRowAtOrAfter = (\n index: ReadonlyArray<{ row: number; offset: number }>,\n target: number,\n): number => {\n let lo = 0;\n let hi = index.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const entry = index[mid];\n if (!entry || entry.row < target) lo = mid + 1;\n else hi = mid;\n }\n return lo < index.length ? lo : -1;\n};\n\n/**\n * Slice a worksheet's bytes to start at the row at index `idxPos` of the\n * row-offset index, wrapping the result with a synthetic `<sheetData>` envelope\n * so saxes parses it in the right namespace.\n */\nconst SHEET_DATA_OPEN = `<?xml version=\"1.0\" encoding=\"UTF-8\"?><sheetData xmlns=\"${SHEET_MAIN_NS}\">`;\nconst SHEET_DATA_CLOSE = `</sheetData>`;\nconst sliceFromRow = (\n bytes: Uint8Array,\n fromOffset: number,\n sheetDataEnd: number,\n): Uint8Array => {\n const prefix = new TextEncoder().encode(SHEET_DATA_OPEN);\n const suffix = new TextEncoder().encode(SHEET_DATA_CLOSE);\n const middle = bytes.subarray(fromOffset, sheetDataEnd);\n const out = new Uint8Array(prefix.length + middle.length + suffix.length);\n out.set(prefix, 0);\n out.set(middle, prefix.length);\n out.set(suffix, prefix.length + middle.length);\n return out;\n};\n\n/**\n * Factory: build a {@link ReadOnlyWorksheet} bound to a single worksheet part\n * inside an opened archive. SAX iteration runs lazily — `iterRows` re-reads the\n * part bytes each time so the caller can iterate the same sheet repeatedly\n * without keeping a buffered decoder around.\n *\n * For `iterRows({ minRow > 1 })`, a row-offset index is built lazily on first\n * use and cached; subsequent band queries jump straight to the byte offset of\n * the first matching row instead of SAX-walking the entire `<sheetData>`.\n */\nconst makeStreamingReadOnlyWorksheet = (\n title: string,\n archive: ZipArchive,\n partPath: string,\n sst: ReadonlyArray<string>,\n): ReadOnlyWorksheet => {\n // Lazy + cached. The index is small (~16 B per row); for 1M rows that's 16 MB\n // of working set, vs. the alternative of walking the sheet bytes through\n // saxes on every band query.\n let cached: ReturnType<typeof buildRowOffsetIndex> | undefined;\n const ensureIndex = (bytes: Uint8Array) => {\n if (!cached) cached = buildRowOffsetIndex(bytes);\n return cached;\n };\n\n const iterRows = (opts: IterRowsOptions = {}): AsyncIterableIterator<ReadOnlyCell[]> => {\n const minRow = opts.minRow ?? 1;\n if (minRow <= 1) {\n // Whole-sheet (or no-min) iter — feed the SAX parser directly off the\n // archive's streaming inflate path so the worksheet's inflated payload\n // is never fully resident. Peak memory for the walk drops to the\n // inflate window + SAX state instead of the entire `<sheetData>` body.\n return iterSheetRows(archive.readStream(partPath), sst, opts);\n }\n // Band query (minRow > 1): the row-offset index needs the full inflated\n // bytes so we can binary-search to the byte offset of the first matching\n // row. Materialise once and reuse via `ensureIndex`.\n const bytes = archive.read(partPath);\n const { index, sheetDataEnd } = ensureIndex(bytes);\n if (index.length === 0) return iterSheetRows(bytes, sst, opts);\n const pos = firstRowAtOrAfter(index, minRow);\n if (pos < 0) {\n // Every row is below minRow — nothing to yield.\n return (async function* () {})();\n }\n const target = index[pos];\n if (!target) return iterSheetRows(bytes, sst, opts);\n const sliced = sliceFromRow(bytes, target.offset, sheetDataEnd);\n return iterSheetRows(sliced, sst, opts);\n };\n const iterValues = async function* (opts: IterRowsOptions = {}): AsyncIterableIterator<CellValue[]> {\n for await (const row of iterRows(opts)) {\n yield row.map((c) => c.value);\n }\n };\n return { title, iterRows, iterValues };\n};\n\n/**\n * Factory: build a {@link ReadOnlyWorkbook} from an opened archive + pre-parsed\n * sheet list / styles / shared strings. Per the project-wide \"no classes\" rule\n * (CLAUDE.md), the workbook is a plain object closing over the archive handle.\n */\nconst makeStreamingReadOnlyWorkbook = (\n sheetNames: string[],\n styles: Stylesheet,\n date1904: boolean,\n archive: ZipArchive,\n entries: ReadonlyMap<string, SheetEntry>,\n sst: ReadonlyArray<string>,\n): ReadOnlyWorkbook => ({\n sheetNames,\n styles,\n date1904,\n openWorksheet(name) {\n const entry = entries.get(name);\n if (!entry) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: no worksheet named \"${name}\"`);\n }\n return makeStreamingReadOnlyWorksheet(name, archive, entry.partPath, sst);\n },\n async close() {\n archive.close();\n },\n});\n\n/** Options for {@link loadWorkbookStream}. */\nexport interface LoadWorkbookStreamOptions {\n /**\n * Decompression-bomb safeguards applied while inflating zip entries.\n * Defaults to limits that fit any legitimate xlsx; pass `false` to disable\n * (only safe for fully trusted sources).\n */\n decompressionLimits?: DecompressionLimits | false;\n}\n\n/** Open an xlsx for read-only streaming access. */\nexport async function loadWorkbookStream(\n source: XlsxSource,\n opts: LoadWorkbookStreamOptions = {},\n): Promise<ReadOnlyWorkbook> {\n const archive = await openZip(\n source,\n opts.decompressionLimits === undefined ? {} : { decompressionLimits: opts.decompressionLimits },\n );\n if (!archive.has(ARC_CONTENT_TYPES)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: missing \"${ARC_CONTENT_TYPES}\"`);\n }\n // Manifest parse is intentionally cheap and discarded — we resolve sheets by\n // walking workbook.xml.rels directly.\n manifestFromBytes(archive.read(ARC_CONTENT_TYPES));\n\n if (!archive.has(ARC_ROOT_RELS)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: missing \"${ARC_ROOT_RELS}\"`);\n }\n const rootRels = relsFromBytes(archive.read(ARC_ROOT_RELS));\n const officeDocRel = rootRels.rels.find((r) => r.type === `${REL_NS}/officeDocument`);\n if (!officeDocRel) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: no officeDocument relationship in root rels`);\n }\n const workbookPath = resolveRelTarget('', officeDocRel.target);\n if (!archive.has(workbookPath)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: workbook part \"${workbookPath}\" missing`);\n }\n const workbookRoot = parseXml(archive.read(workbookPath));\n const sheetEntries = parseSheetList(workbookRoot, workbookPath, archive);\n const entryMap = new Map<string, SheetEntry>();\n for (const e of sheetEntries) entryMap.set(e.name, e);\n\n let sst: SharedStringsTable = makeSharedStrings();\n if (archive.has(ARC_SHARED_STRINGS)) {\n sst = parseSharedStringsXml(archive.read(ARC_SHARED_STRINGS));\n }\n let styles: Stylesheet = makeStylesheet();\n if (archive.has(ARC_STYLE)) {\n styles = parseStylesheetXml(archive.read(ARC_STYLE));\n }\n\n return makeStreamingReadOnlyWorkbook(\n sheetEntries.map((e) => e.name),\n styles,\n parseDate1904(workbookRoot),\n archive,\n entryMap,\n sst.entries.map((e) => (typeof e === 'string' ? e : e.runs.map((r) => r.text).join(''))),\n );\n}\n","// Streaming write-only workbook.\n//\n// `createWriteOnlyWorkbook` lets callers append rows one at a time without\n// holding a full Workbook in memory. Each `appendRow` serialises the row\n// directly into a string buffer (no `Cell` objects, no Worksheet rows Map) —\n// when `close()` runs we glue the rows under a `<sheetData>` envelope and hand\n// the bytes to the streaming-deflate ZIP writer. The buffer keeps ~30 bytes per\n// cell of XML text instead of the ~200-byte V8 footprint a Cell + Map entry\n// costs, so the heap budget at 3M cells drops roughly an order of magnitude vs.\n// the previous setCell-based path.\n\nimport type { Cell, CellValue } from '../cell/cell';\nimport type { XlsxSink } from '../io/sink';\nimport { addDefault, addOverride, makeManifest, manifestToBytes } from '../packaging/manifest';\nimport { makeRelationships, relsToBytes } from '../packaging/relationships';\nimport {\n addBorder,\n addCellXf,\n addFill,\n addFont,\n addNumFmt,\n type CellXf,\n defaultCellXf,\n makeStylesheet,\n type Stylesheet,\n} from '../styles/stylesheet';\nimport { stylesheetToBytes } from '../styles/stylesheet-writer';\nimport type { Alignment } from '../styles/alignment';\nimport type { Border } from '../styles/borders';\nimport type { Fill } from '../styles/fills';\nimport type { Font } from '../styles/fonts';\nimport type { Protection } from '../styles/protection';\nimport { escapeXmlAttr } from '../utils/escape';\nimport { OpenXmlIoError } from '../utils/exceptions';\nimport { utf8ByteLength } from '../utils/utf8';\nimport { makeSharedStrings, sharedStringsToBytes } from '../workbook/shared-strings';\nimport { validateSheetTitle } from '../workbook/workbook';\nimport { serializeCell } from '../worksheet/writer';\nimport {\n ARC_CONTENT_TYPES,\n ARC_ROOT_RELS,\n ARC_SHARED_STRINGS,\n ARC_STYLE,\n ARC_WORKBOOK,\n ARC_WORKBOOK_RELS,\n PKG_REL_NS,\n REL_NS,\n SHARED_STRINGS_TYPE,\n SHEET_MAIN_NS,\n STYLES_TYPE,\n WORKSHEET_TYPE,\n XLSX_TYPE,\n} from '../xml/namespaces';\nimport { createZipWriter } from '../zip/writer';\n\nconst escapeAttr = escapeXmlAttr;\n\nexport interface WriteOnlyOptions {\n /** Reserved — currently ignored (the buffered backend doesn't honour it). */\n estimatedMaxRow?: number;\n}\n\nexport interface WriteOnlyStyle {\n font?: Font;\n fill?: Fill;\n border?: Border;\n alignment?: Alignment;\n numberFormat?: string;\n protection?: Protection;\n}\n\nexport type WriteOnlyRowItem = CellValue | { value: CellValue; style?: WriteOnlyStyle };\n\nexport interface WriteOnlyWorksheet {\n readonly title: string;\n appendRow(row: WriteOnlyRowItem[]): Promise<void>;\n setColumnWidth(col: number, width: number): void;\n close(): Promise<void>;\n}\n\nexport interface WriteOnlyWorkbook {\n /** Add a new worksheet. The previous worksheet must be `close()`d first. */\n addWorksheet(title: string): Promise<WriteOnlyWorksheet>;\n /** Finalise the archive: emits styles / sharedStrings / workbook / manifest / rels. */\n finalize(): Promise<void>;\n /**\n * Release the sink without finalising the archive. Call this from a\n * surrounding catch block when the producer pipeline throws before\n * `finalize()` — without it, streaming destinations (`toFile` /\n * `toWritable`) keep the file descriptor / Writable open and the partial\n * xlsx looks valid on disk.\n *\n * Idempotent. Subsequent `addWorksheet` / `finalize` calls throw.\n */\n abort(cause?: unknown): void;\n}\n\nconst validateTitle = (title: string, taken: Set<string>): void => {\n const reason = validateSheetTitle(title);\n if (reason) {\n throw new OpenXmlIoError(`Worksheet title \"${title}\": ${reason}`);\n }\n if (taken.has(title.toLowerCase())) {\n throw new OpenXmlIoError(`Worksheet title \"${title}\" is already in use`);\n }\n};\n\n/** Allocate a CellXf id for a style spec. Mirrors cell-style.ts but works directly on the pool. */\nconst allocateXfId = (ss: Stylesheet, style: WriteOnlyStyle): number => {\n // `xfId` is intentionally omitted: leaving it undefined skips the\n // cellStyleXfs bounds check and matches what Excel emits when there is no\n // parent style.\n let xf: CellXf = { fontId: 0, fillId: 0, borderId: 0, numFmtId: 0 };\n if (style.font !== undefined) {\n xf = { ...xf, fontId: addFont(ss, style.font), applyFont: true };\n }\n if (style.fill !== undefined) {\n xf = { ...xf, fillId: addFill(ss, style.fill), applyFill: true };\n }\n if (style.border !== undefined) {\n xf = { ...xf, borderId: addBorder(ss, style.border), applyBorder: true };\n }\n if (style.numberFormat !== undefined) {\n xf = { ...xf, numFmtId: addNumFmt(ss, style.numberFormat), applyNumberFormat: true };\n }\n if (style.alignment !== undefined) {\n xf = { ...xf, alignment: style.alignment, applyAlignment: true };\n }\n if (style.protection !== undefined) {\n xf = { ...xf, protection: style.protection, applyProtection: true };\n }\n return addCellXf(ss, xf);\n};\n\ninterface WorkbookState {\n styles: Stylesheet;\n sst: ReturnType<typeof makeSharedStrings>;\n /** Sheet emit metadata, in addWorksheet order. */\n sheets: Array<{\n title: string;\n sheetId: number;\n }>;\n /** True once finalize() has been called (further mutations throw). */\n finalised: boolean;\n /** True while a worksheet is open (the next addWorksheet must wait). */\n hasOpenWorksheet: boolean;\n /** ZIP writer the workbook + each open worksheet stream chunks through. */\n writer: import('../zip/writer').ZipWriter;\n}\n\n/**\n * Flush threshold for the worksheet's pending-row text buffer. Smaller values\n * minimise heap; larger values amortise the TextEncoder + push overhead. 64 KB\n * is a sweet spot — heap stays low and per-row JS work is dominated by the\n * actual XML construction, not flushing.\n */\nconst FLUSH_THRESHOLD_BYTES = 64 * 1024;\n\n/**\n * Factory: build a {@link WriteOnlyWorksheet} that closes over the shared\n * {@link WorkbookState}. Per the project-wide \"no classes\" rule (CLAUDE.md) the\n * worksheet is a plain object holding the row buffer + column-width map in\n * closure state.\n *\n * The worksheet streams its `<sheetData>` body chunk-by-chunk through the ZIP\n * writer's `addStreamingEntry` API, so the heap footprint stays at one ~64 KB\n * pending text buffer plus deflate scratch — no Cell objects, no all-rows\n * accumulation. The XML envelope (decl / worksheet open / cols / sheetData\n * open) flushes on the first `appendRow` (or `close()` if the sheet is empty);\n * column widths staged via `setColumnWidth` *must* land before the first row.\n */\nconst makeWriteOnlyWorksheet = (state: WorkbookState, title: string, sheetId: number): WriteOnlyWorksheet => {\n let nextRow = 1;\n let closed = false;\n let headerFlushed = false;\n const columnWidths = new Map<number, number>();\n const dummyCtx = { sharedStrings: state.sst, rels: makeRelationships() };\n const encoder = new TextEncoder();\n const stream = state.writer.addStreamingEntry(`xl/worksheets/sheet${sheetId}.xml`);\n let pendingText = '';\n let pendingBytes = 0;\n\n const writeText = (text: string): void => {\n pendingText += text;\n // UTF-8 byte length, computed without a full encode: scan once and add the\n // exact codepoint cost. `text.length` would undercount CJK by ~3× and let\n // the buffer balloon past FLUSH_THRESHOLD_BYTES on Japanese / Chinese\n // workloads.\n pendingBytes += utf8ByteLength(text);\n if (pendingBytes >= FLUSH_THRESHOLD_BYTES) {\n stream.write(encoder.encode(pendingText));\n pendingText = '';\n pendingBytes = 0;\n }\n };\n\n const flushHeader = (): void => {\n if (headerFlushed) return;\n headerFlushed = true;\n let header = '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>';\n header += `<worksheet xmlns=\"${SHEET_MAIN_NS}\" xmlns:r=\"${REL_NS}\">`;\n if (columnWidths.size > 0) {\n header += '<cols>';\n const sorted = [...columnWidths.entries()].sort((a, b) => a[0] - b[0]);\n for (const [col, width] of sorted) {\n header += `<col min=\"${col}\" max=\"${col}\" width=\"${width}\" customWidth=\"1\"/>`;\n }\n header += '</cols>';\n }\n header += '<sheetData>';\n writeText(header);\n };\n\n const appendRow = async (row: WriteOnlyRowItem[]): Promise<void> => {\n if (closed) throw new OpenXmlIoError('appendRow: worksheet already closed');\n flushHeader();\n const r = nextRow++;\n let xml = `<row r=\"${r}\">`;\n for (let i = 0; i < row.length; i++) {\n const item = row[i];\n if (item === undefined || item === null) continue;\n const col = i + 1;\n let value: CellValue;\n let style: WriteOnlyStyle | undefined;\n if (item !== null && typeof item === 'object' && 'value' in (item as object)) {\n const wrapped = item as { value: CellValue; style?: WriteOnlyStyle };\n value = wrapped.value;\n style = wrapped.style;\n } else {\n value = item as CellValue;\n }\n const styleId = style ? allocateXfId(state.styles, style) : 0;\n // Ephemeral cell-shaped object — discarded as soon as serializeCell\n // returns its `<c .../>` string. Keeps the heap footprint at the size of\n // the pending text buffer instead of a full Worksheet model.\n const cell: Cell = { row: r, col, value, styleId };\n xml += serializeCell(cell, dummyCtx);\n }\n xml += '</row>';\n writeText(xml);\n };\n\n const setColumnWidth = (col: number, width: number): void => {\n if (closed) throw new OpenXmlIoError('setColumnWidth: worksheet already closed');\n if (headerFlushed) {\n throw new OpenXmlIoError(\n 'setColumnWidth: must be called before the first appendRow — column widths are emitted as part of the worksheet header',\n );\n }\n columnWidths.set(col, width);\n };\n\n const close = async (): Promise<void> => {\n if (closed) return;\n closed = true;\n flushHeader();\n writeText('</sheetData></worksheet>');\n if (pendingText.length > 0) {\n stream.write(encoder.encode(pendingText));\n pendingText = '';\n pendingBytes = 0;\n }\n await stream.end();\n state.sheets.push({ title, sheetId });\n state.hasOpenWorksheet = false;\n };\n\n return { title, appendRow, setColumnWidth, close };\n};\n\n/**\n * Factory: build a {@link WriteOnlyWorkbook} from a sink. State lives in a\n * closure rather than on a class instance per the project-wide \"no classes\"\n * rule (CLAUDE.md).\n */\nconst makeWriteOnlyWorkbook = (sink: XlsxSink): WriteOnlyWorkbook => {\n const styles = makeStylesheet();\n // Reserve cellXfs[0] for the default (no apply* flags). Unstyled cells point\n // at this slot via styleId=0; user-styled cells start at index 1 so the\n // writer emits an `s=\"N\"` attribute for them.\n addCellXf(styles, defaultCellXf());\n // The ZIP writer is created up front: each addWorksheet opens a streaming\n // entry on it and flushes row chunks through the deflate stream as they\n // arrive. Sheets emit before styles / sst / workbook / rels / content-types\n // so the writer can serialise them in order.\n const state: WorkbookState = {\n styles,\n sst: makeSharedStrings(),\n sheets: [],\n finalised: false,\n hasOpenWorksheet: false,\n writer: createZipWriter(sink),\n };\n\n const addWorksheet = async (title: string): Promise<WriteOnlyWorksheet> => {\n if (state.finalised) {\n throw new OpenXmlIoError('addWorksheet: workbook already finalised');\n }\n if (state.hasOpenWorksheet) {\n throw new OpenXmlIoError(\n 'addWorksheet: previous worksheet still open — call close() before opening the next one',\n );\n }\n const taken = new Set(state.sheets.map((s) => s.title.toLowerCase()));\n validateTitle(title, taken);\n state.hasOpenWorksheet = true;\n const sheetId = state.sheets.length + 1;\n return makeWriteOnlyWorksheet(state, title, sheetId);\n };\n\n const finalize = async (): Promise<void> => {\n if (state.finalised) {\n throw new OpenXmlIoError('finalize: already finalised');\n }\n if (state.hasOpenWorksheet) {\n throw new OpenXmlIoError('finalize: a worksheet is still open — call close() before finalising');\n }\n state.finalised = true;\n const writer = state.writer;\n try {\n await finalizeImpl(state, writer);\n } catch (err) {\n // Release the sink so the half-emitted archive doesn't linger as a\n // valid-looking file on disk. abort() is idempotent.\n writer.abort(err);\n throw err;\n }\n };\n\n const abort = (cause?: unknown): void => {\n if (state.finalised) return;\n state.finalised = true;\n state.writer.abort(cause);\n };\n\n return { addWorksheet, finalize, abort };\n};\n\nasync function finalizeImpl(state: WorkbookState, writer: WorkbookState['writer']): Promise<void> {\n // 1. Worksheets — already streamed through writer.addStreamingEntry\n // during each WriteOnlyWorksheet's appendRow / close cycle.\n\n // 2. Stylesheet.\n await writer.addEntry(ARC_STYLE, stylesheetToBytes(state.styles));\n\n // 3. SharedStrings (only when non-empty).\n if (state.sst.entries.length > 0) {\n await writer.addEntry(ARC_SHARED_STRINGS, sharedStringsToBytes(state.sst));\n }\n\n // 4. workbook.xml.\n const workbookXml = serializeWorkbookXml(state.sheets);\n await writer.addEntry(ARC_WORKBOOK, new TextEncoder().encode(workbookXml));\n\n // 5. workbook.xml.rels.\n const wbRels = makeRelationships();\n state.sheets.forEach((s, i) => {\n wbRels.rels.push({\n id: `rId${i + 1}`,\n type: `${REL_NS}/worksheet`,\n target: `worksheets/sheet${s.sheetId}.xml`,\n });\n });\n if (state.sst.entries.length > 0) {\n wbRels.rels.push({\n id: `rId${wbRels.rels.length + 1}`,\n type: `${REL_NS}/sharedStrings`,\n target: 'sharedStrings.xml',\n });\n }\n wbRels.rels.push({\n id: `rId${wbRels.rels.length + 1}`,\n type: `${REL_NS}/styles`,\n target: 'styles.xml',\n });\n await writer.addEntry(ARC_WORKBOOK_RELS, relsToBytes(wbRels));\n\n // 6. root rels.\n const rootRels = makeRelationships();\n rootRels.rels.push({\n id: 'rId1',\n type: `${REL_NS}/officeDocument`,\n target: 'xl/workbook.xml',\n });\n await writer.addEntry(ARC_ROOT_RELS, relsToBytes(rootRels));\n void PKG_REL_NS; // imported for future docProps support\n\n // 7. [Content_Types].xml.\n const manifest = makeManifest();\n // Excel rejects packages whose [Content_Types].xml is missing the Default\n // entries for `rels` / `xml` — without them the package relationships file\n // can't be classified and Excel refuses to open.\n addDefault(manifest, 'rels', 'application/vnd.openxmlformats-package.relationships+xml');\n addDefault(manifest, 'xml', 'application/xml');\n addOverride(manifest, `/${ARC_WORKBOOK}`, XLSX_TYPE);\n for (const s of state.sheets) {\n addOverride(manifest, `/xl/worksheets/sheet${s.sheetId}.xml`, WORKSHEET_TYPE);\n }\n addOverride(manifest, `/${ARC_STYLE}`, STYLES_TYPE);\n if (state.sst.entries.length > 0) {\n addOverride(manifest, `/${ARC_SHARED_STRINGS}`, SHARED_STRINGS_TYPE);\n }\n await writer.addEntry(ARC_CONTENT_TYPES, manifestToBytes(manifest));\n\n await writer.finalize();\n}\n\nconst serializeWorkbookXml = (\n sheets: ReadonlyArray<{ title: string; sheetId: number }>,\n): string => {\n const parts: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>',\n `<workbook xmlns=\"${SHEET_MAIN_NS}\" xmlns:r=\"${REL_NS}\">`,\n '<sheets>',\n ];\n sheets.forEach((s, i) => {\n parts.push(\n `<sheet name=\"${escapeAttr(s.title)}\" sheetId=\"${s.sheetId}\" r:id=\"rId${i + 1}\"/>`,\n );\n });\n parts.push('</sheets></workbook>');\n return parts.join('');\n};\n\n/** Open a workbook for streaming write-only output. */\nexport async function createWriteOnlyWorkbook(\n sink: XlsxSink,\n _opts: WriteOnlyOptions = {},\n): Promise<WriteOnlyWorkbook> {\n // The streaming-deflate ZIP writer is constructed eagerly here: each\n // addWorksheet opens an entry on it and flushes row chunks through fflate's\n // `Zip` + `ZipDeflate` immediately, so peak memory stays at one pending row\n // buffer plus deflate scratch (no all-sheets accumulation).\n return makeWriteOnlyWorkbook(sink);\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"streaming.mjs","names":[],"sources":["../src/streaming/read-only.ts","../src/streaming/write-only.ts"],"sourcesContent":["// Streaming read-only workbook.\n//\n// `loadWorkbookStream` opens the zip + parses workbook.xml / sharedStrings.xml\n// / styles.xml metadata up front (small even on million-row archives), then\n// exposes a lazy `openWorksheet(name)` that SAX-iterates the sheet body via\n// `iterParse`. The iterator streams rows without materialising the full sheet\n// in memory.\n\nimport { makeSharedStrings, parseSharedStringsXml, type SharedStringsTable } from '../workbook/shared-strings.js';\nimport { ARC_CONTENT_TYPES, ARC_ROOT_RELS, ARC_SHARED_STRINGS, ARC_STYLE, REL_NS, SHEET_MAIN_NS } from '../xml/namespaces.js';\nimport { findById, relsFromBytes } from '../packaging/relationships.js';\nimport { manifestFromBytes } from '../packaging/manifest.js';\nimport { OpenXmlSchemaError } from '../utils/exceptions.js';\nimport type { DecompressionLimits } from '../zip/decompression-guard.js';\nimport { type ZipArchive, openZip } from '../zip/reader.js';\nimport type { CellValue, ExcelErrorCode } from '../cell/cell.js';\nimport { ERROR_CODES } from '../utils/inference.js';\nimport { iterParse, type SaxEvent, type SaxInput } from '../xml/iterparse.js';\nimport { parseXml } from '../xml/parser.js';\nimport { findChild, findChildren, type XmlNode } from '../xml/tree.js';\nimport type { XlsxSource } from '../io/source.js';\nimport { coordinateToTuple } from '../utils/coordinate.js';\nimport { type Stylesheet, makeStylesheet } from '../styles/stylesheet.js';\nimport { parseStylesheetXml } from '../styles/stylesheet-reader.js';\nimport { parseDate1904, resolveRelTarget } from '../io/load.js';\n\nconst SHEET_TAG = `{${SHEET_MAIN_NS}}sheet`;\nconst SHEETS_TAG = `{${SHEET_MAIN_NS}}sheets`;\n\nexport interface IterRowsOptions {\n minRow?: number;\n maxRow?: number;\n minCol?: number;\n maxCol?: number;\n}\n\nexport interface ReadOnlyCell {\n readonly row: number;\n readonly col: number;\n readonly value: CellValue;\n readonly styleId: number;\n}\n\nexport interface ReadOnlyWorksheet {\n title: string;\n iterRows(opts?: IterRowsOptions): AsyncIterableIterator<ReadOnlyCell[]>;\n iterValues(opts?: IterRowsOptions): AsyncIterableIterator<CellValue[]>;\n}\n\nexport interface ReadOnlyWorkbook {\n sheetNames: string[];\n styles: Stylesheet;\n /** Date1904 mode toggles between Excel's two epoch systems. */\n date1904: boolean;\n openWorksheet(name: string): ReadOnlyWorksheet;\n close(): Promise<void>;\n}\n\ninterface SheetEntry {\n name: string;\n rId: string;\n partPath: string;\n}\n\nconst parseSheetList = (root: XmlNode, workbookPath: string, archive: ZipArchive): SheetEntry[] => {\n const sheetsEl = findChild(root, SHEETS_TAG);\n if (!sheetsEl) return [];\n const wbRelsPath = relsPathFor(workbookPath);\n const wbRels = archive.has(wbRelsPath) ? relsFromBytes(archive.read(wbRelsPath)) : { rels: [] };\n const out: SheetEntry[] = [];\n for (const sheet of findChildren(sheetsEl, SHEET_TAG)) {\n const name = sheet.attrs['name'];\n const rId = sheet.attrs[`{${REL_NS}}id`];\n if (!name || !rId) continue;\n const rel = findById(wbRels, rId);\n if (!rel) continue;\n const partPath = resolveRelTarget(workbookPath, rel.target);\n out.push({ name, rId, partPath });\n }\n return out;\n};\n\nconst relsPathFor = (partPath: string): string => {\n const i = partPath.lastIndexOf('/');\n if (i < 0) return `_rels/${partPath}.rels`;\n return `${partPath.slice(0, i)}/_rels/${partPath.slice(i + 1)}.rels`;\n};\n\nconst localName = (qname: string): string => {\n const i = qname.lastIndexOf('}');\n return i < 0 ? qname : qname.slice(i + 1);\n};\n\nconst decodeCellValue = (\n t: string,\n vText: string | undefined,\n inlineText: string | undefined,\n sst: ReadonlyArray<string>,\n): CellValue => {\n switch (t) {\n case 'n':\n return vText !== undefined && vText !== '' ? Number.parseFloat(vText) : null;\n case 's': {\n if (vText === undefined) return null;\n const idx = Number.parseInt(vText, 10);\n if (!Number.isInteger(idx) || idx < 0 || idx >= sst.length) return null;\n return sst[idx] ?? null;\n }\n case 'b':\n return vText === '1';\n case 'e': {\n if (!vText || !ERROR_CODES.has(vText)) return null;\n return { kind: 'error', code: vText as ExcelErrorCode };\n }\n case 'str':\n return vText ?? '';\n case 'inlineStr':\n return inlineText ?? '';\n default:\n return vText !== undefined && vText !== '' ? Number.parseFloat(vText) : null;\n }\n};\n\n/**\n * SAX-iterate `<sheetData>/<row>/<c>` events out of the worksheet bytes (or a\n * stream that yields them), yielding one `ReadOnlyCell[]` per row that matches\n * `opts`.\n */\nasync function* iterSheetRows(\n sheetInput: SaxInput,\n sst: ReadonlyArray<string>,\n opts: IterRowsOptions,\n): AsyncIterableIterator<ReadOnlyCell[]> {\n const minRow = opts.minRow ?? 1;\n const maxRow = opts.maxRow ?? Number.POSITIVE_INFINITY;\n const minCol = opts.minCol ?? 1;\n const maxCol = opts.maxCol ?? Number.POSITIVE_INFINITY;\n\n let inSheetData = false;\n let currentRow = -1;\n let currentRowAttrs: Record<string, string> | null = null;\n let currentCells: ReadOnlyCell[] = [];\n\n // Per-cell state. Reset when each <c> starts.\n let cellOpen = false;\n let cellRow = 0;\n let cellCol = 0;\n let cellType = 'n';\n let cellStyleId = 0;\n let inV = false;\n let vText = '';\n let inIs = false;\n let inIsT = false;\n let isText = '';\n\n for await (const ev of iterParse(sheetInput)) {\n const e = ev as SaxEvent;\n if (e.kind === 'start') {\n const local = localName(e.name);\n if (!inSheetData) {\n if (local === 'sheetData') inSheetData = true;\n continue;\n }\n switch (local) {\n case 'row': {\n currentRowAttrs = e.attrs;\n const rRaw = e.attrs['r'];\n currentRow = rRaw ? Number.parseInt(rRaw, 10) : currentRow + 1;\n currentCells = [];\n break;\n }\n case 'c': {\n if (currentRow < 0) break;\n // Skip cell-attr parsing entirely when the row is outside the\n // requested band — saves the parseInt + coordinateToTuple hit on\n // every cell of every excluded row.\n if (currentRow < minRow || currentRow > maxRow) break;\n cellOpen = true;\n cellType = e.attrs['t'] ?? 'n';\n const sRaw = e.attrs['s'];\n cellStyleId = sRaw ? Number.parseInt(sRaw, 10) || 0 : 0;\n const ref = e.attrs['r'];\n if (ref) {\n const tup = coordinateToTuple(ref);\n cellRow = tup.row;\n cellCol = tup.col;\n } else {\n cellRow = currentRow;\n cellCol = (currentCells[currentCells.length - 1]?.col ?? 0) + 1;\n }\n vText = '';\n isText = '';\n break;\n }\n case 'v':\n if (cellOpen) inV = true;\n break;\n case 'is':\n if (cellOpen) inIs = true;\n break;\n case 't':\n if (inIs) inIsT = true;\n break;\n default:\n break;\n }\n continue;\n }\n if (e.kind === 'text') {\n if (inV) vText += e.text;\n else if (inIsT) isText += e.text;\n continue;\n }\n // end\n const local = localName(e.name);\n if (!inSheetData) continue;\n switch (local) {\n case 'sheetData':\n inSheetData = false;\n return;\n case 'row': {\n if (currentRow >= minRow && currentRow <= maxRow && currentCells.length > 0) {\n yield currentCells;\n }\n // Once we've crossed maxRow there are no more rows to yield — every\n // subsequent <row> would just be parsed and dropped. Stop iterating\n // early. ECMA-376 emits rows in ascending order.\n if (currentRow > maxRow) {\n inSheetData = false;\n return;\n }\n currentRow = -1;\n currentRowAttrs = null;\n currentCells = [];\n break;\n }\n case 'c': {\n if (cellOpen && cellCol >= minCol && cellCol <= maxCol && cellRow >= minRow && cellRow <= maxRow) {\n const value = decodeCellValue(cellType, vText, isText, sst);\n currentCells.push({ row: cellRow, col: cellCol, value, styleId: cellStyleId });\n }\n cellOpen = false;\n break;\n }\n case 'v':\n inV = false;\n break;\n case 'is':\n inIs = false;\n break;\n case 't':\n if (inIs) inIsT = false;\n break;\n default:\n break;\n }\n }\n // Avoid unused-var lint when row attrs never touched.\n void currentRowAttrs;\n}\n\n/**\n * Build a sorted `[rowNum, byteOffset]` index for every `<row r=\"N\">`\n * occurrence in a worksheet's bytes. Pure byte-level scan (no SAX), cheap\n * relative to the per-cell SAX walk: ~50 ns per row on M-series Node 22.\n *\n * `sheetDataEnd` is the byte offset of `</sheetData>` so callers can clip the\n * slice that gets handed to saxes.\n */\nconst buildRowOffsetIndex = (\n bytes: Uint8Array,\n): { index: ReadonlyArray<{ row: number; offset: number }>; sheetDataEnd: number } => {\n const out: Array<{ row: number; offset: number }> = [];\n let sheetDataEnd = -1;\n let i = 0;\n while (i < bytes.length) {\n if (bytes[i] !== 0x3c /* '<' */) {\n i++;\n continue;\n }\n // Detect `</sheetData>` once — used to clip the slice fed to saxes.\n if (\n sheetDataEnd < 0 &&\n bytes[i + 1] === 0x2f /* '/' */ &&\n bytes[i + 2] === 0x73 /* 's' */ &&\n bytes[i + 3] === 0x68 /* 'h' */ &&\n bytes[i + 4] === 0x65 /* 'e' */ &&\n bytes[i + 5] === 0x65 /* 'e' */ &&\n bytes[i + 6] === 0x74 /* 't' */ &&\n bytes[i + 7] === 0x44 /* 'D' */ &&\n bytes[i + 8] === 0x61 /* 'a' */ &&\n bytes[i + 9] === 0x74 /* 't' */ &&\n bytes[i + 10] === 0x61 /* 'a' */ &&\n bytes[i + 11] === 0x3e /* '>' */\n ) {\n sheetDataEnd = i;\n break;\n }\n // Match `<row` followed by ASCII whitespace or '>'.\n if (\n bytes[i + 1] !== 0x72 /* 'r' */ ||\n bytes[i + 2] !== 0x6f /* 'o' */ ||\n bytes[i + 3] !== 0x77 /* 'w' */\n ) {\n i++;\n continue;\n }\n const next = bytes[i + 4];\n if (\n next !== 0x20 /* sp */ &&\n next !== 0x09 /* tab */ &&\n next !== 0x0a /* lf */ &&\n next !== 0x0d /* cr */ &&\n next !== 0x3e /* > */ &&\n next !== 0x2f /* / */\n ) {\n i++;\n continue;\n }\n // Walk to the closing '>'; the attrs region carries `r=\"N\"`.\n const start = i;\n let j = i + 4;\n while (j < bytes.length && bytes[j] !== 0x3e) j++;\n if (j >= bytes.length) break;\n const attrsBuf = bytes.subarray(start + 4, j);\n const attrs = new TextDecoder('ascii', { fatal: false }).decode(attrsBuf);\n const m = /\\sr=\"(\\d+)\"/.exec(attrs);\n if (m?.[1]) {\n const row = Number.parseInt(m[1], 10);\n if (Number.isInteger(row)) out.push({ row, offset: start });\n }\n i = j + 1;\n }\n if (sheetDataEnd < 0) sheetDataEnd = bytes.length;\n return { index: out, sheetDataEnd };\n};\n\n/**\n * Binary-search the row index for the first entry with `row >= target`. Returns\n * -1 when every recorded row is below the target.\n */\nconst firstRowAtOrAfter = (\n index: ReadonlyArray<{ row: number; offset: number }>,\n target: number,\n): number => {\n let lo = 0;\n let hi = index.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const entry = index[mid];\n if (!entry || entry.row < target) lo = mid + 1;\n else hi = mid;\n }\n return lo < index.length ? lo : -1;\n};\n\n/**\n * Slice a worksheet's bytes to start at the row at index `idxPos` of the\n * row-offset index, wrapping the result with a synthetic `<sheetData>` envelope\n * so saxes parses it in the right namespace.\n */\nconst SHEET_DATA_OPEN = `<?xml version=\"1.0\" encoding=\"UTF-8\"?><sheetData xmlns=\"${SHEET_MAIN_NS}\">`;\nconst SHEET_DATA_CLOSE = `</sheetData>`;\nconst sliceFromRow = (\n bytes: Uint8Array,\n fromOffset: number,\n sheetDataEnd: number,\n): Uint8Array => {\n const prefix = new TextEncoder().encode(SHEET_DATA_OPEN);\n const suffix = new TextEncoder().encode(SHEET_DATA_CLOSE);\n const middle = bytes.subarray(fromOffset, sheetDataEnd);\n const out = new Uint8Array(prefix.length + middle.length + suffix.length);\n out.set(prefix, 0);\n out.set(middle, prefix.length);\n out.set(suffix, prefix.length + middle.length);\n return out;\n};\n\n/**\n * Factory: build a {@link ReadOnlyWorksheet} bound to a single worksheet part\n * inside an opened archive. SAX iteration runs lazily — `iterRows` re-reads the\n * part bytes each time so the caller can iterate the same sheet repeatedly\n * without keeping a buffered decoder around.\n *\n * For `iterRows({ minRow > 1 })`, a row-offset index is built lazily on first\n * use and cached; subsequent band queries jump straight to the byte offset of\n * the first matching row instead of SAX-walking the entire `<sheetData>`.\n */\nconst makeStreamingReadOnlyWorksheet = (\n title: string,\n archive: ZipArchive,\n partPath: string,\n sst: ReadonlyArray<string>,\n): ReadOnlyWorksheet => {\n // Lazy + cached. The index is small (~16 B per row); for 1M rows that's 16 MB\n // of working set, vs. the alternative of walking the sheet bytes through\n // saxes on every band query.\n let cached: ReturnType<typeof buildRowOffsetIndex> | undefined;\n const ensureIndex = (bytes: Uint8Array) => {\n if (!cached) cached = buildRowOffsetIndex(bytes);\n return cached;\n };\n\n const iterRows = (opts: IterRowsOptions = {}): AsyncIterableIterator<ReadOnlyCell[]> => {\n const minRow = opts.minRow ?? 1;\n if (minRow <= 1) {\n // Whole-sheet (or no-min) iter — feed the SAX parser directly off the\n // archive's streaming inflate path so the worksheet's inflated payload\n // is never fully resident. Peak memory for the walk drops to the\n // inflate window + SAX state instead of the entire `<sheetData>` body.\n return iterSheetRows(archive.readStream(partPath), sst, opts);\n }\n // Band query (minRow > 1): the row-offset index needs the full inflated\n // bytes so we can binary-search to the byte offset of the first matching\n // row. Materialise once and reuse via `ensureIndex`.\n const bytes = archive.read(partPath);\n const { index, sheetDataEnd } = ensureIndex(bytes);\n if (index.length === 0) return iterSheetRows(bytes, sst, opts);\n const pos = firstRowAtOrAfter(index, minRow);\n if (pos < 0) {\n // Every row is below minRow — nothing to yield.\n return (async function* () {})();\n }\n const target = index[pos];\n if (!target) return iterSheetRows(bytes, sst, opts);\n const sliced = sliceFromRow(bytes, target.offset, sheetDataEnd);\n return iterSheetRows(sliced, sst, opts);\n };\n const iterValues = async function* (opts: IterRowsOptions = {}): AsyncIterableIterator<CellValue[]> {\n for await (const row of iterRows(opts)) {\n yield row.map((c) => c.value);\n }\n };\n return { title, iterRows, iterValues };\n};\n\n/**\n * Factory: build a {@link ReadOnlyWorkbook} from an opened archive + pre-parsed\n * sheet list / styles / shared strings. Per the project-wide \"no classes\" rule\n * (CLAUDE.md), the workbook is a plain object closing over the archive handle.\n */\nconst makeStreamingReadOnlyWorkbook = (\n sheetNames: string[],\n styles: Stylesheet,\n date1904: boolean,\n archive: ZipArchive,\n entries: ReadonlyMap<string, SheetEntry>,\n sst: ReadonlyArray<string>,\n): ReadOnlyWorkbook => ({\n sheetNames,\n styles,\n date1904,\n openWorksheet(name) {\n const entry = entries.get(name);\n if (!entry) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: no worksheet named \"${name}\"`);\n }\n return makeStreamingReadOnlyWorksheet(name, archive, entry.partPath, sst);\n },\n async close() {\n archive.close();\n },\n});\n\n/** Options for {@link loadWorkbookStream}. */\nexport interface LoadWorkbookStreamOptions {\n /**\n * Decompression-bomb safeguards applied while inflating zip entries.\n * Defaults to limits that fit any legitimate xlsx; pass `false` to disable\n * (only safe for fully trusted sources).\n */\n decompressionLimits?: DecompressionLimits | false;\n}\n\n/** Open an xlsx for read-only streaming access. */\nexport async function loadWorkbookStream(\n source: XlsxSource,\n opts: LoadWorkbookStreamOptions = {},\n): Promise<ReadOnlyWorkbook> {\n const archive = await openZip(\n source,\n opts.decompressionLimits === undefined ? {} : { decompressionLimits: opts.decompressionLimits },\n );\n if (!archive.has(ARC_CONTENT_TYPES)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: missing \"${ARC_CONTENT_TYPES}\"`);\n }\n // Manifest parse is intentionally cheap and discarded — we resolve sheets by\n // walking workbook.xml.rels directly.\n manifestFromBytes(archive.read(ARC_CONTENT_TYPES));\n\n if (!archive.has(ARC_ROOT_RELS)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: missing \"${ARC_ROOT_RELS}\"`);\n }\n const rootRels = relsFromBytes(archive.read(ARC_ROOT_RELS));\n const officeDocRel = rootRels.rels.find((r) => r.type === `${REL_NS}/officeDocument`);\n if (!officeDocRel) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: no officeDocument relationship in root rels`);\n }\n const workbookPath = resolveRelTarget('', officeDocRel.target);\n if (!archive.has(workbookPath)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: workbook part \"${workbookPath}\" missing`);\n }\n const workbookRoot = parseXml(archive.read(workbookPath));\n const sheetEntries = parseSheetList(workbookRoot, workbookPath, archive);\n const entryMap = new Map<string, SheetEntry>();\n for (const e of sheetEntries) entryMap.set(e.name, e);\n\n let sst: SharedStringsTable = makeSharedStrings();\n if (archive.has(ARC_SHARED_STRINGS)) {\n sst = parseSharedStringsXml(archive.read(ARC_SHARED_STRINGS));\n }\n let styles: Stylesheet = makeStylesheet();\n if (archive.has(ARC_STYLE)) {\n styles = parseStylesheetXml(archive.read(ARC_STYLE));\n }\n\n return makeStreamingReadOnlyWorkbook(\n sheetEntries.map((e) => e.name),\n styles,\n parseDate1904(workbookRoot),\n archive,\n entryMap,\n sst.entries.map((e) => (typeof e === 'string' ? e : e.runs.map((r) => r.text).join(''))),\n );\n}\n","// Streaming write-only workbook.\n//\n// `createWriteOnlyWorkbook` lets callers append rows one at a time without\n// holding a full Workbook in memory. Each `appendRow` serialises the row\n// directly into a string buffer (no `Cell` objects, no Worksheet rows Map) —\n// when `close()` runs we glue the rows under a `<sheetData>` envelope and hand\n// the bytes to the streaming-deflate ZIP writer. The buffer keeps ~30 bytes per\n// cell of XML text instead of the ~200-byte V8 footprint a Cell + Map entry\n// costs, so the heap budget at 3M cells drops roughly an order of magnitude vs.\n// the previous setCell-based path.\n\nimport type { Cell, CellValue } from '../cell/cell.js';\nimport type { XlsxSink } from '../io/sink.js';\nimport { addDefault, addOverride, makeManifest, manifestToBytes } from '../packaging/manifest.js';\nimport { makeRelationships, relsToBytes } from '../packaging/relationships.js';\nimport {\n addBorder,\n addCellXf,\n addFill,\n addFont,\n addNumFmt,\n type CellXf,\n defaultCellXf,\n makeStylesheet,\n type Stylesheet,\n} from '../styles/stylesheet.js';\nimport { stylesheetToBytes } from '../styles/stylesheet-writer.js';\nimport type { Alignment } from '../styles/alignment.js';\nimport type { Border } from '../styles/borders.js';\nimport type { Fill } from '../styles/fills.js';\nimport type { Font } from '../styles/fonts.js';\nimport type { Protection } from '../styles/protection.js';\nimport { escapeXmlAttr } from '../utils/escape.js';\nimport { OpenXmlIoError } from '../utils/exceptions.js';\nimport { utf8ByteLength } from '../utils/utf8.js';\nimport { makeSharedStrings, sharedStringsToBytes } from '../workbook/shared-strings.js';\nimport { validateSheetTitle } from '../workbook/workbook.js';\nimport { serializeCell } from '../worksheet/writer.js';\nimport {\n ARC_CONTENT_TYPES,\n ARC_ROOT_RELS,\n ARC_SHARED_STRINGS,\n ARC_STYLE,\n ARC_WORKBOOK,\n ARC_WORKBOOK_RELS,\n PKG_REL_NS,\n REL_NS,\n SHARED_STRINGS_TYPE,\n SHEET_MAIN_NS,\n STYLES_TYPE,\n WORKSHEET_TYPE,\n XLSX_TYPE,\n} from '../xml/namespaces.js';\nimport { createZipWriter } from '../zip/writer.js';\n\nconst escapeAttr = escapeXmlAttr;\n\nexport interface WriteOnlyOptions {\n /** Reserved — currently ignored (the buffered backend doesn't honour it). */\n estimatedMaxRow?: number;\n}\n\nexport interface WriteOnlyStyle {\n font?: Font;\n fill?: Fill;\n border?: Border;\n alignment?: Alignment;\n numberFormat?: string;\n protection?: Protection;\n}\n\nexport type WriteOnlyRowItem = CellValue | { value: CellValue; style?: WriteOnlyStyle };\n\nexport interface WriteOnlyWorksheet {\n readonly title: string;\n appendRow(row: WriteOnlyRowItem[]): Promise<void>;\n setColumnWidth(col: number, width: number): void;\n close(): Promise<void>;\n}\n\nexport interface WriteOnlyWorkbook {\n /** Add a new worksheet. The previous worksheet must be `close()`d first. */\n addWorksheet(title: string): Promise<WriteOnlyWorksheet>;\n /** Finalise the archive: emits styles / sharedStrings / workbook / manifest / rels. */\n finalize(): Promise<void>;\n /**\n * Release the sink without finalising the archive. Call this from a\n * surrounding catch block when the producer pipeline throws before\n * `finalize()` — without it, streaming destinations (`toFile` /\n * `toWritable`) keep the file descriptor / Writable open and the partial\n * xlsx looks valid on disk.\n *\n * Idempotent. Subsequent `addWorksheet` / `finalize` calls throw.\n */\n abort(cause?: unknown): void;\n}\n\nconst validateTitle = (title: string, taken: Set<string>): void => {\n const reason = validateSheetTitle(title);\n if (reason) {\n throw new OpenXmlIoError(`Worksheet title \"${title}\": ${reason}`);\n }\n if (taken.has(title.toLowerCase())) {\n throw new OpenXmlIoError(`Worksheet title \"${title}\" is already in use`);\n }\n};\n\n/** Allocate a CellXf id for a style spec. Mirrors cell-style.ts but works directly on the pool. */\nconst allocateXfId = (ss: Stylesheet, style: WriteOnlyStyle): number => {\n // `xfId` is intentionally omitted: leaving it undefined skips the\n // cellStyleXfs bounds check and matches what Excel emits when there is no\n // parent style.\n let xf: CellXf = { fontId: 0, fillId: 0, borderId: 0, numFmtId: 0 };\n if (style.font !== undefined) {\n xf = { ...xf, fontId: addFont(ss, style.font), applyFont: true };\n }\n if (style.fill !== undefined) {\n xf = { ...xf, fillId: addFill(ss, style.fill), applyFill: true };\n }\n if (style.border !== undefined) {\n xf = { ...xf, borderId: addBorder(ss, style.border), applyBorder: true };\n }\n if (style.numberFormat !== undefined) {\n xf = { ...xf, numFmtId: addNumFmt(ss, style.numberFormat), applyNumberFormat: true };\n }\n if (style.alignment !== undefined) {\n xf = { ...xf, alignment: style.alignment, applyAlignment: true };\n }\n if (style.protection !== undefined) {\n xf = { ...xf, protection: style.protection, applyProtection: true };\n }\n return addCellXf(ss, xf);\n};\n\ninterface WorkbookState {\n styles: Stylesheet;\n sst: ReturnType<typeof makeSharedStrings>;\n /** Sheet emit metadata, in addWorksheet order. */\n sheets: Array<{\n title: string;\n sheetId: number;\n }>;\n /** True once finalize() has been called (further mutations throw). */\n finalised: boolean;\n /** True while a worksheet is open (the next addWorksheet must wait). */\n hasOpenWorksheet: boolean;\n /** ZIP writer the workbook + each open worksheet stream chunks through. */\n writer: import('../zip/writer.js').ZipWriter;\n}\n\n/**\n * Flush threshold for the worksheet's pending-row text buffer. Smaller values\n * minimise heap; larger values amortise the TextEncoder + push overhead. 64 KB\n * is a sweet spot — heap stays low and per-row JS work is dominated by the\n * actual XML construction, not flushing.\n */\nconst FLUSH_THRESHOLD_BYTES = 64 * 1024;\n\n/**\n * Factory: build a {@link WriteOnlyWorksheet} that closes over the shared\n * {@link WorkbookState}. Per the project-wide \"no classes\" rule (CLAUDE.md) the\n * worksheet is a plain object holding the row buffer + column-width map in\n * closure state.\n *\n * The worksheet streams its `<sheetData>` body chunk-by-chunk through the ZIP\n * writer's `addStreamingEntry` API, so the heap footprint stays at one ~64 KB\n * pending text buffer plus deflate scratch — no Cell objects, no all-rows\n * accumulation. The XML envelope (decl / worksheet open / cols / sheetData\n * open) flushes on the first `appendRow` (or `close()` if the sheet is empty);\n * column widths staged via `setColumnWidth` *must* land before the first row.\n */\nconst makeWriteOnlyWorksheet = (state: WorkbookState, title: string, sheetId: number): WriteOnlyWorksheet => {\n let nextRow = 1;\n let closed = false;\n let headerFlushed = false;\n const columnWidths = new Map<number, number>();\n const dummyCtx = { sharedStrings: state.sst, rels: makeRelationships() };\n const encoder = new TextEncoder();\n const stream = state.writer.addStreamingEntry(`xl/worksheets/sheet${sheetId}.xml`);\n let pendingText = '';\n let pendingBytes = 0;\n\n const writeText = (text: string): void => {\n pendingText += text;\n // UTF-8 byte length, computed without a full encode: scan once and add the\n // exact codepoint cost. `text.length` would undercount CJK by ~3× and let\n // the buffer balloon past FLUSH_THRESHOLD_BYTES on Japanese / Chinese\n // workloads.\n pendingBytes += utf8ByteLength(text);\n if (pendingBytes >= FLUSH_THRESHOLD_BYTES) {\n stream.write(encoder.encode(pendingText));\n pendingText = '';\n pendingBytes = 0;\n }\n };\n\n const flushHeader = (): void => {\n if (headerFlushed) return;\n headerFlushed = true;\n let header = '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>';\n header += `<worksheet xmlns=\"${SHEET_MAIN_NS}\" xmlns:r=\"${REL_NS}\">`;\n if (columnWidths.size > 0) {\n header += '<cols>';\n const sorted = [...columnWidths.entries()].sort((a, b) => a[0] - b[0]);\n for (const [col, width] of sorted) {\n header += `<col min=\"${col}\" max=\"${col}\" width=\"${width}\" customWidth=\"1\"/>`;\n }\n header += '</cols>';\n }\n header += '<sheetData>';\n writeText(header);\n };\n\n const appendRow = async (row: WriteOnlyRowItem[]): Promise<void> => {\n if (closed) throw new OpenXmlIoError('appendRow: worksheet already closed');\n flushHeader();\n const r = nextRow++;\n let xml = `<row r=\"${r}\">`;\n for (let i = 0; i < row.length; i++) {\n const item = row[i];\n if (item === undefined || item === null) continue;\n const col = i + 1;\n let value: CellValue;\n let style: WriteOnlyStyle | undefined;\n if (item !== null && typeof item === 'object' && 'value' in (item as object)) {\n const wrapped = item as { value: CellValue; style?: WriteOnlyStyle };\n value = wrapped.value;\n style = wrapped.style;\n } else {\n value = item as CellValue;\n }\n const styleId = style ? allocateXfId(state.styles, style) : 0;\n // Ephemeral cell-shaped object — discarded as soon as serializeCell\n // returns its `<c .../>` string. Keeps the heap footprint at the size of\n // the pending text buffer instead of a full Worksheet model.\n const cell: Cell = { row: r, col, value, styleId };\n xml += serializeCell(cell, dummyCtx);\n }\n xml += '</row>';\n writeText(xml);\n };\n\n const setColumnWidth = (col: number, width: number): void => {\n if (closed) throw new OpenXmlIoError('setColumnWidth: worksheet already closed');\n if (headerFlushed) {\n throw new OpenXmlIoError(\n 'setColumnWidth: must be called before the first appendRow — column widths are emitted as part of the worksheet header',\n );\n }\n columnWidths.set(col, width);\n };\n\n const close = async (): Promise<void> => {\n if (closed) return;\n closed = true;\n flushHeader();\n writeText('</sheetData></worksheet>');\n if (pendingText.length > 0) {\n stream.write(encoder.encode(pendingText));\n pendingText = '';\n pendingBytes = 0;\n }\n await stream.end();\n state.sheets.push({ title, sheetId });\n state.hasOpenWorksheet = false;\n };\n\n return { title, appendRow, setColumnWidth, close };\n};\n\n/**\n * Factory: build a {@link WriteOnlyWorkbook} from a sink. State lives in a\n * closure rather than on a class instance per the project-wide \"no classes\"\n * rule (CLAUDE.md).\n */\nconst makeWriteOnlyWorkbook = (sink: XlsxSink): WriteOnlyWorkbook => {\n const styles = makeStylesheet();\n // Reserve cellXfs[0] for the default (no apply* flags). Unstyled cells point\n // at this slot via styleId=0; user-styled cells start at index 1 so the\n // writer emits an `s=\"N\"` attribute for them.\n addCellXf(styles, defaultCellXf());\n // The ZIP writer is created up front: each addWorksheet opens a streaming\n // entry on it and flushes row chunks through the deflate stream as they\n // arrive. Sheets emit before styles / sst / workbook / rels / content-types\n // so the writer can serialise them in order.\n const state: WorkbookState = {\n styles,\n sst: makeSharedStrings(),\n sheets: [],\n finalised: false,\n hasOpenWorksheet: false,\n writer: createZipWriter(sink),\n };\n\n const addWorksheet = async (title: string): Promise<WriteOnlyWorksheet> => {\n if (state.finalised) {\n throw new OpenXmlIoError('addWorksheet: workbook already finalised');\n }\n if (state.hasOpenWorksheet) {\n throw new OpenXmlIoError(\n 'addWorksheet: previous worksheet still open — call close() before opening the next one',\n );\n }\n const taken = new Set(state.sheets.map((s) => s.title.toLowerCase()));\n validateTitle(title, taken);\n state.hasOpenWorksheet = true;\n const sheetId = state.sheets.length + 1;\n return makeWriteOnlyWorksheet(state, title, sheetId);\n };\n\n const finalize = async (): Promise<void> => {\n if (state.finalised) {\n throw new OpenXmlIoError('finalize: already finalised');\n }\n if (state.hasOpenWorksheet) {\n throw new OpenXmlIoError('finalize: a worksheet is still open — call close() before finalising');\n }\n state.finalised = true;\n const writer = state.writer;\n try {\n await finalizeImpl(state, writer);\n } catch (err) {\n // Release the sink so the half-emitted archive doesn't linger as a\n // valid-looking file on disk. abort() is idempotent.\n writer.abort(err);\n throw err;\n }\n };\n\n const abort = (cause?: unknown): void => {\n if (state.finalised) return;\n state.finalised = true;\n state.writer.abort(cause);\n };\n\n return { addWorksheet, finalize, abort };\n};\n\nasync function finalizeImpl(state: WorkbookState, writer: WorkbookState['writer']): Promise<void> {\n // 1. Worksheets — already streamed through writer.addStreamingEntry\n // during each WriteOnlyWorksheet's appendRow / close cycle.\n\n // 2. Stylesheet.\n await writer.addEntry(ARC_STYLE, stylesheetToBytes(state.styles));\n\n // 3. SharedStrings (only when non-empty).\n if (state.sst.entries.length > 0) {\n await writer.addEntry(ARC_SHARED_STRINGS, sharedStringsToBytes(state.sst));\n }\n\n // 4. workbook.xml.\n const workbookXml = serializeWorkbookXml(state.sheets);\n await writer.addEntry(ARC_WORKBOOK, new TextEncoder().encode(workbookXml));\n\n // 5. workbook.xml.rels.\n const wbRels = makeRelationships();\n state.sheets.forEach((s, i) => {\n wbRels.rels.push({\n id: `rId${i + 1}`,\n type: `${REL_NS}/worksheet`,\n target: `worksheets/sheet${s.sheetId}.xml`,\n });\n });\n if (state.sst.entries.length > 0) {\n wbRels.rels.push({\n id: `rId${wbRels.rels.length + 1}`,\n type: `${REL_NS}/sharedStrings`,\n target: 'sharedStrings.xml',\n });\n }\n wbRels.rels.push({\n id: `rId${wbRels.rels.length + 1}`,\n type: `${REL_NS}/styles`,\n target: 'styles.xml',\n });\n await writer.addEntry(ARC_WORKBOOK_RELS, relsToBytes(wbRels));\n\n // 6. root rels.\n const rootRels = makeRelationships();\n rootRels.rels.push({\n id: 'rId1',\n type: `${REL_NS}/officeDocument`,\n target: 'xl/workbook.xml',\n });\n await writer.addEntry(ARC_ROOT_RELS, relsToBytes(rootRels));\n void PKG_REL_NS; // imported for future docProps support\n\n // 7. [Content_Types].xml.\n const manifest = makeManifest();\n // Excel rejects packages whose [Content_Types].xml is missing the Default\n // entries for `rels` / `xml` — without them the package relationships file\n // can't be classified and Excel refuses to open.\n addDefault(manifest, 'rels', 'application/vnd.openxmlformats-package.relationships+xml');\n addDefault(manifest, 'xml', 'application/xml');\n addOverride(manifest, `/${ARC_WORKBOOK}`, XLSX_TYPE);\n for (const s of state.sheets) {\n addOverride(manifest, `/xl/worksheets/sheet${s.sheetId}.xml`, WORKSHEET_TYPE);\n }\n addOverride(manifest, `/${ARC_STYLE}`, STYLES_TYPE);\n if (state.sst.entries.length > 0) {\n addOverride(manifest, `/${ARC_SHARED_STRINGS}`, SHARED_STRINGS_TYPE);\n }\n await writer.addEntry(ARC_CONTENT_TYPES, manifestToBytes(manifest));\n\n await writer.finalize();\n}\n\nconst serializeWorkbookXml = (\n sheets: ReadonlyArray<{ title: string; sheetId: number }>,\n): string => {\n const parts: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>',\n `<workbook xmlns=\"${SHEET_MAIN_NS}\" xmlns:r=\"${REL_NS}\">`,\n '<sheets>',\n ];\n sheets.forEach((s, i) => {\n parts.push(\n `<sheet name=\"${escapeAttr(s.title)}\" sheetId=\"${s.sheetId}\" r:id=\"rId${i + 1}\"/>`,\n );\n });\n parts.push('</sheets></workbook>');\n return parts.join('');\n};\n\n/** Open a workbook for streaming write-only output. */\nexport async function createWriteOnlyWorkbook(\n sink: XlsxSink,\n _opts: WriteOnlyOptions = {},\n): Promise<WriteOnlyWorkbook> {\n // The streaming-deflate ZIP writer is constructed eagerly here: each\n // addWorksheet opens an entry on it and flushes row chunks through fflate's\n // `Zip` + `ZipDeflate` immediately, so peak memory stays at one pending row\n // buffer plus deflate scratch (no all-sheets accumulation).\n return makeWriteOnlyWorkbook(sink);\n}\n\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
- import { type Schema } from '../schema/core';
2
- import type { Alignment } from './alignment';
1
+ import { type Schema } from '../schema/core.js';
2
+ import type { Alignment } from './alignment.js';
3
3
  export declare const AlignmentSchema: Schema<Alignment>;
@@ -1,4 +1,4 @@
1
- import { type Color } from './colors';
1
+ import { type Color } from './colors.js';
2
2
  export type SideStyle = 'none' | 'thin' | 'medium' | 'thick' | 'double' | 'hair' | 'dotted' | 'dashed' | 'dashDot' | 'dashDotDot' | 'mediumDashed' | 'mediumDashDot' | 'mediumDashDotDot' | 'slantDashDot';
3
3
  export declare const SIDE_STYLES: ReadonlyArray<SideStyle>;
4
4
  export interface Side {
@@ -1,4 +1,4 @@
1
- import { type Schema } from '../schema/core';
2
- import type { Border, Side } from './borders';
1
+ import { type Schema } from '../schema/core.js';
2
+ import type { Border, Side } from './borders.js';
3
3
  export declare const SideSchema: Schema<Side>;
4
4
  export declare const BorderSchema: Schema<Border>;
@@ -1,12 +1,12 @@
1
- import type { Cell } from '../cell/cell';
2
- import type { Workbook } from '../workbook/workbook';
3
- import { type Worksheet } from '../worksheet/worksheet';
4
- import type { Alignment, HorizontalAlignment, VerticalAlignment } from './alignment';
5
- import type { Border, SideStyle } from './borders';
6
- import type { Color } from './colors';
7
- import type { Fill } from './fills';
8
- import type { Font, UnderlineStyle } from './fonts';
9
- import type { Protection } from './protection';
1
+ import type { Cell } from '../cell/cell.js';
2
+ import type { Workbook } from '../workbook/workbook.js';
3
+ import { type Worksheet } from '../worksheet/worksheet.js';
4
+ import type { Alignment, HorizontalAlignment, VerticalAlignment } from './alignment.js';
5
+ import type { Border, SideStyle } from './borders.js';
6
+ import type { Color } from './colors.js';
7
+ import type { Fill } from './fills.js';
8
+ import type { Font, UnderlineStyle } from './fonts.js';
9
+ import type { Protection } from './protection.js';
10
10
  export declare function getCellFont(wb: Workbook, c: Cell): Font;
11
11
  export declare function getCellFill(wb: Workbook, c: Cell): Fill;
12
12
  export declare function getCellBorder(wb: Workbook, c: Cell): Border;
@@ -1,3 +1,3 @@
1
- import { type Schema } from '../schema/core';
2
- import type { Color } from './colors';
1
+ import { type Schema } from '../schema/core.js';
2
+ import type { Color } from './colors.js';
3
3
  export declare const ColorSchema: Schema<Color>;
@@ -1,10 +1,10 @@
1
- import type { Alignment } from './alignment';
2
- import type { Border } from './borders';
3
- import type { Fill } from './fills';
4
- import type { Font } from './fonts';
5
- import type { NumberFormat } from './numbers';
6
- import type { Protection } from './protection';
7
- import type { Stylesheet } from './stylesheet';
1
+ import type { Alignment } from './alignment.js';
2
+ import type { Border } from './borders.js';
3
+ import type { Fill } from './fills.js';
4
+ import type { Font } from './fonts.js';
5
+ import type { NumberFormat } from './numbers.js';
6
+ import type { Protection } from './protection.js';
7
+ import type { Stylesheet } from './stylesheet.js';
8
8
  /**
9
9
  * Differential ("partial") style. Every component is optional; only
10
10
  * the set fields override the base style of whatever the DXF is
@@ -1,4 +1,4 @@
1
- import { type Color } from './colors';
1
+ import { type Color } from './colors.js';
2
2
  /** Predefined Excel pattern types. `'none'` lives here too as an explicit value. */
3
3
  export type PatternType = 'none' | 'solid' | 'darkDown' | 'darkGray' | 'darkGrid' | 'darkHorizontal' | 'darkTrellis' | 'darkUp' | 'darkVertical' | 'gray0625' | 'gray125' | 'lightDown' | 'lightGray' | 'lightGrid' | 'lightHorizontal' | 'lightTrellis' | 'lightUp' | 'lightVertical' | 'mediumGray';
4
4
  export declare const PATTERN_TYPES: ReadonlyArray<PatternType>;
@@ -1,5 +1,5 @@
1
- import { type XmlNode } from '../xml/tree';
2
- import { type Fill } from './fills';
1
+ import { type XmlNode } from '../xml/tree.js';
2
+ import { type Fill } from './fills.js';
3
3
  /** Build the `<fill>…</fill>` envelope around either variant. */
4
4
  export declare function fillToTree(fill: Fill): XmlNode;
5
5
  /** Inverse of {@link fillToTree}. Reads `<fill>` and dispatches on the child tag. */