@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
package/dist/streaming.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming.mjs","names":[],"sources":["../src/streaming/read-only.ts","../src/streaming/write-only.ts"],"sourcesContent":["// Streaming read-only workbook.\n//\n// `loadWorkbookStream` opens the zip + parses workbook.xml / sharedStrings.xml\n// / styles.xml metadata up front (small even on million-row archives), then\n// exposes a lazy `openWorksheet(name)` that SAX-iterates the sheet body via\n// `iterParse`. The iterator streams rows without materialising the full sheet\n// in memory.\n\nimport { makeSharedStrings, parseSharedStringsXml, type SharedStringsTable } from '../workbook/shared-strings.js';\nimport { ARC_CONTENT_TYPES, ARC_ROOT_RELS, ARC_SHARED_STRINGS, ARC_STYLE, REL_NS, SHEET_MAIN_NS } from '../xml/namespaces.js';\nimport { findById, relsFromBytes } from '../packaging/relationships.js';\nimport { manifestFromBytes } from '../packaging/manifest.js';\nimport { OpenXmlSchemaError } from '../utils/exceptions.js';\nimport type { DecompressionLimits } from '../zip/decompression-guard.js';\nimport { type ZipArchive, openZip } from '../zip/reader.js';\nimport type { CellValue, ExcelErrorCode } from '../cell/cell.js';\nimport { ERROR_CODES } from '../utils/inference.js';\nimport { iterParse, type SaxEvent, type SaxInput } from '../xml/iterparse.js';\nimport { parseXml } from '../xml/parser.js';\nimport { findChild, findChildren, type XmlNode } from '../xml/tree.js';\nimport type { XlsxSource } from '../io/source.js';\nimport { coordinateToTuple } from '../utils/coordinate.js';\nimport { type Stylesheet, makeStylesheet } from '../styles/stylesheet.js';\nimport { parseStylesheetXml } from '../styles/stylesheet-reader.js';\nimport { parseDate1904, resolveRelTarget } from '../io/load.js';\n\nconst SHEET_TAG = `{${SHEET_MAIN_NS}}sheet`;\nconst SHEETS_TAG = `{${SHEET_MAIN_NS}}sheets`;\n\nexport interface IterRowsOptions {\n minRow?: number;\n maxRow?: number;\n minCol?: number;\n maxCol?: number;\n}\n\nexport interface ReadOnlyCell {\n readonly row: number;\n readonly col: number;\n readonly value: CellValue;\n readonly styleId: number;\n}\n\nexport interface ReadOnlyWorksheet {\n title: string;\n iterRows(opts?: IterRowsOptions): AsyncIterableIterator<ReadOnlyCell[]>;\n iterValues(opts?: IterRowsOptions): AsyncIterableIterator<CellValue[]>;\n}\n\nexport interface ReadOnlyWorkbook {\n sheetNames: string[];\n styles: Stylesheet;\n /** Date1904 mode toggles between Excel's two epoch systems. */\n date1904: boolean;\n openWorksheet(name: string): ReadOnlyWorksheet;\n close(): Promise<void>;\n}\n\ninterface SheetEntry {\n name: string;\n rId: string;\n partPath: string;\n}\n\nconst parseSheetList = (root: XmlNode, workbookPath: string, archive: ZipArchive): SheetEntry[] => {\n const sheetsEl = findChild(root, SHEETS_TAG);\n if (!sheetsEl) return [];\n const wbRelsPath = relsPathFor(workbookPath);\n const wbRels = archive.has(wbRelsPath) ? relsFromBytes(archive.read(wbRelsPath)) : { rels: [] };\n const out: SheetEntry[] = [];\n for (const sheet of findChildren(sheetsEl, SHEET_TAG)) {\n const name = sheet.attrs['name'];\n const rId = sheet.attrs[`{${REL_NS}}id`];\n if (!name || !rId) continue;\n const rel = findById(wbRels, rId);\n if (!rel) continue;\n const partPath = resolveRelTarget(workbookPath, rel.target);\n out.push({ name, rId, partPath });\n }\n return out;\n};\n\nconst relsPathFor = (partPath: string): string => {\n const i = partPath.lastIndexOf('/');\n if (i < 0) return `_rels/${partPath}.rels`;\n return `${partPath.slice(0, i)}/_rels/${partPath.slice(i + 1)}.rels`;\n};\n\nconst localName = (qname: string): string => {\n const i = qname.lastIndexOf('}');\n return i < 0 ? qname : qname.slice(i + 1);\n};\n\nconst decodeCellValue = (\n t: string,\n vText: string | undefined,\n inlineText: string | undefined,\n sst: ReadonlyArray<string>,\n): CellValue => {\n switch (t) {\n case 'n':\n return vText !== undefined && vText !== '' ? Number.parseFloat(vText) : null;\n case 's': {\n if (vText === undefined) return null;\n const idx = Number.parseInt(vText, 10);\n if (!Number.isInteger(idx) || idx < 0 || idx >= sst.length) return null;\n return sst[idx] ?? null;\n }\n case 'b':\n return vText === '1';\n case 'e': {\n if (!vText || !ERROR_CODES.has(vText)) return null;\n return { kind: 'error', code: vText as ExcelErrorCode };\n }\n case 'str':\n return vText ?? '';\n case 'inlineStr':\n return inlineText ?? '';\n default:\n return vText !== undefined && vText !== '' ? Number.parseFloat(vText) : null;\n }\n};\n\n/**\n * SAX-iterate `<sheetData>/<row>/<c>` events out of the worksheet bytes (or a\n * stream that yields them), yielding one `ReadOnlyCell[]` per row that matches\n * `opts`.\n */\nasync function* iterSheetRows(\n sheetInput: SaxInput,\n sst: ReadonlyArray<string>,\n opts: IterRowsOptions,\n): AsyncIterableIterator<ReadOnlyCell[]> {\n const minRow = opts.minRow ?? 1;\n const maxRow = opts.maxRow ?? Number.POSITIVE_INFINITY;\n const minCol = opts.minCol ?? 1;\n const maxCol = opts.maxCol ?? Number.POSITIVE_INFINITY;\n\n let inSheetData = false;\n let currentRow = -1;\n let currentRowAttrs: Record<string, string> | null = null;\n let currentCells: ReadOnlyCell[] = [];\n\n // Per-cell state. Reset when each <c> starts.\n let cellOpen = false;\n let cellRow = 0;\n let cellCol = 0;\n let cellType = 'n';\n let cellStyleId = 0;\n let inV = false;\n let vText = '';\n let inIs = false;\n let inIsT = false;\n let isText = '';\n\n for await (const ev of iterParse(sheetInput)) {\n const e = ev as SaxEvent;\n if (e.kind === 'start') {\n const local = localName(e.name);\n if (!inSheetData) {\n if (local === 'sheetData') inSheetData = true;\n continue;\n }\n switch (local) {\n case 'row': {\n currentRowAttrs = e.attrs;\n const rRaw = e.attrs['r'];\n currentRow = rRaw ? Number.parseInt(rRaw, 10) : currentRow + 1;\n currentCells = [];\n break;\n }\n case 'c': {\n if (currentRow < 0) break;\n // Skip cell-attr parsing entirely when the row is outside the\n // requested band — saves the parseInt + coordinateToTuple hit on\n // every cell of every excluded row.\n if (currentRow < minRow || currentRow > maxRow) break;\n cellOpen = true;\n cellType = e.attrs['t'] ?? 'n';\n const sRaw = e.attrs['s'];\n cellStyleId = sRaw ? Number.parseInt(sRaw, 10) || 0 : 0;\n const ref = e.attrs['r'];\n if (ref) {\n const tup = coordinateToTuple(ref);\n cellRow = tup.row;\n cellCol = tup.col;\n } else {\n cellRow = currentRow;\n cellCol = (currentCells[currentCells.length - 1]?.col ?? 0) + 1;\n }\n vText = '';\n isText = '';\n break;\n }\n case 'v':\n if (cellOpen) inV = true;\n break;\n case 'is':\n if (cellOpen) inIs = true;\n break;\n case 't':\n if (inIs) inIsT = true;\n break;\n default:\n break;\n }\n continue;\n }\n if (e.kind === 'text') {\n if (inV) vText += e.text;\n else if (inIsT) isText += e.text;\n continue;\n }\n // end\n const local = localName(e.name);\n if (!inSheetData) continue;\n switch (local) {\n case 'sheetData':\n inSheetData = false;\n return;\n case 'row': {\n if (currentRow >= minRow && currentRow <= maxRow && currentCells.length > 0) {\n yield currentCells;\n }\n // Once we've crossed maxRow there are no more rows to yield — every\n // subsequent <row> would just be parsed and dropped. Stop iterating\n // early. ECMA-376 emits rows in ascending order.\n if (currentRow > maxRow) {\n inSheetData = false;\n return;\n }\n currentRow = -1;\n currentRowAttrs = null;\n currentCells = [];\n break;\n }\n case 'c': {\n if (cellOpen && cellCol >= minCol && cellCol <= maxCol && cellRow >= minRow && cellRow <= maxRow) {\n const value = decodeCellValue(cellType, vText, isText, sst);\n currentCells.push({ row: cellRow, col: cellCol, value, styleId: cellStyleId });\n }\n cellOpen = false;\n break;\n }\n case 'v':\n inV = false;\n break;\n case 'is':\n inIs = false;\n break;\n case 't':\n if (inIs) inIsT = false;\n break;\n default:\n break;\n }\n }\n // Avoid unused-var lint when row attrs never touched.\n void currentRowAttrs;\n}\n\nconst isXmlSpace = (b: number | undefined): boolean =>\n b === 0x20 /* sp */ || b === 0x09 /* tab */ || b === 0x0a /* lf */ || b === 0x0d /* cr */;\n\n/**\n * Read the `r=\"N\"` row number out of a `<row …>` attribute region, scanning\n * bytes directly. Returns -1 when the attribute is absent or malformed.\n *\n * Decoding the region to a string and running a regex instead costs one\n * TextDecoder, one string and one match array per row, which on a million-row\n * sheet dominates the scan this index exists to keep cheap.\n */\nconst readRowAttr = (bytes: Uint8Array, from: number, to: number): number => {\n for (let p = from; p + 3 < to; p++) {\n if (!isXmlSpace(bytes[p])) continue;\n if (bytes[p + 1] !== 0x72 /* 'r' */ || bytes[p + 2] !== 0x3d /* '=' */ || bytes[p + 3] !== 0x22 /* '\"' */) {\n continue;\n }\n let value = 0;\n let digits = 0;\n let q = p + 4;\n while (q < to) {\n const d = bytes[q];\n if (d === undefined || d < 0x30 || d > 0x39) break;\n value = value * 10 + (d - 0x30);\n digits++;\n q++;\n }\n // A non-numeric or unterminated `r` is not the row ref; keep scanning the\n // rest of the region the way the equivalent regex would have.\n if (digits > 0 && q < to && bytes[q] === 0x22 /* '\"' */) return value;\n }\n return -1;\n};\n\nconst isQuote = (b: number | undefined): boolean => b === 0x22 /* dquote */ || b === 0x27 /* squote */;\n\n/**\n * Byte offset just past the worksheet's opening `sheetData` tag, or\n * -1 when there is none. Skips the XML declaration, comments and processing\n * instructions ahead of it, and ignores `>` inside attribute values.\n */\nconst findSheetDataTagEnd = (bytes: Uint8Array): number => {\n const td = new TextDecoder();\n let i = 0;\n while (i < bytes.length) {\n if (bytes[i] !== 0x3c /* '<' */) {\n i++;\n continue;\n }\n const kind = bytes[i + 1];\n if (kind === 0x3f /* '?' */ || kind === 0x21 /* '!' */) {\n // Comments and processing instructions may contain `>` in their body.\n const isComment = bytes[i + 2] === 0x2d /* '-' */ && bytes[i + 3] === 0x2d;\n i += 2;\n while (i < bytes.length) {\n if (bytes[i] === 0x3e /* '>' */ &&\n (isComment ? bytes[i - 1] === 0x2d && bytes[i - 2] === 0x2d\n : kind !== 0x3f || bytes[i - 1] === 0x3f)) break;\n i++;\n }\n i++;\n continue;\n }\n let nameEnd = i + 1;\n while (nameEnd < bytes.length && !isXmlSpace(bytes[nameEnd]) && bytes[nameEnd] !== 0x3e && bytes[nameEnd] !== 0x2f) nameEnd++;\n const isSheetData = td.decode(bytes.subarray(i + 1, nameEnd)) === 'sheetData';\n let quote = 0;\n let tagEnd = -1;\n for (let j = i + 1; j < bytes.length; j++) {\n const b = bytes[j];\n if (b === undefined) break;\n if (quote !== 0) {\n if (b === quote) quote = 0;\n continue;\n }\n if (isQuote(b)) {\n quote = b;\n continue;\n }\n if (b === 0x3e /* '>' */) {\n tagEnd = j + 1;\n break;\n }\n }\n if (tagEnd < 0 || isSheetData) return tagEnd;\n i = tagEnd;\n }\n return -1;\n};\n\n/**\n * Build a sorted `[rowNum, byteOffset]` index for every `<row r=\"N\">`\n * occurrence in a worksheet's bytes. Pure byte-level scan (no SAX), cheap\n * relative to the per-cell SAX walk.\n *\n * `sheetDataEnd` is the byte offset of `</sheetData>` so callers can clip the\n * region that gets handed to saxes. `sheetDataTagEnd` includes the original\n * namespace-bearing ancestor tags, reused by {@link replayFromRow}.\n */\nconst buildRowOffsetIndex = (\n bytes: Uint8Array,\n): { index: ReadonlyArray<{ row: number; offset: number }>; sheetDataEnd: number; sheetDataTagEnd: number } => {\n const out: Array<{ row: number; offset: number }> = [];\n let sheetDataEnd = -1;\n let i = 0;\n while (i < bytes.length) {\n if (bytes[i] !== 0x3c /* '<' */) {\n i++;\n continue;\n }\n // Detect `</sheetData>` once — used to clip the slice fed to saxes.\n if (\n sheetDataEnd < 0 &&\n bytes[i + 1] === 0x2f /* '/' */ &&\n bytes[i + 2] === 0x73 /* 's' */ &&\n bytes[i + 3] === 0x68 /* 'h' */ &&\n bytes[i + 4] === 0x65 /* 'e' */ &&\n bytes[i + 5] === 0x65 /* 'e' */ &&\n bytes[i + 6] === 0x74 /* 't' */ &&\n bytes[i + 7] === 0x44 /* 'D' */ &&\n bytes[i + 8] === 0x61 /* 'a' */ &&\n bytes[i + 9] === 0x74 /* 't' */ &&\n bytes[i + 10] === 0x61 /* 'a' */ &&\n bytes[i + 11] === 0x3e /* '>' */\n ) {\n sheetDataEnd = i;\n break;\n }\n // Match `<row` followed by ASCII whitespace or '>'.\n if (\n bytes[i + 1] !== 0x72 /* 'r' */ ||\n bytes[i + 2] !== 0x6f /* 'o' */ ||\n bytes[i + 3] !== 0x77 /* 'w' */\n ) {\n i++;\n continue;\n }\n const next = bytes[i + 4];\n if (\n next !== 0x20 /* sp */ &&\n next !== 0x09 /* tab */ &&\n next !== 0x0a /* lf */ &&\n next !== 0x0d /* cr */ &&\n next !== 0x3e /* > */ &&\n next !== 0x2f /* / */\n ) {\n i++;\n continue;\n }\n // Walk to the closing '>'; the attrs region carries `r=\"N\"`.\n const start = i;\n let j = i + 4;\n while (j < bytes.length && bytes[j] !== 0x3e) j++;\n if (j >= bytes.length) break;\n const row = readRowAttr(bytes, start + 4, j);\n // Rows are 1-based (ECMA-376 §18.3.1.73), so `r=\"0\"` is not an offset this\n // index can seek to; -1 means there was no usable `r` at all.\n if (row > 0) out.push({ row, offset: start });\n i = j + 1;\n }\n if (sheetDataEnd < 0) sheetDataEnd = bytes.length;\n return { index: out, sheetDataEnd, sheetDataTagEnd: findSheetDataTagEnd(bytes) };\n};\n\n/**\n * Binary-search the row index for the first entry with `row >= target`. Returns\n * -1 when every recorded row is below the target.\n */\nconst firstRowAtOrAfter = (\n index: ReadonlyArray<{ row: number; offset: number }>,\n target: number,\n): number => {\n let lo = 0;\n let hi = index.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const entry = index[mid];\n if (!entry || entry.row < target) lo = mid + 1;\n else hi = mid;\n }\n return lo < index.length ? lo : -1;\n};\n\n/**\n * Replay a row band with the original prefix through the opening sheetData\n * tag. Namespace declarations can occur on either worksheet or sheetData;\n * synthesising either tag loses bindings required by the retained rows.\n * Views avoid copying the inflated sheet just to prepend its ancestor tags.\n */\nconst replayFromRow = (\n bytes: Uint8Array,\n sheetDataTagEnd: number,\n fromOffset: number,\n sheetDataEnd: number,\n): ReadableStream<Uint8Array> => {\n const parts = [\n bytes.subarray(0, sheetDataTagEnd),\n bytes.subarray(fromOffset, sheetDataEnd),\n bytes.subarray(sheetDataEnd),\n ];\n let next = 0;\n return new ReadableStream<Uint8Array>({\n pull(controller) {\n const part = parts[next];\n if (part === undefined) {\n controller.close();\n return;\n }\n next++;\n controller.enqueue(part);\n },\n });\n};\n\ninterface RowIndexCache {\n byWorksheet: WeakMap<object, ReturnType<typeof buildRowOffsetIndex> & { bytes: Uint8Array }>;\n}\n\n/**\n * Factory: build a {@link ReadOnlyWorksheet} bound to a single worksheet part\n * inside an opened archive. SAX iteration runs lazily: a whole-sheet `iterRows`\n * streams the part again on every call, so nothing but the inflate window and\n * the SAX state is ever resident.\n *\n * `iterRows({ minRow > 1 })` needs random access instead, so the first band\n * query inflates the part and indexes its row offsets, and holds both for the\n * life of the worksheet handle or until the workbook closes. Subsequent band\n * queries jump straight to the first matching row without inflating or scanning again.\n */\nconst makeStreamingReadOnlyWorksheet = (\n title: string,\n archive: ZipArchive,\n partPath: string,\n sst: ReadonlyArray<string>,\n indexes: RowIndexCache,\n): ReadOnlyWorksheet => {\n // Lazy + cached, bytes included: the archive only keeps small entries, so a\n // second band query that went back to `read` would inflate the whole part\n // again. The index adds one small object per row; the part is held from the first\n // band query until the worksheet handle goes away or the workbook closes.\n // This avoids parsing or inflating the whole part on every query.\n const cacheKey = {};\n const ensureIndexed = () => {\n let cached = indexes.byWorksheet.get(cacheKey);\n if (!cached) {\n const bytes = archive.read(partPath);\n cached = { bytes, ...buildRowOffsetIndex(bytes) };\n indexes.byWorksheet.set(cacheKey, cached);\n }\n return cached;\n };\n\n const iterRows = (opts: IterRowsOptions = {}): AsyncIterableIterator<ReadOnlyCell[]> => {\n const minRow = opts.minRow ?? 1;\n if (minRow <= 1) {\n // Whole-sheet (or no-min) iter — feed the SAX parser directly off the\n // archive's streaming inflate path so the worksheet's inflated payload\n // is never fully resident. Peak memory for the walk drops to the\n // inflate window + SAX state instead of the entire `<sheetData>` body.\n return iterSheetRows(archive.readStream(partPath), sst, opts);\n }\n // Band query (minRow > 1): the row-offset index needs the full inflated\n // bytes so we can binary-search to the byte offset of the first matching\n // row. Materialise once and reuse via `ensureIndexed`.\n const { bytes, index, sheetDataEnd, sheetDataTagEnd } = ensureIndexed();\n if (index.length === 0 || sheetDataTagEnd < 0) return iterSheetRows(bytes, sst, opts);\n const pos = firstRowAtOrAfter(index, minRow);\n if (pos < 0) {\n // Every row is below minRow, so there is nothing to yield.\n return (async function* () {})();\n }\n const target = index[pos];\n if (!target) return iterSheetRows(bytes, sst, opts);\n return iterSheetRows(replayFromRow(bytes, sheetDataTagEnd, target.offset, sheetDataEnd), sst, opts);\n };\n const iterValues = async function* (opts: IterRowsOptions = {}): AsyncIterableIterator<CellValue[]> {\n for await (const row of iterRows(opts)) {\n yield row.map((c) => c.value);\n }\n };\n return { title, iterRows, iterValues };\n};\n\n/**\n * Factory: build a {@link ReadOnlyWorkbook} from an opened archive + pre-parsed\n * sheet list / styles / shared strings. Per the project-wide \"no classes\" rule\n * (CLAUDE.md), the workbook is a plain object closing over the archive handle.\n */\nconst makeStreamingReadOnlyWorkbook = (\n sheetNames: string[],\n styles: Stylesheet,\n date1904: boolean,\n archive: ZipArchive,\n entries: ReadonlyMap<string, SheetEntry>,\n sst: ReadonlyArray<string>,\n): ReadOnlyWorkbook => {\n // Weak keys let unused worksheet handles release their indexed bytes. The\n // indirection also lets close() release every index while handles remain live.\n const indexes: RowIndexCache = { byWorksheet: new WeakMap() };\n return {\n sheetNames,\n styles,\n date1904,\n openWorksheet(name) {\n const entry = entries.get(name);\n if (!entry) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: no worksheet named \"${name}\"`);\n }\n return makeStreamingReadOnlyWorksheet(name, archive, entry.partPath, sst, indexes);\n },\n async close() {\n archive.close();\n indexes.byWorksheet = new WeakMap();\n },\n };\n};\n\n/** Options for {@link loadWorkbookStream}. */\nexport interface LoadWorkbookStreamOptions {\n /**\n * Decompression-bomb safeguards applied while inflating zip entries.\n * Defaults to limits that fit any legitimate xlsx; pass `false` to disable\n * (only safe for fully trusted sources).\n */\n decompressionLimits?: DecompressionLimits | false;\n}\n\n/** Open an xlsx for read-only streaming access. */\nexport async function loadWorkbookStream(\n source: XlsxSource,\n opts: LoadWorkbookStreamOptions = {},\n): Promise<ReadOnlyWorkbook> {\n const archive = await openZip(\n source,\n opts.decompressionLimits === undefined ? {} : { decompressionLimits: opts.decompressionLimits },\n );\n if (!archive.has(ARC_CONTENT_TYPES)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: missing \"${ARC_CONTENT_TYPES}\"`);\n }\n // Manifest parse is intentionally cheap and discarded — we resolve sheets by\n // walking workbook.xml.rels directly.\n manifestFromBytes(archive.read(ARC_CONTENT_TYPES));\n\n if (!archive.has(ARC_ROOT_RELS)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: missing \"${ARC_ROOT_RELS}\"`);\n }\n const rootRels = relsFromBytes(archive.read(ARC_ROOT_RELS));\n const officeDocRel = rootRels.rels.find((r) => r.type === `${REL_NS}/officeDocument`);\n if (!officeDocRel) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: no officeDocument relationship in root rels`);\n }\n const workbookPath = resolveRelTarget('', officeDocRel.target);\n if (!archive.has(workbookPath)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: workbook part \"${workbookPath}\" missing`);\n }\n const workbookRoot = parseXml(archive.read(workbookPath));\n const sheetEntries = parseSheetList(workbookRoot, workbookPath, archive);\n const entryMap = new Map<string, SheetEntry>();\n for (const e of sheetEntries) entryMap.set(e.name, e);\n\n let sst: SharedStringsTable = makeSharedStrings();\n if (archive.has(ARC_SHARED_STRINGS)) {\n sst = parseSharedStringsXml(archive.read(ARC_SHARED_STRINGS));\n }\n let styles: Stylesheet = makeStylesheet();\n if (archive.has(ARC_STYLE)) {\n styles = parseStylesheetXml(archive.read(ARC_STYLE));\n }\n\n return makeStreamingReadOnlyWorkbook(\n sheetEntries.map((e) => e.name),\n styles,\n parseDate1904(workbookRoot),\n archive,\n entryMap,\n sst.entries.map((e) => (typeof e === 'string' ? e : e.runs.map((r) => r.text).join(''))),\n );\n}\n","// Streaming write-only workbook.\n//\n// `createWriteOnlyWorkbook` lets callers append rows one at a time without\n// holding a full Workbook in memory. Each `appendRow` serialises the row\n// directly into a string buffer (no `Cell` objects, no Worksheet rows Map) —\n// when `close()` runs we glue the rows under a `<sheetData>` envelope and hand\n// the bytes to the streaming-deflate ZIP writer. The buffer keeps ~30 bytes per\n// cell of XML text instead of the ~200-byte V8 footprint a Cell + Map entry\n// costs, so the heap budget at 3M cells drops roughly an order of magnitude vs.\n// the previous setCell-based path.\n\nimport type { Cell, CellValue } from '../cell/cell.js';\nimport type { XlsxSink } from '../io/sink.js';\nimport { addDefault, addOverride, makeManifest, manifestToBytes } from '../packaging/manifest.js';\nimport { makeRelationships, relsToBytes } from '../packaging/relationships.js';\nimport {\n addCellXf,\n buildXfPatch,\n type CellStyleSpec,\n defaultCellXf,\n makeStylesheet,\n type Stylesheet,\n} from '../styles/stylesheet.js';\nimport { stylesheetToBytes } from '../styles/stylesheet-writer.js';\nimport { escapeXmlAttr } from '../utils/escape.js';\nimport { OpenXmlIoError } from '../utils/exceptions.js';\nimport { utf8ByteLength } from '../utils/utf8.js';\nimport { makeSharedStrings, sharedStringsToBytes } from '../workbook/shared-strings.js';\nimport { validateSheetTitle } from '../workbook/workbook.js';\nimport { serializeCell } from '../worksheet/writer.js';\nimport {\n ARC_CONTENT_TYPES,\n ARC_ROOT_RELS,\n ARC_SHARED_STRINGS,\n ARC_STYLE,\n ARC_WORKBOOK,\n ARC_WORKBOOK_RELS,\n PKG_REL_NS,\n REL_NS,\n SHARED_STRINGS_TYPE,\n SHEET_MAIN_NS,\n STYLES_TYPE,\n WORKSHEET_TYPE,\n XLSX_TYPE,\n} from '../xml/namespaces.js';\nimport { type CompressionLevel, createZipWriter, type ZipWriterOptions } from '../zip/writer.js';\n\nconst escapeAttr = escapeXmlAttr;\n\nexport interface WriteOnlyOptions {\n /** Reserved — currently ignored (the buffered backend doesn't honour it). */\n estimatedMaxRow?: number;\n /**\n * Last-modified timestamp for every ZIP entry. Same reproducibility story as\n * `SaveOptions.mtime`: unset, fflate stamps the wall clock per entry and two\n * runs over identical rows differ in bytes. Recorded as the date's UTC wall\n * time, to a two-second resolution, and the year has to fall in 1980-2099.\n */\n mtime?: Date;\n /** Deflate level, 0 (no compression) to 9 (smallest). Defaults to fflate's own 6. */\n compressionLevel?: CompressionLevel;\n}\n\n/**\n * A cell's look on the write-only path. Identical to the modelled writer's\n * {@link CellStyleSpec}: the two writers resolve a spec to an xf through the\n * same builder, so an axis added to one is honoured by both.\n */\nexport type WriteOnlyStyle = CellStyleSpec;\n\nexport type WriteOnlyRowItem = CellValue | { value: CellValue; style?: WriteOnlyStyle };\n\nexport interface WriteOnlyWorksheet {\n readonly title: string;\n appendRow(row: WriteOnlyRowItem[]): Promise<void>;\n setColumnWidth(col: number, width: number): void;\n close(): Promise<void>;\n}\n\nexport interface WriteOnlyWorkbook {\n /** Add a new worksheet. The previous worksheet must be `close()`d first. */\n addWorksheet(title: string): Promise<WriteOnlyWorksheet>;\n /** Finalise the archive: emits styles / sharedStrings / workbook / manifest / rels. */\n finalize(): Promise<void>;\n /**\n * Release the sink without finalising the archive. Call this from a\n * surrounding catch block when the producer pipeline throws before\n * `finalize()` — without it, streaming destinations (`toFile` /\n * `toWritable`) keep the file descriptor / Writable open and the partial\n * xlsx looks valid on disk.\n *\n * Idempotent. Subsequent `addWorksheet` / `finalize` calls throw.\n */\n abort(cause?: unknown): void;\n}\n\nconst validateTitle = (title: string, taken: Set<string>): void => {\n const reason = validateSheetTitle(title);\n if (reason) {\n throw new OpenXmlIoError(`Worksheet title \"${title}\": ${reason}`);\n }\n if (taken.has(title.toLowerCase())) {\n throw new OpenXmlIoError(`Worksheet title \"${title}\" is already in use`);\n }\n};\n\n/**\n * Allocate a CellXf id for a style spec. `defaultCellXf` omits `xfId`, which\n * skips the cellStyleXfs bounds check and matches what Excel emits when there\n * is no parent style.\n */\nconst allocateXfId = (ss: Stylesheet, style: WriteOnlyStyle): number =>\n addCellXf(ss, { ...defaultCellXf(), ...buildXfPatch(ss, style) });\n\ninterface WorkbookState {\n styles: Stylesheet;\n sst: ReturnType<typeof makeSharedStrings>;\n /** Sheet emit metadata, in addWorksheet order. */\n sheets: Array<{\n title: string;\n sheetId: number;\n }>;\n /** True once finalize() has been called (further mutations throw). */\n finalised: boolean;\n /** True while a worksheet is open (the next addWorksheet must wait). */\n hasOpenWorksheet: boolean;\n /** ZIP writer the workbook + each open worksheet stream chunks through. */\n writer: import('../zip/writer.js').ZipWriter;\n}\n\n/**\n * Flush threshold for the worksheet's pending-row text buffer. Smaller values\n * minimise heap; larger values amortise the TextEncoder + push overhead. 64 KB\n * is a sweet spot — heap stays low and per-row JS work is dominated by the\n * actual XML construction, not flushing.\n */\nconst FLUSH_THRESHOLD_BYTES = 64 * 1024;\n\n/**\n * Factory: build a {@link WriteOnlyWorksheet} that closes over the shared\n * {@link WorkbookState}. Per the project-wide \"no classes\" rule (CLAUDE.md) the\n * worksheet is a plain object holding the row buffer + column-width map in\n * closure state.\n *\n * The worksheet streams its `<sheetData>` body chunk-by-chunk through the ZIP\n * writer's `addStreamingEntry` API, so the heap footprint stays at one ~64 KB\n * pending text buffer plus deflate scratch — no Cell objects, no all-rows\n * accumulation. The XML envelope (decl / worksheet open / cols / sheetData\n * open) flushes on the first `appendRow` (or `close()` if the sheet is empty);\n * column widths staged via `setColumnWidth` *must* land before the first row.\n */\nconst makeWriteOnlyWorksheet = (state: WorkbookState, title: string, sheetId: number): WriteOnlyWorksheet => {\n let nextRow = 1;\n let closed = false;\n let headerFlushed = false;\n const columnWidths = new Map<number, number>();\n const dummyCtx = { sharedStrings: state.sst, styles: state.styles, rels: makeRelationships() };\n const encoder = new TextEncoder();\n const stream = state.writer.addStreamingEntry(`xl/worksheets/sheet${sheetId}.xml`);\n let pendingText = '';\n let pendingBytes = 0;\n\n const writeText = (text: string): void => {\n pendingText += text;\n // UTF-8 byte length, computed without a full encode: scan once and add the\n // exact codepoint cost. `text.length` would undercount CJK by ~3× and let\n // the buffer balloon past FLUSH_THRESHOLD_BYTES on Japanese / Chinese\n // workloads.\n pendingBytes += utf8ByteLength(text);\n if (pendingBytes >= FLUSH_THRESHOLD_BYTES) {\n stream.write(encoder.encode(pendingText));\n pendingText = '';\n pendingBytes = 0;\n }\n };\n\n const flushHeader = (): void => {\n if (headerFlushed) return;\n headerFlushed = true;\n let header = '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>';\n header += `<worksheet xmlns=\"${SHEET_MAIN_NS}\" xmlns:r=\"${REL_NS}\">`;\n if (columnWidths.size > 0) {\n header += '<cols>';\n const sorted = [...columnWidths.entries()].sort((a, b) => a[0] - b[0]);\n for (const [col, width] of sorted) {\n header += `<col min=\"${col}\" max=\"${col}\" width=\"${width}\" customWidth=\"1\"/>`;\n }\n header += '</cols>';\n }\n header += '<sheetData>';\n writeText(header);\n };\n\n const appendRow = async (row: WriteOnlyRowItem[]): Promise<void> => {\n if (closed) throw new OpenXmlIoError('appendRow: worksheet already closed');\n flushHeader();\n const r = nextRow++;\n let xml = `<row r=\"${r}\">`;\n for (let i = 0; i < row.length; i++) {\n const item = row[i];\n if (item === undefined || item === null) continue;\n const col = i + 1;\n let value: CellValue;\n let style: WriteOnlyStyle | undefined;\n if (item !== null && typeof item === 'object' && 'value' in (item as object)) {\n const wrapped = item as { value: CellValue; style?: WriteOnlyStyle };\n value = wrapped.value;\n style = wrapped.style;\n } else {\n value = item as CellValue;\n }\n const styleId = style ? allocateXfId(state.styles, style) : 0;\n // Ephemeral cell-shaped object — discarded as soon as serializeCell\n // returns its `<c .../>` string. Keeps the heap footprint at the size of\n // the pending text buffer instead of a full Worksheet model.\n const cell: Cell = { row: r, col, value, styleId };\n xml += serializeCell(cell, dummyCtx);\n }\n xml += '</row>';\n writeText(xml);\n };\n\n const setColumnWidth = (col: number, width: number): void => {\n if (closed) throw new OpenXmlIoError('setColumnWidth: worksheet already closed');\n if (headerFlushed) {\n throw new OpenXmlIoError(\n 'setColumnWidth: must be called before the first appendRow — column widths are emitted as part of the worksheet header',\n );\n }\n columnWidths.set(col, width);\n };\n\n const close = async (): Promise<void> => {\n if (closed) return;\n closed = true;\n flushHeader();\n writeText('</sheetData></worksheet>');\n if (pendingText.length > 0) {\n stream.write(encoder.encode(pendingText));\n pendingText = '';\n pendingBytes = 0;\n }\n await stream.end();\n state.sheets.push({ title, sheetId });\n state.hasOpenWorksheet = false;\n };\n\n return { title, appendRow, setColumnWidth, close };\n};\n\n/**\n * Factory: build a {@link WriteOnlyWorkbook} from a sink. State lives in a\n * closure rather than on a class instance per the project-wide \"no classes\"\n * rule (CLAUDE.md).\n */\nconst makeWriteOnlyWorkbook = (sink: XlsxSink, zipOpts: ZipWriterOptions): WriteOnlyWorkbook => {\n const styles = makeStylesheet();\n // Reserve cellXfs[0] for the default (no apply* flags). Unstyled cells point\n // at this slot via styleId=0; user-styled cells start at index 1 so the\n // writer emits an `s=\"N\"` attribute for them.\n addCellXf(styles, defaultCellXf());\n // The ZIP writer is created up front: each addWorksheet opens a streaming\n // entry on it and flushes row chunks through the deflate stream as they\n // arrive. Sheets emit before styles / sst / workbook / rels / content-types\n // so the writer can serialise them in order.\n const state: WorkbookState = {\n styles,\n sst: makeSharedStrings(),\n sheets: [],\n finalised: false,\n hasOpenWorksheet: false,\n writer: createZipWriter(sink, zipOpts),\n };\n\n const addWorksheet = async (title: string): Promise<WriteOnlyWorksheet> => {\n if (state.finalised) {\n throw new OpenXmlIoError('addWorksheet: workbook already finalised');\n }\n if (state.hasOpenWorksheet) {\n throw new OpenXmlIoError(\n 'addWorksheet: previous worksheet still open — call close() before opening the next one',\n );\n }\n const taken = new Set(state.sheets.map((s) => s.title.toLowerCase()));\n validateTitle(title, taken);\n state.hasOpenWorksheet = true;\n const sheetId = state.sheets.length + 1;\n return makeWriteOnlyWorksheet(state, title, sheetId);\n };\n\n const finalize = async (): Promise<void> => {\n if (state.finalised) {\n throw new OpenXmlIoError('finalize: already finalised');\n }\n if (state.hasOpenWorksheet) {\n throw new OpenXmlIoError('finalize: a worksheet is still open — call close() before finalising');\n }\n state.finalised = true;\n const writer = state.writer;\n try {\n await finalizeImpl(state, writer);\n } catch (err) {\n // Release the sink so the half-emitted archive doesn't linger as a\n // valid-looking file on disk. Awaited so `toFile` has finished removing\n // it by the time the caller sees the error. abort() is idempotent.\n await writer.abort(err);\n throw err;\n }\n };\n\n const abort = (cause?: unknown): void => {\n if (state.finalised) return;\n state.finalised = true;\n // Sync by contract, so a `toFile` sink's unlink can still be in flight when\n // this returns. The failure paths that have to guarantee cleanup before the\n // caller sees an error await the writer's abort themselves.\n void state.writer.abort(cause);\n };\n\n return { addWorksheet, finalize, abort };\n};\n\nasync function finalizeImpl(state: WorkbookState, writer: WorkbookState['writer']): Promise<void> {\n // 1. Worksheets — already streamed through writer.addStreamingEntry\n // during each WriteOnlyWorksheet's appendRow / close cycle.\n\n // 2. Stylesheet.\n await writer.addEntry(ARC_STYLE, stylesheetToBytes(state.styles));\n\n // 3. SharedStrings (only when non-empty).\n if (state.sst.entries.length > 0) {\n await writer.addEntry(ARC_SHARED_STRINGS, sharedStringsToBytes(state.sst));\n }\n\n // 4. workbook.xml.\n const workbookXml = serializeWorkbookXml(state.sheets);\n await writer.addEntry(ARC_WORKBOOK, new TextEncoder().encode(workbookXml));\n\n // 5. workbook.xml.rels.\n const wbRels = makeRelationships();\n state.sheets.forEach((s, i) => {\n wbRels.rels.push({\n id: `rId${i + 1}`,\n type: `${REL_NS}/worksheet`,\n target: `worksheets/sheet${s.sheetId}.xml`,\n });\n });\n if (state.sst.entries.length > 0) {\n wbRels.rels.push({\n id: `rId${wbRels.rels.length + 1}`,\n type: `${REL_NS}/sharedStrings`,\n target: 'sharedStrings.xml',\n });\n }\n wbRels.rels.push({\n id: `rId${wbRels.rels.length + 1}`,\n type: `${REL_NS}/styles`,\n target: 'styles.xml',\n });\n await writer.addEntry(ARC_WORKBOOK_RELS, relsToBytes(wbRels));\n\n // 6. root rels.\n const rootRels = makeRelationships();\n rootRels.rels.push({\n id: 'rId1',\n type: `${REL_NS}/officeDocument`,\n target: 'xl/workbook.xml',\n });\n await writer.addEntry(ARC_ROOT_RELS, relsToBytes(rootRels));\n void PKG_REL_NS; // imported for future docProps support\n\n // 7. [Content_Types].xml.\n const manifest = makeManifest();\n // Excel rejects packages whose [Content_Types].xml is missing the Default\n // entries for `rels` / `xml` — without them the package relationships file\n // can't be classified and Excel refuses to open.\n addDefault(manifest, 'rels', 'application/vnd.openxmlformats-package.relationships+xml');\n addDefault(manifest, 'xml', 'application/xml');\n addOverride(manifest, `/${ARC_WORKBOOK}`, XLSX_TYPE);\n for (const s of state.sheets) {\n addOverride(manifest, `/xl/worksheets/sheet${s.sheetId}.xml`, WORKSHEET_TYPE);\n }\n addOverride(manifest, `/${ARC_STYLE}`, STYLES_TYPE);\n if (state.sst.entries.length > 0) {\n addOverride(manifest, `/${ARC_SHARED_STRINGS}`, SHARED_STRINGS_TYPE);\n }\n await writer.addEntry(ARC_CONTENT_TYPES, manifestToBytes(manifest));\n\n await writer.finalize();\n}\n\nconst serializeWorkbookXml = (\n sheets: ReadonlyArray<{ title: string; sheetId: number }>,\n): string => {\n const parts: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>',\n `<workbook xmlns=\"${SHEET_MAIN_NS}\" xmlns:r=\"${REL_NS}\">`,\n '<sheets>',\n ];\n sheets.forEach((s, i) => {\n parts.push(\n `<sheet name=\"${escapeAttr(s.title)}\" sheetId=\"${s.sheetId}\" r:id=\"rId${i + 1}\"/>`,\n );\n });\n parts.push('</sheets></workbook>');\n return parts.join('');\n};\n\n/** Open a workbook for streaming write-only output. */\nexport async function createWriteOnlyWorkbook(\n sink: XlsxSink,\n opts: WriteOnlyOptions = {},\n): Promise<WriteOnlyWorkbook> {\n // The streaming-deflate ZIP writer is constructed eagerly here: each\n // addWorksheet opens an entry on it and flushes row chunks through fflate's\n // `Zip` + `ZipDeflate` immediately, so peak memory stays at one pending row\n // buffer plus deflate scratch (no all-sheets accumulation).\n return makeWriteOnlyWorkbook(sink, opts);\n}\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"streaming.mjs","names":[],"sources":["../src/streaming/read-only.ts","../src/streaming/string-table.ts","../src/streaming/write-only.ts"],"sourcesContent":["// Streaming read-only workbook.\n//\n// `loadWorkbookStream` opens the zip + parses workbook.xml / sharedStrings.xml\n// / styles.xml metadata up front (small even on million-row archives), then\n// exposes a lazy `openWorksheet(name)` that SAX-iterates the sheet body via\n// `iterParse`. The iterator streams rows without materialising the full sheet\n// in memory.\n\nimport { makeSharedStrings, parseSharedStringsXml, type SharedStringsTable } from '../workbook/shared-strings.js';\nimport { ARC_CONTENT_TYPES, ARC_ROOT_RELS } from '../xml/namespaces.js';\nimport { findById, findByType, makeRelationships, relsFromBytes } from '../packaging/relationships.js';\nimport { manifestFromBytes } from '../packaging/manifest.js';\nimport { parseCellNumber } from '../utils/cell-number.js';\nimport { OpenXmlSchemaError } from '../utils/exceptions.js';\nimport type { DecompressionLimits } from '../zip/decompression-guard.js';\nimport { type ZipArchive, openZip } from '../zip/reader.js';\nimport type { CellValue, ExcelErrorCode } from '../cell/cell.js';\nimport { unescapeCellString } from '../utils/escape.js';\nimport { ERROR_CODES } from '../utils/inference.js';\nimport { parseXsdBoolean } from '../utils/xsd-boolean.js';\nimport { iterParse, type SaxEvent, type SaxInput } from '../xml/iterparse.js';\nimport { parseXml } from '../xml/parser.js';\nimport type { XlsxSource } from '../io/source.js';\nimport { coordinateToTuple, derivedRowNumber, MAX_ROW, rowNumberFromAttr } from '../utils/coordinate.js';\nimport { type Stylesheet, makeStylesheet } from '../styles/stylesheet.js';\nimport { parseStylesheetXml } from '../styles/stylesheet-reader.js';\nimport {\n OFFICE_DOC_REL_TYPE,\n parseDate1904,\n parseSheetEntries,\n readOptionalWorkbookPart,\n resolveRelTarget,\n SHARED_STRINGS_PART,\n STYLES_PART,\n} from '../io/load.js';\n\nexport interface IterRowsOptions {\n minRow?: number;\n maxRow?: number;\n minCol?: number;\n maxCol?: number;\n}\n\nexport interface ReadOnlyCell {\n readonly row: number;\n readonly col: number;\n readonly value: CellValue;\n readonly styleId: number;\n}\n\nexport interface ReadOnlyWorksheet {\n title: string;\n iterRows(opts?: IterRowsOptions): AsyncIterableIterator<ReadOnlyCell[]>;\n iterValues(opts?: IterRowsOptions): AsyncIterableIterator<CellValue[]>;\n}\n\nexport interface ReadOnlyWorkbook {\n sheetNames: string[];\n styles: Stylesheet;\n /** Date1904 mode toggles between Excel's two epoch systems. */\n date1904: boolean;\n openWorksheet(name: string): ReadOnlyWorksheet;\n close(): Promise<void>;\n}\n\nconst relsPathFor = (partPath: string): string => {\n const i = partPath.lastIndexOf('/');\n if (i < 0) return `_rels/${partPath}.rels`;\n return `${partPath.slice(0, i)}/_rels/${partPath.slice(i + 1)}.rels`;\n};\n\nconst localName = (qname: string): string => {\n const i = qname.lastIndexOf('}');\n return i < 0 ? qname : qname.slice(i + 1);\n};\n\nconst decodeCellValue = (\n t: string,\n vText: string | undefined,\n inlineText: string | undefined,\n sst: ReadonlyArray<string>,\n sheet: string,\n col: number,\n row: number,\n): CellValue => {\n switch (t) {\n case 'n':\n // Throws on text or an exponent past the double range, as loadWorkbook\n // does: the two entry points have to answer the same bytes the same way,\n // and a null here would be indistinguishable from an empty cell.\n return parseCellNumber(vText, sheet, col, row);\n case 's': {\n if (vText === undefined) return null;\n const idx = Number.parseInt(vText, 10);\n if (!Number.isInteger(idx) || idx < 0 || idx >= sst.length) return null;\n return sst[idx] ?? null;\n }\n case 'b':\n // Invalid boolean values stay empty in this reader, like out-of-range\n // shared-string indexes. Numeric values have stricter validation.\n return parseXsdBoolean(vText) ?? null;\n case 'e': {\n if (!vText || !ERROR_CODES.has(vText)) return null;\n return { kind: 'error', code: vText as ExcelErrorCode };\n }\n case 'str':\n return vText ?? '';\n case 'inlineStr':\n return inlineText ?? '';\n default:\n // An unhandled `t` (`\"d\"`, or something not in ST_CellType at all). The\n // type says nothing about what the text holds, so there is no finiteness\n // rule to apply; loadWorkbook rejects the cell type outright instead.\n return vText !== undefined && vText !== '' ? Number.parseFloat(vText) : null;\n }\n};\n\n/**\n * SAX-iterate `<sheetData>/<row>/<c>` events out of the worksheet bytes (or a\n * stream that yields them), yielding one `ReadOnlyCell[]` per row that matches\n * `opts`.\n */\nasync function* iterSheetRows(\n title: string,\n sheetInput: SaxInput,\n sst: ReadonlyArray<string>,\n opts: IterRowsOptions,\n): AsyncIterableIterator<ReadOnlyCell[]> {\n const minRow = opts.minRow ?? 1;\n const maxRow = opts.maxRow ?? Number.POSITIVE_INFINITY;\n const minCol = opts.minCol ?? 1;\n const maxCol = opts.maxCol ?? Number.POSITIVE_INFINITY;\n\n let inSheetData = false;\n // -1: outside a <row>. 0: inside one that carried no `@r`, whose number the\n // first located cell settles. `nextRow` is the high-water mark a row with\n // neither an `@r` nor a located cell falls back to.\n let currentRow = -1;\n let nextRow = 1;\n let currentCells: ReadOnlyCell[] = [];\n let nextCol = 1;\n let pendingCells: Array<{ col: number; type: string; text: string; inline: string; styleId: number }> = [];\n const settleRow = (row: number): void => {\n currentRow = row;\n nextRow = Math.max(nextRow, row + 1);\n if (row >= minRow && row <= maxRow) {\n for (const cell of pendingCells) {\n currentCells.push({ row, col: cell.col, value: decodeCellValue(cell.type, cell.text, cell.inline, sst, title, cell.col, row), styleId: cell.styleId });\n }\n }\n pendingCells = [];\n };\n\n // Per-cell state. Reset when each <c> starts.\n let cellOpen = false;\n let cellRow = 0;\n let cellCol = 0;\n let cellType = 'n';\n let cellStyleId = 0;\n let inV = false;\n let vText = '';\n let inIs = false;\n let inIsT = false;\n let isText = '';\n let isRunText = '';\n\n for await (const ev of iterParse(sheetInput)) {\n const e = ev as SaxEvent;\n if (e.kind === 'start') {\n const local = localName(e.name);\n if (!inSheetData) {\n if (local === 'sheetData') inSheetData = true;\n continue;\n }\n switch (local) {\n case 'row': {\n // `@r` is optional on CT_Row (ECMA-376 §18.3.1.73); such a row waits\n // for its first cell to name it.\n const rRaw = e.attrs['r'];\n if (rRaw === undefined) {\n currentRow = 0;\n } else {\n currentRow = rowNumberFromAttr(rRaw, 'loadWorkbookStream');\n nextRow = Math.max(nextRow, currentRow + 1);\n }\n currentCells = [];\n pendingCells = [];\n nextCol = 1;\n break;\n }\n case 'c': {\n if (currentRow < 0) break;\n const ref = e.attrs['r'];\n if (currentRow === 0 && ref) settleRow(coordinateToTuple(ref).row);\n // Skip cell-attr parsing entirely when the row is outside the\n // requested band — saves the parseInt + coordinateToTuple hit on\n // every cell of every excluded row.\n if (currentRow !== 0 && (currentRow < minRow || currentRow > maxRow)) break;\n cellOpen = true;\n cellType = e.attrs['t'] ?? 'n';\n const sRaw = e.attrs['s'];\n cellStyleId = sRaw ? Number.parseInt(sRaw, 10) || 0 : 0;\n if (ref) {\n const tup = coordinateToTuple(ref);\n cellRow = tup.row;\n cellCol = tup.col;\n } else {\n cellRow = currentRow;\n cellCol = nextCol;\n }\n nextCol = cellCol + 1;\n vText = '';\n isText = '';\n break;\n }\n case 'v':\n if (cellOpen) inV = true;\n break;\n case 'is':\n if (cellOpen) inIs = true;\n break;\n case 't':\n if (inIs) {\n inIsT = true;\n isRunText = '';\n }\n break;\n default:\n break;\n }\n continue;\n }\n if (e.kind === 'text') {\n if (inV) vText += e.text;\n else if (inIsT) isRunText += e.text;\n continue;\n }\n // end\n const local = localName(e.name);\n if (!inSheetData) continue;\n switch (local) {\n case 'sheetData':\n inSheetData = false;\n return;\n case 'row': {\n // A row that held no located cell still consumes a slot, so settle it\n // before moving the high-water mark past it.\n if (currentRow === 0) {\n settleRow(derivedRowNumber(nextRow, 'loadWorkbookStream'));\n }\n if (currentRow >= minRow && currentRow <= maxRow && currentCells.length > 0) {\n yield currentCells;\n }\n // Once we've crossed maxRow there are no more rows to yield — every\n // subsequent <row> would just be parsed and dropped. Stop iterating\n // early. ECMA-376 emits rows in ascending order.\n if (currentRow > maxRow) {\n inSheetData = false;\n return;\n }\n currentRow = -1;\n currentCells = [];\n break;\n }\n case 'c': {\n if (cellOpen && cellRow === 0 && cellCol >= minCol && cellCol <= maxCol) {\n pendingCells.push({ col: cellCol, type: cellType, text: vText, inline: isText, styleId: cellStyleId });\n } else if (cellOpen && cellCol >= minCol && cellCol <= maxCol && cellRow >= minRow && cellRow <= maxRow) {\n const value = decodeCellValue(cellType, vText, isText, sst, title, cellCol, cellRow);\n currentCells.push({ row: cellRow, col: cellCol, value, styleId: cellStyleId });\n }\n cellOpen = false;\n break;\n }\n case 'v':\n inV = false;\n break;\n case 'is':\n inIs = false;\n break;\n case 't':\n if (inIsT) {\n // Decode each complete <t>, so SAX chunks can split an escape but\n // adjacent rich-text runs cannot accidentally create one.\n isText += unescapeCellString(isRunText);\n inIsT = false;\n }\n break;\n default:\n break;\n }\n }\n}\n\nconst isXmlSpace = (b: number | undefined): boolean =>\n b === 0x20 /* sp */ || b === 0x09 /* tab */ || b === 0x0a /* lf */ || b === 0x0d /* cr */;\n\n/**\n * Read the `r=\"N\"` row number out of a `<row …>` attribute region, scanning\n * bytes directly. Returns -1 when the attribute is absent, or holds anything\n * `parseRowNumberAttr` rejects: the two accept the same shapes, so the index\n * can never seek by a number the SAX walk reads differently.\n *\n * Decoding the region to a string and running a regex instead costs one\n * TextDecoder, one string and one match array per row, which on a million-row\n * sheet dominates the scan this index exists to keep cheap.\n */\nconst readRowAttr = (bytes: Uint8Array, from: number, to: number): number => {\n for (let p = from; p + 3 < to; p++) {\n if (!isXmlSpace(bytes[p])) continue;\n if (bytes[p + 1] !== 0x72 /* 'r' */ || bytes[p + 2] !== 0x3d /* '=' */ || bytes[p + 3] !== 0x22 /* '\"' */) {\n continue;\n }\n let q = p + 4;\n while (q < to && isXmlSpace(bytes[q])) q++;\n if (bytes[q] === 0x2b /* + */) q++;\n let value = 0;\n let digits = 0;\n while (q < to) {\n const d = bytes[q];\n if (d === undefined || d < 0x30 || d > 0x39) break;\n value = value * 10 + (d - 0x30);\n digits++;\n q++;\n }\n while (q < to && isXmlSpace(bytes[q])) q++;\n // A non-numeric, out-of-range or unterminated `r` is not the row ref; keep\n // scanning the rest of the region the way the equivalent regex would have.\n if (digits > 0 && value >= 1 && value <= MAX_ROW && q < to && bytes[q] === 0x22 /* '\"' */) return value;\n }\n return -1;\n};\n\nconst isQuote = (b: number | undefined): boolean => b === 0x22 /* dquote */ || b === 0x27 /* squote */;\n\n/**\n * Byte offset just past the worksheet's opening `sheetData` tag, or\n * -1 when there is none. Skips the XML declaration, comments and processing\n * instructions ahead of it, and ignores `>` inside attribute values.\n */\nconst findSheetDataTagEnd = (bytes: Uint8Array): number => {\n const td = new TextDecoder();\n let i = 0;\n while (i < bytes.length) {\n if (bytes[i] !== 0x3c /* '<' */) {\n i++;\n continue;\n }\n const kind = bytes[i + 1];\n if (kind === 0x3f /* '?' */ || kind === 0x21 /* '!' */) {\n // Comments and processing instructions may contain `>` in their body.\n const isComment = bytes[i + 2] === 0x2d /* '-' */ && bytes[i + 3] === 0x2d;\n i += 2;\n while (i < bytes.length) {\n if (bytes[i] === 0x3e /* '>' */ &&\n (isComment ? bytes[i - 1] === 0x2d && bytes[i - 2] === 0x2d\n : kind !== 0x3f || bytes[i - 1] === 0x3f)) break;\n i++;\n }\n i++;\n continue;\n }\n let nameEnd = i + 1;\n while (nameEnd < bytes.length && !isXmlSpace(bytes[nameEnd]) && bytes[nameEnd] !== 0x3e && bytes[nameEnd] !== 0x2f) nameEnd++;\n const isSheetData = td.decode(bytes.subarray(i + 1, nameEnd)) === 'sheetData';\n let quote = 0;\n let tagEnd = -1;\n for (let j = i + 1; j < bytes.length; j++) {\n const b = bytes[j];\n if (b === undefined) break;\n if (quote !== 0) {\n if (b === quote) quote = 0;\n continue;\n }\n if (isQuote(b)) {\n quote = b;\n continue;\n }\n if (b === 0x3e /* '>' */) {\n tagEnd = j + 1;\n break;\n }\n }\n if (tagEnd < 0 || isSheetData) return tagEnd;\n i = tagEnd;\n }\n return -1;\n};\n\n/**\n * Build a sorted `[rowNum, byteOffset]` index for every `<row r=\"N\">`\n * occurrence in a worksheet's bytes. Pure byte-level scan (no SAX), cheap\n * relative to the per-cell SAX walk.\n *\n * `sheetDataEnd` is the byte offset of `</sheetData>` so callers can clip the\n * region that gets handed to saxes. `sheetDataTagEnd` includes the original\n * namespace-bearing ancestor tags, reused by {@link replayFromRow}.\n *\n * `hasUnnumberedRow` reports a `<row>` this scan cannot number, which makes the\n * whole sheet unseekable: a row without `@r` takes the row its first cell\n * names, and reading cell refs is the SAX walk's job.\n */\nconst buildRowOffsetIndex = (\n bytes: Uint8Array,\n): {\n index: ReadonlyArray<{ row: number; offset: number }>;\n sheetDataEnd: number;\n sheetDataTagEnd: number;\n hasUnnumberedRow: boolean;\n} => {\n const out: Array<{ row: number; offset: number }> = [];\n let hasUnnumberedRow = false;\n let sheetDataEnd = -1;\n let i = 0;\n while (i < bytes.length) {\n if (bytes[i] !== 0x3c /* '<' */) {\n i++;\n continue;\n }\n // Detect `</sheetData>` once — used to clip the slice fed to saxes.\n if (\n sheetDataEnd < 0 &&\n bytes[i + 1] === 0x2f /* '/' */ &&\n bytes[i + 2] === 0x73 /* 's' */ &&\n bytes[i + 3] === 0x68 /* 'h' */ &&\n bytes[i + 4] === 0x65 /* 'e' */ &&\n bytes[i + 5] === 0x65 /* 'e' */ &&\n bytes[i + 6] === 0x74 /* 't' */ &&\n bytes[i + 7] === 0x44 /* 'D' */ &&\n bytes[i + 8] === 0x61 /* 'a' */ &&\n bytes[i + 9] === 0x74 /* 't' */ &&\n bytes[i + 10] === 0x61 /* 'a' */ &&\n bytes[i + 11] === 0x3e /* '>' */\n ) {\n sheetDataEnd = i;\n break;\n }\n // Match `<row` followed by ASCII whitespace or '>'.\n if (\n bytes[i + 1] !== 0x72 /* 'r' */ ||\n bytes[i + 2] !== 0x6f /* 'o' */ ||\n bytes[i + 3] !== 0x77 /* 'w' */\n ) {\n i++;\n continue;\n }\n const next = bytes[i + 4];\n if (\n next !== 0x20 /* sp */ &&\n next !== 0x09 /* tab */ &&\n next !== 0x0a /* lf */ &&\n next !== 0x0d /* cr */ &&\n next !== 0x3e /* > */ &&\n next !== 0x2f /* / */\n ) {\n i++;\n continue;\n }\n // Walk to the closing '>'; the attrs region carries `r=\"N\"`.\n const start = i;\n let j = i + 4;\n while (j < bytes.length && bytes[j] !== 0x3e) j++;\n if (j >= bytes.length) break;\n const row = readRowAttr(bytes, start + 4, j);\n if (row > 0) out.push({ row, offset: start });\n else hasUnnumberedRow = true;\n i = j + 1;\n }\n if (sheetDataEnd < 0) sheetDataEnd = bytes.length;\n return { index: out, sheetDataEnd, sheetDataTagEnd: findSheetDataTagEnd(bytes), hasUnnumberedRow };\n};\n\n/**\n * Binary-search the row index for the first entry with `row >= target`. Returns\n * -1 when every recorded row is below the target.\n */\nconst firstRowAtOrAfter = (\n index: ReadonlyArray<{ row: number; offset: number }>,\n target: number,\n): number => {\n let lo = 0;\n let hi = index.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const entry = index[mid];\n if (!entry || entry.row < target) lo = mid + 1;\n else hi = mid;\n }\n return lo < index.length ? lo : -1;\n};\n\n/**\n * Replay a row band with the original prefix through the opening sheetData\n * tag. Namespace declarations can occur on either worksheet or sheetData;\n * synthesising either tag loses bindings required by the retained rows.\n * Views avoid copying the inflated sheet just to prepend its ancestor tags.\n */\nconst replayFromRow = (\n bytes: Uint8Array,\n sheetDataTagEnd: number,\n fromOffset: number,\n sheetDataEnd: number,\n): ReadableStream<Uint8Array> => {\n const parts = [\n bytes.subarray(0, sheetDataTagEnd),\n bytes.subarray(fromOffset, sheetDataEnd),\n bytes.subarray(sheetDataEnd),\n ];\n let next = 0;\n return new ReadableStream<Uint8Array>({\n pull(controller) {\n const part = parts[next];\n if (part === undefined) {\n controller.close();\n return;\n }\n next++;\n controller.enqueue(part);\n },\n });\n};\n\n/**\n * A worksheet is seekable when every one of its rows carries an `@r` the byte\n * scan can read. Otherwise the scan's own numbering would disagree with the SAX\n * walk's, so band queries stream the part instead, and nothing is retained.\n */\ntype SheetSeek =\n | { seekable: false }\n | ({ seekable: true; bytes: Uint8Array } & Omit<ReturnType<typeof buildRowOffsetIndex>, 'hasUnnumberedRow'>);\n\ninterface RowIndexCache {\n byWorksheet: WeakMap<object, SheetSeek>;\n}\n\n/**\n * Factory: build a {@link ReadOnlyWorksheet} bound to a single worksheet part\n * inside an opened archive. SAX iteration runs lazily: a whole-sheet `iterRows`\n * streams the part again on every call, so nothing but the inflate window and\n * the SAX state is ever resident.\n *\n * `iterRows({ minRow > 1 })` needs random access instead, so the first band\n * query inflates the part and indexes its row offsets, and holds both for the\n * life of the worksheet handle or until the workbook closes. Subsequent band\n * queries jump straight to the first matching row without inflating or scanning\n * again. A sheet whose rows omit `@r` cannot be indexed by row number, so its\n * band queries keep streaming and hold nothing.\n */\nconst makeStreamingReadOnlyWorksheet = (\n title: string,\n archive: ZipArchive,\n partPath: string,\n sst: ReadonlyArray<string>,\n indexes: RowIndexCache,\n): ReadOnlyWorksheet => {\n // Lazy + cached, bytes included: the archive only keeps small entries, so a\n // second band query that went back to `read` would inflate the whole part\n // again. The index adds one small object per row; the part is held from the first\n // band query until the worksheet handle goes away or the workbook closes.\n // This avoids parsing or inflating the whole part on every query.\n const cacheKey = {};\n const ensureIndexed = (): SheetSeek => {\n let cached = indexes.byWorksheet.get(cacheKey);\n if (!cached) {\n const bytes = archive.read(partPath);\n const { hasUnnumberedRow, index, sheetDataEnd, sheetDataTagEnd } = buildRowOffsetIndex(bytes);\n cached = hasUnnumberedRow\n ? { seekable: false }\n : { seekable: true, bytes, index, sheetDataEnd, sheetDataTagEnd };\n indexes.byWorksheet.set(cacheKey, cached);\n }\n return cached;\n };\n\n const iterRows = (opts: IterRowsOptions = {}): AsyncIterableIterator<ReadOnlyCell[]> => {\n const minRow = opts.minRow ?? 1;\n if (minRow <= 1) {\n // Whole-sheet (or no-min) iter — feed the SAX parser directly off the\n // archive's streaming inflate path so the worksheet's inflated payload\n // is never fully resident. Peak memory for the walk drops to the\n // inflate window + SAX state instead of the entire `<sheetData>` body.\n return iterSheetRows(title, archive.readStream(partPath), sst, opts);\n }\n // Band query (minRow > 1): the row-offset index needs the full inflated\n // bytes so we can binary-search to the byte offset of the first matching\n // row. Materialise once and reuse via `ensureIndexed`.\n const seek = ensureIndexed();\n // Rows the index cannot number: walk the part instead of seeking into it,\n // which is the only way the derived numbers stay the SAX walk's.\n if (!seek.seekable) return iterSheetRows(title, archive.readStream(partPath), sst, opts);\n const { bytes, index, sheetDataEnd, sheetDataTagEnd } = seek;\n if (index.length === 0 || sheetDataTagEnd < 0) return iterSheetRows(title, bytes, sst, opts);\n const pos = firstRowAtOrAfter(index, minRow);\n if (pos < 0) {\n // Every row is below minRow, so there is nothing to yield.\n return (async function* () {})();\n }\n const target = index[pos];\n if (!target) return iterSheetRows(title, bytes, sst, opts);\n return iterSheetRows(title, replayFromRow(bytes, sheetDataTagEnd, target.offset, sheetDataEnd), sst, opts);\n };\n const iterValues = async function* (opts: IterRowsOptions = {}): AsyncIterableIterator<CellValue[]> {\n for await (const row of iterRows(opts)) {\n yield row.map((c) => c.value);\n }\n };\n return { title, iterRows, iterValues };\n};\n\n/**\n * Factory: build a {@link ReadOnlyWorkbook} from an opened archive + pre-parsed\n * sheet list / styles / shared strings. Per the project-wide \"no classes\" rule\n * (CLAUDE.md), the workbook is a plain object closing over the archive handle.\n */\nconst makeStreamingReadOnlyWorkbook = (\n sheetNames: string[],\n styles: Stylesheet,\n date1904: boolean,\n archive: ZipArchive,\n partPathByName: ReadonlyMap<string, string>,\n sst: ReadonlyArray<string>,\n): ReadOnlyWorkbook => {\n // Weak keys let unused worksheet handles release their indexed bytes. The\n // indirection also lets close() release every index while handles remain live.\n const indexes: RowIndexCache = { byWorksheet: new WeakMap() };\n return {\n sheetNames,\n styles,\n date1904,\n openWorksheet(name) {\n const partPath = partPathByName.get(name);\n if (partPath === undefined) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: no worksheet named \"${name}\"`);\n }\n return makeStreamingReadOnlyWorksheet(name, archive, partPath, sst, indexes);\n },\n async close() {\n archive.close();\n indexes.byWorksheet = new WeakMap();\n },\n };\n};\n\n/** Options for {@link loadWorkbookStream}. */\nexport interface LoadWorkbookStreamOptions {\n /**\n * Decompression-bomb safeguards applied while inflating zip entries.\n * Defaults to limits that fit any legitimate xlsx; pass `false` to disable\n * (only safe for fully trusted sources).\n */\n decompressionLimits?: DecompressionLimits | false;\n}\n\n/** Open an xlsx for read-only streaming access. */\nexport async function loadWorkbookStream(\n source: XlsxSource,\n opts: LoadWorkbookStreamOptions = {},\n): Promise<ReadOnlyWorkbook> {\n const archive = await openZip(\n source,\n opts.decompressionLimits === undefined ? {} : { decompressionLimits: opts.decompressionLimits },\n );\n if (!archive.has(ARC_CONTENT_TYPES)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: missing \"${ARC_CONTENT_TYPES}\"`);\n }\n // Manifest parse is intentionally cheap and discarded — we resolve sheets by\n // walking workbook.xml.rels directly.\n manifestFromBytes(archive.read(ARC_CONTENT_TYPES));\n\n if (!archive.has(ARC_ROOT_RELS)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: missing \"${ARC_ROOT_RELS}\"`);\n }\n const rootRels = relsFromBytes(archive.read(ARC_ROOT_RELS));\n const officeDocRel = findByType(rootRels, OFFICE_DOC_REL_TYPE);\n if (!officeDocRel) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: no officeDocument relationship in root rels`);\n }\n const workbookPath = resolveRelTarget('', officeDocRel.target);\n if (!archive.has(workbookPath)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: workbook part \"${workbookPath}\" missing`);\n }\n const workbookRoot = parseXml(archive.read(workbookPath));\n // loadWorkbook's `<sheets>` parser, and its rejections below: a declaration\n // that loader refuses must not read here as a workbook without that sheet.\n const declaredSheets = parseSheetEntries(workbookRoot);\n const wbRelsPath = relsPathFor(workbookPath);\n if (declaredSheets.length > 0 && !archive.has(wbRelsPath)) {\n throw new OpenXmlSchemaError(\n `loadWorkbookStream: workbook has sheets but rels part \"${wbRelsPath}\" is missing`,\n );\n }\n const wbRels = archive.has(wbRelsPath) ? relsFromBytes(archive.read(wbRelsPath)) : makeRelationships();\n const partPathByName = new Map<string, string>();\n for (const declared of declaredSheets) {\n if (partPathByName.has(declared.name)) {\n throw new OpenXmlSchemaError(`loadWorkbookStream: duplicate sheet name \"${declared.name}\"`);\n }\n const rel = findById(wbRels, declared.rId);\n if (!rel) {\n throw new OpenXmlSchemaError(\n `loadWorkbookStream: sheet \"${declared.name}\" rId \"${declared.rId}\" has no matching rels entry`,\n );\n }\n partPathByName.set(declared.name, resolveRelTarget(workbookPath, rel.target));\n }\n\n const sstBytes = readOptionalWorkbookPart(archive, workbookPath, wbRels, SHARED_STRINGS_PART);\n const sst: SharedStringsTable = sstBytes === undefined ? makeSharedStrings() : parseSharedStringsXml(sstBytes);\n const stylesBytes = readOptionalWorkbookPart(archive, workbookPath, wbRels, STYLES_PART);\n const styles: Stylesheet = stylesBytes === undefined ? makeStylesheet() : parseStylesheetXml(stylesBytes);\n\n return makeStreamingReadOnlyWorkbook(\n declaredSheets.map((e) => e.name),\n styles,\n parseDate1904(workbookRoot),\n archive,\n partPathByName,\n sst.entries.map((e) => (typeof e === 'string' ? e : e.runs.map((r) => r.text).join(''))),\n );\n}\n","import { serializeRichString } from '../workbook/shared-strings.js';\nimport type { CellStringWriter } from '../worksheet/writer.js';\nimport { SHEET_MAIN_NS } from '../xml/namespaces.js';\nimport type { StreamingEntryWriter } from '../zip/writer.js';\n\n// Entry count bounds Map/array overhead; payload bounds long strings and rich\n// text markup. UTF-16 accounting is deterministic, not an exact V8 heap metric.\nconst MAX_ENTRIES = 100_000;\nconst MAX_PAYLOAD_BYTES = 8 * 1024 * 1024;\nconst UTF16_BYTES_PER_UNIT = 2;\nconst XML_CHUNK_UNITS = 16 * 1024;\n\nexport const createWriteOnlyStringTable = () => {\n const entries: string[] = [];\n const plainIndex = new Map<string, number>();\n const richIndex = new Map<string, number>();\n let payloadBytes = 0;\n let full = false;\n\n const serialize: CellStringWriter = (value) => {\n const plain = typeof value === 'string';\n // Plain strings can hit the cache without escaping. Rich text is keyed by\n // its emitted XML, which snapshots caller-owned runs and font objects.\n const key = plain ? value : serializeRichString(value);\n const index = plain ? plainIndex : richIndex;\n const cached = index.get(key);\n if (cached !== undefined) return { type: 's', xml: `<v>${cached}</v>` };\n const body = plain ? serializeRichString(value) : key;\n // Count both keys and XML, conservatively even when they share storage.\n const bytes = (key.length + body.length) * UTF16_BYTES_PER_UNIT;\n if (!full && entries.length < MAX_ENTRIES && payloadBytes + bytes <= MAX_PAYLOAD_BYTES) {\n const id = entries.length;\n entries.push(body);\n index.set(key, id);\n payloadBytes += bytes;\n return { type: 's', xml: `<v>${id}</v>` };\n }\n // Never evict: earlier worksheet cells already reference these indices.\n // Once a new entry does not fit, all subsequent new values stay inline.\n full = true;\n return { type: 'inlineStr', xml: `<is>${body}</is>` };\n };\n\n const write = async (stream: StreamingEntryWriter): Promise<void> => {\n const encoder = new TextEncoder();\n let pending = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><sst xmlns=\"${SHEET_MAIN_NS}\" count=\"${entries.length}\" uniqueCount=\"${entries.length}\">`;\n const append = (text: string): void => {\n pending += text;\n while (pending.length >= XML_CHUNK_UNITS) {\n // TextEncoder must see surrogate pairs together, including at a chunk\n // boundary. Otherwise an astral character becomes two replacements.\n let end = XML_CHUNK_UNITS;\n const last = pending.charCodeAt(end - 1);\n if (last >= 0xd800 && last <= 0xdbff) end--;\n stream.write(encoder.encode(pending.slice(0, end)));\n pending = pending.slice(end);\n }\n };\n for (const body of entries) append(`<si>${body}</si>`);\n append('</sst>');\n if (pending.length > 0) stream.write(encoder.encode(pending));\n await stream.end();\n };\n\n return { serialize, write, get size() { return entries.length; } };\n};\n","// Rows are flushed through a bounded text buffer into the ZIP stream. The\n// workbook-wide string table has entry and payload limits; new strings beyond\n// those limits are written inline. Styles and sheet metadata remain resident.\n\nimport type { Cell, CellValue } from '../cell/cell.js';\nimport type { XlsxSink } from '../io/sink.js';\nimport { addDefault, addOverride, makeManifest, manifestToBytes } from '../packaging/manifest.js';\nimport { makeRelationships, relsToBytes } from '../packaging/relationships.js';\nimport {\n addCellXf,\n buildXfPatch,\n type CellStyleSpec,\n defaultCellXf,\n makeStylesheet,\n type Stylesheet,\n} from '../styles/stylesheet.js';\nimport { stylesheetToBytes } from '../styles/stylesheet-writer.js';\nimport { escapeXmlAttr } from '../utils/escape.js';\nimport { OpenXmlIoError } from '../utils/exceptions.js';\nimport { utf8ByteLength } from '../utils/utf8.js';\nimport { makeSharedStrings } from '../workbook/shared-strings.js';\nimport { validateSheetTitle } from '../workbook/workbook.js';\nimport { serializeCell } from '../worksheet/writer.js';\nimport {\n ARC_CONTENT_TYPES,\n ARC_ROOT_RELS,\n ARC_SHARED_STRINGS,\n ARC_STYLE,\n ARC_WORKBOOK,\n ARC_WORKBOOK_RELS,\n PKG_REL_NS,\n REL_NS,\n SHARED_STRINGS_TYPE,\n SHEET_MAIN_NS,\n STYLES_TYPE,\n WORKSHEET_TYPE,\n XLSX_TYPE,\n} from '../xml/namespaces.js';\nimport { type CompressionLevel, createZipWriter, type ZipWriterOptions } from '../zip/writer.js';\n\nimport { createWriteOnlyStringTable } from './string-table.js';\n\nconst escapeAttr = escapeXmlAttr;\n\nexport interface WriteOnlyOptions {\n /** Reserved — currently ignored (the buffered backend doesn't honour it). */\n estimatedMaxRow?: number;\n /**\n * Last-modified timestamp for every ZIP entry. Same reproducibility story as\n * `SaveOptions.mtime`: unset, fflate stamps the wall clock per entry and two\n * runs over identical rows differ in bytes. Recorded as the date's UTC wall\n * time, to a two-second resolution, and the year has to fall in 1980-2099.\n */\n mtime?: Date;\n /** Deflate level, 0 (no compression) to 9 (smallest). Defaults to fflate's own 6. */\n compressionLevel?: CompressionLevel;\n}\n\n/**\n * A cell's look on the write-only path. Identical to the modelled writer's\n * {@link CellStyleSpec}: the two writers resolve a spec to an xf through the\n * same builder, so an axis added to one is honoured by both.\n */\nexport type WriteOnlyStyle = CellStyleSpec;\n\nexport type WriteOnlyRowItem = CellValue | { value: CellValue; style?: WriteOnlyStyle };\n\nexport interface WriteOnlyWorksheet {\n readonly title: string;\n appendRow(row: WriteOnlyRowItem[]): Promise<void>;\n setColumnWidth(col: number, width: number): void;\n close(): Promise<void>;\n}\n\nexport interface WriteOnlyWorkbook {\n /** Add a new worksheet. The previous worksheet must be `close()`d first. */\n addWorksheet(title: string): Promise<WriteOnlyWorksheet>;\n /** Finalise the archive: emits styles / sharedStrings / workbook / manifest / rels. */\n finalize(): Promise<void>;\n /**\n * Release the sink without finalising the archive. Call this from a\n * surrounding catch block when the producer pipeline throws before\n * `finalize()` — without it, streaming destinations (`toFile` /\n * `toWritable`) keep the file descriptor / Writable open and the partial\n * xlsx looks valid on disk.\n *\n * Idempotent. Subsequent `addWorksheet` / `finalize` calls throw.\n */\n abort(cause?: unknown): void;\n}\n\nconst validateTitle = (title: string, taken: Set<string>): void => {\n const reason = validateSheetTitle(title);\n if (reason) {\n throw new OpenXmlIoError(`Worksheet title \"${title}\": ${reason}`);\n }\n if (taken.has(title.toLowerCase())) {\n throw new OpenXmlIoError(`Worksheet title \"${title}\" is already in use`);\n }\n};\n\n/**\n * Allocate a CellXf id for a style spec. `defaultCellXf` omits `xfId`, which\n * skips the cellStyleXfs bounds check and matches what Excel emits when there\n * is no parent style.\n */\nconst allocateXfId = (ss: Stylesheet, style: WriteOnlyStyle): number =>\n addCellXf(ss, { ...defaultCellXf(), ...buildXfPatch(ss, style) });\n\ninterface WorkbookState {\n styles: Stylesheet;\n strings: ReturnType<typeof createWriteOnlyStringTable>;\n /** Sheet emit metadata, in addWorksheet order. */\n sheets: Array<{\n title: string;\n sheetId: number;\n }>;\n /** True once finalize() has been called (further mutations throw). */\n finalised: boolean;\n /** True while a worksheet is open (the next addWorksheet must wait). */\n hasOpenWorksheet: boolean;\n /** ZIP writer the workbook + each open worksheet stream chunks through. */\n writer: import('../zip/writer.js').ZipWriter;\n}\n\n/**\n * Flush threshold for the worksheet's pending-row text buffer. Smaller values\n * minimise heap; larger values amortise the TextEncoder + push overhead. 64 KB\n * is a sweet spot — heap stays low and per-row JS work is dominated by the\n * actual XML construction, not flushing.\n */\nconst FLUSH_THRESHOLD_BYTES = 64 * 1024;\n\n/**\n * Factory: build a {@link WriteOnlyWorksheet} that closes over the shared\n * {@link WorkbookState}. Per the project-wide \"no classes\" rule (CLAUDE.md) the\n * worksheet is a plain object holding the row buffer + column-width map in\n * closure state.\n *\n * The worksheet streams its `<sheetData>` body chunk-by-chunk through the ZIP\n * writer's `addStreamingEntry` API. Row buffering stays at ~64 KB plus the\n * current row and deflate scratch; strings have a separate workbook-wide cap.\n * The XML envelope (decl / worksheet open / cols / sheetData open) flushes on\n * the first `appendRow` (or `close()` if the sheet is empty);\n * column widths staged via `setColumnWidth` *must* land before the first row.\n */\nconst makeWriteOnlyWorksheet = (state: WorkbookState, title: string, sheetId: number): WriteOnlyWorksheet => {\n let nextRow = 1;\n let closed = false;\n let headerFlushed = false;\n const columnWidths = new Map<number, number>();\n // Strings use the bounded workbook-wide writer; other cells still need\n // the regular serialization context (notably the shared style pool).\n const dummyCtx = { sharedStrings: makeSharedStrings(), styles: state.styles };\n const encoder = new TextEncoder();\n const stream = state.writer.addStreamingEntry(`xl/worksheets/sheet${sheetId}.xml`);\n let pendingText = '';\n let pendingBytes = 0;\n\n const writeText = (text: string): void => {\n pendingText += text;\n // UTF-8 byte length, computed without a full encode: scan once and add the\n // exact codepoint cost. `text.length` would undercount CJK by ~3× and let\n // the buffer balloon past FLUSH_THRESHOLD_BYTES on Japanese / Chinese\n // workloads.\n pendingBytes += utf8ByteLength(text);\n if (pendingBytes >= FLUSH_THRESHOLD_BYTES) {\n stream.write(encoder.encode(pendingText));\n pendingText = '';\n pendingBytes = 0;\n }\n };\n\n const flushHeader = (): void => {\n if (headerFlushed) return;\n headerFlushed = true;\n let header = '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>';\n header += `<worksheet xmlns=\"${SHEET_MAIN_NS}\" xmlns:r=\"${REL_NS}\">`;\n if (columnWidths.size > 0) {\n header += '<cols>';\n const sorted = [...columnWidths.entries()].sort((a, b) => a[0] - b[0]);\n for (const [col, width] of sorted) {\n header += `<col min=\"${col}\" max=\"${col}\" width=\"${width}\" customWidth=\"1\"/>`;\n }\n header += '</cols>';\n }\n header += '<sheetData>';\n writeText(header);\n };\n\n const appendRow = async (row: WriteOnlyRowItem[]): Promise<void> => {\n if (closed) throw new OpenXmlIoError('appendRow: worksheet already closed');\n flushHeader();\n const r = nextRow++;\n let xml = `<row r=\"${r}\">`;\n for (let i = 0; i < row.length; i++) {\n const item = row[i];\n if (item === undefined || item === null) continue;\n const col = i + 1;\n let value: CellValue;\n let style: WriteOnlyStyle | undefined;\n if (item !== null && typeof item === 'object' && 'value' in (item as object)) {\n const wrapped = item as { value: CellValue; style?: WriteOnlyStyle };\n value = wrapped.value;\n style = wrapped.style;\n } else {\n value = item as CellValue;\n }\n const styleId = style ? allocateXfId(state.styles, style) : 0;\n // Ephemeral cell-shaped object — discarded as soon as serializeCell\n // returns its `<c .../>` string. Keeps the heap footprint at the size of\n // the pending text buffer instead of a full Worksheet model.\n const cell: Cell = { row: r, col, value, styleId };\n xml += serializeCell(cell, dummyCtx, state.strings.serialize);\n }\n xml += '</row>';\n writeText(xml);\n };\n\n const setColumnWidth = (col: number, width: number): void => {\n if (closed) throw new OpenXmlIoError('setColumnWidth: worksheet already closed');\n if (headerFlushed) {\n throw new OpenXmlIoError(\n 'setColumnWidth: must be called before the first appendRow — column widths are emitted as part of the worksheet header',\n );\n }\n columnWidths.set(col, width);\n };\n\n const close = async (): Promise<void> => {\n if (closed) return;\n closed = true;\n flushHeader();\n writeText('</sheetData></worksheet>');\n if (pendingText.length > 0) {\n stream.write(encoder.encode(pendingText));\n pendingText = '';\n pendingBytes = 0;\n }\n await stream.end();\n state.sheets.push({ title, sheetId });\n state.hasOpenWorksheet = false;\n };\n\n return { title, appendRow, setColumnWidth, close };\n};\n\n/**\n * Factory: build a {@link WriteOnlyWorkbook} from a sink. State lives in a\n * closure rather than on a class instance per the project-wide \"no classes\"\n * rule (CLAUDE.md).\n */\nconst makeWriteOnlyWorkbook = (sink: XlsxSink, zipOpts: ZipWriterOptions): WriteOnlyWorkbook => {\n const styles = makeStylesheet();\n // Reserve cellXfs[0] for the default (no apply* flags). Unstyled cells point\n // at this slot via styleId=0; user-styled cells start at index 1 so the\n // writer emits an `s=\"N\"` attribute for them.\n addCellXf(styles, defaultCellXf());\n // The ZIP writer is created up front: each addWorksheet opens a streaming\n // entry on it and flushes row chunks through the deflate stream as they\n // arrive. Sheets emit before styles / sst / workbook / rels / content-types\n // so the writer can serialise them in order.\n const state: WorkbookState = {\n styles,\n strings: createWriteOnlyStringTable(),\n sheets: [],\n finalised: false,\n hasOpenWorksheet: false,\n writer: createZipWriter(sink, zipOpts),\n };\n\n const addWorksheet = async (title: string): Promise<WriteOnlyWorksheet> => {\n if (state.finalised) {\n throw new OpenXmlIoError('addWorksheet: workbook already finalised');\n }\n if (state.hasOpenWorksheet) {\n throw new OpenXmlIoError(\n 'addWorksheet: previous worksheet still open — call close() before opening the next one',\n );\n }\n const taken = new Set(state.sheets.map((s) => s.title.toLowerCase()));\n validateTitle(title, taken);\n state.hasOpenWorksheet = true;\n const sheetId = state.sheets.length + 1;\n return makeWriteOnlyWorksheet(state, title, sheetId);\n };\n\n const finalize = async (): Promise<void> => {\n if (state.finalised) {\n throw new OpenXmlIoError('finalize: already finalised');\n }\n if (state.hasOpenWorksheet) {\n throw new OpenXmlIoError('finalize: a worksheet is still open — call close() before finalising');\n }\n state.finalised = true;\n const writer = state.writer;\n try {\n await finalizeImpl(state, writer);\n } catch (err) {\n // Release the sink so the half-emitted archive doesn't linger as a\n // valid-looking file on disk. Awaited so `toFile` has finished removing\n // it by the time the caller sees the error. abort() is idempotent.\n await writer.abort(err);\n throw err;\n }\n };\n\n const abort = (cause?: unknown): void => {\n if (state.finalised) return;\n state.finalised = true;\n // Sync by contract, so a `toFile` sink's unlink can still be in flight when\n // this returns. The failure paths that have to guarantee cleanup before the\n // caller sees an error await the writer's abort themselves.\n void state.writer.abort(cause);\n };\n\n return { addWorksheet, finalize, abort };\n};\n\nasync function finalizeImpl(state: WorkbookState, writer: WorkbookState['writer']): Promise<void> {\n // 1. Worksheets — already streamed through writer.addStreamingEntry\n // during each WriteOnlyWorksheet's appendRow / close cycle.\n\n // 2. Stylesheet.\n await writer.addEntry(ARC_STYLE, stylesheetToBytes(state.styles));\n\n // 3. SharedStrings (only when non-empty).\n if (state.strings.size > 0) {\n await state.strings.write(writer.addStreamingEntry(ARC_SHARED_STRINGS));\n }\n\n // 4. workbook.xml.\n const workbookXml = serializeWorkbookXml(state.sheets);\n await writer.addEntry(ARC_WORKBOOK, new TextEncoder().encode(workbookXml));\n\n // 5. workbook.xml.rels.\n const wbRels = makeRelationships();\n state.sheets.forEach((s, i) => {\n wbRels.rels.push({\n id: `rId${i + 1}`,\n type: `${REL_NS}/worksheet`,\n target: `worksheets/sheet${s.sheetId}.xml`,\n });\n });\n if (state.strings.size > 0) {\n wbRels.rels.push({\n id: `rId${wbRels.rels.length + 1}`,\n type: `${REL_NS}/sharedStrings`,\n target: 'sharedStrings.xml',\n });\n }\n wbRels.rels.push({\n id: `rId${wbRels.rels.length + 1}`,\n type: `${REL_NS}/styles`,\n target: 'styles.xml',\n });\n await writer.addEntry(ARC_WORKBOOK_RELS, relsToBytes(wbRels));\n\n // 6. root rels.\n const rootRels = makeRelationships();\n rootRels.rels.push({\n id: 'rId1',\n type: `${REL_NS}/officeDocument`,\n target: 'xl/workbook.xml',\n });\n await writer.addEntry(ARC_ROOT_RELS, relsToBytes(rootRels));\n void PKG_REL_NS; // imported for future docProps support\n\n // 7. [Content_Types].xml.\n const manifest = makeManifest();\n // Excel rejects packages whose [Content_Types].xml is missing the Default\n // entries for `rels` / `xml` — without them the package relationships file\n // can't be classified and Excel refuses to open.\n addDefault(manifest, 'rels', 'application/vnd.openxmlformats-package.relationships+xml');\n addDefault(manifest, 'xml', 'application/xml');\n addOverride(manifest, `/${ARC_WORKBOOK}`, XLSX_TYPE);\n for (const s of state.sheets) {\n addOverride(manifest, `/xl/worksheets/sheet${s.sheetId}.xml`, WORKSHEET_TYPE);\n }\n addOverride(manifest, `/${ARC_STYLE}`, STYLES_TYPE);\n if (state.strings.size > 0) {\n addOverride(manifest, `/${ARC_SHARED_STRINGS}`, SHARED_STRINGS_TYPE);\n }\n await writer.addEntry(ARC_CONTENT_TYPES, manifestToBytes(manifest));\n\n await writer.finalize();\n}\n\nconst serializeWorkbookXml = (\n sheets: ReadonlyArray<{ title: string; sheetId: number }>,\n): string => {\n const parts: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>',\n `<workbook xmlns=\"${SHEET_MAIN_NS}\" xmlns:r=\"${REL_NS}\">`,\n '<sheets>',\n ];\n sheets.forEach((s, i) => {\n parts.push(\n `<sheet name=\"${escapeAttr(s.title)}\" sheetId=\"${s.sheetId}\" r:id=\"rId${i + 1}\"/>`,\n );\n });\n parts.push('</sheets></workbook>');\n return parts.join('');\n};\n\n/** Open a workbook for streaming write-only output. */\nexport async function createWriteOnlyWorkbook(\n sink: XlsxSink,\n opts: WriteOnlyOptions = {},\n): Promise<WriteOnlyWorkbook> {\n // The streaming-deflate ZIP writer is constructed eagerly here: each\n // addWorksheet opens an entry on it and flushes row chunks through fflate's\n // `Zip` + `ZipDeflate` immediately, so peak memory stays at one pending row\n // buffer plus deflate scratch, with bounded workbook-wide string retention.\n return makeWriteOnlyWorkbook(sink, opts);\n}\n"],"mappings":"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"}
|
package/dist/styles.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { An as pickReadableTextColor, Cn as hexToHsl, Dn as makeColor, En as luminance, Mn as rgbColor, Nn as rotateHue, On as mixColors, Sn as darken, Tn as lighten, bn as colorToHex, jn as resolveIndexedColor, kn as normaliseRgb, vn as adjustLightness, wn as hslToHex, xn as contrastRatio, yn as adjustSaturation } from "./worksheet-
|
|
2
|
-
import { $ as BUILTIN_NAMED_STYLES, $t as makeAlignment, A as setCellBorder, At as isBuiltinFormat, B as setItalic, C as setBold, Ct as FORMAT_NUMBER_00, D as setCellAsNumber, Dt as builtinFormatCode, E as setCellAsDate, Et as FORMAT_TEXT, F as setCellProtection, G as setRangeNumberFormat, Gt as makePatternFill, H as setRangeBackgroundColor, Ht as makeFill, I as setCellStyle, J as setRangeWrapText, Jt as makeBorder, K as setRangeProtection, L as setFontColor, M as setCellFill, Mt as isTimedeltaFormat, N as setCellFont, Nt as makeNumberFormat, O as setCellAsPercent, Ot as builtinFormatId, P as setCellNumberFormat, Pt as DEFAULT_FONT, Q as makeProtection, Qt as alignmentToCss, R as setFontName, Rt as fontToCss, S as rotateCellText, St as FORMAT_NUMBER, T as setCellAsCurrency, Tt as FORMAT_PERCENTAGE_00, U as setRangeBorderBox, Ut as makeGradientFill, V as setRangeAlignment, Vt as fillToCss, W as setRangeFont, Wt as makeGradientStop, X as setUnderline, Y as setStrikethrough, Yt as makeSide, Z as wrapCellText, _ as getCellNumberFormat, _t as BUILTIN_FORMATS_MAX_SIZE, a as cellStyleToCss, at as addFill, b as patchCellFont, bt as FORMAT_DATE_YYYYMMDD2, c as clearCellStyle, d as copyCellStyle, dt as listCellStyleXfs, et as addNamedStyle, f as formatAsHeader, ft as listCellXfs, g as getCellFont, gt as BUILTIN_FORMATS, h as getCellFill, ht as makeStylesheet, i as applyNamedStyle, it as addCellXf, j as setCellBorderAll, jt as isDateFormat, k as setCellBackgroundColor, kt as classifyDateFormat, l as clearRangeStyle, lt as defaultCellXf, m as getCellBorder, mt as listFonts, n as alignCellVertical, nt as addBorder, o as centerCell, ot as addFont, p as getCellAlignment, pt as listFills, q as setRangeStyle, qt as borderToCss, r as applyBuiltinStyle, rt as addCellStyleXf, s as clearCellBackground, st as addNumFmt, t as alignCellHorizontal, tt as ensureBuiltinStyle, u as cloneCellStyle, ut as listBorders, v as getCellProtection, vt as FORMAT_DATE_DATETIME, w as setCellAlignment, wt as FORMAT_PERCENTAGE, x as registerCellStyle, xt as FORMAT_GENERAL, y as indentCell, yt as FORMAT_DATE_TIMEDELTA, z as setFontSize, zt as makeFont } from "./cell-style-
|
|
3
|
-
import { r as makeDifferentialStyle, t as addDxf } from "./differential-
|
|
1
|
+
import { An as pickReadableTextColor, Cn as hexToHsl, Dn as makeColor, En as luminance, Mn as rgbColor, Nn as rotateHue, On as mixColors, Sn as darken, Tn as lighten, bn as colorToHex, jn as resolveIndexedColor, kn as normaliseRgb, vn as adjustLightness, wn as hslToHex, xn as contrastRatio, yn as adjustSaturation } from "./worksheet-Cxn2c-jz.mjs";
|
|
2
|
+
import { $ as BUILTIN_NAMED_STYLES, $t as makeAlignment, A as setCellBorder, At as isBuiltinFormat, B as setItalic, C as setBold, Ct as FORMAT_NUMBER_00, D as setCellAsNumber, Dt as builtinFormatCode, E as setCellAsDate, Et as FORMAT_TEXT, F as setCellProtection, G as setRangeNumberFormat, Gt as makePatternFill, H as setRangeBackgroundColor, Ht as makeFill, I as setCellStyle, J as setRangeWrapText, Jt as makeBorder, K as setRangeProtection, L as setFontColor, M as setCellFill, Mt as isTimedeltaFormat, N as setCellFont, Nt as makeNumberFormat, O as setCellAsPercent, Ot as builtinFormatId, P as setCellNumberFormat, Pt as DEFAULT_FONT, Q as makeProtection, Qt as alignmentToCss, R as setFontName, Rt as fontToCss, S as rotateCellText, St as FORMAT_NUMBER, T as setCellAsCurrency, Tt as FORMAT_PERCENTAGE_00, U as setRangeBorderBox, Ut as makeGradientFill, V as setRangeAlignment, Vt as fillToCss, W as setRangeFont, Wt as makeGradientStop, X as setUnderline, Y as setStrikethrough, Yt as makeSide, Z as wrapCellText, _ as getCellNumberFormat, _t as BUILTIN_FORMATS_MAX_SIZE, a as cellStyleToCss, at as addFill, b as patchCellFont, bt as FORMAT_DATE_YYYYMMDD2, c as clearCellStyle, d as copyCellStyle, dt as listCellStyleXfs, et as addNamedStyle, f as formatAsHeader, ft as listCellXfs, g as getCellFont, gt as BUILTIN_FORMATS, h as getCellFill, ht as makeStylesheet, i as applyNamedStyle, it as addCellXf, j as setCellBorderAll, jt as isDateFormat, k as setCellBackgroundColor, kt as classifyDateFormat, l as clearRangeStyle, lt as defaultCellXf, m as getCellBorder, mt as listFonts, n as alignCellVertical, nt as addBorder, o as centerCell, ot as addFont, p as getCellAlignment, pt as listFills, q as setRangeStyle, qt as borderToCss, r as applyBuiltinStyle, rt as addCellStyleXf, s as clearCellBackground, st as addNumFmt, t as alignCellHorizontal, tt as ensureBuiltinStyle, u as cloneCellStyle, ut as listBorders, v as getCellProtection, vt as FORMAT_DATE_DATETIME, w as setCellAlignment, wt as FORMAT_PERCENTAGE, x as registerCellStyle, xt as FORMAT_GENERAL, y as indentCell, yt as FORMAT_DATE_TIMEDELTA, z as setFontSize, zt as makeFont } from "./cell-style-DjKKPWDL.mjs";
|
|
3
|
+
import { r as makeDifferentialStyle, t as addDxf } from "./differential-7KGzbliB.mjs";
|
|
4
4
|
export { BUILTIN_FORMATS, BUILTIN_FORMATS_MAX_SIZE, BUILTIN_NAMED_STYLES, DEFAULT_FONT, FORMAT_DATE_DATETIME, FORMAT_DATE_TIMEDELTA, FORMAT_DATE_YYYYMMDD2, FORMAT_GENERAL, FORMAT_NUMBER, FORMAT_NUMBER_00, FORMAT_PERCENTAGE, FORMAT_PERCENTAGE_00, FORMAT_TEXT, addBorder, addCellStyleXf, addCellXf, addDxf, addFill, addFont, addNamedStyle, addNumFmt, adjustLightness, adjustSaturation, alignCellHorizontal, alignCellVertical, alignmentToCss, applyBuiltinStyle, applyNamedStyle, borderToCss, builtinFormatCode, builtinFormatId, cellStyleToCss, centerCell, classifyDateFormat, clearCellBackground, clearCellStyle, clearRangeStyle, cloneCellStyle, colorToHex, contrastRatio, copyCellStyle, darken, defaultCellXf, ensureBuiltinStyle, fillToCss, fontToCss, formatAsHeader, getCellAlignment, getCellBorder, getCellFill, getCellFont, getCellNumberFormat, getCellProtection, hexToHsl, hslToHex, indentCell, isBuiltinFormat, isDateFormat, isTimedeltaFormat, lighten, listBorders, listCellStyleXfs, listCellXfs, listFills, listFonts, luminance, makeAlignment, makeBorder, makeColor, makeDifferentialStyle, makeFill, makeFont, makeGradientFill, makeGradientStop, makeNumberFormat, makePatternFill, makeProtection, makeSide, makeStylesheet, mixColors, normaliseRgb, patchCellFont, pickReadableTextColor, registerCellStyle, resolveIndexedColor, rgbColor, rotateCellText, rotateHue, setBold, setCellAlignment, setCellAsCurrency, setCellAsDate, setCellAsNumber, setCellAsPercent, setCellBackgroundColor, setCellBorder, setCellBorderAll, setCellFill, setCellFont, setCellNumberFormat, setCellProtection, setCellStyle, setFontColor, setFontName, setFontSize, setItalic, setRangeAlignment, setRangeBackgroundColor, setRangeBorderBox, setRangeFont, setRangeNumberFormat, setRangeProtection, setRangeStyle, setRangeWrapText, setStrikethrough, setUnderline, wrapCellText };
|