@openjsxl/core 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -4
- package/dist/index.js +0 -2
- package/package.json +1 -1
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# @openjsxl/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@openjsxl/core)
|
|
4
|
+
[](https://www.npmjs.com/package/@openjsxl/core?activeTab=dependencies)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
7
|
+
The zero-dependency OOXML engine behind [`openjsxl`](https://www.npmjs.com/package/openjsxl):
|
|
4
8
|
the `zip → xml → ooxml → reader` layers that turn an `.xlsx` into typed cells, built only on
|
|
5
|
-
platform Web APIs (`DecompressionStream`, `TextDecoder`, …).
|
|
9
|
+
platform Web APIs (`DecompressionStream`, `TextDecoder`, …). No runtime dependencies.
|
|
6
10
|
|
|
7
11
|
**Most users should install [`openjsxl`](https://www.npmjs.com/package/openjsxl) instead** — it
|
|
8
12
|
re-exports everything here and is the stable public surface. Install `@openjsxl/core` directly
|
|
@@ -12,12 +16,37 @@ only if you want the engine without the facade.
|
|
|
12
16
|
npm install @openjsxl/core
|
|
13
17
|
```
|
|
14
18
|
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
15
21
|
```ts
|
|
16
22
|
import { openXlsx, streamSheetRows, XlsxError } from '@openjsxl/core'
|
|
23
|
+
import { readFile } from 'node:fs/promises'
|
|
24
|
+
|
|
25
|
+
const wb = await openXlsx(await readFile('data.xlsx'))
|
|
26
|
+
const sheet = wb.sheet('Sheet1')
|
|
27
|
+
|
|
28
|
+
sheet.cell('A1') // { ref, type, value } — narrow on `type` for a typed value
|
|
29
|
+
sheet.numberFormat('C1') // "mm-dd-yy" | undefined
|
|
30
|
+
sheet.mergedCells // ["A1:B1", …]
|
|
31
|
+
|
|
32
|
+
// Constant-memory streaming for large sheets — one row at a time.
|
|
33
|
+
for await (const row of streamSheetRows(await readFile('huge.xlsx'))) {
|
|
34
|
+
console.log(row.index, row.cells.length)
|
|
35
|
+
}
|
|
17
36
|
```
|
|
18
37
|
|
|
19
|
-
|
|
20
|
-
|
|
38
|
+
Malformed input throws a typed `XlsxError` with a discriminating `.code`
|
|
39
|
+
(`'not-a-zip' | 'not-xlsx' | 'missing-part' | 'corrupt-zip' | 'part-too-large' | …`), never a
|
|
40
|
+
bare `TypeError` from a corrupt file.
|
|
41
|
+
|
|
42
|
+
## Exports
|
|
43
|
+
|
|
44
|
+
- **Reader:** `openXlsx`, `streamSheetRows`, `Workbook`, `Worksheet`, `ReadOptions`
|
|
45
|
+
- **Errors:** `XlsxError`, `XlsxErrorCode`
|
|
46
|
+
- **Types:** `Row`, `Cell`, `CellType`, `Comment`, `Hyperlink`, `SheetInfo`, `CellRef`
|
|
47
|
+
- **A1 & dates:** `columnToIndex`, `indexToColumn`, `parseRef`, `formatRef`, `serialToDate`
|
|
48
|
+
|
|
49
|
+
Full guide, design notes, and roadmap: <https://github.com/joaquimserafim/openjsxl>
|
|
21
50
|
|
|
22
51
|
## License
|
|
23
52
|
|
package/dist/index.js
CHANGED
|
@@ -1258,5 +1258,3 @@ async function* streamSheetRows(source, sheetName, options) {
|
|
|
1258
1258
|
}
|
|
1259
1259
|
|
|
1260
1260
|
export { Workbook, Worksheet, XlsxError, columnToIndex, formatRef, indexToColumn, openXlsx, parseRef, serialToDate, streamSheetRows };
|
|
1261
|
-
//# sourceMappingURL=index.js.map
|
|
1262
|
-
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/ooxml/a1.ts","../src/ooxml/dates.ts","../src/ooxml/cell.ts","../src/utils/chars.ts","../src/utils/xml-names.ts","../src/xml/entities.ts","../src/xml/tokenizer.ts","../src/xml/stream.ts","../src/ooxml/rels.ts","../src/ooxml/shared-strings.ts","../src/ooxml/styles.ts","../src/ooxml/workbook.ts","../src/zip/inflate.ts","../src/zip/central-directory.ts","../src/reader/worksheet.ts","../src/reader/workbook.ts"],"names":["end","name","decoder","r"],"mappings":"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","file":"index.js","sourcesContent":["// A single typed error for the ways opening or reading an .xlsx can fail, discriminated by\n// `code` so callers can branch without matching on message strings. Messages stay\n// human-readable; `cause` carries the underlying error where there is one (e.g. a failed\n// inflate). All file-level failures thrown by the reader and zip layers are XlsxError.\n\nexport type XlsxErrorCode =\n\t| 'not-a-zip' // the bytes are not a ZIP archive at all\n\t| 'not-xlsx' // a valid ZIP, but not an OOXML spreadsheet\n\t| 'missing-part' // a required part is absent from the package\n\t| 'corrupt-zip' // the ZIP structure is malformed, or an entry failed to inflate\n\t| 'unsupported' // a valid but unsupported feature (ZIP64, encryption, unknown method)\n\t| 'no-such-sheet' // the caller asked for a sheet name the workbook does not have\n\t| 'part-too-large' // a part's decompressed size exceeds the caller's maxPartBytes limit\n\nexport class XlsxError extends Error {\n\t/** Machine-readable discriminant; branch on this rather than the message. */\n\treadonly code: XlsxErrorCode\n\n\tconstructor(code: XlsxErrorCode, message: string, options?: { cause?: unknown }) {\n\t\tsuper(message, options)\n\t\tthis.name = 'XlsxError'\n\t\tthis.code = code\n\t}\n}\n","// A1 reference helpers. Excel columns use bijective base-26 (A=1 … Z=26, AA=27),\n// which is not ordinary base-26 because there is no zero digit.\n\nexport interface CellRef {\n\t/** 1-based column index (A = 1). */\n\treadonly col: number\n\t/** 1-based row index. */\n\treadonly row: number\n}\n\nconst CODE_UPPER_A = 65\nconst CODE_UPPER_Z = 90\nconst CODE_LOWER_A = 97\nconst CODE_LOWER_Z = 122\n\nexport function columnToIndex(letters: string): number {\n\tif (letters.length === 0) throw new Error('empty column reference')\n\tlet index = 0\n\tfor (let i = 0; i < letters.length; i++) {\n\t\tconst code = letters.charCodeAt(i)\n\t\tlet value = 0\n\t\tif (code >= CODE_UPPER_A && code <= CODE_UPPER_Z) value = code - CODE_UPPER_A + 1\n\t\telse if (code >= CODE_LOWER_A && code <= CODE_LOWER_Z) value = code - CODE_LOWER_A + 1\n\t\telse throw new Error(`invalid column reference: ${letters}`)\n\t\tindex = index * 26 + value\n\t\t// An absurdly long ref (far beyond Excel's XFD/16384 limit) overflows past exact\n\t\t// integer precision — bail before it silently becomes a lossy float or Infinity, which\n\t\t// would poison downstream column arithmetic and formatRef. Bailing here also caps work\n\t\t// on a megabyte-long attacker-supplied ref. Callers that tolerate bad refs (the reader's\n\t\t// safeColumn) catch this and fall back to positional addressing.\n\t\tif (index > Number.MAX_SAFE_INTEGER)\n\t\t\tthrow new Error(`column reference too large: ${letters}`)\n\t}\n\treturn index\n}\n\nexport function indexToColumn(index: number): string {\n\tif (!Number.isInteger(index) || index < 1) throw new Error(`invalid column index: ${index}`)\n\tlet remaining = index\n\tlet letters = ''\n\twhile (remaining > 0) {\n\t\tconst digit = (remaining - 1) % 26\n\t\tletters = String.fromCharCode(CODE_UPPER_A + digit) + letters\n\t\tremaining = Math.floor((remaining - 1) / 26)\n\t}\n\treturn letters\n}\n\nconst A1_PATTERN = /^([A-Za-z]+)([1-9][0-9]*)$/\n\nexport function parseRef(ref: string): CellRef {\n\tconst match = A1_PATTERN.exec(ref)\n\tif (match === null) throw new Error(`invalid A1 reference: ${ref}`)\n\treturn {\n\t\tcol: columnToIndex(match[1] as string),\n\t\trow: Number.parseInt(match[2] as string, 10),\n\t}\n}\n\nexport function formatRef(ref: CellRef): string {\n\tif (!Number.isInteger(ref.row) || ref.row < 1) throw new Error(`invalid row index: ${ref.row}`)\n\treturn `${indexToColumn(ref.col)}${ref.row}`\n}\n","// Excel stores dates and times as serial numbers. Whether a number IS a date is\n// decided by the cell's number format (see ./styles), never by the value itself.\n// Two epoch systems exist, selected by the workbook's date1904 flag.\n//\n// 1900 system: serial 1 is 1900-01-01. Excel wrongly treats 1900 as a leap year, so\n// serial 60 is a phantom 1900-02-29. Anchoring at 1899-12-30 makes every date from\n// 1900-03-01 onward correct — the convention every major library follows.\n// 1904 system (legacy Mac): serial 0 is 1904-01-01.\n\nconst MS_PER_DAY = 86_400_000\nconst EPOCH_1900_UTC = Date.UTC(1899, 11, 30)\nconst EPOCH_1904_UTC = Date.UTC(1904, 0, 1)\n\nexport function serialToDate(serial: number, date1904 = false): Date {\n\tconst epoch = date1904 ? EPOCH_1904_UTC : EPOCH_1900_UTC\n\treturn new Date(epoch + Math.round(serial * MS_PER_DAY))\n}\n","import type { Cell } from '../types'\nimport { serialToDate } from './dates'\nimport type { StyleTable } from './styles'\n\n// Turn a worksheet `<c>` element's raw pieces into a typed Cell. The `t` attribute selects\n// how the value text is interpreted; when absent the cell is a number (the OOXML default).\n//\n// t value source meaning\n// ───────── ────────────────── ──────────────────────────────────────────────\n// (absent) <v> number\n// \"n\" <v> number\n// \"s\" <v> zero-based index into the shared string table\n// \"str\" <v> a formula's cached string result\n// \"inlineStr\" <is><t> text stored inline on the cell\n// \"b\" <v> boolean — \"1\"/\"0\" (NOT a number)\n// \"e\" <v> error literal, e.g. \"#DIV/0!\"\n//\n// Booleans and errors live inside `<v>` and must not be read as numbers. Malformed or\n// missing values degrade to an `empty` cell rather than throwing — a reader stays resilient\n// on imperfect files, matching the tokenizer and zip layers. A numeric cell becomes a `date`\n// only when the context carries a style table and the cell's style applies a date/time\n// number format (F2.1); nothing about a number's value reveals that on its own.\n\nexport interface RawCell {\n\t/** A1 reference, e.g. \"B2\". */\n\treadonly ref: string\n\t/** The `t` attribute; `undefined` means the default (number). */\n\treadonly type: string | undefined\n\t/** `<v>` text, or concatenated inline `<is>` text; `undefined` when the cell has none. */\n\treadonly value: string | undefined\n\t/** The `s` attribute (index into `cellXfs`); drives date detection. `undefined` ⇒ style 0. */\n\treadonly style: number | undefined\n}\n\nexport interface DecodeContext {\n\t/** The workbook's shared string table (F1.5), indexed by `s`-type cells. */\n\treadonly sharedStrings: readonly string[]\n\t/** Style table (F2.1); when present, date-styled numbers decode as `date` cells. */\n\treadonly styles?: StyleTable\n\t/** Workbook 1904 date system flag, selecting the serial epoch. Defaults to false. */\n\treadonly date1904?: boolean\n}\n\nexport function decodeCell(raw: RawCell, ctx: DecodeContext): Cell {\n\tconst { ref, value } = raw\n\n\tswitch (raw.type) {\n\t\tcase 's': {\n\t\t\t// Shared string: the value is an index. Out-of-range or non-integer indices\n\t\t\t// point at nothing, so the cell reads as empty rather than inventing text.\n\t\t\tconst index = Number.parseInt(value ?? '', 10)\n\t\t\tconst resolved = Number.isInteger(index) ? ctx.sharedStrings[index] : undefined\n\t\t\treturn resolved === undefined\n\t\t\t\t? { ref, type: 'empty', value: null }\n\t\t\t\t: { ref, type: 'string', value: resolved }\n\t\t}\n\t\tcase 'inlineStr':\n\t\tcase 'str':\n\t\t\treturn value === undefined\n\t\t\t\t? { ref, type: 'empty', value: null }\n\t\t\t\t: { ref, type: 'string', value }\n\t\tcase 'b':\n\t\t\treturn value === undefined\n\t\t\t\t? { ref, type: 'empty', value: null }\n\t\t\t\t: { ref, type: 'boolean', value: value === '1' }\n\t\tcase 'e':\n\t\t\treturn value === undefined\n\t\t\t\t? { ref, type: 'empty', value: null }\n\t\t\t\t: { ref, type: 'error', value }\n\t\tdefault: {\n\t\t\t// Absent or \"n\": a number. Reject empty/non-finite content as empty.\n\t\t\tif (value === undefined || value === '') return { ref, type: 'empty', value: null }\n\t\t\tconst num = Number(value)\n\t\t\tif (!Number.isFinite(num)) return { ref, type: 'empty', value: null }\n\t\t\t// A date-styled serial is a date; everything else stays a number.\n\t\t\tif (ctx.styles?.isDateStyle(raw.style)) {\n\t\t\t\treturn { ref, type: 'date', value: serialToDate(num, ctx.date1904 ?? false) }\n\t\t\t}\n\t\t\treturn { ref, type: 'number', value: num }\n\t\t}\n\t}\n}\n","// Small, pure character predicates shared across the parsing layers. Kept inside core\n// for now; may graduate to a standalone @openjsxl/utils package later.\n\n/** True for the four characters XML treats as whitespace: space, tab, CR, LF. */\nexport function isWhitespace(ch: string | undefined): boolean {\n\treturn ch === ' ' || ch === '\\t' || ch === '\\n' || ch === '\\r'\n}\n","// XML-name helpers shared across the OOXML parsing layers.\n\n// Strip a namespace prefix from a qualified name: `r:id` -> `id`, `si` -> `si`. The\n// tokenizer treats prefixes as part of the literal name (it does no namespace\n// resolution), so consumers that only care about the local name normalise here. Excel\n// almost always uses the default (unprefixed) namespace, but other producers may not.\nexport function localName(name: string): string {\n\tconst colon = name.indexOf(':')\n\treturn colon === -1 ? name : name.slice(colon + 1)\n}\n\n// The relationship id on an element is conventionally `r:id`, but the `r` prefix is only\n// bound by convention — fall back to any attribute whose local name is `id`. Shared by the\n// workbook (<sheet r:id>) and worksheet (<hyperlink r:id>) parsers.\n//\n// This trusts the prefix/local name rather than resolving the relationships namespace URI —\n// the tokenizer does no namespace resolution, by design. It is safe for the elements we call\n// it on: <sheet> and <hyperlink> carry no attribute whose local name is `id` other than the\n// relationship id, so the fallback cannot mis-match. Reusing it on an element that may carry a\n// foreign `*:id` attribute would need revisiting.\nexport function relationshipId(attrs: Readonly<Record<string, string>>): string | undefined {\n\tif (attrs['r:id'] !== undefined) return attrs['r:id']\n\tfor (const key of Object.keys(attrs)) {\n\t\tif (localName(key) === 'id') return attrs[key]\n\t}\n\treturn undefined\n}\n","// Decode the XML character entities that appear in OOXML text: the five predefined\n// entities plus decimal and hexadecimal numeric character references. The tokenizer\n// uses this for both element text and attribute values.\n//\n// Per the XML spec, hex references use a lowercase `x` (`A`); anything that does\n// not match a known form is left untouched so malformed input round-trips unchanged.\n\nconst ENTITY_PATTERN = /&(#x[0-9a-fA-F]+|#[0-9]+|amp|lt|gt|quot|apos);/g\n\nexport function decodeXmlEntities(input: string): string {\n\tif (!input.includes('&')) return input\n\treturn input.replace(ENTITY_PATTERN, (match, body: string) => {\n\t\tswitch (body) {\n\t\t\tcase 'amp':\n\t\t\t\treturn '&'\n\t\t\tcase 'lt':\n\t\t\t\treturn '<'\n\t\t\tcase 'gt':\n\t\t\t\treturn '>'\n\t\t\tcase 'quot':\n\t\t\t\treturn '\"'\n\t\t\tcase 'apos':\n\t\t\t\treturn \"'\"\n\t\t\tdefault: {\n\t\t\t\t// Numeric reference: body is \"#NNN\" (decimal) or \"#xHHH\" (hex).\n\t\t\t\tconst code =\n\t\t\t\t\tbody[1] === 'x'\n\t\t\t\t\t\t? Number.parseInt(body.slice(2), 16)\n\t\t\t\t\t\t: Number.parseInt(body.slice(1), 10)\n\t\t\t\t// Reject out-of-range values and lone surrogates (U+D800–U+DFFF): both would\n\t\t\t\t// produce an ill-formed scalar, so leave the reference as literal text instead.\n\t\t\t\tconst isScalar =\n\t\t\t\t\tcode >= 0 && code <= 0x10ffff && !(code >= 0xd800 && code <= 0xdfff)\n\t\t\t\treturn isScalar ? String.fromCodePoint(code) : match\n\t\t\t}\n\t\t}\n\t})\n}\n","import { isWhitespace } from '../utils'\nimport { decodeXmlEntities } from './entities'\n\n// Streaming, non-validating tokenizer for the OOXML subset of XML. It yields a flat\n// event stream rather than building a DOM — the reason pure-JS parsers can keep up with\n// native ones is that they never materialise a tree.\n//\n// Handles: elements, attributes (single or double quoted), self-closing tags, text,\n// CDATA, the `<?xml?>` prolog, and comments. Entity references (F1.1) are decoded in\n// element text and attribute values. `xml:space=\"preserve\"` needs no special handling\n// here — all text is emitted verbatim (after entity decoding) and significance is the\n// consumer's call.\n//\n// Deliberately NOT supported: DTD validation, namespace resolution (prefixes such as\n// `r:id` are part of the literal name), and processing instructions beyond the prolog.\n//\n// Robustness contract: for ANY input it never throws, hangs, or reads out of bounds, and\n// it never invents a phantom element for an unescaped `<`. It does NOT guarantee\n// completeness — a truncated part yields a plausible-but-shorter stream with no error\n// signal, so callers must validate document structure themselves. Character data is\n// emitted as one `text` event per run between markup, so consumers must concatenate\n// consecutive `text` events (CDATA, comments, and entities all split a run).\n\nexport type XmlToken =\n\t| {\n\t\t\treadonly kind: 'open'\n\t\t\treadonly name: string\n\t\t\treadonly attrs: Readonly<Record<string, string>>\n\t\t\treadonly selfClosing: boolean\n\t }\n\t| { readonly kind: 'text'; readonly value: string }\n\t| { readonly kind: 'close'; readonly name: string }\n\nexport function* tokenize(xml: string): Generator<XmlToken> {\n\tconst len = xml.length\n\t// Skip a leading UTF-8 BOM if present (common from LibreOffice and older Excel).\n\tlet i = xml.charCodeAt(0) === 0xfeff ? 1 : 0\n\n\twhile (i < len) {\n\t\tconst lt = xml.indexOf('<', i)\n\n\t\tif (lt === -1) {\n\t\t\tconst text = xml.slice(i)\n\t\t\tif (text.length > 0) yield { kind: 'text', value: decodeXmlEntities(text) }\n\t\t\tbreak\n\t\t}\n\n\t\tif (lt > i) {\n\t\t\tyield { kind: 'text', value: decodeXmlEntities(xml.slice(i, lt)) }\n\t\t}\n\n\t\tconst next = xml[lt + 1]\n\n\t\t// <?xml ... ?> prolog / processing instruction\n\t\tif (next === '?') {\n\t\t\tconst end = xml.indexOf('?>', lt + 2)\n\t\t\ti = end === -1 ? len : end + 2\n\t\t\tcontinue\n\t\t}\n\n\t\t// <!-- comment -->, <![CDATA[ ... ]]>, or other declaration\n\t\tif (next === '!') {\n\t\t\tif (xml.startsWith('<!--', lt)) {\n\t\t\t\tconst end = xml.indexOf('-->', lt + 4)\n\t\t\t\ti = end === -1 ? len : end + 3\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (xml.startsWith('<![CDATA[', lt)) {\n\t\t\t\tconst end = xml.indexOf(']]>', lt + 9)\n\t\t\t\tconst content = xml.slice(lt + 9, end === -1 ? len : end)\n\t\t\t\tif (content.length > 0) yield { kind: 'text', value: content } // CDATA is literal\n\t\t\t\ti = end === -1 ? len : end + 3\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst end = xml.indexOf('>', lt + 2)\n\t\t\ti = end === -1 ? len : end + 1\n\t\t\tcontinue\n\t\t}\n\n\t\t// </name> close tag\n\t\tif (next === '/') {\n\t\t\tconst end = xml.indexOf('>', lt + 2)\n\t\t\tconst name = xml.slice(lt + 2, end === -1 ? len : end).trim()\n\t\t\tyield { kind: 'close', name }\n\t\t\ti = end === -1 ? len : end + 1\n\t\t\tcontinue\n\t\t}\n\n\t\t// A '<' not followed by a name-start character is a literal '<' in (malformed or\n\t\t// unescaped) text — emit it verbatim rather than inventing a phantom element and\n\t\t// swallowing the following close tag.\n\t\tif (next === undefined || next === '>' || next === '=' || isWhitespace(next)) {\n\t\t\tyield { kind: 'text', value: '<' }\n\t\t\ti = lt + 1\n\t\t\tcontinue\n\t\t}\n\n\t\t// <name ...> open or self-closing tag\n\t\tlet j = lt + 1\n\t\tconst nameStart = j\n\t\twhile (j < len) {\n\t\t\tconst ch = xml[j]\n\t\t\tif (isWhitespace(ch) || ch === '>' || ch === '/') break\n\t\t\tj++\n\t\t}\n\t\tconst name = xml.slice(nameStart, j)\n\t\tconst attrs: Record<string, string> = {}\n\t\tlet selfClosing = false\n\n\t\twhile (j < len) {\n\t\t\twhile (j < len && isWhitespace(xml[j])) j++\n\t\t\tif (j >= len) break\n\n\t\t\tconst ch = xml[j]\n\t\t\tif (ch === '>') {\n\t\t\t\tj++\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (ch === '/') {\n\t\t\t\t// Self-close marker: record it and advance by one, letting the loop consume the\n\t\t\t\t// real '>'. Do NOT jump to the next '>' — that can swallow following markup.\n\t\t\t\tselfClosing = true\n\t\t\t\tj++\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst attrNameStart = j\n\t\t\twhile (j < len) {\n\t\t\t\tconst c = xml[j]\n\t\t\t\tif (c === '=' || c === '>' || c === '/' || isWhitespace(c)) break\n\t\t\t\tj++\n\t\t\t}\n\t\t\tconst attrName = xml.slice(attrNameStart, j)\n\n\t\t\twhile (j < len && isWhitespace(xml[j])) j++\n\t\t\tif (xml[j] === '=') {\n\t\t\t\tj++\n\t\t\t\twhile (j < len && isWhitespace(xml[j])) j++\n\t\t\t\tconst quote = xml[j]\n\t\t\t\tif (quote === '\"' || quote === \"'\") {\n\t\t\t\t\tj++\n\t\t\t\t\tconst close = xml.indexOf(quote, j)\n\t\t\t\t\tconst end = close === -1 ? len : close\n\t\t\t\t\tif (attrName.length > 0) attrs[attrName] = decodeXmlEntities(xml.slice(j, end))\n\t\t\t\t\tj = close === -1 ? len : close + 1\n\t\t\t\t} else {\n\t\t\t\t\t// Unquoted value (malformed XML, but be lenient): read to whitespace/end-of-tag.\n\t\t\t\t\tconst valStart = j\n\t\t\t\t\twhile (j < len && !isWhitespace(xml[j]) && xml[j] !== '>' && xml[j] !== '/') j++\n\t\t\t\t\tif (attrName.length > 0)\n\t\t\t\t\t\tattrs[attrName] = decodeXmlEntities(xml.slice(valStart, j))\n\t\t\t\t}\n\t\t\t} else if (attrName.length > 0) {\n\t\t\t\tattrs[attrName] = ''\n\t\t\t}\n\t\t}\n\n\t\tyield { kind: 'open', name, attrs, selfClosing }\n\t\ti = j\n\t}\n}\n","import { tokenize, type XmlToken } from './tokenizer'\n\n// A chunk-fed wrapper around the streaming tokenizer (./tokenizer). Decompressed worksheet\n// text arrives in arbitrary chunks, and a single token — a tag, a comment, a CDATA section,\n// an entity reference — can straddle a chunk boundary. `createXmlStream` buffers the input\n// and only ever hands the underlying `tokenize` a prefix it is *certain* is complete, so\n// peak memory tracks the largest single unfinished construct (one tag, or one run of text\n// up to the next `<`), not the whole part.\n//\n// Consumers must still concatenate consecutive `text` tokens: a text run split across two\n// chunks emits as two `text` events, exactly as CDATA/entities already split runs.\n\nexport interface XmlStream {\n\t/** Feed the next text chunk; returns the tokens that became complete. */\n\tpush(text: string): XmlToken[]\n\t/** Tokenize whatever remains after the last chunk (call once at end of input). */\n\tflush(): XmlToken[]\n}\n\nconst CDATA_OPEN = '<![CDATA['\nconst COMMENT_OPEN = '<!--'\n\n// A real entity reference is short (`` is 10 chars). If a `&` in trailing text is\n// further than this from the end with no `;`, it cannot be a split entity — it is a literal\n// `&` (only valid in escaped form, but tolerated) and is emitted rather than pinning the\n// buffer, so a stray `&` can't defeat the constant-memory guarantee.\nconst MAX_ENTITY_TAIL = 16\n\n// Is `buf.slice(at)` a non-empty proper prefix of `marker` — i.e. an incomplete marker that\n// might complete once more text arrives? (e.g. \"<!-\" is a prefix of \"<!--\".)\nfunction isPartialMarkerOf(buf: string, at: number, marker: string): boolean {\n\tconst tail = buf.length - at\n\treturn tail < marker.length && marker.startsWith(buf.slice(at))\n}\n\n// The length of the longest prefix of `buf` that contains only complete constructs, so it\n// can be tokenized now with no construct straddling the cut. The remainder is kept buffered.\nfunction safeBoundary(buf: string): number {\n\tconst len = buf.length\n\tlet i = 0 // scan cursor\n\tlet safe = 0 // end of the last complete construct (the cut point)\n\n\twhile (i < len) {\n\t\tconst lt = buf.indexOf('<', i)\n\n\t\tif (lt === -1) {\n\t\t\t// Trailing text with no following markup. It is safe except for a split entity\n\t\t\t// (e.g. \"&\" awaiting its \";\"): keep from an unterminated \"&\" onward — but only\n\t\t\t// while it could still be a short entity, so a stray literal \"&\" doesn't pin it.\n\t\t\tconst amp = buf.lastIndexOf('&')\n\t\t\tconst splitEntity =\n\t\t\t\tamp >= i && buf.indexOf(';', amp) === -1 && len - amp <= MAX_ENTITY_TAIL\n\t\t\treturn splitEntity ? amp : len\n\t\t}\n\n\t\t// An incomplete comment/CDATA marker (e.g. \"<!-\", \"<![CD\") must wait for more input,\n\t\t// otherwise it would be misread as a declaration.\n\t\tif (isPartialMarkerOf(buf, lt, COMMENT_OPEN) || isPartialMarkerOf(buf, lt, CDATA_OPEN)) {\n\t\t\treturn lt\n\t\t}\n\n\t\tlet end: number\n\t\tif (buf.startsWith(COMMENT_OPEN, lt)) {\n\t\t\tend = buf.indexOf('-->', lt + COMMENT_OPEN.length)\n\t\t\tif (end === -1) return lt\n\t\t\ti = end + 3\n\t\t} else if (buf.startsWith(CDATA_OPEN, lt)) {\n\t\t\tend = buf.indexOf(']]>', lt + CDATA_OPEN.length)\n\t\t\tif (end === -1) return lt\n\t\t\ti = end + 3\n\t\t} else if (buf[lt + 1] === '?') {\n\t\t\tend = buf.indexOf('?>', lt + 2)\n\t\t\tif (end === -1) return lt\n\t\t\ti = end + 2\n\t\t} else {\n\t\t\t// A tag (open/close/declaration). Scan for its '>', skipping quoted attribute\n\t\t\t// values so a '>' inside a value can't end it early.\n\t\t\tlet k = lt + 1\n\t\t\tlet quote = ''\n\t\t\tlet close = -1\n\t\t\twhile (k < len) {\n\t\t\t\tconst ch = buf[k]\n\t\t\t\tif (quote !== '') {\n\t\t\t\t\tif (ch === quote) quote = ''\n\t\t\t\t} else if (ch === '\"' || ch === \"'\") {\n\t\t\t\t\tquote = ch\n\t\t\t\t} else if (ch === '>') {\n\t\t\t\t\tclose = k\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tk++\n\t\t\t}\n\t\t\tif (close === -1) return lt // tag (or its quoted value) not closed yet\n\t\t\ti = close + 1\n\t\t}\n\t\tsafe = i\n\t}\n\n\treturn safe\n}\n\nexport function createXmlStream(): XmlStream {\n\tlet buffer = ''\n\n\treturn {\n\t\tpush(text: string): XmlToken[] {\n\t\t\tbuffer += text\n\t\t\tconst cut = safeBoundary(buffer)\n\t\t\tif (cut === 0) return []\n\t\t\tconst tokens = [...tokenize(buffer.slice(0, cut))]\n\t\t\tbuffer = buffer.slice(cut)\n\t\t\treturn tokens\n\t\t},\n\t\tflush(): XmlToken[] {\n\t\t\tif (buffer === '') return []\n\t\t\tconst tokens = [...tokenize(buffer)]\n\t\t\tbuffer = ''\n\t\t\treturn tokens\n\t\t},\n\t}\n}\n","import { localName } from '../utils'\nimport { tokenize } from '../xml'\n\n// Relationship parts (_rels/*.rels) are the source of truth for locating parts. A part's\n// relationships live in `<dir>/_rels/<part>.rels`, and their Targets resolve against\n// `<dir>` — so a worksheet is found by following workbook.xml's r:id into\n// workbook.xml.rels, never by guessing a filename.\n\nexport interface Relationship {\n\treadonly id: string\n\treadonly type: string\n\t/** Target exactly as written; resolve internal ones with resolveTarget. */\n\treadonly target: string\n\treadonly targetMode: 'Internal' | 'External'\n}\n\nexport function parseRels(xml: string): Map<string, Relationship> {\n\tconst rels = new Map<string, Relationship>()\n\tfor (const token of tokenize(xml)) {\n\t\tif (token.kind !== 'open' || localName(token.name) !== 'Relationship') continue\n\t\tconst id = token.attrs.Id\n\t\tconst target = token.attrs.Target\n\t\tif (id === undefined || target === undefined) continue\n\t\trels.set(id, {\n\t\t\tid,\n\t\t\ttype: token.attrs.Type ?? '',\n\t\t\ttarget,\n\t\t\ttargetMode: token.attrs.TargetMode === 'External' ? 'External' : 'Internal',\n\t\t})\n\t}\n\treturn rels\n}\n\n// Resolve a relationship Target (relative to `baseDir`, the directory of the owning part)\n// to a package-absolute part path. A leading \"/\" makes the Target package-absolute; \".\"\n// and \"..\" segments are honoured. External targets (URLs) should not be passed here.\nexport function resolveTarget(baseDir: string, target: string): string {\n\tconst segments = target.startsWith('/') || baseDir === '' ? [] : baseDir.split('/')\n\tfor (const part of target.split('/')) {\n\t\tif (part === '' || part === '.') continue\n\t\tif (part === '..') segments.pop()\n\t\telse segments.push(part)\n\t}\n\treturn segments.join('/')\n}\n","import { localName } from '../utils'\nimport { tokenize } from '../xml'\n\n// The shared string table (xl/sharedStrings.xml) deduplicates text across the workbook:\n// every `<si>` is one string, and a cell of type `s` stores a zero-based index into the\n// table rather than repeating the text. Parsing it once up front turns those indices into\n// O(1) lookups while reading sheets.\n//\n// An `<si>` is either a single `<t>` (plain text) or a sequence of `<r>` runs each with its\n// own `<t>` (rich text with per-run formatting we don't keep) — the value is every run's\n// text concatenated in order. Two subtleties:\n// * Whitespace is significant. The tokenizer emits text verbatim, and we only collect\n// text that sits *inside* a `<t>`, so layout whitespace between elements never leaks in\n// and `xml:space=\"preserve\"` needs no special handling.\n// * Phonetic guides (`<rPh>` and `<phoneticPr>`) carry an alternate reading, not part of\n// the displayed value, so their `<t>` text is excluded — matching openpyxl/Excel.\n//\n// The tokenizer does not validate structure, so misnested markup is possible. We hold one\n// invariant for robustness: exactly one table entry per `<si>` start. A new `<si>`/`<si/>`\n// seen while an item is still open finalizes that open item first, so a stray tag can never\n// silently drop or shift the index of a well-formed neighbour (indices feed cell lookups,\n// where an off-by-one would mislabel unrelated cells).\n\nexport function parseSharedStrings(xml: string): string[] {\n\tconst strings: string[] = []\n\n\tlet inItem = false // within an <si>\n\tlet current = '' // accumulated text for the current <si>\n\tlet textDepth = 0 // open <t> elements (text counts only when > 0)\n\tlet phoneticDepth = 0 // open <rPh>/<phoneticPr> elements (their text is excluded)\n\n\tfor (const token of tokenize(xml)) {\n\t\tif (token.kind === 'open') {\n\t\t\tconst name = localName(token.name)\n\t\t\tif (name === 'si') {\n\t\t\t\t// Finalize an item left open by misnested markup before starting the next.\n\t\t\t\tif (inItem) {\n\t\t\t\t\tstrings.push(current)\n\t\t\t\t\tinItem = false\n\t\t\t\t}\n\t\t\t\tif (token.selfClosing) {\n\t\t\t\t\tstrings.push('') // an empty self-closed item\n\t\t\t\t} else {\n\t\t\t\t\tinItem = true\n\t\t\t\t\tcurrent = ''\n\t\t\t\t\ttextDepth = 0\n\t\t\t\t\tphoneticDepth = 0\n\t\t\t\t}\n\t\t\t} else if (inItem && !token.selfClosing) {\n\t\t\t\tif (name === 't') textDepth++\n\t\t\t\telse if (name === 'rPh' || name === 'phoneticPr') phoneticDepth++\n\t\t\t}\n\t\t} else if (token.kind === 'text') {\n\t\t\tif (inItem && textDepth > 0 && phoneticDepth === 0) current += token.value\n\t\t} else {\n\t\t\t// close\n\t\t\tconst name = localName(token.name)\n\t\t\tif (!inItem) continue\n\t\t\tif (name === 't') {\n\t\t\t\tif (textDepth > 0) textDepth--\n\t\t\t} else if (name === 'rPh' || name === 'phoneticPr') {\n\t\t\t\tif (phoneticDepth > 0) phoneticDepth--\n\t\t\t} else if (name === 'si') {\n\t\t\t\tstrings.push(current)\n\t\t\t\tinItem = false\n\t\t\t}\n\t\t}\n\t}\n\n\treturn strings\n}\n","import { localName } from '../utils'\nimport { tokenize } from '../xml'\n\n// xl/styles.xml is what makes a number a date: a cell's `s` attribute indexes `<cellXfs>`,\n// each `<xf>` names a `numFmtId`, and the number format that id resolves to decides whether\n// the value is a date/time. We keep only what date detection needs — the numFmtId per\n// cell-format and the custom format codes — not the full style record.\n//\n// numFmtId < 164 built-in, NOT written into <numFmts>. The date/time ones are fixed by\n// the spec (14–22, 45–47) plus the locale date/time block (27–36, 50–58).\n// numFmtId ≥ 164 custom, defined in <numFmts> with a formatCode we sniff for date tokens.\n\nexport interface StyleTable {\n\t/** True when the cell format at this `s` index applies a date/time number format. */\n\tisDateStyle(styleIndex: number | undefined): boolean\n\t/**\n\t * The number-format code applied at this `s` index — a custom code (`<numFmts>`) or a\n\t * built-in one (e.g. `\"0.00%\"`, `\"mm-dd-yy\"`). `undefined` when the id is a locale/reserved\n\t * built-in with no portable code, or the index is out of range.\n\t */\n\tformatCode(styleIndex: number | undefined): string | undefined\n}\n\n// Built-in number formats (ECMA-376 §18.8.30) with a fixed, non-locale code. The locale and\n// reserved ids (23–36, 41–44, 50–58) have no portable code and resolve to undefined; date\n// detection still recognises those via isBuiltinDateId, we just don't fabricate their string.\nconst BUILTIN_FORMATS: Readonly<Record<number, string>> = {\n\t0: 'General',\n\t1: '0',\n\t2: '0.00',\n\t3: '#,##0',\n\t4: '#,##0.00',\n\t5: '\"$\"#,##0_);(\"$\"#,##0)',\n\t6: '\"$\"#,##0_);[Red](\"$\"#,##0)',\n\t7: '\"$\"#,##0.00_);(\"$\"#,##0.00)',\n\t8: '\"$\"#,##0.00_);[Red](\"$\"#,##0.00)',\n\t9: '0%',\n\t10: '0.00%',\n\t11: '0.00E+00',\n\t12: '# ?/?',\n\t13: '# ??/??',\n\t14: 'mm-dd-yy',\n\t15: 'd-mmm-yy',\n\t16: 'd-mmm',\n\t17: 'mmm-yy',\n\t18: 'h:mm AM/PM',\n\t19: 'h:mm:ss AM/PM',\n\t20: 'h:mm',\n\t21: 'h:mm:ss',\n\t22: 'm/d/yy h:mm',\n\t37: '#,##0_);(#,##0)',\n\t38: '#,##0_);[Red](#,##0)',\n\t39: '#,##0.00_);(#,##0.00)',\n\t40: '#,##0.00_);[Red](#,##0.00)',\n\t45: 'mm:ss',\n\t46: '[h]:mm:ss',\n\t47: 'mmss.0',\n\t48: '##0.0E+0',\n\t49: '@',\n}\n\nfunction isBuiltinDateId(id: number): boolean {\n\treturn (\n\t\t(id >= 14 && id <= 22) ||\n\t\t(id >= 27 && id <= 36) ||\n\t\t(id >= 45 && id <= 47) ||\n\t\t(id >= 50 && id <= 58)\n\t)\n}\n\n// A format code is a date/time format when, after removing the parts that can never be date\n// tokens — quoted literals (\"…\"), escaped characters (\\x), and bracketed sections ([Red],\n// [$-409], [>100]) — one of the date/time letters d m y h s remains.\n//\n// Elapsed-time tokens — [h], [hh], [mm], [ss] — are an exception: they ARE time formats but\n// live inside brackets the NON_TOKEN pass would strip, so a code like \"[h]\" (or \"[mm]:[ss]\")\n// would otherwise reduce to nothing. Detect them up front. (Ordinary elapsed formats like\n// \"[h]:mm:ss\" already pass via the mm/ss outside the brackets.)\nconst ELAPSED_TIME = /\\[(?:h+|m+|s+)\\]/i\nconst NON_TOKEN = /\\[[^\\]]*\\]|\"[^\"]*\"|\\\\./g\nconst DATE_TOKEN = /[dmyhs]/i\n\nexport function isDateFormatCode(formatCode: string): boolean {\n\tif (ELAPSED_TIME.test(formatCode)) return true\n\treturn DATE_TOKEN.test(formatCode.replace(NON_TOKEN, ''))\n}\n\nexport function parseStyles(xml: string): StyleTable {\n\tconst customFormats = new Map<number, string>()\n\tconst cellFormatIds: number[] = []\n\tlet inNumFmts = false\n\tlet inCellXfs = false // NOT cellStyleXfs — a cell's `s` indexes cellXfs only\n\n\tfor (const token of tokenize(xml)) {\n\t\tif (token.kind === 'text') continue\n\t\tconst name = localName(token.name)\n\t\tif (token.kind === 'open') {\n\t\t\tif (name === 'numFmts') {\n\t\t\t\tif (!token.selfClosing) inNumFmts = true\n\t\t\t} else if (name === 'cellXfs') {\n\t\t\t\tif (!token.selfClosing) inCellXfs = true\n\t\t\t} else if (name === 'numFmt' && inNumFmts) {\n\t\t\t\tconst id = Number(token.attrs.numFmtId)\n\t\t\t\tconst code = token.attrs.formatCode\n\t\t\t\tif (Number.isInteger(id) && code !== undefined) customFormats.set(id, code)\n\t\t\t} else if (name === 'xf' && inCellXfs) {\n\t\t\t\tconst id = Number(token.attrs.numFmtId ?? '0')\n\t\t\t\tcellFormatIds.push(Number.isInteger(id) ? id : 0)\n\t\t\t}\n\t\t} else if (token.kind === 'close') {\n\t\t\tif (name === 'numFmts') inNumFmts = false\n\t\t\telse if (name === 'cellXfs') inCellXfs = false\n\t\t}\n\t}\n\n\tfunction isDateStyle(styleIndex: number | undefined): boolean {\n\t\t// An omitted `s` means style 0, the implicit default format.\n\t\tconst numFmtId = cellFormatIds[styleIndex ?? 0]\n\t\tif (numFmtId === undefined) return false\n\t\tconst custom = customFormats.get(numFmtId)\n\t\treturn custom !== undefined ? isDateFormatCode(custom) : isBuiltinDateId(numFmtId)\n\t}\n\n\tfunction formatCode(styleIndex: number | undefined): string | undefined {\n\t\t// An omitted `s` means style 0, the implicit default format. A custom code for the id\n\t\t// wins over the built-in table (a file may redefine one); unknown ids stay undefined.\n\t\tconst numFmtId = cellFormatIds[styleIndex ?? 0]\n\t\tif (numFmtId === undefined) return undefined\n\t\treturn customFormats.get(numFmtId) ?? BUILTIN_FORMATS[numFmtId]\n\t}\n\n\treturn { isDateStyle, formatCode }\n}\n","import { localName, relationshipId } from '../utils'\nimport { tokenize } from '../xml'\n\n// xl/workbook.xml lists the workbook's sheets in tab order. Each <sheet> gives a display\n// name and an r:id — NOT a filename — that points into workbook.xml.rels to locate the\n// actual worksheet part. (sheetId is an internal key, not a file mapping.) It also carries\n// the workbook-wide date system flag (<workbookPr date1904>).\n\nexport interface WorkbookSheet {\n\t/** Sheet name as shown on the tab. */\n\treadonly name: string\n\t/** Relationship id (r:id) resolving to the worksheet part via workbook.xml.rels. */\n\treadonly rid: string\n\t/** false for hidden or very-hidden sheets (the `state` attribute). */\n\treadonly visible: boolean\n}\n\nexport interface WorkbookMeta {\n\treadonly sheets: readonly WorkbookSheet[]\n\t/** The 1904 date system flag (`<workbookPr date1904>`); selects the date serial epoch. */\n\treadonly date1904: boolean\n}\n\nexport function parseWorkbook(xml: string): WorkbookMeta {\n\tconst sheets: WorkbookSheet[] = []\n\tlet date1904 = false\n\tfor (const token of tokenize(xml)) {\n\t\tif (token.kind !== 'open') continue\n\t\tconst tag = localName(token.name)\n\t\tif (tag === 'workbookPr') {\n\t\t\tconst flag = token.attrs.date1904\n\t\t\tif (flag === '1' || flag === 'true') date1904 = true\n\t\t} else if (tag === 'sheet') {\n\t\t\tconst name = token.attrs.name\n\t\t\tconst rid = relationshipId(token.attrs)\n\t\t\tif (name === undefined || rid === undefined) continue\n\t\t\tconst state = token.attrs.state\n\t\t\tsheets.push({ name, rid, visible: state !== 'hidden' && state !== 'veryHidden' })\n\t\t}\n\t}\n\treturn { sheets, date1904 }\n}\n","// Raw DEFLATE decompression using the platform Compression Streams API — available on\n// Node >= 18, Deno, Bun, modern browsers, and Cloudflare Workers. This is why openjsxl\n// needs no zip/inflate dependency: the runtime already ships one.\n//\n// `maxBytes` bounds the output: decompression is aborted and an error thrown once the\n// inflated size would exceed it. Callers pass the entry's declared uncompressed size so a\n// malformed or hostile stream can't expand without bound (a decompression bomb).\n\nexport async function inflateRaw(\n\tdata: Uint8Array,\n\tmaxBytes = Number.POSITIVE_INFINITY,\n): Promise<Uint8Array> {\n\t// The Blob accepts our bytes at runtime; the cast sidesteps a TS lib / @types/node\n\t// disagreement over whether the backing buffer is an ArrayBuffer or SharedArrayBuffer.\n\tconst blob = new Blob([data as BlobPart])\n\tconst reader = blob.stream().pipeThrough(new DecompressionStream('deflate-raw')).getReader()\n\n\tconst chunks: Uint8Array[] = []\n\tlet total = 0\n\tfor (;;) {\n\t\tconst { done, value } = await reader.read()\n\t\tif (done) break\n\t\ttotal += value.byteLength\n\t\tif (total > maxBytes) {\n\t\t\tawait reader.cancel()\n\t\t\tthrow new Error(`inflated output exceeds the expected ${maxBytes} bytes`)\n\t\t}\n\t\tchunks.push(value)\n\t}\n\n\tconst out = new Uint8Array(total)\n\tlet offset = 0\n\tfor (const chunk of chunks) {\n\t\tout.set(chunk, offset)\n\t\toffset += chunk.byteLength\n\t}\n\treturn out\n}\n\n// Streaming variant: yield decompressed chunks instead of one buffer, so a large part can be\n// consumed without ever materializing it whole. `maxBytes` bounds the total output (a bomb\n// cap); the stream is cancelled if the consumer stops early.\nexport async function* inflateRawStream(\n\tdata: Uint8Array,\n\tmaxBytes = Number.POSITIVE_INFINITY,\n): AsyncGenerator<Uint8Array> {\n\tconst blob = new Blob([data as BlobPart])\n\tconst reader = blob.stream().pipeThrough(new DecompressionStream('deflate-raw')).getReader()\n\n\tlet total = 0\n\ttry {\n\t\tfor (;;) {\n\t\t\tconst { done, value } = await reader.read()\n\t\t\tif (done) break\n\t\t\ttotal += value.byteLength\n\t\t\tif (total > maxBytes) {\n\t\t\t\tthrow new Error(`inflated output exceeds the expected ${maxBytes} bytes`)\n\t\t\t}\n\t\t\tyield value\n\t\t}\n\t} finally {\n\t\tawait reader.cancel().catch(() => {})\n\t}\n}\n","import { XlsxError } from '../errors'\nimport { inflateRaw, inflateRawStream } from './inflate'\n\n// Minimal reader for the ZIP (OPC) container that wraps every .xlsx. We locate the\n// End-Of-Central-Directory record, walk the central directory to find each entry, and read\n// its bytes on demand — inflating with ./inflate when an entry is deflate-compressed\n// (method 8) or returning it verbatim when stored (method 0).\n//\n// Sizes and the data offset come from the CENTRAL directory + LOCAL header (never the\n// local header's size fields), so the data-descriptor layout (general-purpose bit 3) that\n// Excel and LibreOffice emit reads correctly.\n//\n// Not supported (the reader detects and rejects these rather than misreading): ZIP64\n// (> 4 GB or > 65535 entries), encryption, and multi-disk archives.\n//\n// Entry policy: directory placeholders (`name/`) are skipped; duplicate part names are refused\n// (OPC forbids them, and an ambiguous package is a zip-confusion vector).\n\nexport interface ZipEntry {\n\treadonly name: string\n\t/** 0 = stored, 8 = raw deflate */\n\treadonly method: number\n\treadonly compressedSize: number\n\treadonly uncompressedSize: number\n\t/** absolute offset of the local file header within the archive */\n\treadonly localHeaderOffset: number\n}\n\nexport interface ZipArchive {\n\treadonly entries: ReadonlyMap<string, ZipEntry>\n\thas(name: string): boolean\n\tread(name: string): Promise<Uint8Array>\n\t/** Read an entry as a stream of chunks, without materializing the whole part. */\n\treadStream(name: string): AsyncGenerator<Uint8Array>\n}\n\nconst SIG_EOCD = 0x06054b50\nconst SIG_CENTRAL = 0x02014b50\nconst SIG_LOCAL = 0x04034b50\nconst EOCD_MIN_SIZE = 22\nconst MAX_COMMENT = 0xffff\nconst ZIP64_SENTINEL = 0xffffffff\n\n// The EOCD record sits at the very end, after an optional ≤64 KB comment. Scan backwards\n// for its signature and confirm the comment length lands exactly on the end of file (so a\n// signature appearing inside compressed data can't be mistaken for it).\nfunction findEocd(view: DataView, len: number): number {\n\tconst earliest = Math.max(0, len - EOCD_MIN_SIZE - MAX_COMMENT)\n\tfor (let pos = len - EOCD_MIN_SIZE; pos >= earliest; pos--) {\n\t\tif (view.getUint32(pos, true) !== SIG_EOCD) continue\n\t\tconst commentLen = view.getUint16(pos + 20, true)\n\t\tif (pos + EOCD_MIN_SIZE + commentLen === len) return pos\n\t}\n\treturn -1\n}\n\nexport function openZip(bytes: Uint8Array, options?: { maxPartBytes?: number }): ZipArchive {\n\tconst len = bytes.byteLength\n\tconst view = new DataView(bytes.buffer, bytes.byteOffset, len)\n\t// An absolute ceiling on a single part's declared decompressed size, independent of the\n\t// (attacker-controllable) uncompressedSize the inflate already caps at — a zip-bomb guard\n\t// callers opt into. undefined ⇒ no ceiling beyond the declared size.\n\tconst maxPartBytes = options?.maxPartBytes\n\n\tconst eocd = findEocd(view, len)\n\tif (eocd === -1) {\n\t\tthrow new XlsxError(\n\t\t\t'not-a-zip',\n\t\t\t'not a zip archive: end-of-central-directory record not found',\n\t\t)\n\t}\n\n\tconst entryCount = view.getUint16(eocd + 10, true)\n\tconst cdOffset = view.getUint32(eocd + 16, true)\n\tif (cdOffset === ZIP64_SENTINEL)\n\t\tthrow new XlsxError('unsupported', 'ZIP64 archives are not supported')\n\tif (cdOffset > len) {\n\t\tthrow new XlsxError('corrupt-zip', 'corrupt zip: central directory offset past end of file')\n\t}\n\n\tconst decoder = new TextDecoder()\n\tconst entries = new Map<string, ZipEntry>()\n\tlet pos = cdOffset\n\tfor (let i = 0; i < entryCount; i++) {\n\t\tif (pos + 46 > len || view.getUint32(pos, true) !== SIG_CENTRAL) {\n\t\t\tthrow new XlsxError(\n\t\t\t\t'corrupt-zip',\n\t\t\t\t`corrupt zip: bad central directory header at offset ${pos}`,\n\t\t\t)\n\t\t}\n\t\tconst method = view.getUint16(pos + 10, true)\n\t\tconst compressedSize = view.getUint32(pos + 20, true)\n\t\tconst uncompressedSize = view.getUint32(pos + 24, true)\n\t\tconst nameLen = view.getUint16(pos + 28, true)\n\t\tconst extraLen = view.getUint16(pos + 30, true)\n\t\tconst commentLen = view.getUint16(pos + 32, true)\n\t\tconst localHeaderOffset = view.getUint32(pos + 42, true)\n\t\tif (\n\t\t\tcompressedSize === ZIP64_SENTINEL ||\n\t\t\tuncompressedSize === ZIP64_SENTINEL ||\n\t\t\tlocalHeaderOffset === ZIP64_SENTINEL\n\t\t) {\n\t\t\tthrow new XlsxError('unsupported', 'ZIP64 archives are not supported')\n\t\t}\n\t\tconst name = decoder.decode(bytes.subarray(pos + 46, pos + 46 + nameLen))\n\t\tpos += 46 + nameLen + extraLen + commentLen\n\t\t// Directory entries (`name/`) are placeholders, not parts — skip them.\n\t\tif (name.endsWith('/')) continue\n\t\t// OPC forbids duplicate part names; a duplicate makes the package ambiguous (a\n\t\t// zip-confusion vector), so refuse it rather than silently resolving to one entry.\n\t\tif (entries.has(name)) {\n\t\t\tthrow new XlsxError('corrupt-zip', `corrupt zip: duplicate entry name ${name}`)\n\t\t}\n\t\tentries.set(name, { name, method, compressedSize, uncompressedSize, localHeaderOffset })\n\t}\n\n\t// Find an entry's raw (still-compressed) payload. The local header repeats name/extra\n\t// lengths, which may differ from the central directory's — trust the local header to find\n\t// where the data actually starts.\n\tfunction locate(name: string): { entry: ZipEntry; payload: Uint8Array } {\n\t\tconst entry = entries.get(name)\n\t\tif (entry === undefined) throw new XlsxError('missing-part', `zip entry not found: ${name}`)\n\t\tif (maxPartBytes !== undefined && entry.uncompressedSize > maxPartBytes) {\n\t\t\tthrow new XlsxError(\n\t\t\t\t'part-too-large',\n\t\t\t\t`zip part ${name} declares ${entry.uncompressedSize} bytes, over the ${maxPartBytes}-byte limit`,\n\t\t\t)\n\t\t}\n\t\tconst header = entry.localHeaderOffset\n\t\tif (header + 30 > len || view.getUint32(header, true) !== SIG_LOCAL) {\n\t\t\tthrow new XlsxError('corrupt-zip', `corrupt zip: bad local header for ${name}`)\n\t\t}\n\t\tconst nameLen = view.getUint16(header + 26, true)\n\t\tconst extraLen = view.getUint16(header + 28, true)\n\t\tconst dataStart = header + 30 + nameLen + extraLen\n\t\tif (dataStart + entry.compressedSize > len) {\n\t\t\tthrow new XlsxError(\n\t\t\t\t'corrupt-zip',\n\t\t\t\t`corrupt zip: entry data for ${name} runs past end of file`,\n\t\t\t)\n\t\t}\n\t\treturn { entry, payload: bytes.subarray(dataStart, dataStart + entry.compressedSize) }\n\t}\n\n\tasync function read(name: string): Promise<Uint8Array> {\n\t\tconst { entry, payload } = locate(name)\n\t\tif (entry.method === 0) return payload\n\t\tif (entry.method === 8) {\n\t\t\tif (entry.compressedSize === 0) return new Uint8Array(0)\n\t\t\ttry {\n\t\t\t\treturn await inflateRaw(payload, entry.uncompressedSize)\n\t\t\t} catch (cause) {\n\t\t\t\tthrow new XlsxError('corrupt-zip', `corrupt zip: failed to inflate ${name}`, {\n\t\t\t\t\tcause,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tthrow new XlsxError(\n\t\t\t'unsupported',\n\t\t\t`unsupported zip compression method ${entry.method} for ${name}`,\n\t\t)\n\t}\n\n\t// Read an entry as a stream of chunks, never materializing the whole part. Stored entries\n\t// yield their (already in-memory) payload as one chunk; deflate entries stream the inflate.\n\tasync function* readStream(name: string): AsyncGenerator<Uint8Array> {\n\t\tconst { entry, payload } = locate(name)\n\t\tif (entry.method === 0) {\n\t\t\tif (payload.byteLength > 0) yield payload\n\t\t\treturn\n\t\t}\n\t\tif (entry.method === 8) {\n\t\t\tif (entry.compressedSize === 0) return\n\t\t\ttry {\n\t\t\t\tyield* inflateRawStream(payload, entry.uncompressedSize)\n\t\t\t} catch (cause) {\n\t\t\t\tthrow new XlsxError('corrupt-zip', `corrupt zip: failed to inflate ${name}`, {\n\t\t\t\t\tcause,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tthrow new XlsxError(\n\t\t\t'unsupported',\n\t\t\t`unsupported zip compression method ${entry.method} for ${name}`,\n\t\t)\n\t}\n\n\treturn {\n\t\tentries,\n\t\thas: (name) => entries.has(name),\n\t\tread,\n\t\treadStream,\n\t}\n}\n","import { type DecodeContext, decodeCell, formatRef, parseRef, type Relationship } from '../ooxml'\nimport type { Cell, Comment, Hyperlink } from '../types'\nimport { localName, relationshipId } from '../utils'\nimport { createXmlStream, tokenize, type XmlToken } from '../xml'\n\n// Turn a worksheet part (xl/worksheets/sheetN.xml) into rows of typed cells. We walk the\n// tokenizer event stream rather than building a DOM, so peak memory tracks one row, not the\n// whole sheet. The same row state machine drives both the in-memory `readRows` (over a full\n// string) and the constant-memory `streamRows` (over decompressed chunks) — see F2.2.\n//\n// Cells and rows are sparse and may appear out of order, so each cell carries its own A1\n// ref and callers key by that ref — never by position in the array. When a `<c>` omits its\n// `r` attribute (some streaming writers do), the column is taken positionally: one past the\n// previous cell, exactly as the spec prescribes.\n//\n// Robustness mirrors the lower layers: the tokenizer never throws and does not validate\n// structure, so this code must not corrupt a well-formed row because of a malformed\n// neighbour. A new `<row>`/`<c>` opening while one is still unclosed finalizes the open one\n// first, and a row left open at end-of-input (truncated file) is still emitted.\n\nexport interface Row {\n\t/** 1-based row index — from `<row r>`, or positional when the attribute is absent. */\n\treadonly index: number\n\t/** Cells present in the row, in document order. Gaps are simply absent (sparse). */\n\treadonly cells: readonly Cell[]\n}\n\nfunction safeColumn(ref: string): number | undefined {\n\ttry {\n\t\treturn parseRef(ref).col\n\t} catch {\n\t\treturn undefined\n\t}\n}\n\n// A cell's format can be set at three levels, not just on the cell. `<c s>` is per-cell, but a\n// whole column can be formatted with `<col … style>` and a whole row with `<row s customFormat>`.\n// The effective style index resolves in this precedence (SpreadsheetML §18.3.1.13/.73/.4):\n//\n// cell's own `s` > row default (customFormat) > column default (<col>) > style 0\n//\n// Without this, a date column whose cells omit `s` reads as plain numbers, and numberFormat()\n// returns the wrong code — the common case where a producer formats a column once instead of\n// per cell. All three levels are indices into the SAME cellXfs table, so the resolved index\n// drops straight into StyleTable.isDateStyle/formatCode with no further translation.\n\n// A column-default style: `<col … style>` applies to every cell in columns [min, max] that does\n// not set its own `s`. (`style` is the column's default cell format — an index into cellXfs.)\ninterface ColumnStyle {\n\treadonly min: number\n\treadonly max: number\n\treadonly style: number\n}\n\nfunction columnStyleFromToken(attrs: Readonly<Record<string, string>>): ColumnStyle | undefined {\n\t// A <col> with no `style` sets width/visibility only — it contributes no default format.\n\tif (attrs.style === undefined) return undefined\n\tconst style = Number(attrs.style)\n\tconst min = Number(attrs.min)\n\tconst max = Number(attrs.max)\n\tif (!Number.isInteger(style) || !Number.isInteger(min) || !Number.isInteger(max))\n\t\treturn undefined\n\treturn { min, max, style }\n}\n\n// A row's default style is honored ONLY when `customFormat=\"1\"`. The spec is explicit: `<row>`'s\n// `s` is \"only applied if the customFormat attribute is '1'\". Writers routinely emit a bookkeeping\n// `s` on ordinary rows, so without this gate we would restyle cells the file never meant to format.\nfunction rowDefaultStyleFromToken(attrs: Readonly<Record<string, string>>): number | undefined {\n\tif (attrs.customFormat !== '1' && attrs.customFormat !== 'true') return undefined\n\tif (attrs.s === undefined) return undefined\n\tconst s = Number(attrs.s)\n\treturn Number.isInteger(s) ? s : undefined\n}\n\n// Resolve the precedence above for one cell. A present-but-unparseable cell `s` still counts as\n// \"the cell declared its own style\" — it opts out of inherited defaults and falls back to style 0,\n// rather than silently borrowing the row/column format.\nfunction effectiveStyle(\n\townS: string | undefined,\n\trowDefault: number | undefined,\n\tcol: number | undefined,\n\tcolumns: readonly ColumnStyle[],\n): number | undefined {\n\tif (ownS !== undefined) {\n\t\tconst s = Number(ownS)\n\t\treturn Number.isInteger(s) ? s : undefined\n\t}\n\tif (rowDefault !== undefined) return rowDefault\n\tif (col !== undefined) {\n\t\t// First covering range wins. Ranges don't overlap in a valid file; first-match keeps\n\t\t// resolution deterministic even if a malformed file declares a column twice.\n\t\tconst range = columns.find((c) => col >= c.min && col <= c.max)\n\t\tif (range !== undefined) return range.style\n\t}\n\treturn undefined\n}\n\ninterface RowAssembler {\n\t/** Advance the state machine by one token; returns any rows that completed. */\n\tpush(token: XmlToken): Row[]\n\t/** Emit a row left open at end of input (truncated file). */\n\tflush(): Row[]\n}\n\nfunction createRowAssembler(ctx: DecodeContext): RowAssembler {\n\tlet inSheetData = false\n\tlet inRow = false\n\tlet lastRow = 0\n\tlet rowIndex = 0\n\tlet cells: Cell[] = []\n\tlet lastCol = 0\n\n\t// Column defaults from `<cols>` (which precedes `<sheetData>`, so it is fully seen before any\n\t// cell) and the current row's default (customFormat) — both feed effectiveStyle for cells\n\t// that omit their own `s`. See the ColumnStyle/effectiveStyle notes above.\n\tconst columns: ColumnStyle[] = []\n\tlet rowDefault: number | undefined\n\n\tlet inCell = false\n\tlet cellRef = ''\n\tlet cellType: string | undefined\n\tlet cellStyle: number | undefined // the `s` attribute (index into cellXfs)\n\tlet cellIsInline = false // type === 'inlineStr': value lives in <is>, not <v>\n\tlet cellValue = ''\n\tlet hasValue = false // the value channel's element was present (even if empty)\n\tlet inValue = false // inside <v>\n\tlet inInline = false // inside <is>\n\tlet textDepth = 0 // open <t> within <is>\n\tlet phoneticDepth = 0 // open <rPh>/<phoneticPr> within <is> (excluded from the value)\n\n\t// Finalize the open cell into the current row. A no-op when no cell is open.\n\tconst flushCell = () => {\n\t\tif (!inCell) return\n\t\tcells.push(\n\t\t\tdecodeCell(\n\t\t\t\t{\n\t\t\t\t\tref: cellRef,\n\t\t\t\t\ttype: cellType,\n\t\t\t\t\tvalue: hasValue ? cellValue : undefined,\n\t\t\t\t\tstyle: cellStyle,\n\t\t\t\t},\n\t\t\t\tctx,\n\t\t\t),\n\t\t)\n\t\tinCell = false\n\t}\n\n\tfunction push(token: XmlToken): Row[] {\n\t\tconst out: Row[] = []\n\n\t\tif (token.kind === 'open') {\n\t\t\tconst name = localName(token.name)\n\n\t\t\tif (name === 'sheetData') {\n\t\t\t\tif (!token.selfClosing) inSheetData = true\n\t\t\t\treturn out\n\t\t\t}\n\t\t\t// `<col>` lives in `<cols>`, a sibling that precedes `<sheetData>` — capture its\n\t\t\t// default style before the inSheetData guard below would skip it.\n\t\t\tif (name === 'col') {\n\t\t\t\tconst cs = columnStyleFromToken(token.attrs)\n\t\t\t\tif (cs !== undefined) columns.push(cs)\n\t\t\t\treturn out\n\t\t\t}\n\t\t\tif (!inSheetData) return out\n\n\t\t\tif (name === 'row') {\n\t\t\t\tflushCell()\n\t\t\t\tif (inRow) out.push({ index: rowIndex, cells })\n\t\t\t\tconst r = token.attrs.r\n\t\t\t\tconst parsed = r !== undefined ? Number.parseInt(r, 10) : Number.NaN\n\t\t\t\trowIndex = Number.isInteger(parsed) && parsed > 0 ? parsed : lastRow + 1\n\t\t\t\tlastRow = rowIndex\n\t\t\t\t// A non-customFormat row overwrites this back to undefined — no stale carryover.\n\t\t\t\trowDefault = rowDefaultStyleFromToken(token.attrs)\n\t\t\t\tcells = []\n\t\t\t\tlastCol = 0\n\t\t\t\tif (token.selfClosing) {\n\t\t\t\t\tout.push({ index: rowIndex, cells })\n\t\t\t\t\tinRow = false\n\t\t\t\t} else {\n\t\t\t\t\tinRow = true\n\t\t\t\t}\n\t\t\t\treturn out\n\t\t\t}\n\t\t\tif (!inRow) return out\n\n\t\t\tif (name === 'c') {\n\t\t\t\tflushCell()\n\t\t\t\tconst r = token.attrs.r\n\t\t\t\t// The cell's column index, needed to resolve a `<col>` default style. Known even\n\t\t\t\t// when `r` is absent (positional: one past the previous cell).\n\t\t\t\tlet col: number | undefined\n\t\t\t\tif (r !== undefined) {\n\t\t\t\t\tcellRef = r\n\t\t\t\t\tcol = safeColumn(r)\n\t\t\t\t\tif (col !== undefined) lastCol = col\n\t\t\t\t} else {\n\t\t\t\t\tlastCol += 1\n\t\t\t\t\tcol = lastCol\n\t\t\t\t\tcellRef = formatRef({ col: lastCol, row: rowIndex })\n\t\t\t\t}\n\t\t\t\tcellType = token.attrs.t\n\t\t\t\t// Effective style: cell `s` → row default → column default → style 0.\n\t\t\t\tcellStyle = effectiveStyle(token.attrs.s, rowDefault, col, columns)\n\t\t\t\tcellIsInline = cellType === 'inlineStr'\n\t\t\t\tcellValue = ''\n\t\t\t\thasValue = false\n\t\t\t\tinValue = false\n\t\t\t\tinInline = false\n\t\t\t\ttextDepth = 0\n\t\t\t\tphoneticDepth = 0\n\t\t\t\tif (token.selfClosing) {\n\t\t\t\t\tcells.push(\n\t\t\t\t\t\tdecodeCell(\n\t\t\t\t\t\t\t{ ref: cellRef, type: cellType, value: undefined, style: cellStyle },\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\tinCell = true\n\t\t\t\t}\n\t\t\t\treturn out\n\t\t\t}\n\t\t\tif (!inCell) return out\n\n\t\t\t// A cell's value lives in exactly one channel, picked by its type: inline strings\n\t\t\t// in <is>/<t>, everything else in <v>. Gate on the type so a stray element from\n\t\t\t// the other channel can't pollute the value. Mark the value present as soon as its\n\t\t\t// element opens, so an explicit but empty <v></v> or <is><t></t></is> reads as \"\"\n\t\t\t// rather than collapsing to a blank cell.\n\t\t\tif (cellIsInline) {\n\t\t\t\tif (name === 'is') {\n\t\t\t\t\thasValue = true\n\t\t\t\t\tif (!token.selfClosing) inInline = true\n\t\t\t\t} else if (name === 't') {\n\t\t\t\t\tif (inInline && !token.selfClosing) textDepth++\n\t\t\t\t} else if (name === 'rPh' || name === 'phoneticPr') {\n\t\t\t\t\tif (inInline && !token.selfClosing) phoneticDepth++\n\t\t\t\t}\n\t\t\t} else if (name === 'v') {\n\t\t\t\thasValue = true\n\t\t\t\tif (!token.selfClosing) inValue = true\n\t\t\t}\n\t\t\treturn out\n\t\t}\n\n\t\tif (token.kind === 'text') {\n\t\t\tconst collect = cellIsInline\n\t\t\t\t? inInline && textDepth > 0 && phoneticDepth === 0\n\t\t\t\t: inValue\n\t\t\tif (inCell && collect) {\n\t\t\t\tcellValue += token.value\n\t\t\t\thasValue = true\n\t\t\t}\n\t\t\treturn out\n\t\t}\n\n\t\t// close\n\t\tconst name = localName(token.name)\n\t\tif (name === 'sheetData') {\n\t\t\tflushCell()\n\t\t\tif (inRow) {\n\t\t\t\tout.push({ index: rowIndex, cells })\n\t\t\t\tinRow = false\n\t\t\t}\n\t\t\tinSheetData = false\n\t\t\treturn out\n\t\t}\n\t\tif (name === 'row') {\n\t\t\tif (inRow) {\n\t\t\t\tflushCell()\n\t\t\t\tout.push({ index: rowIndex, cells })\n\t\t\t\tinRow = false\n\t\t\t}\n\t\t\treturn out\n\t\t}\n\t\tif (!inCell) return out\n\t\tif (name === 'c') flushCell()\n\t\telse if (name === 'v') inValue = false\n\t\telse if (name === 'is') inInline = false\n\t\telse if (name === 't') {\n\t\t\tif (textDepth > 0) textDepth--\n\t\t} else if (name === 'rPh' || name === 'phoneticPr') {\n\t\t\tif (phoneticDepth > 0) phoneticDepth--\n\t\t}\n\t\treturn out\n\t}\n\n\tfunction flush(): Row[] {\n\t\tflushCell()\n\t\tif (inRow) {\n\t\t\tinRow = false\n\t\t\treturn [{ index: rowIndex, cells }]\n\t\t}\n\t\treturn []\n\t}\n\n\treturn { push, flush }\n}\n\n/**\n * The comments a worksheet carries. Comments live in a separate part (xl/commentsN.xml) that\n * pairs an `<authors>` list with a `<commentList>`; each `<comment ref authorId>` holds rich\n * text in `<text>`. We concatenate the `<t>` runs (dropping formatting, matching how shared\n * strings read) and resolve the authorId against the authors list. A comment with no `ref`, or\n * an authorId that resolves to nothing, still yields text — the author is just omitted.\n */\nexport function parseComments(xml: string): Comment[] {\n\tconst authors: string[] = []\n\tconst comments: Comment[] = []\n\tlet inAuthors = false\n\tlet authorText: string | undefined // non-undefined while inside an <author>\n\tlet current: { ref: string; authorId: number } | undefined // inside a <comment>\n\tlet inText = false // inside the current comment's <text>\n\tlet tDepth = 0 // open <t> within <text>\n\tlet text = ''\n\n\tfor (const token of tokenize(xml)) {\n\t\tif (token.kind === 'open') {\n\t\t\tconst name = localName(token.name)\n\t\t\tif (name === 'authors') {\n\t\t\t\tif (!token.selfClosing) inAuthors = true\n\t\t\t} else if (name === 'author' && inAuthors) {\n\t\t\t\tif (token.selfClosing) authors.push('')\n\t\t\t\telse authorText = ''\n\t\t\t} else if (name === 'comment') {\n\t\t\t\tconst ref = token.attrs.ref\n\t\t\t\t// A missing/empty/non-integer authorId is unresolved (-1) so the author is omitted,\n\t\t\t\t// rather than falling through Number('')===0 to author 0 — don't fabricate an\n\t\t\t\t// attribution the file never made.\n\t\t\t\tconst rawId = token.attrs.authorId\n\t\t\t\tconst authorId =\n\t\t\t\t\trawId !== undefined && rawId !== '' && Number.isInteger(Number(rawId))\n\t\t\t\t\t\t? Number(rawId)\n\t\t\t\t\t\t: -1\n\t\t\t\tcurrent = ref !== undefined && ref !== '' ? { ref, authorId } : undefined\n\t\t\t\ttext = ''\n\t\t\t\tinText = false\n\t\t\t\ttDepth = 0\n\t\t\t} else if (name === 'text' && current !== undefined) {\n\t\t\t\tif (!token.selfClosing) inText = true\n\t\t\t} else if (name === 't' && inText) {\n\t\t\t\tif (!token.selfClosing) tDepth++\n\t\t\t}\n\t\t} else if (token.kind === 'text') {\n\t\t\tif (authorText !== undefined) authorText += token.value\n\t\t\telse if (inText && tDepth > 0) text += token.value\n\t\t} else {\n\t\t\tconst name = localName(token.name)\n\t\t\tif (name === 'authors') inAuthors = false\n\t\t\telse if (name === 'author' && authorText !== undefined) {\n\t\t\t\tauthors.push(authorText)\n\t\t\t\tauthorText = undefined\n\t\t\t} else if (name === 't') {\n\t\t\t\tif (tDepth > 0) tDepth--\n\t\t\t} else if (name === 'text') inText = false\n\t\t\telse if (name === 'comment' && current !== undefined) {\n\t\t\t\tconst author = authors[current.authorId]\n\t\t\t\tcomments.push({\n\t\t\t\t\tref: current.ref,\n\t\t\t\t\t...(author !== undefined && author !== '' ? { author } : {}),\n\t\t\t\t\ttext,\n\t\t\t\t})\n\t\t\t\tcurrent = undefined\n\t\t\t}\n\t\t}\n\t}\n\treturn comments\n}\n\n/**\n * The worksheet's declared used range — the `<dimension ref>` (e.g. \"A1:E10\", or a single\n * cell). Optional in OOXML: undefined when the producer omits it, or when it is empty. The\n * element sits near the top of the part, so the scan returns as soon as it is found.\n */\nexport function parseDimension(xml: string): string | undefined {\n\tfor (const token of tokenize(xml)) {\n\t\tif (token.kind === 'open' && localName(token.name) === 'dimension') {\n\t\t\tconst ref = token.attrs.ref\n\t\t\tif (ref !== undefined && ref !== '') return ref\n\t\t}\n\t}\n\treturn undefined\n}\n\n/**\n * Map each cell to its EFFECTIVE style index, for resolving per-cell number formats. Effective\n * means the same precedence date detection uses — cell `s`, else the row default (`<row s\n * customFormat>`), else the column default (`<col … style>`), else style 0. A cell that resolves\n * to no style is omitted (the lookup falls back to style 0 anyway).\n *\n * Addressing MUST match the row assembler so numberFormat() and cell()/rows() agree on the same\n * ref: an explicit `r` is used verbatim; a cell without `r` is positioned one past the previous\n * cell (`formatRef`), exactly as the assembler synthesizes its ref — otherwise a no-`r` cell that\n * inherits a column/row style would read as a date via cell() but as \"General\" via numberFormat().\n */\nexport function parseCellStyles(xml: string): Map<string, number> {\n\tconst styles = new Map<string, number>()\n\tconst columns: ColumnStyle[] = []\n\tlet rowDefault: number | undefined\n\tlet lastRow = 0\n\tlet rowIndex = 0\n\tlet lastCol = 0\n\tfor (const token of tokenize(xml)) {\n\t\tif (token.kind !== 'open') continue\n\t\tconst name = localName(token.name)\n\t\tif (name === 'col') {\n\t\t\tconst cs = columnStyleFromToken(token.attrs)\n\t\t\tif (cs !== undefined) columns.push(cs)\n\t\t\tcontinue\n\t\t}\n\t\tif (name === 'row') {\n\t\t\tconst r = token.attrs.r\n\t\t\tconst parsed = r !== undefined ? Number.parseInt(r, 10) : Number.NaN\n\t\t\trowIndex = Number.isInteger(parsed) && parsed > 0 ? parsed : lastRow + 1\n\t\t\tlastRow = rowIndex\n\t\t\trowDefault = rowDefaultStyleFromToken(token.attrs)\n\t\t\tlastCol = 0\n\t\t\tcontinue\n\t\t}\n\t\tif (name !== 'c') continue\n\t\t// Resolve the cell's ref and column with the same positional rule as the assembler.\n\t\tconst r = token.attrs.r\n\t\tlet ref: string\n\t\tlet col: number | undefined\n\t\tif (r !== undefined) {\n\t\t\tref = r\n\t\t\tcol = safeColumn(r)\n\t\t\tif (col !== undefined) lastCol = col\n\t\t} else {\n\t\t\tlastCol += 1\n\t\t\tcol = lastCol\n\t\t\tref = formatRef({ col: lastCol, row: rowIndex })\n\t\t}\n\t\tconst index = effectiveStyle(token.attrs.s, rowDefault, col, columns)\n\t\tif (index !== undefined) styles.set(ref, index)\n\t}\n\treturn styles\n}\n\n/** Read rows from a fully in-memory worksheet string. */\nexport function* readRows(xml: string, ctx: DecodeContext): Generator<Row> {\n\tconst assembler = createRowAssembler(ctx)\n\tfor (const token of tokenize(xml)) yield* assembler.push(token)\n\tyield* assembler.flush()\n}\n\n/**\n * The merged-cell ranges a worksheet declares, in document order, as A1 ranges (e.g. `A1:B2`).\n * They live in a `<mergeCells>` block after `<sheetData>`, so we scan the token stream for the\n * `<mergeCell ref>` children rather than the row state machine. Refs are returned verbatim as\n * the producer wrote them; a missing or empty `ref` is skipped.\n */\nexport function parseMergedCells(xml: string): string[] {\n\tconst ranges: string[] = []\n\tfor (const token of tokenize(xml)) {\n\t\tif (token.kind === 'open' && localName(token.name) === 'mergeCell') {\n\t\t\tconst ref = token.attrs.ref\n\t\t\tif (ref !== undefined && ref !== '') ranges.push(ref)\n\t\t}\n\t}\n\treturn ranges\n}\n\n/**\n * The hyperlinks a worksheet declares, in document order. They live in a `<hyperlinks>` block\n * (a sibling of `<sheetData>`); each `<hyperlink>` carries the covered `ref` plus some of:\n * an `r:id` pointing into the worksheet's own relationships (the external target), an\n * in-workbook `location`, a `tooltip`, and a `display` override. The external target is joined\n * from `rels` here so callers get the resolved URL, not a bare relationship id; a link with no\n * resolvable `r:id` simply has no `target`. A missing/empty `ref` is skipped.\n */\nexport function parseHyperlinks(xml: string, rels?: Map<string, Relationship>): Hyperlink[] {\n\tconst links: Hyperlink[] = []\n\tfor (const token of tokenize(xml)) {\n\t\tif (token.kind !== 'open' || localName(token.name) !== 'hyperlink') continue\n\t\tconst ref = token.attrs.ref\n\t\tif (ref === undefined || ref === '') continue\n\n\t\t// Built immutably (Hyperlink is readonly): include only the attributes that are present.\n\t\tconst rid = relationshipId(token.attrs)\n\t\tconst target = rid !== undefined ? rels?.get(rid)?.target : undefined\n\t\tconst location = token.attrs.location\n\t\tconst tooltip = token.attrs.tooltip\n\t\tconst display = token.attrs.display\n\t\tlinks.push({\n\t\t\tref,\n\t\t\t...(target !== undefined ? { target } : {}),\n\t\t\t...(location !== undefined && location !== '' ? { location } : {}),\n\t\t\t...(tooltip !== undefined ? { tooltip } : {}),\n\t\t\t...(display !== undefined ? { display } : {}),\n\t\t})\n\t}\n\treturn links\n}\n\n/**\n * Read rows from a stream of decompressed worksheet chunks without materializing the part —\n * peak memory tracks one row, not the whole sheet (F2.2). Bytes are decoded with a streaming\n * `TextDecoder` (multi-byte sequences may split across chunks) and fed through the chunk-safe\n * tokenizer.\n */\nexport async function* streamRows(\n\tchunks: AsyncIterable<Uint8Array>,\n\tctx: DecodeContext,\n): AsyncGenerator<Row> {\n\tconst assembler = createRowAssembler(ctx)\n\tconst xml = createXmlStream()\n\tconst decoder = new TextDecoder()\n\n\tfor await (const bytes of chunks) {\n\t\tconst text = decoder.decode(bytes, { stream: true })\n\t\tif (text === '') continue\n\t\tfor (const token of xml.push(text)) yield* assembler.push(token)\n\t}\n\tconst tail = decoder.decode() // finalize any pending multi-byte sequence\n\tif (tail !== '') for (const token of xml.push(tail)) yield* assembler.push(token)\n\tfor (const token of xml.flush()) yield* assembler.push(token)\n\tyield* assembler.flush()\n}\n","import { XlsxError } from '../errors'\nimport {\n\ttype DecodeContext,\n\tparseRels,\n\tparseSharedStrings,\n\tparseStyles,\n\tparseWorkbook,\n\ttype Relationship,\n\tresolveTarget,\n\ttype StyleTable,\n} from '../ooxml'\nimport type { Cell, Comment, Hyperlink, SheetInfo } from '../types'\nimport { openZip, type ZipArchive } from '../zip'\nimport {\n\tparseCellStyles,\n\tparseComments,\n\tparseDimension,\n\tparseHyperlinks,\n\tparseMergedCells,\n\ttype Row,\n\treadRows,\n\tstreamRows,\n} from './worksheet'\n\n// The reader's public entry point. `openXlsx` follows the OPC relationship graph — never\n// guessed filenames — from the package root to the workbook, then to each worksheet and the\n// shared string table, and returns a Workbook of typed cells.\n//\n// Worksheet XML is decompressed up front (so cell access is synchronous) but only parsed\n// into cells on first use; a sheet you never touch costs a decompression, not a parse.\n\nconst decoder = new TextDecoder()\n\n// Relationship type URIs end in these segments; matching the suffix avoids hard-coding the\n// 2006 namespace and tolerates the strict/transitional variants.\nconst REL_OFFICE_DOCUMENT = '/officeDocument'\nconst REL_SHARED_STRINGS = '/sharedStrings'\nconst REL_STYLES = '/styles'\nconst REL_COMMENTS = '/comments'\n\nfunction directoryOf(path: string): string {\n\tconst slash = path.lastIndexOf('/')\n\treturn slash === -1 ? '' : path.slice(0, slash)\n}\n\n// The relationships for a part live in `<dir>/_rels/<file>.rels`.\nfunction relsPathFor(path: string): string {\n\tconst slash = path.lastIndexOf('/')\n\tconst dir = slash === -1 ? '' : path.slice(0, slash)\n\tconst file = slash === -1 ? path : path.slice(slash + 1)\n\treturn dir === '' ? `_rels/${file}.rels` : `${dir}/_rels/${file}.rels`\n}\n\nasync function readText(zip: ZipArchive, path: string): Promise<string> {\n\tif (!zip.has(path))\n\t\tthrow new XlsxError('missing-part', `xlsx is missing a required part: ${path}`)\n\treturn decoder.decode(await zip.read(path))\n}\n\nexport class Worksheet {\n\t/** Sheet name as shown on Excel's tab. */\n\treadonly name: string\n\treadonly #info: SheetInfo\n\treadonly #xml: string\n\treadonly #context: DecodeContext\n\treadonly #rels: Map<string, Relationship> | undefined\n\treadonly #commentsXml: string | undefined\n\n\t#cells: Map<string, Cell> | undefined\n\t#merged: readonly string[] | undefined\n\t#hyperlinks: readonly Hyperlink[] | undefined\n\t#cellStyles: Map<string, number> | undefined\n\t#dimension: string | undefined\n\t#dimensionRead = false\n\t#comments: readonly Comment[] | undefined\n\n\tconstructor(\n\t\tinfo: SheetInfo,\n\t\txml: string,\n\t\tcontext: DecodeContext,\n\t\trels?: Map<string, Relationship>,\n\t\tcommentsXml?: string,\n\t) {\n\t\tthis.name = info.name\n\t\tthis.#info = info\n\t\tthis.#xml = xml\n\t\tthis.#context = context\n\t\tthis.#rels = rels\n\t\tthis.#commentsXml = commentsXml\n\t}\n\n\t/** Workbook-relative part path, e.g. `xl/worksheets/sheet1.xml`. */\n\tget path(): string {\n\t\treturn this.#info.path\n\t}\n\n\t/** false for hidden or very-hidden sheets. */\n\tget visible(): boolean {\n\t\treturn this.#info.visible\n\t}\n\n\t/**\n\t * Merged-cell ranges in A1 notation (e.g. `['A1:B1', 'A2:A4']`), in document order. Only the\n\t * top-left cell of a merge holds a value; the rest read as `empty`. Empty when none.\n\t */\n\tget mergedCells(): readonly string[] {\n\t\tif (this.#merged === undefined) this.#merged = parseMergedCells(this.#xml)\n\t\treturn this.#merged\n\t}\n\n\t/**\n\t * Hyperlinks declared on this sheet, in document order. Each carries the covered `ref` and,\n\t * where present, a resolved external `target`, an in-workbook `location`, a `tooltip`, and a\n\t * `display` override. Empty when none.\n\t */\n\tget hyperlinks(): readonly Hyperlink[] {\n\t\tif (this.#hyperlinks === undefined) {\n\t\t\tthis.#hyperlinks = parseHyperlinks(this.#xml, this.#rels)\n\t\t}\n\t\treturn this.#hyperlinks\n\t}\n\n\t/**\n\t * The number-format code applied to the cell at `ref` — a custom code like `\"yyyy-mm-dd\"`\n\t * or `\"0.00%\"`, or a built-in one. `undefined` when the workbook has no style table or the\n\t * id has no portable code. An unstyled or absent cell resolves to the default format (style\n\t * 0, usually `\"General\"`), mirroring how date detection defaults.\n\t */\n\tnumberFormat(ref: string): string | undefined {\n\t\treturn this.#context.styles?.formatCode(this.#cellStyleMap().get(ref))\n\t}\n\n\t/**\n\t * The sheet's declared used range in A1 notation (e.g. `\"A1:E10\"`, or a single cell), from\n\t * the worksheet's `<dimension>`. `undefined` when the producer omits it — it is an optional\n\t * hint, not authoritative, so treat a present value as advisory.\n\t */\n\tget dimension(): string | undefined {\n\t\tif (!this.#dimensionRead) {\n\t\t\tthis.#dimension = parseDimension(this.#xml)\n\t\t\tthis.#dimensionRead = true\n\t\t}\n\t\treturn this.#dimension\n\t}\n\n\t/**\n\t * The comments anchored to cells on this sheet, in document order — each with its `ref`,\n\t * resolved `author`, and plain `text`. Empty when the sheet has no comments part.\n\t */\n\tget comments(): readonly Comment[] {\n\t\tif (this.#comments === undefined) {\n\t\t\tthis.#comments = this.#commentsXml === undefined ? [] : parseComments(this.#commentsXml)\n\t\t}\n\t\treturn this.#comments\n\t}\n\n\t#cellStyleMap(): Map<string, number> {\n\t\tif (this.#cellStyles === undefined) this.#cellStyles = parseCellStyles(this.#xml)\n\t\treturn this.#cellStyles\n\t}\n\n\t/** The cell at an A1 reference. Absent cells read as `empty` (Excel treats them blank). */\n\tcell(ref: string): Cell {\n\t\treturn this.#index().get(ref) ?? { ref, type: 'empty', value: null }\n\t}\n\n\t/** Stream the populated rows in document order. Sparse: empty rows/cells are absent. */\n\tasync *rows(): AsyncGenerator<Row> {\n\t\tfor (const row of readRows(this.#xml, this.#context)) {\n\t\t\tyield row\n\t\t}\n\t}\n\n\t#index(): Map<string, Cell> {\n\t\tif (this.#cells === undefined) {\n\t\t\tconst cells = new Map<string, Cell>()\n\t\t\tfor (const row of readRows(this.#xml, this.#context)) {\n\t\t\t\tfor (const cell of row.cells) cells.set(cell.ref, cell)\n\t\t\t}\n\t\t\tthis.#cells = cells\n\t\t}\n\t\treturn this.#cells\n\t}\n}\n\nexport class Workbook {\n\t/** Sheets in tab order. */\n\treadonly sheets: readonly SheetInfo[]\n\treadonly #byName: Map<string, Worksheet>\n\n\tconstructor(sheets: SheetInfo[], byName: Map<string, Worksheet>) {\n\t\tthis.sheets = sheets\n\t\tthis.#byName = byName\n\t}\n\n\t/** The worksheet with this tab name. Throws if there is none. */\n\tsheet(name: string): Worksheet {\n\t\tconst worksheet = this.#byName.get(name)\n\t\tif (worksheet === undefined) {\n\t\t\tconst available = this.sheets.map((s) => s.name).join(', ')\n\t\t\tthrow new XlsxError(\n\t\t\t\t'no-such-sheet',\n\t\t\t\t`no sheet named ${JSON.stringify(name)}; available: ${available}`,\n\t\t\t)\n\t\t}\n\t\treturn worksheet\n\t}\n}\n\ninterface LoadedWorkbook {\n\treadonly zip: ZipArchive\n\t/** Shared decode context (shared strings, styles, date system) for every sheet. */\n\treadonly context: DecodeContext\n\t/** Sheets in tab order, each with its resolved part path. */\n\treadonly sheets: ReadonlyArray<{ readonly info: SheetInfo; readonly path: string }>\n}\n\n// Read the small parts every sheet depends on — relationships, the workbook, shared strings,\n// styles — and resolve each sheet's part path through the relationship graph. Worksheets\n// themselves are NOT read here, so this stays cheap whether the caller wants random access\n// (openXlsx) or a constant-memory stream (streamSheetRows).\nasync function loadWorkbook(\n\tsource: Uint8Array | ArrayBuffer,\n\toptions?: ReadOptions,\n): Promise<LoadedWorkbook> {\n\tconst bytes = source instanceof Uint8Array ? source : new Uint8Array(source)\n\tconst zip = openZip(bytes, options)\n\n\t// Package relationships → the workbook part.\n\tconst packageRels = parseRels(await readText(zip, '_rels/.rels'))\n\tconst office = [...packageRels.values()].find((r) => r.type.endsWith(REL_OFFICE_DOCUMENT))\n\tif (office === undefined) {\n\t\tthrow new XlsxError('not-xlsx', 'not an xlsx: no officeDocument relationship')\n\t}\n\tconst workbookPath = resolveTarget('', office.target)\n\tconst workbookDir = directoryOf(workbookPath)\n\n\t// Workbook sheet list + date system + the workbook's own relationships.\n\tconst { sheets: workbookSheets, date1904 } = parseWorkbook(await readText(zip, workbookPath))\n\tconst workbookRels = parseRels(await readText(zip, relsPathFor(workbookPath)))\n\n\t// Shared string table (optional — a workbook may use only inline strings).\n\tlet sharedStrings: string[] = []\n\tconst sst = [...workbookRels.values()].find((r) => r.type.endsWith(REL_SHARED_STRINGS))\n\tif (sst !== undefined && sst.targetMode !== 'External') {\n\t\tconst sstPath = resolveTarget(workbookDir, sst.target)\n\t\tif (zip.has(sstPath)) {\n\t\t\tsharedStrings = parseSharedStrings(decoder.decode(await zip.read(sstPath)))\n\t\t}\n\t}\n\n\t// Style table (optional) — needed to tell date-styled numbers from plain ones.\n\tlet styles: StyleTable | undefined\n\tconst stylesRel = [...workbookRels.values()].find((r) => r.type.endsWith(REL_STYLES))\n\tif (stylesRel !== undefined && stylesRel.targetMode !== 'External') {\n\t\tconst stylesPath = resolveTarget(workbookDir, stylesRel.target)\n\t\tif (zip.has(stylesPath)) {\n\t\t\tstyles = parseStyles(decoder.decode(await zip.read(stylesPath)))\n\t\t}\n\t}\n\tconst context: DecodeContext =\n\t\tstyles !== undefined ? { sharedStrings, date1904, styles } : { sharedStrings, date1904 }\n\n\t// Resolve each sheet's r:id to a part path.\n\tconst sheets: Array<{ info: SheetInfo; path: string }> = []\n\tfor (const entry of workbookSheets) {\n\t\tconst rel = workbookRels.get(entry.rid)\n\t\tif (rel === undefined || rel.targetMode === 'External') continue\n\t\tconst path = resolveTarget(workbookDir, rel.target)\n\t\tif (!zip.has(path)) continue\n\t\tsheets.push({ info: { name: entry.name, path, visible: entry.visible }, path })\n\t}\n\n\treturn { zip, context, sheets }\n}\n\n/**\n * Reader options. `maxPartBytes` caps the declared decompressed size of any single part — a\n * zip-bomb guard independent of the archive's own (untrusted) size fields. Omit for no ceiling.\n */\nexport interface ReadOptions {\n\treadonly maxPartBytes?: number\n}\n\nexport async function openXlsx(\n\tsource: Uint8Array | ArrayBuffer,\n\toptions?: ReadOptions,\n): Promise<Workbook> {\n\tconst { zip, context, sheets } = await loadWorkbook(source, options)\n\n\t// Decompress each worksheet (so cell access is synchronous) and build the Worksheet.\n\tconst infos: SheetInfo[] = []\n\tconst byName = new Map<string, Worksheet>()\n\tfor (const { info, path } of sheets) {\n\t\tconst xml = decoder.decode(await zip.read(path))\n\t\t// The sheet's own relationships (xl/worksheets/_rels/sheetN.xml.rels) resolve hyperlink\n\t\t// r:ids and locate the comments part. Optional — a plain sheet has no rels part.\n\t\tconst relsPath = relsPathFor(path)\n\t\tconst rels = zip.has(relsPath)\n\t\t\t? parseRels(decoder.decode(await zip.read(relsPath)))\n\t\t\t: undefined\n\n\t\t// Comments live in a separate part linked from the worksheet rels.\n\t\tlet commentsXml: string | undefined\n\t\tconst commentsRel = rels && [...rels.values()].find((r) => r.type.endsWith(REL_COMMENTS))\n\t\tif (commentsRel !== undefined && commentsRel.targetMode !== 'External') {\n\t\t\tconst commentsPath = resolveTarget(directoryOf(path), commentsRel.target)\n\t\t\tif (zip.has(commentsPath)) commentsXml = decoder.decode(await zip.read(commentsPath))\n\t\t}\n\n\t\tinfos.push(info)\n\t\t// First definition wins if two sheets somehow share a name.\n\t\tif (!byName.has(info.name)) {\n\t\t\tbyName.set(info.name, new Worksheet(info, xml, context, rels, commentsXml))\n\t\t}\n\t}\n\n\treturn new Workbook(infos, byName)\n}\n\n/**\n * Stream the rows of one sheet with roughly constant memory: the worksheet is never\n * materialized as a whole string — it is decompressed and tokenized chunk by chunk, and each\n * row is yielded then discarded (F2.2). Use this for large sheets; use `openXlsx` when you\n * need random `cell()` access. `sheetName` defaults to the first sheet in tab order.\n */\nexport async function* streamSheetRows(\n\tsource: Uint8Array | ArrayBuffer,\n\tsheetName?: string,\n\toptions?: ReadOptions,\n): AsyncGenerator<Row> {\n\tconst { zip, context, sheets } = await loadWorkbook(source, options)\n\tconst first = sheets[0]\n\tif (first === undefined) throw new XlsxError('not-xlsx', 'xlsx has no readable worksheets')\n\n\tlet path = first.path\n\tif (sheetName !== undefined) {\n\t\tconst match = sheets.find((s) => s.info.name === sheetName)\n\t\tif (match === undefined) {\n\t\t\tconst available = sheets.map((s) => s.info.name).join(', ')\n\t\t\tthrow new XlsxError(\n\t\t\t\t'no-such-sheet',\n\t\t\t\t`no sheet named ${JSON.stringify(sheetName)}; available: ${available}`,\n\t\t\t)\n\t\t}\n\t\tpath = match.path\n\t}\n\n\tyield* streamRows(zip.readStream(path), context)\n}\n"]}
|