@office-kit/xlsx 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -8
- package/dist/cell/cell.d.ts +12 -19
- package/dist/{cell-Df3cKRIl.mjs → cell-B5OUUdfI.mjs} +13 -7
- package/dist/cell-B5OUUdfI.mjs.map +1 -0
- package/dist/{cell-style-CNsET6WU.mjs → cell-style-DjKKPWDL.mjs} +2 -2
- package/dist/{cell-style-CNsET6WU.mjs.map → cell-style-DjKKPWDL.mjs.map} +1 -1
- package/dist/cell.mjs +1 -1
- package/dist/{coordinate-Bt5Gni2I.mjs → coordinate-CxC88uBk.mjs} +31 -2
- package/dist/coordinate-CxC88uBk.mjs.map +1 -0
- package/dist/{defined-names-Ctu3F6ls.mjs → defined-names-Cmp8rbvI.mjs} +2 -2
- package/dist/{defined-names-Ctu3F6ls.mjs.map → defined-names-Cmp8rbvI.mjs.map} +1 -1
- package/dist/{differential-BPKa7wXi.mjs → differential-7KGzbliB.mjs} +2 -2
- package/dist/{differential-BPKa7wXi.mjs.map → differential-7KGzbliB.mjs.map} +1 -1
- package/dist/{drawing-ZJ3h4VHD.mjs → drawing-Cv6UtInY.mjs} +2 -2
- package/dist/{drawing-ZJ3h4VHD.mjs.map → drawing-Cv6UtInY.mjs.map} +1 -1
- package/dist/drawing.mjs +1 -1
- package/dist/{escape-rnWSPpWY.mjs → escape-rA5UpibT.mjs} +26 -3
- package/dist/escape-rA5UpibT.mjs.map +1 -0
- package/dist/io/load.d.ts +28 -0
- package/dist/io.mjs +2 -2
- package/dist/{load-CspGc399.mjs → load-DIdQ_zum.mjs} +66 -39
- package/dist/{load-CspGc399.mjs.map → load-DIdQ_zum.mjs.map} +1 -1
- package/dist/{manifest-pLmx7KYh.mjs → manifest-BHUYpjUG.mjs} +3 -3
- package/dist/{manifest-pLmx7KYh.mjs.map → manifest-BHUYpjUG.mjs.map} +1 -1
- package/dist/node.mjs +1 -1
- package/dist/packaging.mjs +1 -1
- package/dist/{reader-DHMxLBQV.mjs → reader-pC7bxYAs.mjs} +30 -7
- package/dist/reader-pC7bxYAs.mjs.map +1 -0
- package/dist/{save-DgPf1DyF.mjs → save-ax11Gsw0.mjs} +7 -7
- package/dist/{save-DgPf1DyF.mjs.map → save-ax11Gsw0.mjs.map} +1 -1
- package/dist/schema.mjs +1 -1
- package/dist/{serialize-BC2Wu3bR.mjs → serialize-Dmb6Vtt9.mjs} +23 -6
- package/dist/serialize-Dmb6Vtt9.mjs.map +1 -0
- package/dist/{serializer-C6nm0mRJ.mjs → serializer-dhv07Z6F.mjs} +2 -2
- package/dist/{serializer-C6nm0mRJ.mjs.map → serializer-dhv07Z6F.mjs.map} +1 -1
- package/dist/streaming/string-table.d.ts +7 -0
- package/dist/streaming.mjs +189 -83
- package/dist/streaming.mjs.map +1 -1
- package/dist/styles.mjs +3 -3
- package/dist/{stylesheet-writer-TxsinwbO.mjs → stylesheet-writer-BBYjNSMA.mjs} +201 -118
- package/dist/stylesheet-writer-BBYjNSMA.mjs.map +1 -0
- package/dist/{table-BrP0RwUd.mjs → table-BFi2WmgG.mjs} +2 -2
- package/dist/{table-BrP0RwUd.mjs.map → table-BFi2WmgG.mjs.map} +1 -1
- package/dist/utils/cell-number.d.ts +10 -0
- package/dist/utils/coordinate.d.ts +11 -0
- package/dist/utils/escape.d.ts +17 -0
- package/dist/utils/xsd-boolean.d.ts +9 -0
- package/dist/utils.mjs +2 -2
- package/dist/workbook/shared-strings.d.ts +2 -0
- package/dist/{workbook-DQCslHzY.mjs → workbook-CMel6UcI.mjs} +13 -12
- package/dist/workbook-CMel6UcI.mjs.map +1 -0
- package/dist/workbook.mjs +2 -2
- package/dist/worksheet/writer.d.ts +9 -5
- package/dist/{worksheet-B2NOQ6dM.mjs → worksheet-Cxn2c-jz.mjs} +3 -3
- package/dist/{worksheet-B2NOQ6dM.mjs.map → worksheet-Cxn2c-jz.mjs.map} +1 -1
- package/dist/worksheet.mjs +2 -2
- package/dist/xml.mjs +2 -2
- package/dist/zip.mjs +1 -1
- package/package.json +1 -1
- package/dist/cell-Df3cKRIl.mjs.map +0 -1
- package/dist/coordinate-Bt5Gni2I.mjs.map +0 -1
- package/dist/escape-rnWSPpWY.mjs.map +0 -1
- package/dist/reader-DHMxLBQV.mjs.map +0 -1
- package/dist/serialize-BC2Wu3bR.mjs.map +0 -1
- package/dist/stylesheet-writer-TxsinwbO.mjs.map +0 -1
- package/dist/workbook-DQCslHzY.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-pLmx7KYh.mjs","names":[],"sources":["../src/packaging/relationships.ts","../src/packaging/core.ts","../src/packaging/custom.ts","../src/packaging/extended.ts","../src/packaging/manifest.ts"],"sourcesContent":["// `*.rels` files — Open Packaging Conventions relationship lists.\n//\n// Mirrors openpyxl/openpyxl/packaging/relationship.py. Relationship Ids\n// (`rId{N}`) auto-increment using the smallest unused integer so the list stays\n// deterministic even when callers mix in pre-assigned ids.\n\nimport { defineSchema, type Schema } from '../schema/core.js';\nimport { fromTree, toTree } from '../schema/serialize.js';\nimport { PKG_REL_NS } from '../xml/namespaces.js';\nimport { parseXml } from '../xml/parser.js';\nimport { serializeXml } from '../xml/serializer.js';\n\nexport interface Relationship {\n /** rIdN identifier; unique within the parent .rels file. */\n id: string;\n /** Full relationship type URI. */\n type: string;\n /** Target — relative part path or absolute URL when targetMode === 'External'. */\n target: string;\n /** Defaults to internal. */\n targetMode?: 'External' | 'Internal';\n}\n\nexport interface Relationships {\n rels: Relationship[];\n}\n\nconst RelationshipSchema = defineSchema<Relationship>({\n tagname: 'Relationship',\n xmlNs: PKG_REL_NS,\n attrs: {\n id: { kind: 'string', xmlName: 'Id' },\n type: { kind: 'string', xmlName: 'Type' },\n target: { kind: 'string', xmlName: 'Target' },\n targetMode: {\n kind: 'enum',\n values: ['External', 'Internal'],\n xmlName: 'TargetMode',\n optional: true,\n },\n },\n elements: [],\n});\n\nconst RelationshipsSchema: Schema<Relationships> = defineSchema<Relationships>({\n tagname: 'Relationships',\n xmlNs: PKG_REL_NS,\n attrs: {},\n elements: [\n {\n kind: 'sequence',\n key: 'rels',\n itemName: 'Relationship',\n itemNs: PKG_REL_NS,\n itemSchema: () => RelationshipSchema,\n },\n ],\n});\n\nexport function makeRelationships(): Relationships {\n return { rels: [] };\n}\n\nconst RID_RE = /^rId(\\d+)$/;\n\nconst allocateNextId = (rels: Relationships): string => {\n // Smallest positive integer not yet used as `rId{N}`. Linear scan is fine\n // because rels lists are small (tens of entries in real workbooks).\n const used = new Set<number>();\n for (const r of rels.rels) {\n const m = RID_RE.exec(r.id);\n if (m !== null) {\n const n = Number.parseInt(m[1] ?? '0', 10);\n if (Number.isFinite(n) && n > 0) used.add(n);\n }\n }\n let n = 1;\n while (used.has(n)) n++;\n return `rId${n}`;\n};\n\n/**\n * Append a relationship and return the resulting object. Auto-assigns the next\n * free `rId{N}` Id.\n */\nexport function appendRel(rels: Relationships, type: string, target: string, targetMode?: 'External'): Relationship {\n const next: Relationship = { id: allocateNextId(rels), type, target };\n if (targetMode !== undefined) next.targetMode = targetMode;\n rels.rels.push(next);\n return next;\n}\n\nexport function findById(rels: Relationships, id: string): Relationship | undefined {\n for (const r of rels.rels) if (r.id === id) return r;\n return undefined;\n}\n\n/**\n * Build an id → relationship index for callers that look up the same .rels\n * file many times in a hot loop. Cheaper than repeated {@link findById} once\n * the rels count crosses a handful of entries.\n */\nexport function indexRelsById(rels: Relationships): Map<string, Relationship> {\n const out = new Map<string, Relationship>();\n for (const r of rels.rels) out.set(r.id, r);\n return out;\n}\n\nexport function findByType(rels: Relationships, type: string): Relationship | undefined {\n for (const r of rels.rels) if (r.type === type) return r;\n return undefined;\n}\n\nexport function findAllByType(rels: Relationships, type: string): Relationship[] {\n const out: Relationship[] = [];\n for (const r of rels.rels) if (r.type === type) out.push(r);\n return out;\n}\n\nexport function relsToBytes(rels: Relationships): Uint8Array {\n return serializeXml(toTree(rels, RelationshipsSchema));\n}\n\nexport function relsFromBytes(bytes: Uint8Array | string): Relationships {\n return fromTree(parseXml(bytes), RelationshipsSchema);\n}\n","// `docProps/core.xml` — Dublin Core / Office core document properties.\n//\n// Each property lives in its own namespace (cp / dc / dcterms). The dcterms\n// timestamps carry an `xsi:type=\"dcterms:W3CDTF\"` marker which we reproduce as\n// a fixed attr on those text elements via the schema layer's `text` element\n// kind.\n\nimport { defineSchema, type Schema } from '../schema/core.js';\nimport { fromTree, toTree } from '../schema/serialize.js';\nimport { COREPROPS_NS, DCORE_NS, DCTERMS_NS, XSI_NS } from '../xml/namespaces.js';\nimport { parseXml } from '../xml/parser.js';\nimport { serializeXml } from '../xml/serializer.js';\n\n/**\n * Set of properties exposed under `docProps/core.xml`. All fields are optional;\n * the workbook only emits those that are set. Timestamps are stored as ISO-8601\n * strings (the W3CDTF subset) — no Date conversion happens at this layer;\n * phase-3 saveWorkbook is responsible for stamping `modified` to `now()` on\n * each save.\n */\nexport interface CoreProperties {\n category?: string;\n contentStatus?: string;\n /** ISO-8601 W3CDTF; auto-stamped on save in phase 3. */\n created?: string;\n creator?: string;\n description?: string;\n identifier?: string;\n keywords?: string;\n language?: string;\n lastModifiedBy?: string;\n /** ISO-8601 W3CDTF. */\n lastPrinted?: string;\n /** ISO-8601 W3CDTF; auto-stamped on save in phase 3. */\n modified?: string;\n revision?: string;\n subject?: string;\n title?: string;\n version?: string;\n}\n\nconst W3CDTF_ATTRS: Record<string, string> = {\n [`{${XSI_NS}}type`]: 'dcterms:W3CDTF',\n};\n\nconst CorePropertiesSchema: Schema<CoreProperties> = defineSchema<CoreProperties>({\n tagname: 'coreProperties',\n xmlNs: COREPROPS_NS,\n attrs: {},\n elements: [\n // openpyxl's child-namespace assignment, mirrored exactly:\n { kind: 'text', key: 'category', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'contentStatus', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'keywords', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'lastModifiedBy', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n {\n kind: 'text',\n key: 'lastPrinted',\n xmlNs: DCTERMS_NS,\n primitive: 'string',\n optional: true,\n attrs: W3CDTF_ATTRS,\n },\n { kind: 'text', key: 'revision', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'version', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'description', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'identifier', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'language', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'subject', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'title', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'creator', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n {\n kind: 'text',\n key: 'created',\n xmlNs: DCTERMS_NS,\n primitive: 'string',\n optional: true,\n attrs: W3CDTF_ATTRS,\n },\n {\n kind: 'text',\n key: 'modified',\n xmlNs: DCTERMS_NS,\n primitive: 'string',\n optional: true,\n attrs: W3CDTF_ATTRS,\n },\n ],\n});\n\nexport function makeCoreProperties(): CoreProperties {\n return {};\n}\n\nexport function corePropsToBytes(p: CoreProperties): Uint8Array {\n return serializeXml(toTree(p, CorePropertiesSchema));\n}\n\nexport function corePropsFromBytes(bytes: Uint8Array | string): CoreProperties {\n return fromTree(parseXml(bytes), CorePropertiesSchema);\n}\n\n// ---- Workbook ergonomic helpers ----------------------------------------\n\nimport type { Workbook } from '../workbook/workbook.js';\n\nconst ensureCoreProperties = (wb: Workbook): CoreProperties => {\n if (!wb.properties) wb.properties = {};\n return wb.properties;\n};\n\n/** Set the document author (Excel \"File → Properties → Author\"). */\nexport const setWorkbookCreator = (wb: Workbook, creator: string): void => {\n ensureCoreProperties(wb).creator = creator;\n};\n\n/** Set the document title. */\nexport const setWorkbookTitle = (wb: Workbook, title: string): void => {\n ensureCoreProperties(wb).title = title;\n};\n\n/** Set the document subject. */\nexport const setWorkbookSubject = (wb: Workbook, subject: string): void => {\n ensureCoreProperties(wb).subject = subject;\n};\n\n/** Set the document description / abstract. */\nexport const setWorkbookDescription = (wb: Workbook, description: string): void => {\n ensureCoreProperties(wb).description = description;\n};\n\n/** Set comma- or semicolon-separated keywords. */\nexport const setWorkbookKeywords = (wb: Workbook, keywords: string): void => {\n ensureCoreProperties(wb).keywords = keywords;\n};\n\n/** Set the \"last modified by\" name (defaults to creator if absent). */\nexport const setWorkbookLastModifiedBy = (wb: Workbook, name: string): void => {\n ensureCoreProperties(wb).lastModifiedBy = name;\n};\n\n/** Set the document category (e.g. \"Reports\", \"Drafts\"). */\nexport const setWorkbookCategory = (wb: Workbook, category: string): void => {\n ensureCoreProperties(wb).category = category;\n};\n","// `docProps/custom.xml` — user-defined document properties. Each <property>\n// carries fmtid/pid/name attributes plus a single typed value child from the\n// vt: namespace (vt:lpwstr, vt:i4, vt:bool, …).\n//\n// The Schema layer drives the <property> element attribute set; the typed-value\n// child is stored as a raw XmlNode and the `make*Value` / `read*Value` helpers\n// below cover the most common conversions.\n\nimport { OpenXmlSchemaError } from '../utils/exceptions.js';\nimport { CPROPS_FMTID, CUSTPROPS_NS, parseQName, VTYPES_NS } from '../xml/namespaces.js';\nimport { parseXml } from '../xml/parser.js';\nimport { serializeXml } from '../xml/serializer.js';\nimport { el, type XmlNode } from '../xml/tree.js';\n\nexport interface CustomProperty {\n /** User-visible property name (must be unique within the workbook). */\n name: string;\n /** OOXML \"Property Identifier\"; ≥ 2. Auto-allocated if absent on append. */\n pid: number;\n /** Format ID GUID. Defaults to the well-known {D5CDD505-…} on append. */\n fmtid?: string;\n /** Typed value as a raw vt: element. Use the `make*Value` helpers. */\n value: XmlNode;\n}\n\nexport interface CustomProperties {\n properties: CustomProperty[];\n}\n\nexport function makeCustomProperties(): CustomProperties {\n return { properties: [] };\n}\n\nconst PROPERTY_NAME = `{${CUSTPROPS_NS}}property`;\nconst PROPERTIES_NAME = `{${CUSTPROPS_NS}}Properties`;\n\n// ---- typed-value constructors ----------------------------------------------\n\nconst vt = (local: string, text: string): XmlNode => el(`{${VTYPES_NS}}${local}`, {}, [], text);\n\nexport function makeStringValue(s: string): XmlNode {\n return vt('lpwstr', s);\n}\nexport function makeAsciiStringValue(s: string): XmlNode {\n return vt('lpstr', s);\n}\nexport function makeIntValue(n: number): XmlNode {\n if (!Number.isInteger(n)) throw new OpenXmlSchemaError(`makeIntValue: ${n} is not an integer`);\n return vt('i4', String(n));\n}\nexport function makeDoubleValue(n: number): XmlNode {\n if (!Number.isFinite(n)) throw new OpenXmlSchemaError(`makeDoubleValue: ${n} is not finite`);\n return vt('r8', String(n));\n}\nexport function makeBoolValue(b: boolean): XmlNode {\n return vt('bool', b ? '1' : '0');\n}\nexport function makeFiletimeValue(iso: string): XmlNode {\n return vt('filetime', iso);\n}\nexport function makeDateValue(iso: string): XmlNode {\n return vt('date', iso);\n}\n\n// ---- typed-value readers ---------------------------------------------------\n\nconst localNameOf = (n: XmlNode): string => parseQName(n.name).local;\n\nexport function readStringValue(v: XmlNode): string | undefined {\n const ln = localNameOf(v);\n if (ln === 'lpwstr' || ln === 'lpstr' || ln === 'bstr') return v.text ?? '';\n return undefined;\n}\nexport function readIntValue(v: XmlNode): number | undefined {\n const ln = localNameOf(v);\n if (\n ln === 'i4' ||\n ln === 'i2' ||\n ln === 'i1' ||\n ln === 'int' ||\n ln === 'uint' ||\n ln === 'ui4' ||\n ln === 'ui2' ||\n ln === 'ui1'\n ) {\n const n = Number.parseInt(v.text ?? '', 10);\n return Number.isFinite(n) ? n : undefined;\n }\n return undefined;\n}\nexport function readDoubleValue(v: XmlNode): number | undefined {\n const ln = localNameOf(v);\n if (ln === 'r4' || ln === 'r8' || ln === 'decimal' || ln === 'cy') {\n const n = Number.parseFloat(v.text ?? '');\n return Number.isFinite(n) ? n : undefined;\n }\n return undefined;\n}\nexport function readBoolValue(v: XmlNode): boolean | undefined {\n if (localNameOf(v) !== 'bool') return undefined;\n const t = (v.text ?? '').toLowerCase();\n if (t === '1' || t === 'true' || t === 't') return true;\n if (t === '0' || t === 'false' || t === 'f') return false;\n return undefined;\n}\nexport function readFiletimeValue(v: XmlNode): string | undefined {\n if (localNameOf(v) === 'filetime') return v.text ?? '';\n return undefined;\n}\n\n// ---- collection ops --------------------------------------------------------\n\nconst allocatePid = (props: CustomProperties): number => {\n // pid 0 / 1 are reserved by the OPC spec; user pids start at 2.\n const used = new Set<number>();\n for (const p of props.properties) used.add(p.pid);\n let n = 2;\n while (used.has(n)) n++;\n return n;\n};\n\nexport function appendCustomProperty(\n props: CustomProperties,\n name: string,\n value: XmlNode,\n opts?: { pid?: number; fmtid?: string },\n): CustomProperty {\n const pid = opts?.pid ?? allocatePid(props);\n const out: CustomProperty = { name, pid, value };\n if (opts?.fmtid !== undefined) out.fmtid = opts.fmtid;\n props.properties.push(out);\n return out;\n}\n\nexport function findCustomPropertyByName(props: CustomProperties, name: string): CustomProperty | undefined {\n for (const p of props.properties) if (p.name === name) return p;\n return undefined;\n}\n\n// ---- bytes round-trip ------------------------------------------------------\n\nexport function customPropsToBytes(p: CustomProperties): Uint8Array {\n const root = el(PROPERTIES_NAME);\n for (const prop of p.properties) {\n const propEl = el(PROPERTY_NAME, {\n fmtid: prop.fmtid ?? CPROPS_FMTID,\n pid: String(prop.pid),\n name: prop.name,\n });\n propEl.children.push(prop.value);\n root.children.push(propEl);\n }\n return serializeXml(root);\n}\n\nexport function customPropsFromBytes(bytes: Uint8Array | string): CustomProperties {\n const root = parseXml(bytes);\n if (root.name !== PROPERTIES_NAME) {\n throw new OpenXmlSchemaError(`customPropsFromBytes: expected <Properties>, got \"${root.name}\"`);\n }\n const properties: CustomProperty[] = [];\n for (const propEl of root.children) {\n if (propEl.name !== PROPERTY_NAME) continue;\n const fmtid = propEl.attrs['fmtid'];\n const pidRaw = propEl.attrs['pid'];\n const name = propEl.attrs['name'];\n if (name === undefined || pidRaw === undefined) {\n throw new OpenXmlSchemaError('custom.xml: <property> requires name and pid attributes');\n }\n const pid = Number.parseInt(pidRaw, 10);\n if (!Number.isFinite(pid)) {\n throw new OpenXmlSchemaError(`custom.xml: <property> pid is not an integer (got \"${pidRaw}\")`);\n }\n const value = propEl.children[0];\n if (value === undefined) {\n throw new OpenXmlSchemaError(`custom.xml: <property name=\"${name}\"> has no typed-value child`);\n }\n const out: CustomProperty = { name, pid, value };\n if (fmtid !== undefined) out.fmtid = fmtid;\n properties.push(out);\n }\n return { properties };\n}\n\n// ---- Workbook ergonomic helpers ----------------------------------------\n\nimport type { Workbook } from '../workbook/workbook.js';\n\nconst ensureCustomProperties = (wb: Workbook): CustomProperties => {\n if (!wb.customProperties) wb.customProperties = makeCustomProperties();\n return wb.customProperties;\n};\n\nconst replaceOrAppend = (\n wb: Workbook,\n name: string,\n value: XmlNode,\n opts?: { fmtid?: string },\n): CustomProperty => {\n const props = ensureCustomProperties(wb);\n const existing = findCustomPropertyByName(props, name);\n if (existing) {\n existing.value = value;\n if (opts?.fmtid !== undefined) existing.fmtid = opts.fmtid;\n return existing;\n }\n return appendCustomProperty(props, name, value, opts);\n};\n\n/** Set (or replace) a custom string property. */\nexport const setCustomStringProperty = (wb: Workbook, name: string, value: string): CustomProperty =>\n replaceOrAppend(wb, name, makeStringValue(value));\n\n/**\n * Set (or replace) a custom numeric property. Integers (within Int32 range) are\n * stored as `vt:i4`; non-integer / out-of-range numbers as `vt:r8` doubles.\n */\nexport const setCustomNumberProperty = (wb: Workbook, name: string, value: number): CustomProperty => {\n if (!Number.isFinite(value)) {\n throw new OpenXmlSchemaError(`setCustomNumberProperty: value \"${value}\" is not finite`);\n }\n const isInt32 = Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;\n const node = isInt32 ? makeIntValue(value) : makeDoubleValue(value);\n return replaceOrAppend(wb, name, node);\n};\n\n/** Set (or replace) a custom boolean property. */\nexport const setCustomBoolProperty = (wb: Workbook, name: string, value: boolean): CustomProperty =>\n replaceOrAppend(wb, name, makeBoolValue(value));\n\n/**\n * Set (or replace) a custom date property. Accepts a `Date` (converted to ISO\n * via `toISOString()`) or a pre-formatted W3C-DTF string.\n */\nexport const setCustomDateProperty = (\n wb: Workbook,\n name: string,\n value: Date | string,\n): CustomProperty => {\n const iso = value instanceof Date ? value.toISOString() : value;\n return replaceOrAppend(wb, name, makeFiletimeValue(iso));\n};\n\n/**\n * Read the typed value of a custom property by name. Tries each decoder in turn\n * — string, int, double, bool, filetime — and returns the first hit. Returns\n * `undefined` for unknown names or unsupported types.\n */\nexport const getCustomPropertyValue = (\n wb: Workbook,\n name: string,\n): string | number | boolean | undefined => {\n if (!wb.customProperties) return undefined;\n const prop = findCustomPropertyByName(wb.customProperties, name);\n if (!prop) return undefined;\n const s = readStringValue(prop.value);\n if (s !== undefined) return s;\n const i = readIntValue(prop.value);\n if (i !== undefined) return i;\n const d = readDoubleValue(prop.value);\n if (d !== undefined) return d;\n const b = readBoolValue(prop.value);\n if (b !== undefined) return b;\n const ft = readFiletimeValue(prop.value);\n if (ft !== undefined) return ft;\n return undefined;\n};\n\n/**\n * Remove a custom property by name. Returns `true` when one was removed,\n * `false` when the name wasn't found.\n */\nexport const removeCustomProperty = (wb: Workbook, name: string): boolean => {\n if (!wb.customProperties) return false;\n const arr = wb.customProperties.properties;\n const i = arr.findIndex((p) => p.name === name);\n if (i < 0) return false;\n arr.splice(i, 1);\n return true;\n};\n\n/** Read-only snapshot of every custom property. */\nexport const listCustomProperties = (wb: Workbook): ReadonlyArray<CustomProperty> => {\n return wb.customProperties?.properties ?? [];\n};\n","// `docProps/app.xml` — Office \"extended\" document properties.\n//\n// Mirrors openpyxl/openpyxl/packaging/extended.py. Most fields are flat (text\n// or numeric). The four vector-shaped children — HeadingPairs, TitlesOfParts,\n// HLinks, DigSig — are kept as raw XmlNode subtrees and round-tripped verbatim;\n// modelling vt:vector explicitly is a phase-3 concern at the earliest. See row\n// for `packaging/extended.py`.\n\nimport { defineSchema, type Schema } from '../schema/core.js';\nimport { fromTree, toTree } from '../schema/serialize.js';\nimport { XPROPS_NS } from '../xml/namespaces.js';\nimport { parseXml } from '../xml/parser.js';\nimport { serializeXml } from '../xml/serializer.js';\nimport type { XmlNode } from '../xml/tree.js';\n\nexport interface ExtendedProperties {\n application?: string;\n appVersion?: string;\n characters?: number;\n charactersWithSpaces?: number;\n company?: string;\n digitalSignature?: XmlNode;\n docSecurity?: number;\n hLinks?: XmlNode;\n headingPairs?: XmlNode;\n hiddenSlides?: number;\n hyperlinkBase?: string;\n hyperlinks?: XmlNode;\n hyperlinksChanged?: boolean;\n lines?: number;\n linksUpToDate?: boolean;\n manager?: string;\n mmClips?: number;\n notes?: number;\n pages?: number;\n paragraphs?: number;\n presentationFormat?: string;\n scaleCrop?: boolean;\n sharedDoc?: boolean;\n slides?: number;\n template?: string;\n titlesOfParts?: XmlNode;\n totalTime?: number;\n words?: number;\n}\n\nconst ExtendedSchema: Schema<ExtendedProperties> = defineSchema<ExtendedProperties>({\n tagname: 'Properties',\n xmlNs: XPROPS_NS,\n attrs: {},\n // Element order chosen to match the Office output convention.\n elements: [\n { kind: 'text', key: 'template', xmlNs: XPROPS_NS, name: 'Template', primitive: 'string', optional: true },\n { kind: 'text', key: 'manager', xmlNs: XPROPS_NS, name: 'Manager', primitive: 'string', optional: true },\n { kind: 'text', key: 'company', xmlNs: XPROPS_NS, name: 'Company', primitive: 'string', optional: true },\n { kind: 'text', key: 'pages', xmlNs: XPROPS_NS, name: 'Pages', primitive: 'int', optional: true },\n { kind: 'text', key: 'words', xmlNs: XPROPS_NS, name: 'Words', primitive: 'int', optional: true },\n { kind: 'text', key: 'characters', xmlNs: XPROPS_NS, name: 'Characters', primitive: 'int', optional: true },\n {\n kind: 'text',\n key: 'presentationFormat',\n xmlNs: XPROPS_NS,\n name: 'PresentationFormat',\n primitive: 'string',\n optional: true,\n },\n { kind: 'text', key: 'lines', xmlNs: XPROPS_NS, name: 'Lines', primitive: 'int', optional: true },\n { kind: 'text', key: 'paragraphs', xmlNs: XPROPS_NS, name: 'Paragraphs', primitive: 'int', optional: true },\n { kind: 'text', key: 'slides', xmlNs: XPROPS_NS, name: 'Slides', primitive: 'int', optional: true },\n { kind: 'text', key: 'notes', xmlNs: XPROPS_NS, name: 'Notes', primitive: 'int', optional: true },\n { kind: 'text', key: 'totalTime', xmlNs: XPROPS_NS, name: 'TotalTime', primitive: 'int', optional: true },\n { kind: 'text', key: 'hiddenSlides', xmlNs: XPROPS_NS, name: 'HiddenSlides', primitive: 'int', optional: true },\n { kind: 'text', key: 'mmClips', xmlNs: XPROPS_NS, name: 'MMClips', primitive: 'int', optional: true },\n { kind: 'text', key: 'scaleCrop', xmlNs: XPROPS_NS, name: 'ScaleCrop', primitive: 'bool', optional: true },\n { kind: 'raw', key: 'headingPairs', xmlNs: XPROPS_NS, name: 'HeadingPairs', optional: true },\n { kind: 'raw', key: 'titlesOfParts', xmlNs: XPROPS_NS, name: 'TitlesOfParts', optional: true },\n { kind: 'raw', key: 'hLinks', xmlNs: XPROPS_NS, name: 'HLinks', optional: true },\n { kind: 'raw', key: 'hyperlinks', xmlNs: XPROPS_NS, name: 'Hyperlinks', optional: true },\n { kind: 'text', key: 'linksUpToDate', xmlNs: XPROPS_NS, name: 'LinksUpToDate', primitive: 'bool', optional: true },\n { kind: 'text', key: 'sharedDoc', xmlNs: XPROPS_NS, name: 'SharedDoc', primitive: 'bool', optional: true },\n {\n kind: 'text',\n key: 'hyperlinkBase',\n xmlNs: XPROPS_NS,\n name: 'HyperlinkBase',\n primitive: 'string',\n optional: true,\n },\n {\n kind: 'text',\n key: 'hyperlinksChanged',\n xmlNs: XPROPS_NS,\n name: 'HyperlinksChanged',\n primitive: 'bool',\n optional: true,\n },\n { kind: 'raw', key: 'digitalSignature', xmlNs: XPROPS_NS, name: 'DigSig', optional: true },\n { kind: 'text', key: 'application', xmlNs: XPROPS_NS, name: 'Application', primitive: 'string', optional: true },\n { kind: 'text', key: 'appVersion', xmlNs: XPROPS_NS, name: 'AppVersion', primitive: 'string', optional: true },\n { kind: 'text', key: 'docSecurity', xmlNs: XPROPS_NS, name: 'DocSecurity', primitive: 'int', optional: true },\n {\n kind: 'text',\n key: 'charactersWithSpaces',\n xmlNs: XPROPS_NS,\n name: 'CharactersWithSpaces',\n primitive: 'int',\n optional: true,\n },\n ],\n});\n\nexport function makeExtendedProperties(): ExtendedProperties {\n return {};\n}\n\nexport function extendedPropsToBytes(p: ExtendedProperties): Uint8Array {\n return serializeXml(toTree(p, ExtendedSchema));\n}\n\nexport function extendedPropsFromBytes(bytes: Uint8Array | string): ExtendedProperties {\n return fromTree(parseXml(bytes), ExtendedSchema);\n}\n\n// ---- Workbook ergonomic helpers ----------------------------------------\n\nimport type { Workbook } from '../workbook/workbook.js';\n\nconst ensureAppProperties = (wb: Workbook): ExtendedProperties => {\n if (!wb.appProperties) wb.appProperties = {};\n return wb.appProperties;\n};\n\n/** Set the company name on docProps/app.xml. */\nexport const setWorkbookCompany = (wb: Workbook, company: string): void => {\n ensureAppProperties(wb).company = company;\n};\n\n/** Set the manager / supervisor name on docProps/app.xml. */\nexport const setWorkbookManager = (wb: Workbook, manager: string): void => {\n ensureAppProperties(wb).manager = manager;\n};\n\n/** Set the application name (e.g. `\"Microsoft Excel\"`). */\nexport const setWorkbookApplication = (wb: Workbook, application: string): void => {\n ensureAppProperties(wb).application = application;\n};\n\n/** Set the application version (typically `\"16.0300\"` for Excel 365). */\nexport const setWorkbookAppVersion = (wb: Workbook, version: string): void => {\n ensureAppProperties(wb).appVersion = version;\n};\n\n/** Set the hyperlink base URL — Excel uses this as a prefix for relative `&F` codes. */\nexport const setWorkbookHyperlinkBase = (wb: Workbook, base: string): void => {\n ensureAppProperties(wb).hyperlinkBase = base;\n};\n","// [Content_Types].xml — the package manifest. Tracks default content types per\n// file extension and per-part Override entries.\n\nimport { defineSchema, type Schema } from '../schema/core.js';\nimport { fromTree, toTree } from '../schema/serialize.js';\nimport { CONTYPES_NS } from '../xml/namespaces.js';\nimport { parseXml } from '../xml/parser.js';\nimport { serializeXml } from '../xml/serializer.js';\n\nexport interface DefaultEntry {\n /** File extension without leading dot (e.g. \"rels\", \"xml\", \"png\"). */\n ext: string;\n contentType: string;\n}\n\nexport interface OverrideEntry {\n /** Part name path including leading slash (e.g. \"/xl/workbook.xml\"). */\n partName: string;\n contentType: string;\n}\n\nexport interface Manifest {\n defaults: DefaultEntry[];\n overrides: OverrideEntry[];\n}\n\nconst DefaultSchema = defineSchema<DefaultEntry>({\n tagname: 'Default',\n xmlNs: CONTYPES_NS,\n attrs: {\n ext: { kind: 'string', xmlName: 'Extension' },\n contentType: { kind: 'string', xmlName: 'ContentType' },\n },\n elements: [],\n});\n\nconst OverrideSchema = defineSchema<OverrideEntry>({\n tagname: 'Override',\n xmlNs: CONTYPES_NS,\n attrs: {\n partName: { kind: 'string', xmlName: 'PartName' },\n contentType: { kind: 'string', xmlName: 'ContentType' },\n },\n elements: [],\n});\n\nconst ManifestSchema: Schema<Manifest> = defineSchema<Manifest>({\n tagname: 'Types',\n xmlNs: CONTYPES_NS,\n attrs: {},\n elements: [\n {\n kind: 'sequence',\n key: 'defaults',\n itemName: 'Default',\n itemNs: CONTYPES_NS,\n itemSchema: () => DefaultSchema,\n },\n {\n kind: 'sequence',\n key: 'overrides',\n itemName: 'Override',\n itemNs: CONTYPES_NS,\n itemSchema: () => OverrideSchema,\n },\n ],\n});\n\nexport function makeManifest(): Manifest {\n return { defaults: [], overrides: [] };\n}\n\n/** Register a default content type for an extension. Idempotent. */\nexport function addDefault(m: Manifest, ext: string, contentType: string): void {\n for (const d of m.defaults) {\n if (d.ext === ext) {\n if (d.contentType !== contentType) {\n d.contentType = contentType; // newer wins; matches openpyxl behaviour\n }\n return;\n }\n }\n m.defaults.push({ ext, contentType });\n}\n\n/** Register an Override for a specific part. Idempotent. */\nexport function addOverride(m: Manifest, partName: string, contentType: string): void {\n for (const o of m.overrides) {\n if (o.partName === partName) {\n if (o.contentType !== contentType) o.contentType = contentType;\n return;\n }\n }\n m.overrides.push({ partName, contentType });\n}\n\nexport function findOverride(m: Manifest, partName: string): OverrideEntry | undefined {\n for (const o of m.overrides) if (o.partName === partName) return o;\n return undefined;\n}\n\n/** Find the first Override matching a content type. */\nexport function findOverrideByContentType(m: Manifest, contentType: string): OverrideEntry | undefined {\n for (const o of m.overrides) if (o.contentType === contentType) return o;\n return undefined;\n}\n\nexport function manifestToBytes(m: Manifest): Uint8Array {\n return serializeXml(toTree(m, ManifestSchema));\n}\n\nexport function manifestFromBytes(bytes: Uint8Array | string): Manifest {\n return fromTree(parseXml(bytes), ManifestSchema);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"manifest-BHUYpjUG.mjs","names":[],"sources":["../src/packaging/relationships.ts","../src/packaging/core.ts","../src/packaging/custom.ts","../src/packaging/extended.ts","../src/packaging/manifest.ts"],"sourcesContent":["// `*.rels` files — Open Packaging Conventions relationship lists.\n//\n// Mirrors openpyxl/openpyxl/packaging/relationship.py. Relationship Ids\n// (`rId{N}`) auto-increment using the smallest unused integer so the list stays\n// deterministic even when callers mix in pre-assigned ids.\n\nimport { defineSchema, type Schema } from '../schema/core.js';\nimport { fromTree, toTree } from '../schema/serialize.js';\nimport { PKG_REL_NS } from '../xml/namespaces.js';\nimport { parseXml } from '../xml/parser.js';\nimport { serializeXml } from '../xml/serializer.js';\n\nexport interface Relationship {\n /** rIdN identifier; unique within the parent .rels file. */\n id: string;\n /** Full relationship type URI. */\n type: string;\n /** Target — relative part path or absolute URL when targetMode === 'External'. */\n target: string;\n /** Defaults to internal. */\n targetMode?: 'External' | 'Internal';\n}\n\nexport interface Relationships {\n rels: Relationship[];\n}\n\nconst RelationshipSchema = defineSchema<Relationship>({\n tagname: 'Relationship',\n xmlNs: PKG_REL_NS,\n attrs: {\n id: { kind: 'string', xmlName: 'Id' },\n type: { kind: 'string', xmlName: 'Type' },\n target: { kind: 'string', xmlName: 'Target' },\n targetMode: {\n kind: 'enum',\n values: ['External', 'Internal'],\n xmlName: 'TargetMode',\n optional: true,\n },\n },\n elements: [],\n});\n\nconst RelationshipsSchema: Schema<Relationships> = defineSchema<Relationships>({\n tagname: 'Relationships',\n xmlNs: PKG_REL_NS,\n attrs: {},\n elements: [\n {\n kind: 'sequence',\n key: 'rels',\n itemName: 'Relationship',\n itemNs: PKG_REL_NS,\n itemSchema: () => RelationshipSchema,\n },\n ],\n});\n\nexport function makeRelationships(): Relationships {\n return { rels: [] };\n}\n\nconst RID_RE = /^rId(\\d+)$/;\n\nconst allocateNextId = (rels: Relationships): string => {\n // Smallest positive integer not yet used as `rId{N}`. Linear scan is fine\n // because rels lists are small (tens of entries in real workbooks).\n const used = new Set<number>();\n for (const r of rels.rels) {\n const m = RID_RE.exec(r.id);\n if (m !== null) {\n const n = Number.parseInt(m[1] ?? '0', 10);\n if (Number.isFinite(n) && n > 0) used.add(n);\n }\n }\n let n = 1;\n while (used.has(n)) n++;\n return `rId${n}`;\n};\n\n/**\n * Append a relationship and return the resulting object. Auto-assigns the next\n * free `rId{N}` Id.\n */\nexport function appendRel(rels: Relationships, type: string, target: string, targetMode?: 'External'): Relationship {\n const next: Relationship = { id: allocateNextId(rels), type, target };\n if (targetMode !== undefined) next.targetMode = targetMode;\n rels.rels.push(next);\n return next;\n}\n\nexport function findById(rels: Relationships, id: string): Relationship | undefined {\n for (const r of rels.rels) if (r.id === id) return r;\n return undefined;\n}\n\n/**\n * Build an id → relationship index for callers that look up the same .rels\n * file many times in a hot loop. Cheaper than repeated {@link findById} once\n * the rels count crosses a handful of entries.\n */\nexport function indexRelsById(rels: Relationships): Map<string, Relationship> {\n const out = new Map<string, Relationship>();\n for (const r of rels.rels) out.set(r.id, r);\n return out;\n}\n\nexport function findByType(rels: Relationships, type: string): Relationship | undefined {\n for (const r of rels.rels) if (r.type === type) return r;\n return undefined;\n}\n\nexport function findAllByType(rels: Relationships, type: string): Relationship[] {\n const out: Relationship[] = [];\n for (const r of rels.rels) if (r.type === type) out.push(r);\n return out;\n}\n\nexport function relsToBytes(rels: Relationships): Uint8Array {\n return serializeXml(toTree(rels, RelationshipsSchema));\n}\n\nexport function relsFromBytes(bytes: Uint8Array | string): Relationships {\n return fromTree(parseXml(bytes), RelationshipsSchema);\n}\n","// `docProps/core.xml` — Dublin Core / Office core document properties.\n//\n// Each property lives in its own namespace (cp / dc / dcterms). The dcterms\n// timestamps carry an `xsi:type=\"dcterms:W3CDTF\"` marker which we reproduce as\n// a fixed attr on those text elements via the schema layer's `text` element\n// kind.\n\nimport { defineSchema, type Schema } from '../schema/core.js';\nimport { fromTree, toTree } from '../schema/serialize.js';\nimport { COREPROPS_NS, DCORE_NS, DCTERMS_NS, XSI_NS } from '../xml/namespaces.js';\nimport { parseXml } from '../xml/parser.js';\nimport { serializeXml } from '../xml/serializer.js';\n\n/**\n * Set of properties exposed under `docProps/core.xml`. All fields are optional;\n * the workbook only emits those that are set. Timestamps are stored as ISO-8601\n * strings (the W3CDTF subset) — no Date conversion happens at this layer;\n * phase-3 saveWorkbook is responsible for stamping `modified` to `now()` on\n * each save.\n */\nexport interface CoreProperties {\n category?: string;\n contentStatus?: string;\n /** ISO-8601 W3CDTF; auto-stamped on save in phase 3. */\n created?: string;\n creator?: string;\n description?: string;\n identifier?: string;\n keywords?: string;\n language?: string;\n lastModifiedBy?: string;\n /** ISO-8601 W3CDTF. */\n lastPrinted?: string;\n /** ISO-8601 W3CDTF; auto-stamped on save in phase 3. */\n modified?: string;\n revision?: string;\n subject?: string;\n title?: string;\n version?: string;\n}\n\nconst W3CDTF_ATTRS: Record<string, string> = {\n [`{${XSI_NS}}type`]: 'dcterms:W3CDTF',\n};\n\nconst CorePropertiesSchema: Schema<CoreProperties> = defineSchema<CoreProperties>({\n tagname: 'coreProperties',\n xmlNs: COREPROPS_NS,\n attrs: {},\n elements: [\n // openpyxl's child-namespace assignment, mirrored exactly:\n { kind: 'text', key: 'category', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'contentStatus', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'keywords', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'lastModifiedBy', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n {\n kind: 'text',\n key: 'lastPrinted',\n xmlNs: DCTERMS_NS,\n primitive: 'string',\n optional: true,\n attrs: W3CDTF_ATTRS,\n },\n { kind: 'text', key: 'revision', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'version', xmlNs: COREPROPS_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'description', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'identifier', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'language', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'subject', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'title', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n { kind: 'text', key: 'creator', xmlNs: DCORE_NS, primitive: 'string', optional: true },\n {\n kind: 'text',\n key: 'created',\n xmlNs: DCTERMS_NS,\n primitive: 'string',\n optional: true,\n attrs: W3CDTF_ATTRS,\n },\n {\n kind: 'text',\n key: 'modified',\n xmlNs: DCTERMS_NS,\n primitive: 'string',\n optional: true,\n attrs: W3CDTF_ATTRS,\n },\n ],\n});\n\nexport function makeCoreProperties(): CoreProperties {\n return {};\n}\n\nexport function corePropsToBytes(p: CoreProperties): Uint8Array {\n return serializeXml(toTree(p, CorePropertiesSchema));\n}\n\nexport function corePropsFromBytes(bytes: Uint8Array | string): CoreProperties {\n return fromTree(parseXml(bytes), CorePropertiesSchema);\n}\n\n// ---- Workbook ergonomic helpers ----------------------------------------\n\nimport type { Workbook } from '../workbook/workbook.js';\n\nconst ensureCoreProperties = (wb: Workbook): CoreProperties => {\n if (!wb.properties) wb.properties = {};\n return wb.properties;\n};\n\n/** Set the document author (Excel \"File → Properties → Author\"). */\nexport const setWorkbookCreator = (wb: Workbook, creator: string): void => {\n ensureCoreProperties(wb).creator = creator;\n};\n\n/** Set the document title. */\nexport const setWorkbookTitle = (wb: Workbook, title: string): void => {\n ensureCoreProperties(wb).title = title;\n};\n\n/** Set the document subject. */\nexport const setWorkbookSubject = (wb: Workbook, subject: string): void => {\n ensureCoreProperties(wb).subject = subject;\n};\n\n/** Set the document description / abstract. */\nexport const setWorkbookDescription = (wb: Workbook, description: string): void => {\n ensureCoreProperties(wb).description = description;\n};\n\n/** Set comma- or semicolon-separated keywords. */\nexport const setWorkbookKeywords = (wb: Workbook, keywords: string): void => {\n ensureCoreProperties(wb).keywords = keywords;\n};\n\n/** Set the \"last modified by\" name (defaults to creator if absent). */\nexport const setWorkbookLastModifiedBy = (wb: Workbook, name: string): void => {\n ensureCoreProperties(wb).lastModifiedBy = name;\n};\n\n/** Set the document category (e.g. \"Reports\", \"Drafts\"). */\nexport const setWorkbookCategory = (wb: Workbook, category: string): void => {\n ensureCoreProperties(wb).category = category;\n};\n","// `docProps/custom.xml` — user-defined document properties. Each <property>\n// carries fmtid/pid/name attributes plus a single typed value child from the\n// vt: namespace (vt:lpwstr, vt:i4, vt:bool, …).\n//\n// The Schema layer drives the <property> element attribute set; the typed-value\n// child is stored as a raw XmlNode and the `make*Value` / `read*Value` helpers\n// below cover the most common conversions.\n\nimport { OpenXmlSchemaError } from '../utils/exceptions.js';\nimport { CPROPS_FMTID, CUSTPROPS_NS, parseQName, VTYPES_NS } from '../xml/namespaces.js';\nimport { parseXml } from '../xml/parser.js';\nimport { serializeXml } from '../xml/serializer.js';\nimport { el, type XmlNode } from '../xml/tree.js';\n\nexport interface CustomProperty {\n /** User-visible property name (must be unique within the workbook). */\n name: string;\n /** OOXML \"Property Identifier\"; ≥ 2. Auto-allocated if absent on append. */\n pid: number;\n /** Format ID GUID. Defaults to the well-known {D5CDD505-…} on append. */\n fmtid?: string;\n /** Typed value as a raw vt: element. Use the `make*Value` helpers. */\n value: XmlNode;\n}\n\nexport interface CustomProperties {\n properties: CustomProperty[];\n}\n\nexport function makeCustomProperties(): CustomProperties {\n return { properties: [] };\n}\n\nconst PROPERTY_NAME = `{${CUSTPROPS_NS}}property`;\nconst PROPERTIES_NAME = `{${CUSTPROPS_NS}}Properties`;\n\n// ---- typed-value constructors ----------------------------------------------\n\nconst vt = (local: string, text: string): XmlNode => el(`{${VTYPES_NS}}${local}`, {}, [], text);\n\nexport function makeStringValue(s: string): XmlNode {\n return vt('lpwstr', s);\n}\nexport function makeAsciiStringValue(s: string): XmlNode {\n return vt('lpstr', s);\n}\nexport function makeIntValue(n: number): XmlNode {\n if (!Number.isInteger(n)) throw new OpenXmlSchemaError(`makeIntValue: ${n} is not an integer`);\n return vt('i4', String(n));\n}\nexport function makeDoubleValue(n: number): XmlNode {\n if (!Number.isFinite(n)) throw new OpenXmlSchemaError(`makeDoubleValue: ${n} is not finite`);\n return vt('r8', String(n));\n}\nexport function makeBoolValue(b: boolean): XmlNode {\n return vt('bool', b ? '1' : '0');\n}\nexport function makeFiletimeValue(iso: string): XmlNode {\n return vt('filetime', iso);\n}\nexport function makeDateValue(iso: string): XmlNode {\n return vt('date', iso);\n}\n\n// ---- typed-value readers ---------------------------------------------------\n\nconst localNameOf = (n: XmlNode): string => parseQName(n.name).local;\n\nexport function readStringValue(v: XmlNode): string | undefined {\n const ln = localNameOf(v);\n if (ln === 'lpwstr' || ln === 'lpstr' || ln === 'bstr') return v.text ?? '';\n return undefined;\n}\nexport function readIntValue(v: XmlNode): number | undefined {\n const ln = localNameOf(v);\n if (\n ln === 'i4' ||\n ln === 'i2' ||\n ln === 'i1' ||\n ln === 'int' ||\n ln === 'uint' ||\n ln === 'ui4' ||\n ln === 'ui2' ||\n ln === 'ui1'\n ) {\n const n = Number.parseInt(v.text ?? '', 10);\n return Number.isFinite(n) ? n : undefined;\n }\n return undefined;\n}\nexport function readDoubleValue(v: XmlNode): number | undefined {\n const ln = localNameOf(v);\n if (ln === 'r4' || ln === 'r8' || ln === 'decimal' || ln === 'cy') {\n const n = Number.parseFloat(v.text ?? '');\n return Number.isFinite(n) ? n : undefined;\n }\n return undefined;\n}\nexport function readBoolValue(v: XmlNode): boolean | undefined {\n if (localNameOf(v) !== 'bool') return undefined;\n const t = (v.text ?? '').toLowerCase();\n if (t === '1' || t === 'true' || t === 't') return true;\n if (t === '0' || t === 'false' || t === 'f') return false;\n return undefined;\n}\nexport function readFiletimeValue(v: XmlNode): string | undefined {\n if (localNameOf(v) === 'filetime') return v.text ?? '';\n return undefined;\n}\n\n// ---- collection ops --------------------------------------------------------\n\nconst allocatePid = (props: CustomProperties): number => {\n // pid 0 / 1 are reserved by the OPC spec; user pids start at 2.\n const used = new Set<number>();\n for (const p of props.properties) used.add(p.pid);\n let n = 2;\n while (used.has(n)) n++;\n return n;\n};\n\nexport function appendCustomProperty(\n props: CustomProperties,\n name: string,\n value: XmlNode,\n opts?: { pid?: number; fmtid?: string },\n): CustomProperty {\n const pid = opts?.pid ?? allocatePid(props);\n const out: CustomProperty = { name, pid, value };\n if (opts?.fmtid !== undefined) out.fmtid = opts.fmtid;\n props.properties.push(out);\n return out;\n}\n\nexport function findCustomPropertyByName(props: CustomProperties, name: string): CustomProperty | undefined {\n for (const p of props.properties) if (p.name === name) return p;\n return undefined;\n}\n\n// ---- bytes round-trip ------------------------------------------------------\n\nexport function customPropsToBytes(p: CustomProperties): Uint8Array {\n const root = el(PROPERTIES_NAME);\n for (const prop of p.properties) {\n const propEl = el(PROPERTY_NAME, {\n fmtid: prop.fmtid ?? CPROPS_FMTID,\n pid: String(prop.pid),\n name: prop.name,\n });\n propEl.children.push(prop.value);\n root.children.push(propEl);\n }\n return serializeXml(root);\n}\n\nexport function customPropsFromBytes(bytes: Uint8Array | string): CustomProperties {\n const root = parseXml(bytes);\n if (root.name !== PROPERTIES_NAME) {\n throw new OpenXmlSchemaError(`customPropsFromBytes: expected <Properties>, got \"${root.name}\"`);\n }\n const properties: CustomProperty[] = [];\n for (const propEl of root.children) {\n if (propEl.name !== PROPERTY_NAME) continue;\n const fmtid = propEl.attrs['fmtid'];\n const pidRaw = propEl.attrs['pid'];\n const name = propEl.attrs['name'];\n if (name === undefined || pidRaw === undefined) {\n throw new OpenXmlSchemaError('custom.xml: <property> requires name and pid attributes');\n }\n const pid = Number.parseInt(pidRaw, 10);\n if (!Number.isFinite(pid)) {\n throw new OpenXmlSchemaError(`custom.xml: <property> pid is not an integer (got \"${pidRaw}\")`);\n }\n const value = propEl.children[0];\n if (value === undefined) {\n throw new OpenXmlSchemaError(`custom.xml: <property name=\"${name}\"> has no typed-value child`);\n }\n const out: CustomProperty = { name, pid, value };\n if (fmtid !== undefined) out.fmtid = fmtid;\n properties.push(out);\n }\n return { properties };\n}\n\n// ---- Workbook ergonomic helpers ----------------------------------------\n\nimport type { Workbook } from '../workbook/workbook.js';\n\nconst ensureCustomProperties = (wb: Workbook): CustomProperties => {\n if (!wb.customProperties) wb.customProperties = makeCustomProperties();\n return wb.customProperties;\n};\n\nconst replaceOrAppend = (\n wb: Workbook,\n name: string,\n value: XmlNode,\n opts?: { fmtid?: string },\n): CustomProperty => {\n const props = ensureCustomProperties(wb);\n const existing = findCustomPropertyByName(props, name);\n if (existing) {\n existing.value = value;\n if (opts?.fmtid !== undefined) existing.fmtid = opts.fmtid;\n return existing;\n }\n return appendCustomProperty(props, name, value, opts);\n};\n\n/** Set (or replace) a custom string property. */\nexport const setCustomStringProperty = (wb: Workbook, name: string, value: string): CustomProperty =>\n replaceOrAppend(wb, name, makeStringValue(value));\n\n/**\n * Set (or replace) a custom numeric property. Integers (within Int32 range) are\n * stored as `vt:i4`; non-integer / out-of-range numbers as `vt:r8` doubles.\n */\nexport const setCustomNumberProperty = (wb: Workbook, name: string, value: number): CustomProperty => {\n if (!Number.isFinite(value)) {\n throw new OpenXmlSchemaError(`setCustomNumberProperty: value \"${value}\" is not finite`);\n }\n const isInt32 = Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;\n const node = isInt32 ? makeIntValue(value) : makeDoubleValue(value);\n return replaceOrAppend(wb, name, node);\n};\n\n/** Set (or replace) a custom boolean property. */\nexport const setCustomBoolProperty = (wb: Workbook, name: string, value: boolean): CustomProperty =>\n replaceOrAppend(wb, name, makeBoolValue(value));\n\n/**\n * Set (or replace) a custom date property. Accepts a `Date` (converted to ISO\n * via `toISOString()`) or a pre-formatted W3C-DTF string.\n */\nexport const setCustomDateProperty = (\n wb: Workbook,\n name: string,\n value: Date | string,\n): CustomProperty => {\n const iso = value instanceof Date ? value.toISOString() : value;\n return replaceOrAppend(wb, name, makeFiletimeValue(iso));\n};\n\n/**\n * Read the typed value of a custom property by name. Tries each decoder in turn\n * — string, int, double, bool, filetime — and returns the first hit. Returns\n * `undefined` for unknown names or unsupported types.\n */\nexport const getCustomPropertyValue = (\n wb: Workbook,\n name: string,\n): string | number | boolean | undefined => {\n if (!wb.customProperties) return undefined;\n const prop = findCustomPropertyByName(wb.customProperties, name);\n if (!prop) return undefined;\n const s = readStringValue(prop.value);\n if (s !== undefined) return s;\n const i = readIntValue(prop.value);\n if (i !== undefined) return i;\n const d = readDoubleValue(prop.value);\n if (d !== undefined) return d;\n const b = readBoolValue(prop.value);\n if (b !== undefined) return b;\n const ft = readFiletimeValue(prop.value);\n if (ft !== undefined) return ft;\n return undefined;\n};\n\n/**\n * Remove a custom property by name. Returns `true` when one was removed,\n * `false` when the name wasn't found.\n */\nexport const removeCustomProperty = (wb: Workbook, name: string): boolean => {\n if (!wb.customProperties) return false;\n const arr = wb.customProperties.properties;\n const i = arr.findIndex((p) => p.name === name);\n if (i < 0) return false;\n arr.splice(i, 1);\n return true;\n};\n\n/** Read-only snapshot of every custom property. */\nexport const listCustomProperties = (wb: Workbook): ReadonlyArray<CustomProperty> => {\n return wb.customProperties?.properties ?? [];\n};\n","// `docProps/app.xml` — Office \"extended\" document properties.\n//\n// Mirrors openpyxl/openpyxl/packaging/extended.py. Most fields are flat (text\n// or numeric). The four vector-shaped children — HeadingPairs, TitlesOfParts,\n// HLinks, DigSig — are kept as raw XmlNode subtrees and round-tripped verbatim;\n// modelling vt:vector explicitly is a phase-3 concern at the earliest. See row\n// for `packaging/extended.py`.\n\nimport { defineSchema, type Schema } from '../schema/core.js';\nimport { fromTree, toTree } from '../schema/serialize.js';\nimport { XPROPS_NS } from '../xml/namespaces.js';\nimport { parseXml } from '../xml/parser.js';\nimport { serializeXml } from '../xml/serializer.js';\nimport type { XmlNode } from '../xml/tree.js';\n\nexport interface ExtendedProperties {\n application?: string;\n appVersion?: string;\n characters?: number;\n charactersWithSpaces?: number;\n company?: string;\n digitalSignature?: XmlNode;\n docSecurity?: number;\n hLinks?: XmlNode;\n headingPairs?: XmlNode;\n hiddenSlides?: number;\n hyperlinkBase?: string;\n hyperlinks?: XmlNode;\n hyperlinksChanged?: boolean;\n lines?: number;\n linksUpToDate?: boolean;\n manager?: string;\n mmClips?: number;\n notes?: number;\n pages?: number;\n paragraphs?: number;\n presentationFormat?: string;\n scaleCrop?: boolean;\n sharedDoc?: boolean;\n slides?: number;\n template?: string;\n titlesOfParts?: XmlNode;\n totalTime?: number;\n words?: number;\n}\n\nconst ExtendedSchema: Schema<ExtendedProperties> = defineSchema<ExtendedProperties>({\n tagname: 'Properties',\n xmlNs: XPROPS_NS,\n attrs: {},\n // Element order chosen to match the Office output convention.\n elements: [\n { kind: 'text', key: 'template', xmlNs: XPROPS_NS, name: 'Template', primitive: 'string', optional: true },\n { kind: 'text', key: 'manager', xmlNs: XPROPS_NS, name: 'Manager', primitive: 'string', optional: true },\n { kind: 'text', key: 'company', xmlNs: XPROPS_NS, name: 'Company', primitive: 'string', optional: true },\n { kind: 'text', key: 'pages', xmlNs: XPROPS_NS, name: 'Pages', primitive: 'int', optional: true },\n { kind: 'text', key: 'words', xmlNs: XPROPS_NS, name: 'Words', primitive: 'int', optional: true },\n { kind: 'text', key: 'characters', xmlNs: XPROPS_NS, name: 'Characters', primitive: 'int', optional: true },\n {\n kind: 'text',\n key: 'presentationFormat',\n xmlNs: XPROPS_NS,\n name: 'PresentationFormat',\n primitive: 'string',\n optional: true,\n },\n { kind: 'text', key: 'lines', xmlNs: XPROPS_NS, name: 'Lines', primitive: 'int', optional: true },\n { kind: 'text', key: 'paragraphs', xmlNs: XPROPS_NS, name: 'Paragraphs', primitive: 'int', optional: true },\n { kind: 'text', key: 'slides', xmlNs: XPROPS_NS, name: 'Slides', primitive: 'int', optional: true },\n { kind: 'text', key: 'notes', xmlNs: XPROPS_NS, name: 'Notes', primitive: 'int', optional: true },\n { kind: 'text', key: 'totalTime', xmlNs: XPROPS_NS, name: 'TotalTime', primitive: 'int', optional: true },\n { kind: 'text', key: 'hiddenSlides', xmlNs: XPROPS_NS, name: 'HiddenSlides', primitive: 'int', optional: true },\n { kind: 'text', key: 'mmClips', xmlNs: XPROPS_NS, name: 'MMClips', primitive: 'int', optional: true },\n { kind: 'text', key: 'scaleCrop', xmlNs: XPROPS_NS, name: 'ScaleCrop', primitive: 'bool', optional: true },\n { kind: 'raw', key: 'headingPairs', xmlNs: XPROPS_NS, name: 'HeadingPairs', optional: true },\n { kind: 'raw', key: 'titlesOfParts', xmlNs: XPROPS_NS, name: 'TitlesOfParts', optional: true },\n { kind: 'raw', key: 'hLinks', xmlNs: XPROPS_NS, name: 'HLinks', optional: true },\n { kind: 'raw', key: 'hyperlinks', xmlNs: XPROPS_NS, name: 'Hyperlinks', optional: true },\n { kind: 'text', key: 'linksUpToDate', xmlNs: XPROPS_NS, name: 'LinksUpToDate', primitive: 'bool', optional: true },\n { kind: 'text', key: 'sharedDoc', xmlNs: XPROPS_NS, name: 'SharedDoc', primitive: 'bool', optional: true },\n {\n kind: 'text',\n key: 'hyperlinkBase',\n xmlNs: XPROPS_NS,\n name: 'HyperlinkBase',\n primitive: 'string',\n optional: true,\n },\n {\n kind: 'text',\n key: 'hyperlinksChanged',\n xmlNs: XPROPS_NS,\n name: 'HyperlinksChanged',\n primitive: 'bool',\n optional: true,\n },\n { kind: 'raw', key: 'digitalSignature', xmlNs: XPROPS_NS, name: 'DigSig', optional: true },\n { kind: 'text', key: 'application', xmlNs: XPROPS_NS, name: 'Application', primitive: 'string', optional: true },\n { kind: 'text', key: 'appVersion', xmlNs: XPROPS_NS, name: 'AppVersion', primitive: 'string', optional: true },\n { kind: 'text', key: 'docSecurity', xmlNs: XPROPS_NS, name: 'DocSecurity', primitive: 'int', optional: true },\n {\n kind: 'text',\n key: 'charactersWithSpaces',\n xmlNs: XPROPS_NS,\n name: 'CharactersWithSpaces',\n primitive: 'int',\n optional: true,\n },\n ],\n});\n\nexport function makeExtendedProperties(): ExtendedProperties {\n return {};\n}\n\nexport function extendedPropsToBytes(p: ExtendedProperties): Uint8Array {\n return serializeXml(toTree(p, ExtendedSchema));\n}\n\nexport function extendedPropsFromBytes(bytes: Uint8Array | string): ExtendedProperties {\n return fromTree(parseXml(bytes), ExtendedSchema);\n}\n\n// ---- Workbook ergonomic helpers ----------------------------------------\n\nimport type { Workbook } from '../workbook/workbook.js';\n\nconst ensureAppProperties = (wb: Workbook): ExtendedProperties => {\n if (!wb.appProperties) wb.appProperties = {};\n return wb.appProperties;\n};\n\n/** Set the company name on docProps/app.xml. */\nexport const setWorkbookCompany = (wb: Workbook, company: string): void => {\n ensureAppProperties(wb).company = company;\n};\n\n/** Set the manager / supervisor name on docProps/app.xml. */\nexport const setWorkbookManager = (wb: Workbook, manager: string): void => {\n ensureAppProperties(wb).manager = manager;\n};\n\n/** Set the application name (e.g. `\"Microsoft Excel\"`). */\nexport const setWorkbookApplication = (wb: Workbook, application: string): void => {\n ensureAppProperties(wb).application = application;\n};\n\n/** Set the application version (typically `\"16.0300\"` for Excel 365). */\nexport const setWorkbookAppVersion = (wb: Workbook, version: string): void => {\n ensureAppProperties(wb).appVersion = version;\n};\n\n/** Set the hyperlink base URL — Excel uses this as a prefix for relative `&F` codes. */\nexport const setWorkbookHyperlinkBase = (wb: Workbook, base: string): void => {\n ensureAppProperties(wb).hyperlinkBase = base;\n};\n","// [Content_Types].xml — the package manifest. Tracks default content types per\n// file extension and per-part Override entries.\n\nimport { defineSchema, type Schema } from '../schema/core.js';\nimport { fromTree, toTree } from '../schema/serialize.js';\nimport { CONTYPES_NS } from '../xml/namespaces.js';\nimport { parseXml } from '../xml/parser.js';\nimport { serializeXml } from '../xml/serializer.js';\n\nexport interface DefaultEntry {\n /** File extension without leading dot (e.g. \"rels\", \"xml\", \"png\"). */\n ext: string;\n contentType: string;\n}\n\nexport interface OverrideEntry {\n /** Part name path including leading slash (e.g. \"/xl/workbook.xml\"). */\n partName: string;\n contentType: string;\n}\n\nexport interface Manifest {\n defaults: DefaultEntry[];\n overrides: OverrideEntry[];\n}\n\nconst DefaultSchema = defineSchema<DefaultEntry>({\n tagname: 'Default',\n xmlNs: CONTYPES_NS,\n attrs: {\n ext: { kind: 'string', xmlName: 'Extension' },\n contentType: { kind: 'string', xmlName: 'ContentType' },\n },\n elements: [],\n});\n\nconst OverrideSchema = defineSchema<OverrideEntry>({\n tagname: 'Override',\n xmlNs: CONTYPES_NS,\n attrs: {\n partName: { kind: 'string', xmlName: 'PartName' },\n contentType: { kind: 'string', xmlName: 'ContentType' },\n },\n elements: [],\n});\n\nconst ManifestSchema: Schema<Manifest> = defineSchema<Manifest>({\n tagname: 'Types',\n xmlNs: CONTYPES_NS,\n attrs: {},\n elements: [\n {\n kind: 'sequence',\n key: 'defaults',\n itemName: 'Default',\n itemNs: CONTYPES_NS,\n itemSchema: () => DefaultSchema,\n },\n {\n kind: 'sequence',\n key: 'overrides',\n itemName: 'Override',\n itemNs: CONTYPES_NS,\n itemSchema: () => OverrideSchema,\n },\n ],\n});\n\nexport function makeManifest(): Manifest {\n return { defaults: [], overrides: [] };\n}\n\n/** Register a default content type for an extension. Idempotent. */\nexport function addDefault(m: Manifest, ext: string, contentType: string): void {\n for (const d of m.defaults) {\n if (d.ext === ext) {\n if (d.contentType !== contentType) {\n d.contentType = contentType; // newer wins; matches openpyxl behaviour\n }\n return;\n }\n }\n m.defaults.push({ ext, contentType });\n}\n\n/** Register an Override for a specific part. Idempotent. */\nexport function addOverride(m: Manifest, partName: string, contentType: string): void {\n for (const o of m.overrides) {\n if (o.partName === partName) {\n if (o.contentType !== contentType) o.contentType = contentType;\n return;\n }\n }\n m.overrides.push({ partName, contentType });\n}\n\nexport function findOverride(m: Manifest, partName: string): OverrideEntry | undefined {\n for (const o of m.overrides) if (o.partName === partName) return o;\n return undefined;\n}\n\n/** Find the first Override matching a content type. */\nexport function findOverrideByContentType(m: Manifest, contentType: string): OverrideEntry | undefined {\n for (const o of m.overrides) if (o.contentType === contentType) return o;\n return undefined;\n}\n\nexport function manifestToBytes(m: Manifest): Uint8Array {\n return serializeXml(toTree(m, ManifestSchema));\n}\n\nexport function manifestFromBytes(bytes: Uint8Array | string): Manifest {\n return fromTree(parseXml(bytes), ManifestSchema);\n}\n"],"mappings":"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"}
|
package/dist/node.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as OpenXmlIoError } from "./exceptions-D-CFwxgm.mjs";
|
|
2
|
-
import { t as saveWorkbook } from "./save-
|
|
2
|
+
import { t as saveWorkbook } from "./save-ax11Gsw0.mjs";
|
|
3
3
|
import { createReadStream, createWriteStream, readFileSync } from "node:fs";
|
|
4
4
|
import { readFile, unlink } from "node:fs/promises";
|
|
5
5
|
import { once } from "node:events";
|
package/dist/packaging.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as findByType, A as readBoolValue, B as corePropsFromBytes, C as makeBoolValue, D as makeFiletimeValue, E as makeDoubleValue, F as removeCustomProperty, G as setWorkbookDescription, H as makeCoreProperties, I as setCustomBoolProperty, J as setWorkbookSubject, K as setWorkbookKeywords, L as setCustomDateProperty, M as readFiletimeValue, N as readIntValue, O as makeIntValue, P as readStringValue, Q as findById, R as setCustomNumberProperty, S as makeAsciiStringValue, T as makeDateValue, U as setWorkbookCategory, V as corePropsToBytes, W as setWorkbookCreator, X as appendRel, Y as setWorkbookTitle, Z as findAllByType, _ as customPropsFromBytes, a as makeManifest, b as getCustomPropertyValue, c as extendedPropsFromBytes, d as setWorkbookAppVersion, f as setWorkbookApplication, g as appendCustomProperty, h as setWorkbookManager, i as findOverrideByContentType, j as readDoubleValue, k as makeStringValue, l as extendedPropsToBytes, m as setWorkbookHyperlinkBase, n as addOverride, nt as relsFromBytes, o as manifestFromBytes, p as setWorkbookCompany, q as setWorkbookLastModifiedBy, r as findOverride, rt as relsToBytes, s as manifestToBytes, t as addDefault, tt as makeRelationships, u as makeExtendedProperties, v as customPropsToBytes, w as makeCustomProperties, x as listCustomProperties, y as findCustomPropertyByName, z as setCustomStringProperty } from "./manifest-
|
|
1
|
+
import { $ as findByType, A as readBoolValue, B as corePropsFromBytes, C as makeBoolValue, D as makeFiletimeValue, E as makeDoubleValue, F as removeCustomProperty, G as setWorkbookDescription, H as makeCoreProperties, I as setCustomBoolProperty, J as setWorkbookSubject, K as setWorkbookKeywords, L as setCustomDateProperty, M as readFiletimeValue, N as readIntValue, O as makeIntValue, P as readStringValue, Q as findById, R as setCustomNumberProperty, S as makeAsciiStringValue, T as makeDateValue, U as setWorkbookCategory, V as corePropsToBytes, W as setWorkbookCreator, X as appendRel, Y as setWorkbookTitle, Z as findAllByType, _ as customPropsFromBytes, a as makeManifest, b as getCustomPropertyValue, c as extendedPropsFromBytes, d as setWorkbookAppVersion, f as setWorkbookApplication, g as appendCustomProperty, h as setWorkbookManager, i as findOverrideByContentType, j as readDoubleValue, k as makeStringValue, l as extendedPropsToBytes, m as setWorkbookHyperlinkBase, n as addOverride, nt as relsFromBytes, o as manifestFromBytes, p as setWorkbookCompany, q as setWorkbookLastModifiedBy, r as findOverride, rt as relsToBytes, s as manifestToBytes, t as addDefault, tt as makeRelationships, u as makeExtendedProperties, v as customPropsToBytes, w as makeCustomProperties, x as listCustomProperties, y as findCustomPropertyByName, z as setCustomStringProperty } from "./manifest-BHUYpjUG.mjs";
|
|
2
2
|
export { addDefault, addOverride, appendCustomProperty, appendRel, corePropsFromBytes, corePropsToBytes, customPropsFromBytes, customPropsToBytes, extendedPropsFromBytes, extendedPropsToBytes, findAllByType, findById, findByType, findCustomPropertyByName, findOverride, findOverrideByContentType, getCustomPropertyValue, listCustomProperties, makeAsciiStringValue, makeBoolValue, makeCoreProperties, makeCustomProperties, makeDateValue, makeDoubleValue, makeExtendedProperties, makeFiletimeValue, makeIntValue, makeManifest, makeRelationships, makeStringValue, manifestFromBytes, manifestToBytes, readBoolValue, readDoubleValue, readFiletimeValue, readIntValue, readStringValue, relsFromBytes, relsToBytes, removeCustomProperty, setCustomBoolProperty, setCustomDateProperty, setCustomNumberProperty, setCustomStringProperty, setWorkbookAppVersion, setWorkbookApplication, setWorkbookCategory, setWorkbookCompany, setWorkbookCreator, setWorkbookDescription, setWorkbookHyperlinkBase, setWorkbookKeywords, setWorkbookLastModifiedBy, setWorkbookManager, setWorkbookSubject, setWorkbookTitle };
|
|
@@ -231,7 +231,6 @@ function parseCentralDirectory(b, cdOffset, expectedCount) {
|
|
|
231
231
|
let p = cdOffset;
|
|
232
232
|
for (let i = 0; i < expectedCount; i++) {
|
|
233
233
|
if (u32(b, p) !== SIG_CD) throw new OpenXmlIoError(`openZip: malformed central directory at byte ${p}`);
|
|
234
|
-
const gpFlag = u16(b, p + 8);
|
|
235
234
|
const compMethod = u16(b, p + 10);
|
|
236
235
|
let compSize = u32(b, p + 20);
|
|
237
236
|
let uncompSize = u32(b, p + 24);
|
|
@@ -255,19 +254,30 @@ function parseCentralDirectory(b, cdOffset, expectedCount) {
|
|
|
255
254
|
lfhOffset,
|
|
256
255
|
compMethod,
|
|
257
256
|
compSize,
|
|
258
|
-
uncompSize
|
|
259
|
-
gpFlag
|
|
257
|
+
uncompSize
|
|
260
258
|
});
|
|
261
259
|
p += 46 + nameLen + extraLen + commentLen;
|
|
262
260
|
}
|
|
263
261
|
return entries;
|
|
264
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* RFC 1951 gives every deflate stream at least one block, and the last block
|
|
265
|
+
* carries the BFINAL bit, so a method-8 entry declaring zero compressed bytes
|
|
266
|
+
* has no stream to decode. Reject it where both read paths meet the bytes,
|
|
267
|
+
* rather than letting each one invent an answer for an entry that isn't there.
|
|
268
|
+
*/
|
|
269
|
+
const requireDeflatePayload = (path, compressed) => {
|
|
270
|
+
if (compressed.byteLength === 0) throw new OpenXmlIoError(`openZip: entry "${path}" is declared DEFLATE but carries no compressed bytes`);
|
|
271
|
+
};
|
|
272
|
+
/** Message for a deflate stream that runs out before signalling its last block. */
|
|
273
|
+
const incompleteDeflateError = (path) => new OpenXmlIoError(`openZip: deflate stream for "${path}" ended before its final block`);
|
|
265
274
|
/** Read the compressed bytes for a CD entry by walking its local file header. */
|
|
266
275
|
function readCompressedBytes(b, entry) {
|
|
267
276
|
if (u32(b, entry.lfhOffset) !== SIG_LFH) throw new OpenXmlIoError(`openZip: malformed local file header for "${entry.path}"`);
|
|
268
277
|
const nameLen = u16(b, entry.lfhOffset + 26);
|
|
269
278
|
const extraLen = u16(b, entry.lfhOffset + 28);
|
|
270
279
|
const dataStart = entry.lfhOffset + 30 + nameLen + extraLen;
|
|
280
|
+
if (dataStart + entry.compSize > b.length) throw new OpenXmlIoError(`openZip: entry "${entry.path}" declares ${entry.compSize} compressed bytes at offset ${dataStart}, past the end of the ${b.length}-byte archive`);
|
|
271
281
|
return b.subarray(dataStart, dataStart + entry.compSize);
|
|
272
282
|
}
|
|
273
283
|
/**
|
|
@@ -355,6 +365,7 @@ function openRandomAccessArchive(bytes, decompressionLimits) {
|
|
|
355
365
|
return singleChunkStream(compressed.slice());
|
|
356
366
|
}
|
|
357
367
|
if (entry.compMethod !== COMP_DEFLATE) throw new OpenXmlIoError(`openZip: unsupported compression method ${entry.compMethod} for "${path}"`);
|
|
368
|
+
requireDeflatePayload(path, compressed);
|
|
358
369
|
const entryCap = budget ? entryInflateCap(budget, compressed.byteLength) : Number.POSITIVE_INFINITY;
|
|
359
370
|
const record = budget ? beginEntryInflate(budget, path) : null;
|
|
360
371
|
let entryEmitted = 0;
|
|
@@ -380,6 +391,14 @@ function openRandomAccessArchive(bytes, decompressionLimits) {
|
|
|
380
391
|
}
|
|
381
392
|
if (final) inflaterFinal = true;
|
|
382
393
|
});
|
|
394
|
+
const settleWhenDrained = (controller) => {
|
|
395
|
+
if (pending.length > 0 || pushedOffset < compressed.byteLength) return;
|
|
396
|
+
if (inflaterFinal) {
|
|
397
|
+
controller.close();
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
controller.error(incompleteDeflateError(path));
|
|
401
|
+
};
|
|
383
402
|
return new ReadableStream({
|
|
384
403
|
pull(controller) {
|
|
385
404
|
if (inflateError) {
|
|
@@ -389,7 +408,7 @@ function openRandomAccessArchive(bytes, decompressionLimits) {
|
|
|
389
408
|
const buffered = pending.shift();
|
|
390
409
|
if (buffered) {
|
|
391
410
|
controller.enqueue(buffered);
|
|
392
|
-
|
|
411
|
+
settleWhenDrained(controller);
|
|
393
412
|
return;
|
|
394
413
|
}
|
|
395
414
|
while (pending.length === 0 && pushedOffset < compressed.byteLength) {
|
|
@@ -411,7 +430,7 @@ function openRandomAccessArchive(bytes, decompressionLimits) {
|
|
|
411
430
|
}
|
|
412
431
|
const next = pending.shift();
|
|
413
432
|
if (next) controller.enqueue(next);
|
|
414
|
-
|
|
433
|
+
settleWhenDrained(controller);
|
|
415
434
|
},
|
|
416
435
|
cancel() {
|
|
417
436
|
pending.length = 0;
|
|
@@ -454,12 +473,15 @@ function openRandomAccessArchive(bytes, decompressionLimits) {
|
|
|
454
473
|
* after fflate has materialised the entire payload.
|
|
455
474
|
*/
|
|
456
475
|
function inflateBounded(path, compressed, budget) {
|
|
476
|
+
requireDeflatePayload(path, compressed);
|
|
457
477
|
const cap = budget ? entryInflateCap(budget, compressed.byteLength) : Number.POSITIVE_INFINITY;
|
|
458
478
|
const record = budget ? beginEntryInflate(budget, path) : null;
|
|
459
479
|
const acc = [];
|
|
460
480
|
let emitted = 0;
|
|
461
481
|
let aborted;
|
|
462
|
-
|
|
482
|
+
let sawFinal = false;
|
|
483
|
+
const inflater = new Inflate((chunk, final) => {
|
|
484
|
+
if (final) sawFinal = true;
|
|
463
485
|
if (aborted) return;
|
|
464
486
|
if (chunk.byteLength === 0) return;
|
|
465
487
|
emitted += chunk.byteLength;
|
|
@@ -488,6 +510,7 @@ function inflateBounded(path, compressed, budget) {
|
|
|
488
510
|
if (aborted) throw aborted;
|
|
489
511
|
off = end;
|
|
490
512
|
}
|
|
513
|
+
if (!sawFinal) throw incompleteDeflateError(path);
|
|
491
514
|
const out = new Uint8Array(emitted);
|
|
492
515
|
let cursor = 0;
|
|
493
516
|
for (const chunk of acc) {
|
|
@@ -587,4 +610,4 @@ async function openZip(source, opts = {}) {
|
|
|
587
610
|
//#endregion
|
|
588
611
|
export { DEFAULT_DECOMPRESSION_LIMITS as n, openZip as t };
|
|
589
612
|
|
|
590
|
-
//# sourceMappingURL=reader-
|
|
613
|
+
//# sourceMappingURL=reader-pC7bxYAs.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader-pC7bxYAs.mjs","names":[],"sources":["../src/zip/decompression-guard.ts","../src/zip/inflate-cache.ts","../src/zip/random-access-reader.ts","../src/zip/reader.ts"],"sourcesContent":["// Decompression-bomb safeguards for the ZIP reader.\n//\n// Zip-bombs encode pathological compression ratios (e.g. 100 B → 1 GB) so that\n// a naive `inflate` exhausts memory before the caller can react. The guards\n// here apply three orthogonal bounds:\n//\n// 1. Per-entry uncompressed cap — hard ceiling on a single payload.\n// 2. Total-archive uncompressed cap — hard ceiling summed across the archive.\n// 3. Per-entry compression ratio — bounds the *amplification factor* so that\n// even small compressed entries can't decompress into hundreds of MB.\n//\n// Defaults are sized to admit any legitimate xlsx (xml compresses well but\n// rarely exceeds the per-entry cap; office templates with embedded media stay\n// well under the total cap) while rejecting plausible bombs. Trusted callers\n// (e.g. a backend that only ever loads xlsx it generated itself) can pass\n// `false` to disable the guard.\n\nimport { OpenXmlDecompressionBombError, OpenXmlError } from '../utils/exceptions.js';\n\n/** Per-archive limits enforced during {@link openZip}. */\nexport interface DecompressionLimits {\n /**\n * Maximum decompressed bytes for a single archive entry. Default 512 MiB.\n * Legitimate xlsx sheets stay well below this even with millions of cells.\n */\n maxEntryUncompressedBytes?: number;\n /**\n * Maximum decompressed bytes summed across every entry the caller reads.\n * Default 1 GiB.\n */\n maxTotalUncompressedBytes?: number;\n /**\n * Maximum allowed `uncompressed / compressed` ratio for a single entry.\n * Default 1000. xml usually compresses 5–20×, but highly repetitive payloads\n * (long runs of zeros, sparse worksheets) can hit several hundred ×\n * legitimately. Classic zip-bombs run 10 000× and up, so a 1000× ceiling\n * still catches them while admitting realistic content. The implementation\n * treats compressed sizes below 64 B as exempt — there's no amplification\n * budget worth policing on such small entries, and the absolute per-entry /\n * archive limits already cover them.\n */\n maxCompressionRatio?: number;\n}\n\n/** Resolved limits with no `undefined` fields. */\nexport interface ResolvedDecompressionLimits {\n readonly maxEntryUncompressedBytes: number;\n readonly maxTotalUncompressedBytes: number;\n readonly maxCompressionRatio: number;\n}\n\n/** Default safeguards applied when the caller doesn't override them. */\nexport const DEFAULT_DECOMPRESSION_LIMITS: ResolvedDecompressionLimits = {\n maxEntryUncompressedBytes: 512 * 1024 * 1024,\n maxTotalUncompressedBytes: 1024 * 1024 * 1024,\n maxCompressionRatio: 1000,\n};\n\n/** Below this compressed size, the ratio check is skipped — see {@link DecompressionLimits}. */\nconst RATIO_CHECK_MIN_COMPRESSED_BYTES = 64;\n\n/**\n * `DecompressionLimits` plus the sentinel `false` to disable the guard.\n * Anything else is treated as \"use defaults\".\n */\nexport type DecompressionLimitsInput = DecompressionLimits | false | undefined;\n\n// Each limit must be a positive finite number to be meaningful; NaN / Infinity\n// / 0 / negatives silently turn `emitted > cap` and `totalInflated > cap` into\n// no-ops and disable the guard. Reject those at the boundary so the only way\n// the guard is off is the explicit `false` sentinel.\nconst requirePositiveFinite = (field: string, value: number): void => {\n if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {\n throw new OpenXmlError(\n `resolveDecompressionLimits: ${field} must be a positive finite number; got ${String(value)}`,\n );\n }\n};\n\n/** Returns null when the guard is disabled. */\nexport function resolveDecompressionLimits(\n input: DecompressionLimitsInput,\n): ResolvedDecompressionLimits | null {\n if (input === false) return null;\n if (!input) return DEFAULT_DECOMPRESSION_LIMITS;\n const resolved: ResolvedDecompressionLimits = {\n maxEntryUncompressedBytes:\n input.maxEntryUncompressedBytes ?? DEFAULT_DECOMPRESSION_LIMITS.maxEntryUncompressedBytes,\n maxTotalUncompressedBytes:\n input.maxTotalUncompressedBytes ?? DEFAULT_DECOMPRESSION_LIMITS.maxTotalUncompressedBytes,\n maxCompressionRatio:\n input.maxCompressionRatio ?? DEFAULT_DECOMPRESSION_LIMITS.maxCompressionRatio,\n };\n requirePositiveFinite('maxEntryUncompressedBytes', resolved.maxEntryUncompressedBytes);\n requirePositiveFinite('maxTotalUncompressedBytes', resolved.maxTotalUncompressedBytes);\n requirePositiveFinite('maxCompressionRatio', resolved.maxCompressionRatio);\n return resolved;\n}\n\n/**\n * Per-archive byte accounting shared across every read of an archive opened\n * with the given limits. Tracks total inflated bytes so the cap is enforced\n * even when individual entries stay below the per-entry ceiling.\n */\nexport interface DecompressionBudget {\n readonly limits: ResolvedDecompressionLimits;\n totalInflated: number;\n /**\n * Largest number of bytes any single inflate of an entry has charged to the\n * archive total, keyed by path. {@link beginEntryInflate} keeps\n * {@link DecompressionBudget.totalInflated} equal to the sum of these.\n */\n readonly chargedByPath: Map<string, number>;\n}\n\nexport function createBudget(limits: ResolvedDecompressionLimits): DecompressionBudget {\n return { limits, totalInflated: 0, chargedByPath: new Map() };\n}\n\n/**\n * Start inflating `path`, returning the function every chunk of it must be\n * recorded through. The recorder throws {@link OpenXmlDecompressionBombError}\n * once the archive total is exceeded, naming `path`.\n *\n * The total bounds how much distinct payload an archive expands to, which is\n * what `checkDeclaredTotals` enforces from the central directory by counting\n * each entry once. An entry can be inflated more than once though: a\n * `readStream` and a `read` of the same part, or a re-read of one the inflate\n * cache turned away. So each path is charged its high-water mark rather than\n * the sum of its reads, and a second inflate only adds what it pushes that mark\n * past. Reads that overlap in any interleaving stay correct for the same\n * reason. The per-entry cap is independent of this and is re-evaluated from\n * scratch on every read.\n */\nexport function beginEntryInflate(\n budget: DecompressionBudget,\n path: string,\n): (bytes: number) => void {\n let inflated = 0;\n return (bytes: number): void => {\n inflated += bytes;\n const charged = budget.chargedByPath.get(path) ?? 0;\n if (inflated > charged) {\n budget.totalInflated += inflated - charged;\n budget.chargedByPath.set(path, inflated);\n }\n // A failed inflate also advances the high-water mark. Check the total\n // even when this read adds nothing, or retrying a rejected entry bypasses\n // the archive limit using the charge left by the first attempt.\n if (budget.totalInflated > budget.limits.maxTotalUncompressedBytes) {\n throw new OpenXmlDecompressionBombError(\n `openZip: archive-wide inflated size exceeded ${budget.limits.maxTotalUncompressedBytes} bytes` +\n ` while reading \"${path}\" (decompression-bomb guard).`,\n );\n }\n };\n}\n\n/**\n * Per-entry inflate cap, accounting for both the absolute per-entry bound and\n * the ratio-based bound. Returns the smaller of the two — whichever fires\n * first stops the inflate loop.\n */\nexport function entryInflateCap(budget: DecompressionBudget, compressedSize: number): number {\n const { maxEntryUncompressedBytes, maxCompressionRatio } = budget.limits;\n if (compressedSize < RATIO_CHECK_MIN_COMPRESSED_BYTES) {\n return maxEntryUncompressedBytes;\n }\n const ratioCap = compressedSize * maxCompressionRatio;\n return Math.min(maxEntryUncompressedBytes, ratioCap);\n}\n\n/** Throw if the declared central-directory totals already exceed the limits. */\nexport function checkDeclaredTotals(\n budget: DecompressionBudget,\n declaredEntries: ReadonlyArray<{ path: string; compSize: number; uncompSize: number }>,\n): void {\n let declaredTotal = 0;\n for (const entry of declaredEntries) {\n declaredTotal += entry.uncompSize;\n if (entry.uncompSize > budget.limits.maxEntryUncompressedBytes) {\n throw new OpenXmlDecompressionBombError(\n `openZip: entry \"${entry.path}\" declares ${entry.uncompSize} uncompressed bytes,` +\n ` exceeding the ${budget.limits.maxEntryUncompressedBytes}-byte per-entry limit` +\n ` (decompression-bomb guard).`,\n );\n }\n if (\n entry.compSize >= RATIO_CHECK_MIN_COMPRESSED_BYTES &&\n entry.uncompSize > entry.compSize * budget.limits.maxCompressionRatio\n ) {\n throw new OpenXmlDecompressionBombError(\n `openZip: entry \"${entry.path}\" declares ratio ${(entry.uncompSize / entry.compSize).toFixed(1)}x` +\n ` (${entry.uncompSize}/${entry.compSize}), exceeding the ${budget.limits.maxCompressionRatio}x` +\n ` per-entry limit (decompression-bomb guard).`,\n );\n }\n }\n if (declaredTotal > budget.limits.maxTotalUncompressedBytes) {\n throw new OpenXmlDecompressionBombError(\n `openZip: declared total uncompressed size ${declaredTotal} bytes exceeds the` +\n ` ${budget.limits.maxTotalUncompressedBytes}-byte archive limit (decompression-bomb guard).`,\n );\n }\n}\n\n/** Build the message thrown when a single entry exceeds its cap mid-inflate. */\nexport function entryOverflowError(path: string, cap: number): OpenXmlDecompressionBombError {\n return new OpenXmlDecompressionBombError(\n `openZip: inflated size of \"${path}\" exceeded ${cap} bytes (decompression-bomb guard).`,\n );\n}\n","// Bounded cache of inflated ZIP entries.\n//\n// A load comes back to a handful of parts more than once (the `.rels` files the\n// relationship walk revisits, above all), and inflating those again is waste.\n// Keeping every entry is worse than that waste: it puts the whole uncompressed\n// package back in memory, which is the cost the random-access reader exists to\n// avoid. So the cache takes small entries only, holds a few MB of them at most,\n// and drops the least recently used first. Anything it turns away or evicts\n// inflates again on the next read.\n\n/**\n * Largest entry the cache accepts. Sized for the parts a load revisits, which\n * are small; a sheet or a media blob is normally read once, so keeping one buys\n * nothing and costs its full inflated size for the life of the archive.\n */\nexport const CACHE_MAX_ENTRY_BYTES = 64 * 1024;\n\n/**\n * Ceiling on everything the cache holds, so an archive with thousands of small\n * parts cannot accumulate without limit.\n */\nexport const CACHE_MAX_TOTAL_BYTES = 4 * 1024 * 1024;\n\nexport interface InflateCache {\n /**\n * Cached bytes for `path`, or `undefined`. The caller owns the array it gets\n * back and may mutate it. A hit counts as a use for eviction order.\n */\n get(path: string): Uint8Array | undefined;\n /** Offer `bytes` for later re-reads. Entries above the size ceiling are ignored. */\n set(path: string, bytes: Uint8Array): void;\n clear(): void;\n}\n\nexport function createInflateCache(): InflateCache {\n // Insertion-ordered, so the first key `keys()` yields is the least recently\n // used for as long as every hit re-inserts.\n const held = new Map<string, Uint8Array>();\n let total = 0;\n\n return {\n get(path) {\n const hit = held.get(path);\n if (!hit) return undefined;\n // `set` on an existing key leaves it where it was, so a hit has to delete\n // first. Without this the entries being re-read are the first evicted.\n held.delete(path);\n held.set(path, hit);\n return hit.slice();\n },\n set(path, bytes) {\n if (bytes.byteLength > CACHE_MAX_ENTRY_BYTES) return;\n total += bytes.byteLength - (held.get(path)?.byteLength ?? 0);\n // Hold a copy, so the array the caller was handed stays theirs to mutate.\n held.set(path, bytes.slice());\n for (const [lru, entry] of held) {\n if (total <= CACHE_MAX_TOTAL_BYTES) break;\n held.delete(lru);\n total -= entry.byteLength;\n }\n },\n clear() {\n held.clear();\n total = 0;\n },\n };\n}\n","// Random-access ZIP reader.\n//\n// Handing every entry to `fflate.unzipSync` materialises every uncompressed\n// payload at once, so a 100 MB xlsx with 500 MB of decompressed sheet data\n// spikes the resident set accordingly. This reader keeps only the compressed\n// archive bytes resident, parses the central directory once (cheap, about 46 B\n// per entry plus the filename), and inflates each entry lazily on `read(path)`.\n//\n// Small inflated payloads are kept for re-reads (see ./inflate-cache.ts).\n// Keeping every one of them would put the whole uncompressed package back in\n// memory, which is the cost this reader exists to avoid, so that cache is\n// bounded in both entry size and total and anything outside those bounds\n// inflates again on the next read.\n//\n// Limitations:\n// - ZIP64 reads only when the standard ZIP32 fields fit. EOCD with\n// sentinel values (0xFFFF / 0xFFFFFFFF) falls back to fflate's `unzipSync` so\n// external ZIP64 archives still load (the writer side has its own ZIP32 cap\n// guard).\n// - Compression methods: STORE (0) and DEFLATE (8). Anything else\n// throws OpenXmlIoError.\n\nimport { Inflate, unzipSync } from 'fflate';\nimport { OpenXmlDecompressionBombError, OpenXmlIoError } from '../utils/exceptions.js';\nimport {\n beginEntryInflate,\n checkDeclaredTotals,\n createBudget,\n type DecompressionBudget,\n type DecompressionLimitsInput,\n entryInflateCap,\n entryOverflowError,\n resolveDecompressionLimits,\n} from './decompression-guard.js';\nimport { createInflateCache } from './inflate-cache.js';\nimport type { ZipArchive } from './reader.js';\n\n/**\n * Chunk size used when feeding compressed bytes into fflate's `Inflate` for\n * streaming reads. 64 KB matches the saxes/SAX consumer's typical batch and\n * keeps peak transient memory bounded.\n */\nconst INFLATE_CHUNK_BYTES = 64 * 1024;\n\n/**\n * `decode()` without `{ stream: true }` resets the decoder's state on every\n * call, so one instance is safe to share across entries and across archives.\n */\nconst CD_NAME_DECODER = new TextDecoder('utf-8');\n\nconst singleChunkStream = (bytes: Uint8Array): ReadableStream<Uint8Array> =>\n new ReadableStream<Uint8Array>({\n start(controller) {\n if (bytes.byteLength > 0) controller.enqueue(bytes);\n controller.close();\n },\n });\n\nconst SIG_EOCD = 0x06054b50;\nconst SIG_CD = 0x02014b50;\nconst SIG_LFH = 0x04034b50;\nconst SIG_ZIP64_EOCD = 0x06064b50;\nconst SIG_ZIP64_EOCD_LOCATOR = 0x07064b50;\nconst ZIP32_MAX_U16 = 0xffff;\nconst ZIP32_MAX_U32 = 0xffffffff;\nconst ZIP64_LOCATOR_SIZE = 20;\nconst ZIP64_EXTRA_HEADER_ID = 0x0001;\nconst COMP_STORE = 0;\nconst COMP_DEFLATE = 8;\n\ninterface CdEntry {\n path: string;\n lfhOffset: number;\n compMethod: number;\n compSize: number;\n uncompSize: number;\n}\n\nconst u16 = (b: Uint8Array, off: number): number => (b[off] ?? 0) | ((b[off + 1] ?? 0) << 8);\nconst u32 = (b: Uint8Array, off: number): number => {\n const v0 = b[off] ?? 0;\n const v1 = b[off + 1] ?? 0;\n const v2 = b[off + 2] ?? 0;\n const v3 = b[off + 3] ?? 0;\n return (v0 | (v1 << 8) | (v2 << 16) | (v3 << 24)) >>> 0;\n};\n\n// Read a little-endian 64-bit value as a JS Number. Safe for values up to\n// 2^53-1 (Number.MAX_SAFE_INTEGER ~ 9 PiB), which is well past any realistic\n// xlsx archive — we throw if a parsed value exceeds the safe-integer range.\nconst u64 = (b: Uint8Array, off: number): number => {\n const lo = u32(b, off);\n const hi = u32(b, off + 4);\n if (hi > 0x1fffff) {\n throw new OpenXmlIoError(\n `openZip: ZIP64 field at byte ${off} exceeds the safe-integer range (${hi}*2^32 + ${lo})`,\n );\n }\n return hi * 0x100000000 + lo;\n};\n\n/** Find the End-of-Central-Directory record by scanning backwards from EOF. */\nfunction findEocd(b: Uint8Array): number {\n const minStart = Math.max(0, b.length - 22 - 0xffff);\n for (let i = b.length - 22; i >= minStart; i--) {\n if (u32(b, i) === SIG_EOCD) return i;\n }\n throw new OpenXmlIoError('openZip: no End-of-Central-Directory signature found');\n}\n\ninterface CdSummary {\n totalEntries: number;\n cdSize: number;\n cdOffset: number;\n}\n\n/**\n * Resolve the central-directory totals. When the EOCD carries ZIP64 sentinel\n * values (0xFFFF / 0xFFFFFFFF) the real totals live in a ZIP64 EOCD record\n * located via the ZIP64 EOCD locator just before the regular EOCD. ECMA-376\n * xlsx archives stay in ZIP32 territory; the ZIP64 path exists so the\n * decompression-bomb guards still apply to large external archives instead of\n * falling all the way back to `unzipSync` (which produces every entry's bytes\n * before any cap can fire).\n */\nfunction readCdSummary(b: Uint8Array, eocdOff: number): CdSummary {\n let totalEntries = u16(b, eocdOff + 10);\n let cdSize = u32(b, eocdOff + 12);\n let cdOffset = u32(b, eocdOff + 16);\n\n const usesZip64Eocd =\n totalEntries === ZIP32_MAX_U16 || cdSize === ZIP32_MAX_U32 || cdOffset === ZIP32_MAX_U32;\n if (!usesZip64Eocd) {\n return { totalEntries, cdSize, cdOffset };\n }\n\n // Locate the ZIP64 EOCD locator. It sits immediately before the regular\n // EOCD when one is present.\n const locatorOff = eocdOff - ZIP64_LOCATOR_SIZE;\n if (locatorOff < 0 || u32(b, locatorOff) !== SIG_ZIP64_EOCD_LOCATOR) {\n throw new OpenXmlIoError('openZip: ZIP64 EOCD locator missing despite EOCD sentinel values');\n }\n const zip64EocdOff = u64(b, locatorOff + 8);\n if (zip64EocdOff < 0 || zip64EocdOff + 56 > b.length) {\n throw new OpenXmlIoError(`openZip: ZIP64 EOCD offset ${zip64EocdOff} out of bounds`);\n }\n if (u32(b, zip64EocdOff) !== SIG_ZIP64_EOCD) {\n throw new OpenXmlIoError(`openZip: ZIP64 EOCD signature missing at byte ${zip64EocdOff}`);\n }\n totalEntries = u64(b, zip64EocdOff + 32);\n cdSize = u64(b, zip64EocdOff + 40);\n cdOffset = u64(b, zip64EocdOff + 48);\n return { totalEntries, cdSize, cdOffset };\n}\n\n/** Walk the ZIP64 Extended Information extra field for sentinel-valued sizes/offset. */\nfunction readZip64Extra(\n b: Uint8Array,\n extraStart: number,\n extraLen: number,\n wantsUncompSize: boolean,\n wantsCompSize: boolean,\n wantsLfhOffset: boolean,\n entryPath: string,\n): { uncompSize?: number; compSize?: number; lfhOffset?: number } {\n let p = extraStart;\n const end = extraStart + extraLen;\n while (p + 4 <= end) {\n const id = u16(b, p);\n const size = u16(b, p + 2);\n const dataStart = p + 4;\n const next = dataStart + size;\n if (next > end) break;\n if (id === ZIP64_EXTRA_HEADER_ID) {\n // Sanity-check that the declared extra-field size actually covers every\n // u64 the CD asked us to read. A truncated / mis-sized ZIP64 extra\n // field would otherwise let u64() interpret bytes belonging to the\n // next extra record (or the next CD entry) as a size/offset, producing\n // bogus values that downstream bomb checks then trust. Fail closed.\n const needed = (wantsUncompSize ? 8 : 0) + (wantsCompSize ? 8 : 0) + (wantsLfhOffset ? 8 : 0);\n if (size < needed) {\n throw new OpenXmlIoError(\n `openZip: ZIP64 extended-info field for \"${entryPath}\" declares ${size} bytes` +\n ` but the central directory sentinels require ${needed}`,\n );\n }\n let q = dataStart;\n const result: { uncompSize?: number; compSize?: number; lfhOffset?: number } = {};\n if (wantsUncompSize) {\n result.uncompSize = u64(b, q);\n q += 8;\n }\n if (wantsCompSize) {\n result.compSize = u64(b, q);\n q += 8;\n }\n if (wantsLfhOffset) {\n result.lfhOffset = u64(b, q);\n q += 8;\n }\n return result;\n }\n p = next;\n }\n return {};\n}\n\n/** Parse the central directory into an array of entry descriptors. */\nfunction parseCentralDirectory(b: Uint8Array, cdOffset: number, expectedCount: number): CdEntry[] {\n const entries: CdEntry[] = [];\n let p = cdOffset;\n for (let i = 0; i < expectedCount; i++) {\n if (u32(b, p) !== SIG_CD) {\n throw new OpenXmlIoError(`openZip: malformed central directory at byte ${p}`);\n }\n const compMethod = u16(b, p + 10);\n let compSize = u32(b, p + 20);\n let uncompSize = u32(b, p + 24);\n const nameLen = u16(b, p + 28);\n const extraLen = u16(b, p + 30);\n const commentLen = u16(b, p + 32);\n let lfhOffset = u32(b, p + 42);\n const nameBytes = b.subarray(p + 46, p + 46 + nameLen);\n // Bit 11 of the general-purpose flag signals a UTF-8 name, but every name\n // decodes as UTF-8 without consulting it: CP437 and UTF-8 agree on ASCII,\n // and xlsx part names are ASCII.\n const path = CD_NAME_DECODER.decode(nameBytes);\n\n // ZIP64 Extended Information rewrites whichever of {uncompSize, compSize,\n // lfhOffset} are 0xFFFFFFFF sentinels in the canonical fields. The extra\n // field stores them in the order listed in the spec (and omits any that\n // weren't sentinels), so we have to track which slots to read.\n const wantsUncomp = uncompSize === ZIP32_MAX_U32;\n const wantsComp = compSize === ZIP32_MAX_U32;\n const wantsOffset = lfhOffset === ZIP32_MAX_U32;\n if (wantsUncomp || wantsComp || wantsOffset) {\n const extra = readZip64Extra(b, p + 46 + nameLen, extraLen, wantsUncomp, wantsComp, wantsOffset, path);\n if (extra.uncompSize !== undefined) uncompSize = extra.uncompSize;\n if (extra.compSize !== undefined) compSize = extra.compSize;\n if (extra.lfhOffset !== undefined) lfhOffset = extra.lfhOffset;\n }\n entries.push({ path, lfhOffset, compMethod, compSize, uncompSize });\n p += 46 + nameLen + extraLen + commentLen;\n }\n return entries;\n}\n\n/**\n * RFC 1951 gives every deflate stream at least one block, and the last block\n * carries the BFINAL bit, so a method-8 entry declaring zero compressed bytes\n * has no stream to decode. Reject it where both read paths meet the bytes,\n * rather than letting each one invent an answer for an entry that isn't there.\n */\nconst requireDeflatePayload = (path: string, compressed: Uint8Array): void => {\n if (compressed.byteLength === 0) {\n throw new OpenXmlIoError(`openZip: entry \"${path}\" is declared DEFLATE but carries no compressed bytes`);\n }\n};\n\n/** Message for a deflate stream that runs out before signalling its last block. */\nconst incompleteDeflateError = (path: string): OpenXmlIoError =>\n new OpenXmlIoError(`openZip: deflate stream for \"${path}\" ended before its final block`);\n\n/** Read the compressed bytes for a CD entry by walking its local file header. */\nfunction readCompressedBytes(b: Uint8Array, entry: CdEntry): Uint8Array {\n if (u32(b, entry.lfhOffset) !== SIG_LFH) {\n throw new OpenXmlIoError(`openZip: malformed local file header for \"${entry.path}\"`);\n }\n const nameLen = u16(b, entry.lfhOffset + 26);\n const extraLen = u16(b, entry.lfhOffset + 28);\n const dataStart = entry.lfhOffset + 30 + nameLen + extraLen;\n // `subarray` clamps to the end of the buffer instead of throwing, so without\n // this an entry whose declared span runs past EOF would silently inflate (or\n // pass STORE through) from however many bytes happened to be left.\n if (dataStart + entry.compSize > b.length) {\n throw new OpenXmlIoError(\n `openZip: entry \"${entry.path}\" declares ${entry.compSize} compressed bytes at offset ${dataStart},` +\n ` past the end of the ${b.length}-byte archive`,\n );\n }\n return b.subarray(dataStart, dataStart + entry.compSize);\n}\n\n/**\n * Open a buffered xlsx archive in random-access mode. The archive bytes stay\n * resident; entries inflate on demand inside `read(path)`.\n *\n * Falls back to `fflate.unzipSync` when the central directory uses ZIP64\n * sentinel values (entry count == 0xFFFF or any size field == 0xFFFFFFFF) so\n * external ZIP64 archives still load. xlsx files in the wild fit comfortably in\n * ZIP32; the fallback exists for safety.\n *\n * `decompressionLimits` opts the archive into the zip-bomb safeguards\n * documented on {@link DecompressionLimits}; pass `false` to disable. Defaults\n * fit any legitimate xlsx.\n */\nexport function openRandomAccessArchive(\n bytes: Uint8Array,\n decompressionLimits?: DecompressionLimitsInput,\n): ZipArchive {\n // Quick sanity on min archive size.\n if (bytes.length < 22) {\n throw new OpenXmlIoError('openZip: archive is shorter than the minimum EOCD size (22 bytes)');\n }\n\n let eocdOff: number;\n try {\n eocdOff = findEocd(bytes);\n } catch (cause) {\n throw new OpenXmlIoError('openZip: archive is not a valid zip', { cause });\n }\n\n const resolvedLimits = resolveDecompressionLimits(decompressionLimits);\n\n // Detect ZIP64 up front so a malformed ZIP64 record fails closed instead of\n // falling back to `unzipSync`. The fallback inflates every entry before any\n // bomb cap runs; the whole point of the ZIP64 path is to keep the streaming\n // caps in play, so we must not silently downgrade when ZIP64 is in use.\n const eocdTotalEntries = u16(bytes, eocdOff + 10);\n const eocdCdSize = u32(bytes, eocdOff + 12);\n const eocdCdOffset = u32(bytes, eocdOff + 16);\n const claimsZip64 =\n eocdTotalEntries === ZIP32_MAX_U16 ||\n eocdCdSize === ZIP32_MAX_U32 ||\n eocdCdOffset === ZIP32_MAX_U32;\n\n let summary: CdSummary;\n try {\n summary = readCdSummary(bytes, eocdOff);\n } catch (cause) {\n if (claimsZip64) {\n // ZIP64 sentinels are set but the matching record / locator is missing\n // or invalid. Fail closed — `unzipSync` would inflate every entry.\n throw cause instanceof OpenXmlIoError\n ? cause\n : new OpenXmlIoError('openZip: ZIP64 central directory is malformed', { cause });\n }\n // Plain ZIP32 with an unparseable EOCD — fflate's `unzipSync` is more\n // tolerant of quirky archives; the post-hoc bomb check still applies.\n return openViaUnzipSync(bytes, resolvedLimits);\n }\n\n let entries: CdEntry[];\n try {\n entries = parseCentralDirectory(bytes, summary.cdOffset, summary.totalEntries);\n } catch (cause) {\n if (claimsZip64) {\n throw cause instanceof OpenXmlIoError\n ? cause\n : new OpenXmlIoError('openZip: ZIP64 central directory is malformed', { cause });\n }\n // Malformed ZIP32 CD — fall back to fflate which is more tolerant.\n return openViaUnzipSync(bytes, resolvedLimits);\n }\n\n const byPath = new Map<string, CdEntry>();\n for (const e of entries) byPath.set(e.path, e);\n\n const budget: DecompressionBudget | null = resolvedLimits ? createBudget(resolvedLimits) : null;\n if (budget) {\n // Declared CD totals are cheap to inspect — reject obvious bombs before\n // wiring up the inflate state machine.\n checkDeclaredTotals(budget, entries);\n }\n\n // Re-read cache for small entries, so the `.rels` parts the passthrough walk\n // revisits do not inflate twice.\n const inflateCache = createInflateCache();\n let live = true;\n let archiveBytes: Uint8Array | undefined = bytes;\n\n const ensureLive = (): Uint8Array => {\n if (!live || !archiveBytes) {\n throw new OpenXmlIoError('openZip: archive is closed');\n }\n return archiveBytes;\n };\n\n const readEntry = (path: string): Uint8Array => {\n const buf = ensureLive();\n const cached = inflateCache.get(path);\n if (cached) return cached;\n const entry = byPath.get(path);\n if (!entry) {\n throw new OpenXmlIoError(`openZip: no entry at \"${path}\"`);\n }\n const compressed = readCompressedBytes(buf, entry);\n let out: Uint8Array;\n if (entry.compMethod === COMP_STORE) {\n // STORE has ratio 1, so the only thing left to check is the absolute\n // size cap (and the running archive total).\n if (budget) {\n if (compressed.byteLength > budget.limits.maxEntryUncompressedBytes) {\n throw entryOverflowError(path, budget.limits.maxEntryUncompressedBytes);\n }\n const record = beginEntryInflate(budget, path);\n record(compressed.byteLength);\n }\n // Copy so callers can safely mutate the returned bytes without perturbing\n // the underlying archive view.\n out = compressed.slice();\n } else if (entry.compMethod === COMP_DEFLATE) {\n out = inflateBounded(path, compressed, budget);\n } else {\n throw new OpenXmlIoError(`openZip: unsupported compression method ${entry.compMethod} for \"${path}\"`);\n }\n inflateCache.set(path, out);\n return out;\n };\n\n const readEntryStream = (path: string): ReadableStream<Uint8Array> => {\n const buf = ensureLive();\n const cached = inflateCache.get(path);\n if (cached) return singleChunkStream(cached);\n const entry = byPath.get(path);\n if (!entry) {\n throw new OpenXmlIoError(`openZip: no entry at \"${path}\"`);\n }\n const compressed = readCompressedBytes(buf, entry);\n if (entry.compMethod === COMP_STORE) {\n // STORE means the bytes on disk are the bytes the caller wants; no need\n // to involve the inflate state machine. Run the same caps the sync\n // `read()` STORE branch applies — otherwise an uncompressed bomb entry\n // reached via `readStream()` would bypass the per-entry / archive-total\n // accounting. Ratio is fixed at 1, so only the absolute bounds apply.\n if (budget) {\n if (compressed.byteLength > budget.limits.maxEntryUncompressedBytes) {\n throw entryOverflowError(path, budget.limits.maxEntryUncompressedBytes);\n }\n const record = beginEntryInflate(budget, path);\n record(compressed.byteLength);\n }\n // Copy because callers may mutate the returned bytes.\n return singleChunkStream(compressed.slice());\n }\n if (entry.compMethod !== COMP_DEFLATE) {\n throw new OpenXmlIoError(`openZip: unsupported compression method ${entry.compMethod} for \"${path}\"`);\n }\n requireDeflatePayload(path, compressed);\n // DEFLATE: drive fflate's `Inflate` from `pull()` so the consumer's\n // demand controls how much we inflate. Each `pull()` either emits one\n // already-buffered inflated chunk or pushes one more block of compressed\n // input — never both — so the ReadableStream internal queue stays at\n // depth 1 and the producer can't race ahead of the consumer.\n const entryCap = budget ? entryInflateCap(budget, compressed.byteLength) : Number.POSITIVE_INFINITY;\n const record = budget ? beginEntryInflate(budget, path) : null;\n let entryEmitted = 0;\n const pending: Uint8Array[] = [];\n let pushedOffset = 0;\n let inflaterFinal = false;\n let inflateError: Error | undefined;\n const inflater = new Inflate((chunk, final) => {\n if (inflateError) return;\n if (chunk.byteLength > 0) {\n entryEmitted += chunk.byteLength;\n if (entryEmitted > entryCap) {\n inflateError = entryOverflowError(path, entryCap);\n return;\n }\n if (record) {\n try {\n record(chunk.byteLength);\n } catch (err) {\n inflateError = err as Error;\n return;\n }\n }\n pending.push(chunk);\n }\n if (final) inflaterFinal = true;\n });\n // Every `pull` must enqueue, close or error: a return that does none of\n // the three leaves the stream machinery to call it again with identical\n // state, which is an uncancellable busy loop. This is the close/error\n // half. An empty `pending` with every compressed byte pushed means there\n // is nothing left to emit, and getting there without a final block from\n // the inflater means the deflate stream ended early.\n const settleWhenDrained = (controller: ReadableStreamDefaultController<Uint8Array>): void => {\n if (pending.length > 0 || pushedOffset < compressed.byteLength) return;\n if (inflaterFinal) {\n controller.close();\n return;\n }\n controller.error(incompleteDeflateError(path));\n };\n return new ReadableStream<Uint8Array>({\n pull(controller) {\n if (inflateError) {\n controller.error(inflateError);\n return;\n }\n // Emit at most one already-buffered inflated chunk per pull; subsequent\n // pulls drain the rest. This caps the stream's internal queue at one\n // chunk regardless of how many ondata callbacks fflate fired off the\n // most recent push.\n const buffered = pending.shift();\n if (buffered) {\n controller.enqueue(buffered);\n settleWhenDrained(controller);\n return;\n }\n // No buffered output: push one block of compressed input and let\n // inflate's ondata fill `pending`. We stop pushing the moment we have\n // something to emit so the next pull can return it without racing\n // further inflation.\n while (pending.length === 0 && pushedOffset < compressed.byteLength) {\n const end = Math.min(pushedOffset + INFLATE_CHUNK_BYTES, compressed.byteLength);\n const slice = compressed.subarray(pushedOffset, end);\n const isLast = end >= compressed.byteLength;\n try {\n inflater.push(slice, isLast);\n } catch (cause) {\n if (!inflateError) {\n inflateError = new OpenXmlIoError(`openZip: failed to inflate \"${path}\"`, { cause });\n }\n controller.error(inflateError);\n return;\n }\n // The ondata callback may have set inflateError (decompression-bomb\n // guard tripping mid-inflate). Surface it to the consumer before\n // continuing — otherwise we'd loop forever on a CD-lying bomb whose\n // chunks all land beyond the cap and never make it into `pending`.\n if (inflateError) {\n controller.error(inflateError);\n return;\n }\n pushedOffset = end;\n }\n const next = pending.shift();\n if (next) {\n controller.enqueue(next);\n }\n settleWhenDrained(controller);\n },\n cancel() {\n // Consumer abandoned the stream early — drop buffered chunks and\n // advance the cursor past the end so the inflater and the compressed\n // slice are eligible for GC. fflate's `Inflate` has no terminate API\n // but losing the only reference is enough.\n pending.length = 0;\n pushedOffset = compressed.byteLength;\n inflaterFinal = true;\n },\n });\n };\n\n return {\n list(): string[] {\n ensureLive();\n return [...byPath.keys()].sort();\n },\n has(path: string): boolean {\n if (!live) return false;\n return byPath.has(path);\n },\n read(path: string): Uint8Array {\n return readEntry(path);\n },\n async readAsync(path: string): Promise<Uint8Array> {\n return readEntry(path);\n },\n readStream(path: string): ReadableStream<Uint8Array> {\n return readEntryStream(path);\n },\n close(): void {\n live = false;\n archiveBytes = undefined;\n inflateCache.clear();\n budget?.chargedByPath.clear();\n byPath.clear();\n },\n };\n}\n\n/**\n * Inflate `compressed` into a single `Uint8Array`, abort if it crosses the\n * configured per-entry cap or the archive-wide budget. Uses fflate's streaming\n * `Inflate` so the abort can fire on any internal block boundary rather than\n * after fflate has materialised the entire payload.\n */\nfunction inflateBounded(\n path: string,\n compressed: Uint8Array,\n budget: DecompressionBudget | null,\n): Uint8Array {\n requireDeflatePayload(path, compressed);\n const cap = budget ? entryInflateCap(budget, compressed.byteLength) : Number.POSITIVE_INFINITY;\n const record = budget ? beginEntryInflate(budget, path) : null;\n const acc: Uint8Array[] = [];\n let emitted = 0;\n let aborted: Error | undefined;\n let sawFinal = false;\n const inflater = new Inflate((chunk, final) => {\n // Record the final block before the early returns below: a zero-byte\n // entry's stream reports `final` on a chunk that carries no bytes.\n if (final) sawFinal = true;\n if (aborted) return;\n if (chunk.byteLength === 0) return;\n emitted += chunk.byteLength;\n if (emitted > cap) {\n aborted = entryOverflowError(path, cap);\n return;\n }\n if (record) {\n try {\n record(chunk.byteLength);\n } catch (err) {\n aborted = err as Error;\n return;\n }\n }\n acc.push(chunk);\n });\n let off = 0;\n while (off < compressed.byteLength) {\n const end = Math.min(off + INFLATE_CHUNK_BYTES, compressed.byteLength);\n const isLast = end >= compressed.byteLength;\n try {\n inflater.push(compressed.subarray(off, end), isLast);\n } catch (cause) {\n if (aborted) throw aborted;\n throw new OpenXmlIoError(`openZip: failed to inflate \"${path}\"`, { cause });\n }\n if (aborted) throw aborted;\n off = end;\n }\n if (!sawFinal) {\n throw incompleteDeflateError(path);\n }\n const out = new Uint8Array(emitted);\n let cursor = 0;\n for (const chunk of acc) {\n out.set(chunk, cursor);\n cursor += chunk.byteLength;\n }\n return out;\n}\n\n/**\n * Fallback for archives we can't parse ourselves. The random-access reader\n * now understands ZIP64 EOCD + the Zip64 Extended Information extra field, so\n * the only way to reach this path is a malformed central directory. fflate's\n * `unzipSync` is more forgiving but inflates every entry up front; for\n * adversarial archives we still rely on a post-hoc cap check (the only one\n * available without our own streaming decoder).\n */\nfunction openViaUnzipSync(\n bytes: Uint8Array,\n limits: ReturnType<typeof resolveDecompressionLimits>,\n): ZipArchive {\n let entries: Record<string, Uint8Array> | undefined;\n try {\n entries = unzipSync(bytes);\n } catch (cause) {\n throw new OpenXmlIoError('openZip: archive is not a valid zip', { cause });\n }\n // fflate's `unzipSync` returns already-inflated bytes — we can't abort the\n // inflate mid-flight here, but a post-hoc check still rejects a malicious\n // archive *before* any caller-level code touches the bytes. The peak memory\n // spike is bounded by what fflate just produced; the random-access path\n // catches the common cases (ZIP64 + malformed-but-parseable CDs) up front.\n if (limits) {\n const budget = createBudget(limits);\n for (const [path, payload] of Object.entries(entries)) {\n if (payload.byteLength > limits.maxEntryUncompressedBytes) {\n throw new OpenXmlDecompressionBombError(\n `openZip: entry \"${path}\" inflated to ${payload.byteLength} bytes,` +\n ` exceeding the ${limits.maxEntryUncompressedBytes}-byte per-entry limit` +\n ` (decompression-bomb guard).`,\n );\n }\n const record = beginEntryInflate(budget, path);\n record(payload.byteLength);\n }\n }\n let live = true;\n return {\n list(): string[] {\n if (!live || !entries) throw new OpenXmlIoError('openZip: archive is closed');\n return Object.keys(entries).sort();\n },\n has(path: string): boolean {\n if (!live || !entries) return false;\n return Object.hasOwn(entries, path);\n },\n read(path: string): Uint8Array {\n if (!live || !entries) throw new OpenXmlIoError('openZip: archive is closed');\n const e = entries[path];\n if (!e) throw new OpenXmlIoError(`openZip: no entry at \"${path}\"`);\n // Copy, as the random-access path does: `read` hands the caller an array\n // of its own, and this one holds every entry for the archive's lifetime.\n return e.slice();\n },\n async readAsync(path: string): Promise<Uint8Array> {\n return this.read(path);\n },\n readStream(path: string): ReadableStream<Uint8Array> {\n // The unzipSync fallback path already has the entry fully inflated\n // (that's the price of dropping back from random-access). Hand it out as\n // a single-chunk stream so callers using the streaming reader don't have\n // to branch on the implementation.\n const inflated = this.read(path);\n return singleChunkStream(inflated);\n },\n close(): void {\n live = false;\n entries = undefined;\n },\n };\n}\n","// ZIP read layer.\n//\n// `openZip(source)` walks the central directory once and inflates each entry on\n// demand inside `read(path)` (see `./random-access-reader.ts`). That keeps peak\n// memory at compressed-archive size + per-entry inflate scratch + the bounded\n// cache of small re-read entries (`./inflate-cache.ts`), instead of holding\n// every uncompressed entry resident at once the way the old `unzipSync`\n// shortcut did. The fallback path through fflate's `unzipSync` is preserved for\n// ZIP64 / non-standard archives.\n\nimport type { XlsxSource } from '../io/source.js';\nimport { OpenXmlIoError, OpenXmlNotImplementedError } from '../utils/exceptions.js';\nimport type { DecompressionLimits } from './decompression-guard.js';\nimport { openRandomAccessArchive } from './random-access-reader.js';\n\nconst CFB_MAGIC = [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1];\n\nconst isCfbCompoundDocument = (bytes: Uint8Array): boolean => {\n if (bytes.length < CFB_MAGIC.length) return false;\n for (let i = 0; i < CFB_MAGIC.length; i++) {\n if (bytes[i] !== CFB_MAGIC[i]) return false;\n }\n return true;\n};\n\nexport interface ZipArchive {\n /** Sorted list of all entry paths in the archive. */\n list(): string[];\n /**\n * Synchronous read; throws OpenXmlIoError when the path is unknown. Each\n * call returns an array the caller owns: mutating it changes neither the\n * archive nor what a later read of the same path returns.\n */\n read(path: string): Uint8Array;\n /** Promise variant for symmetry with the future streaming reader. */\n readAsync(path: string): Promise<Uint8Array>;\n /**\n * Streaming read: returns the entry's inflated bytes as a Web\n * `ReadableStream<Uint8Array>` chunk-by-chunk. Lets callers (the streaming\n * worksheet iterator, in particular) push the inflated payload through a SAX\n * parser without first materialising it in full — peak memory for a sheet\n * walk drops to the inflate window + SAX state instead of the entire\n * uncompressed worksheet body. Throws OpenXmlIoError when the path is\n * unknown.\n */\n readStream(path: string): ReadableStream<Uint8Array>;\n /** Whether the archive holds an entry at the given path. */\n has(path: string): boolean;\n /** Release the in-memory entry table. Subsequent reads throw. */\n close(): void;\n}\n\n/** Options for {@link openZip}. */\nexport interface OpenZipOptions {\n /**\n * Decompression-bomb safeguards applied while inflating archive entries. The\n * default limits admit any legitimate xlsx and reject pathological archives\n * (extreme compression ratios, gigabyte-scale entries). Pass `false` to\n * disable the guard entirely — only safe when the source is fully trusted.\n * See {@link DecompressionLimits} for the individual knobs.\n */\n decompressionLimits?: DecompressionLimits | false;\n}\n\n/**\n * Open a zip archive from any {@link XlsxSource}. The source is fully\n * materialised in memory, the central directory is parsed once, and each\n * entry is inflated on demand by {@link openRandomAccessArchive}: peak memory\n * stays at compressed-archive size, plus per-entry inflate scratch, plus a few\n * MB at most of small entries kept for re-reads, rather than holding every\n * uncompressed entry resident. The fflate `unzipSync` fallback is preserved\n * internally for ZIP64 / non-standard archives the random-access reader\n * rejects, and it does hold every entry inflated.\n */\nexport async function openZip(source: XlsxSource, opts: OpenZipOptions = {}): Promise<ZipArchive> {\n let bytes: Uint8Array;\n try {\n bytes = await source.toBytes();\n } catch (cause) {\n throw new OpenXmlIoError('openZip: failed to read source bytes', { cause });\n }\n\n // Encrypted xlsx files (Excel 2007+ password protection) wrap the real\n // package inside an OLE Compound File Binary container with the magic\n // signature `D0 CF 11 E0 A1 B1 1A E1`. Detect that early and surface a clear\n // \"decrypt first\" error rather than letting fflate fail with a generic\n // invalid-zip message.\n if (isCfbCompoundDocument(bytes)) {\n throw new OpenXmlNotImplementedError(\n 'Encrypted xlsx is not supported. Decrypt with msoffcrypto-tool first.',\n );\n }\n\n return openRandomAccessArchive(bytes, opts.decompressionLimits);\n}\n"],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { i as OpenXmlIoError, o as OpenXmlSchemaError } from "./exceptions-D-CFwxgm.mjs";
|
|
2
2
|
import { r as normalizeFormulaText } from "./inference-BMvv9cUY.mjs";
|
|
3
|
-
import { m as IMAGE_FORMAT_MIME, p as IMAGE_FORMAT_EXTENSION } from "./drawing-
|
|
4
|
-
import { n as escapeXmlAttr, r as escapeXmlText } from "./escape-
|
|
3
|
+
import { m as IMAGE_FORMAT_MIME, p as IMAGE_FORMAT_EXTENSION } from "./drawing-Cv6UtInY.mjs";
|
|
4
|
+
import { n as escapeXmlAttr, r as escapeXmlText } from "./escape-rA5UpibT.mjs";
|
|
5
5
|
import { At as parseQName, M as CPROPS_TYPE, _ as ARC_WORKBOOK_RELS, c as ARC_CONTENT_TYPES, ct as PKG_REL_NS, f as ARC_ROOT_RELS, ft as SHEET_MAIN_NS, g as ARC_WORKBOOK, h as ARC_THEME, l as ARC_CORE, lt as REL_NS, m as ARC_STYLE, mt as THEME_TYPE, p as ARC_SHARED_STRINGS, pt as STYLES_TYPE, s as ARC_APP, u as ARC_CUSTOM, ut as SHARED_STRINGS_TYPE, wt as XLSX_TYPE, x as CHARTEX_TYPE, yt as WORKSHEET_TYPE } from "./tree-BX-sRRVp.mjs";
|
|
6
|
-
import { C as
|
|
7
|
-
import { t as serializeXml } from "./serializer-
|
|
8
|
-
import { V as corePropsToBytes, a as makeManifest, l as extendedPropsToBytes, n as addOverride, rt as relsToBytes, s as manifestToBytes, t as addDefault, tt as makeRelationships, v as customPropsToBytes } from "./manifest-
|
|
9
|
-
import { D as makeSharedStrings,
|
|
6
|
+
import { C as userShapesToBytes, D as chartToBytes, g as chartsheetToBytes, i as commentsToBytes, m as drawingToBytes, o as placeholderVmlDrawing, r as tableToBytes, t as stylesheetToBytes, w as chartExToBytes, y as writeWorksheetXml } from "./stylesheet-writer-BBYjNSMA.mjs";
|
|
7
|
+
import { t as serializeXml } from "./serializer-dhv07Z6F.mjs";
|
|
8
|
+
import { V as corePropsToBytes, a as makeManifest, l as extendedPropsToBytes, n as addOverride, rt as relsToBytes, s as manifestToBytes, t as addDefault, tt as makeRelationships, v as customPropsToBytes } from "./manifest-BHUYpjUG.mjs";
|
|
9
|
+
import { D as makeSharedStrings, M as sharedStringsToBytes, S as validateSheetTitle } from "./workbook-CMel6UcI.mjs";
|
|
10
10
|
import { t as utf8ByteLength } from "./utf8-OAkCDG5g.mjs";
|
|
11
11
|
import { t as createZipWriter } from "./writer-C38RBZCy.mjs";
|
|
12
12
|
//#region src/io/save.ts
|
|
@@ -832,4 +832,4 @@ function serializeChildNode(node, inScopePrefixes) {
|
|
|
832
832
|
//#endregion
|
|
833
833
|
export { workbookToBytes as n, saveWorkbook as t };
|
|
834
834
|
|
|
835
|
-
//# sourceMappingURL=save-
|
|
835
|
+
//# sourceMappingURL=save-ax11Gsw0.mjs.map
|