{"version":3,"file":"index.cjs","names":["F_WIDE","F_EXT","F_RICH","BYTES_PER_RUN"],"sources":["../src/types.ts","../src/errors.ts","../src/biff/record-stream.ts","../src/byte-reader.ts","../src/biff/error-code.ts","../src/biff/rk-number.ts","../src/biff/unicode-string.ts","../src/biff/cell-records.ts","../src/biff/record-types.ts","../src/biff/sheet-decoder.ts","../src/excel-serial-date.ts","../src/biff/number-format.ts","../src/biff/continued-reader.ts","../src/biff/shared-strings.ts","../src/biff/workbook-globals.ts","../src/biff/parse-workbook.ts","../src/cfb/cfb-header.ts","../src/cfb/directory.ts","../src/cfb/sector-chains.ts","../src/cfb/compound-file.ts","../src/reader.ts","../src/sheet-to-objects.ts","../src/sheet-to-csv.ts"],"sourcesContent":["// The seven Excel error values, in their worksheet spelling ([MS-XLS] BErr).\nexport type ExcelErrorCode =\n  \"#NULL!\" | \"#DIV/0!\" | \"#VALUE!\" | \"#REF!\" | \"#NAME?\" | \"#NUM!\" | \"#N/A\";\n\n// An Excel error value sitting in a cell (e.g. `#DIV/0!`). It's a distinct type\n// rather than `null` so an importer can tell an errored cell from a blank one,\n// and rather than a plain string so it can't be confused with a text cell that\n// literally contains \"#N/A\". Serializes to `{ \"code\": \"#DIV/0!\" }` in JSON.\n//\n// @example\n//   if (cell instanceof CellError) console.warn(`errored: ${cell.code}`);\nexport class CellError {\n  constructor(readonly code: ExcelErrorCode) {}\n  toString(): string {\n    return this.code;\n  }\n}\n\n// A single cell value, already decoded from BIFF8 to a plain JS value. Numbers\n// formatted as dates in the source come back as `Date`; error cells come back as\n// a `CellError`; empty/blank cells come back as `null`.\nexport type Cell = string | number | boolean | Date | CellError | null;\n\n// How a sheet is surfaced in Excel: normally visible, hidden (re-shown from the\n// sheet-tab menu), or very-hidden (only togglable from the VBA editor — often a\n// lookup/config sheet the author meant to keep out of sight).\nexport type SheetVisibility = \"visible\" | \"hidden\" | \"very-hidden\";\n\n// One worksheet: its name, visibility, and a dense grid of rows. Rows are\n// 0-indexed and each row is padded with `null` up to the sheet's last used\n// column, so `rows[r][c]` is safe for any cell within the used range.\nexport interface Sheet {\n  readonly name: string;\n  readonly visibility: SheetVisibility;\n  readonly rows: ReadonlyArray<ReadonlyArray<Cell>>;\n}\n\n// A parsed workbook: every worksheet in file order.\nexport interface Workbook {\n  readonly sheets: readonly Sheet[];\n}\n\n// One data row turned into an object keyed by a sheet's header row, produced by\n// `sheetToObjects`. Values are the same decoded `Cell`s as `Sheet.rows`.\nexport type RowObject = Record<string, Cell>;\n","// Thrown when the input isn't a readable BIFF8 .xls file. Carries a message that\n// names the offending value and what was expected, so callers can log or branch\n// (e.g. \"not an .xls — try an .xlsx reader instead\").\nexport class XlsError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"XlsError\";\n  }\n}\n","// One BIFF record: a 16-bit type, 16-bit length, then `length` bytes of data.\n// `offset` is the byte position of the record header within the stream — needed\n// because BOUNDSHEET8 points at a sheet's BOF by absolute offset.\nexport interface BiffRecord {\n  readonly type: number;\n  readonly data: Uint8Array;\n  readonly offset: number;\n}\n\n// Splits a BIFF stream into its records. Stops cleanly if the stream ends mid-\n// header (some writers pad the final sector). Reading everything up front is\n// fine: worksheet streams are megabytes at most.\nexport function readRecords(stream: Uint8Array): BiffRecord[] {\n  const view = new DataView(stream.buffer, stream.byteOffset, stream.byteLength);\n  const records: BiffRecord[] = [];\n  let pos = 0;\n  while (pos + 4 <= stream.length) {\n    const type = view.getUint16(pos, true);\n    const length = view.getUint16(pos + 2, true);\n    if (pos + 4 + length > stream.length) break;\n    records.push({ type, data: stream.subarray(pos + 4, pos + 4 + length), offset: pos });\n    pos += 4 + length;\n  }\n  return records;\n}\n","import { XlsError } from \"./errors\";\n\n// Little-endian cursor over a byte range. BIFF8 and the OLE2 container are both\n// little-endian, so every multi-byte read here is LE. Bounds are checked so a\n// truncated/corrupt file fails loudly instead of reading garbage.\nexport class ByteReader {\n  private readonly view: DataView;\n  private cursor: number;\n\n  constructor(\n    private readonly bytes: Uint8Array,\n    start = 0,\n  ) {\n    this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n    this.cursor = start;\n  }\n\n  get position(): number {\n    return this.cursor;\n  }\n\n  set position(value: number) {\n    this.cursor = value;\n  }\n\n  get remaining(): number {\n    return this.bytes.length - this.cursor;\n  }\n\n  u8(): number {\n    this.require(1);\n    const value = this.view.getUint8(this.cursor);\n    this.cursor += 1;\n    return value;\n  }\n\n  u16(): number {\n    this.require(2);\n    const value = this.view.getUint16(this.cursor, true);\n    this.cursor += 2;\n    return value;\n  }\n\n  u32(): number {\n    this.require(4);\n    const value = this.view.getUint32(this.cursor, true);\n    this.cursor += 4;\n    return value;\n  }\n\n  f64(): number {\n    this.require(8);\n    const value = this.view.getFloat64(this.cursor, true);\n    this.cursor += 8;\n    return value;\n  }\n\n  // Returns a view (not a copy) over the next `length` bytes and advances.\n  slice(length: number): Uint8Array {\n    this.require(length);\n    const view = this.bytes.subarray(this.cursor, this.cursor + length);\n    this.cursor += length;\n    return view;\n  }\n\n  skip(length: number): void {\n    this.cursor += length;\n  }\n\n  private require(length: number): void {\n    // Guard a corrupt/negative cursor (e.g. from an out-of-range sector offset)\n    // so it surfaces as XlsError instead of a raw DataView RangeError.\n    if (!Number.isInteger(this.cursor) || this.cursor < 0) {\n      throw new XlsError(`Invalid read offset ${this.cursor}: corrupt structure`);\n    }\n    if (this.cursor + length > this.bytes.length) {\n      throw new XlsError(\n        `Unexpected end of data: needed ${length} byte(s) at offset ${this.cursor}, but only ${this.remaining} remain`,\n      );\n    }\n  }\n}\n","import { CellError, type ExcelErrorCode } from \"../types\";\n\n// BIFF8 stores an error cell's kind as a single byte ([MS-XLS] BErr). Map it to\n// the worksheet-facing error, or `null` when the byte isn't one of the seven\n// defined codes (a corrupt/unknown value — treated as blank rather than guessed).\nconst CODE_BY_BYTE: ReadonlyMap<number, ExcelErrorCode> = new Map([\n  [0x00, \"#NULL!\"],\n  [0x07, \"#DIV/0!\"],\n  [0x0f, \"#VALUE!\"],\n  [0x17, \"#REF!\"],\n  [0x1d, \"#NAME?\"],\n  [0x24, \"#NUM!\"],\n  [0x2a, \"#N/A\"],\n]);\n\n// Turns a BIFF error byte into a CellError, or null if the byte is unrecognized.\nexport function errorFromByte(byte: number): CellError | null {\n  const code = CODE_BY_BYTE.get(byte);\n  return code === undefined ? null : new CellError(code);\n}\n","// Decodes a BIFF8 RK value: a 32-bit compact number. The low two bits are flags;\n// the upper 30 bits are either a signed integer or the high bits of an IEEE-754\n// double (with the low 34 bits implied zero). fX100 means the stored value was\n// multiplied by 100.\nexport function decodeRk(rk: number): number {\n  const dividedBy100 = (rk & 0x01) !== 0;\n  const isInteger = (rk & 0x02) !== 0;\n  const value = isInteger ? rk >> 2 : rkAsDouble(rk);\n  return dividedBy100 ? value / 100 : value;\n}\n\n// The 30 significant bits sit in the high word of the double; the low word is 0.\nfunction rkAsDouble(rk: number): number {\n  const buffer = new ArrayBuffer(8);\n  const view = new DataView(buffer);\n  view.setUint32(4, rk & 0xfffffffc, true);\n  return view.getFloat64(0, true);\n}\n","import type { ByteReader } from \"../byte-reader\";\n\nconst F_WIDE = 0x01;\nconst F_EXT = 0x04;\nconst F_RICH = 0x08;\nconst BYTES_PER_RUN = 4;\n\n// Reads a self-contained BIFF8 unicode string (XLUnicodeString) from a reader:\n// a length, a flags byte, then the characters, then any rich-run / phonetic tail\n// which we skip. Used for sheet names (1-byte length) and inline LABEL cells\n// (2-byte length). CONTINUE-spanning strings are only expected in the SST, which\n// has its own reader.\nexport function readUnicodeString(reader: ByteReader, shortLength: boolean): string {\n  const charCount = shortLength ? reader.u8() : reader.u16();\n  const flags = reader.u8();\n  const wide = (flags & F_WIDE) !== 0;\n  const runCount = (flags & F_RICH) !== 0 ? reader.u16() : 0;\n  const extSize = (flags & F_EXT) !== 0 ? reader.u32() : 0;\n  let text = \"\";\n  for (let i = 0; i < charCount; i++)\n    text += String.fromCharCode(wide ? reader.u16() : reader.u8());\n  reader.skip(runCount * BYTES_PER_RUN + extSize);\n  return text;\n}\n","import { ByteReader } from \"../byte-reader\";\nimport type { Cell } from \"../types\";\nimport { errorFromByte } from \"./error-code\";\nimport { decodeRk } from \"./rk-number\";\nimport { readUnicodeString } from \"./unicode-string\";\n\n// A decoded cell with its position. Row/column are 0-based.\nexport interface PositionedCell {\n  readonly row: number;\n  readonly col: number;\n  readonly value: Cell;\n}\n\n// What a cell decoder needs from the workbook globals: the shared strings, and a\n// function that turns a raw number into a number or a Date depending on the\n// cell's format (the xf index).\nexport interface CellContext {\n  readonly sharedStrings: readonly string[];\n  readonly numeric: (xfIndex: number, value: number) => number | Date;\n}\n\n// FORMULA results are either an immediate value or a promise of a STRING record\n// that follows; the workbook loop resolves the latter.\nexport type FormulaResult =\n  | { readonly kind: \"value\"; readonly cell: PositionedCell }\n  | { readonly kind: \"pending-string\"; readonly row: number; readonly col: number };\n\nexport function decodeLabelSst(data: Uint8Array, ctx: CellContext): PositionedCell {\n  const reader = new ByteReader(data);\n  const { row, col } = readHead(reader);\n  const index = reader.u32();\n  return { row, col, value: ctx.sharedStrings[index] ?? \"\" };\n}\n\nexport function decodeLabel(data: Uint8Array): PositionedCell {\n  const reader = new ByteReader(data);\n  const { row, col } = readHead(reader);\n  return { row, col, value: readUnicodeString(reader, false) };\n}\n\nexport function decodeNumber(data: Uint8Array, ctx: CellContext): PositionedCell {\n  const reader = new ByteReader(data);\n  const { row, col, xf } = readHead(reader);\n  return { row, col, value: ctx.numeric(xf, reader.f64()) };\n}\n\nexport function decodeRkCell(data: Uint8Array, ctx: CellContext): PositionedCell {\n  const reader = new ByteReader(data);\n  const { row, col, xf } = readHead(reader);\n  return { row, col, value: ctx.numeric(xf, decodeRk(reader.u32())) };\n}\n\nexport function decodeBlank(data: Uint8Array): PositionedCell {\n  const reader = new ByteReader(data);\n  const { row, col } = readHead(reader);\n  return { row, col, value: null };\n}\n\nexport function decodeBoolErr(data: Uint8Array): PositionedCell {\n  const reader = new ByteReader(data);\n  const { row, col } = readHead(reader);\n  const raw = reader.u8();\n  const isError = reader.u8() !== 0;\n  return { row, col, value: isError ? errorFromByte(raw) : raw !== 0 };\n}\n\n// MULRK packs several RK cells sharing a row: [row][colFirst] then one (xf, rk)\n// per column, then colLast. We derive the count from the record length.\nexport function decodeMulRk(data: Uint8Array, ctx: CellContext): PositionedCell[] {\n  const reader = new ByteReader(data);\n  const row = reader.u16();\n  const colFirst = reader.u16();\n  const count = (data.length - 6) / 6; // 6 header/trailer bytes; 6 bytes per entry\n  const cells: PositionedCell[] = [];\n  for (let i = 0; i < count; i++) {\n    const xf = reader.u16();\n    cells.push({ row, col: colFirst + i, value: ctx.numeric(xf, decodeRk(reader.u32())) });\n  }\n  return cells;\n}\n\n// MULBLANK is a run of blank cells: [row][colFirst] then one xf per column.\nexport function decodeMulBlank(data: Uint8Array): PositionedCell[] {\n  const row = new ByteReader(data).u16();\n  const colFirst = new ByteReader(data, 2).u16();\n  const count = (data.length - 6) / 2; // 6 header/trailer bytes; 2 bytes per xf\n  const cells: PositionedCell[] = [];\n  for (let i = 0; i < count; i++) cells.push({ row, col: colFirst + i, value: null });\n  return cells;\n}\n\nexport function decodeFormula(data: Uint8Array, ctx: CellContext): FormulaResult {\n  const reader = new ByteReader(data);\n  const { row, col, xf } = readHead(reader);\n  const result = data.subarray(reader.position, reader.position + 8);\n  if (isNonNumericResult(result)) return nonNumericResult(row, col, result);\n  return { kind: \"value\", cell: { row, col, value: ctx.numeric(xf, reader.f64()) } };\n}\n\n// A cached formula result is a plain double unless its last two bytes are 0xFFFF,\n// which tags a string/boolean/error/blank result keyed by the leading byte.\nfunction isNonNumericResult(result: Uint8Array): boolean {\n  return result[6] === 0xff && result[7] === 0xff;\n}\n\nfunction nonNumericResult(row: number, col: number, result: Uint8Array): FormulaResult {\n  const kind = result[0];\n  if (kind === 0) return { kind: \"pending-string\", row, col };\n  if (kind === 1) return { kind: \"value\", cell: { row, col, value: result[2] !== 0 } };\n  // Byte 2 carries the value: for kind 2 (error) it's the error code, same slot\n  // the boolean above reads; kind 3 is a blank result.\n  const value = kind === 2 ? errorFromByte(result[2] ?? 0xff) : null;\n  return { kind: \"value\", cell: { row, col, value } };\n}\n\n// Every cell record starts with row (u16), column (u16), and an xf index (u16).\nfunction readHead(reader: ByteReader): { row: number; col: number; xf: number } {\n  return { row: reader.u16(), col: reader.u16(), xf: reader.u16() };\n}\n","// BIFF8 record type ids we decode. See [MS-XLS]. Grouped by role; anything not\n// listed is skipped by the record walker.\nexport const RecordType = {\n  BOF: 0x0809, // beginning of a substream (globals or a sheet)\n  EOF: 0x000a, // end of a substream\n  BOUNDSHEET8: 0x0085, // sheet name + byte offset of its BOF\n  DATEMODE: 0x0022, // 1900 vs 1904 date system\n  FORMAT: 0x041e, // a number-format string keyed by format index\n  XF: 0x00e0, // cell format record; carries its format index\n  SST: 0x00fc, // shared string table\n  CONTINUE: 0x003c, // spillover for the preceding record (notably SST)\n  LABELSST: 0x00fd, // string cell → index into the SST\n  LABEL: 0x0204, // inline string cell (old-style)\n  RSTRING: 0x00d6, // inline rich string cell\n  NUMBER: 0x0203, // IEEE-754 double cell\n  RK: 0x027e, // compact numeric cell\n  MULRK: 0x00bd, // run of RK cells sharing a row\n  BLANK: 0x0201, // formatted-but-empty cell\n  MULBLANK: 0x00be, // run of blank cells\n  BOOLERR: 0x0205, // boolean or error cell\n  FORMULA: 0x0006, // formula cell; result is a double or a typed sentinel\n  STRING: 0x0207, // string result of the preceding FORMULA\n} as const;\n","import { ByteReader } from \"../byte-reader\";\nimport { XlsError } from \"../errors\";\nimport type { Cell, Sheet } from \"../types\";\nimport {\n  decodeBlank,\n  decodeBoolErr,\n  decodeFormula,\n  decodeLabel,\n  decodeLabelSst,\n  decodeMulBlank,\n  decodeMulRk,\n  decodeNumber,\n  decodeRkCell,\n  type CellContext,\n  type PositionedCell,\n} from \"./cell-records\";\nimport type { BiffRecord } from \"./record-stream\";\nimport { RecordType } from \"./record-types\";\nimport { readUnicodeString } from \"./unicode-string\";\nimport type { BoundSheet, WorkbookGlobals } from \"./workbook-globals\";\n\ntype Decoder = (data: Uint8Array, ctx: CellContext) => PositionedCell[];\n\n// Cell records that decode to zero or more cells without look-ahead. FORMULA is\n// handled separately because its string result arrives in a following record.\nconst DECODERS: ReadonlyMap<number, Decoder> = new Map([\n  [RecordType.LABELSST, (d, c) => [decodeLabelSst(d, c)]],\n  [RecordType.LABEL, (d) => [decodeLabel(d)]],\n  [RecordType.RSTRING, (d) => [decodeLabel(d)]],\n  [RecordType.NUMBER, (d, c) => [decodeNumber(d, c)]],\n  [RecordType.RK, (d, c) => [decodeRkCell(d, c)]],\n  [RecordType.MULRK, (d, c) => decodeMulRk(d, c)],\n  [RecordType.BLANK, (d) => [decodeBlank(d)]],\n  [RecordType.MULBLANK, (d) => decodeMulBlank(d)],\n  [RecordType.BOOLERR, (d) => [decodeBoolErr(d)]],\n]);\n\n// Decodes one worksheet: walk its records (from its BOF to EOF) into positioned\n// cells, then pack them into a dense, null-padded grid.\nexport function decodeSheet(\n  records: readonly BiffRecord[],\n  boundSheet: BoundSheet,\n  offsetToIndex: ReadonlyMap<number, number>,\n  globals: WorkbookGlobals,\n): Sheet {\n  const ctx: CellContext = { sharedStrings: globals.sharedStrings, numeric: globals.numeric };\n  const cells = collectCells(records, offsetToIndex.get(boundSheet.offset), ctx);\n  return { name: boundSheet.name, visibility: boundSheet.visibility, rows: toGrid(cells) };\n}\n\nfunction collectCells(\n  records: readonly BiffRecord[],\n  start: number | undefined,\n  ctx: CellContext,\n): PositionedCell[] {\n  if (start === undefined) return [];\n  const cells: PositionedCell[] = [];\n  let pending: { row: number; col: number } | null = null;\n  for (let i = start + 1; i < records.length; i++) {\n    const record = records[i];\n    if (record === undefined || record.type === RecordType.EOF) break;\n    pending = handleRecord(record, cells, pending, ctx);\n  }\n  return cells;\n}\n\n// Processes one record, appending any decoded cells. Threads the \"a FORMULA is\n// waiting for its STRING result\" state through the loop.\nfunction handleRecord(\n  record: BiffRecord,\n  cells: PositionedCell[],\n  pending: { row: number; col: number } | null,\n  ctx: CellContext,\n): { row: number; col: number } | null {\n  if (record.type === RecordType.STRING && pending) {\n    cells.push({ ...pending, value: readUnicodeString(new ByteReader(record.data), false) });\n    return null;\n  }\n  if (record.type === RecordType.FORMULA) return appendFormula(record.data, cells, ctx);\n  const decode = DECODERS.get(record.type);\n  if (decode) cells.push(...decode(record.data, ctx));\n  return null;\n}\n\nfunction appendFormula(\n  data: Uint8Array,\n  cells: PositionedCell[],\n  ctx: CellContext,\n): { row: number; col: number } | null {\n  const result = decodeFormula(data, ctx);\n  if (result.kind === \"value\") {\n    cells.push(result.cell);\n    return null;\n  }\n  return { row: result.row, col: result.col };\n}\n\n// BIFF8 grid limits ([MS-XLS]): a worksheet is at most 65536 rows × 256 columns.\n// A cell position outside these means the record is corrupt — and an unchecked\n// column especially is dangerous, since the dense grid below is sized to the max\n// column, so a bogus col (e.g. 6400) would allocate a ~hundreds-of-MB grid from a\n// tiny file. Reject rather than crash.\nconst MAX_ROW = 65535;\nconst MAX_COL = 255;\n\n// Packs sparse positioned cells into a dense grid, padding gaps with null so\n// every row has the same length (the sheet's last used column + 1).\nfunction toGrid(cells: readonly PositionedCell[]): Cell[][] {\n  if (cells.length === 0) return [];\n  const maxRow = cells.reduce((max, cell) => Math.max(max, cell.row), 0);\n  const maxCol = cells.reduce((max, cell) => Math.max(max, cell.col), 0);\n  if (maxRow > MAX_ROW || maxCol > MAX_COL) {\n    throw new XlsError(\n      `Corrupt sheet: cell position (row ${maxRow}, col ${maxCol}) exceeds the BIFF8 ` +\n        `limit of ${MAX_ROW + 1} rows × ${MAX_COL + 1} columns`,\n    );\n  }\n  const rows: Cell[][] = Array.from({ length: maxRow + 1 }, () =>\n    new Array<Cell>(maxCol + 1).fill(null),\n  );\n  for (const cell of cells) {\n    const row = rows[cell.row];\n    if (row) row[cell.col] = cell.value;\n  }\n  return rows;\n}\n","const MS_PER_DAY = 86_400_000;\n\n// Excel stores dates as a serial day count. Two epochs exist: the 1900 system\n// (Windows) and the 1904 system (old Mac); the workbook's DATEMODE record says\n// which. We anchor the 1900 system at 1899-12-30 UTC, which absorbs Excel's\n// fictitious 1900-02-29 leap day for every date on/after 1900-03-01 (serial 61)\n// — i.e. all real-world bank data. Dates in Jan/Feb 1900 would be off by one;\n// that's a documented limitation.\n//\n// The result is a UTC Date; the fractional part of the serial becomes the time\n// of day. @example excelSerialToDate(45384, false) // 2024-04-02T00:00:00.000Z\nexport function excelSerialToDate(serial: number, date1904: boolean): Date {\n  const epochUtc = date1904 ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 30);\n  return new Date(epochUtc + serial * MS_PER_DAY);\n}\n","// Built-in number-format ids that Excel renders as dates/times ([MS-XLS]\n// §2.5.198.17). Custom formats (id >= 164, or overridden builtins) are checked\n// by their format string instead.\nconst BUILTIN_DATE_FORMAT_IDS = new Set([\n  14, 15, 16, 17, 18, 19, 20, 21, 22, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 45, 46, 47, 50, 51,\n  52, 53, 54, 55, 56, 57, 58,\n]);\n\n// Whether a cell with this format index should be read as a date. A numeric cell\n// is only a \"date\" because of its format, so this decides Date vs number.\nexport function isDateFormatIndex(\n  formatIndex: number,\n  customFormats: ReadonlyMap<number, string>,\n): boolean {\n  if (BUILTIN_DATE_FORMAT_IDS.has(formatIndex)) return true;\n  const format = customFormats.get(formatIndex);\n  return format !== undefined && looksLikeDateFormat(format);\n}\n\n// A format string is a date/time format if, after removing literals, it still\n// contains a date/time token (y, m, d, h, s). Stripping avoids false positives\n// like \"m\" inside a quoted currency prefix.\nfunction looksLikeDateFormat(format: string): boolean {\n  const stripped = format\n    .replace(/\\\\./g, \"\")\n    .replace(/\"[^\"]*\"/g, \"\")\n    .replace(/\\[[^\\]]*\\]/g, \"\");\n  return /[ymdhs]/i.test(stripped);\n}\n","import { XlsError } from \"../errors\";\n\n// A cursor over the SST record and its CONTINUE spillovers, kept as separate\n// chunks because BIFF8 has a subtle rule: a shared string's character array can\n// be split at a record boundary, and each continuation begins with a fresh\n// grbit byte that re-declares whether the *remaining* characters are wide\n// (16-bit) or compressed (8-bit). Header fields (cch, flags, run/ext sizes)\n// never split, so those reads may safely settle across chunks.\nexport class ContinuedReader {\n  private chunkIndex = 0;\n  private offset = 0;\n\n  constructor(private readonly chunks: readonly Uint8Array[]) {}\n\n  get done(): boolean {\n    this.settle();\n    return this.chunkIndex >= this.chunks.length;\n  }\n\n  u8(): number {\n    this.settle();\n    return this.rawByte();\n  }\n\n  u16(): number {\n    return this.u8() | (this.u8() << 8);\n  }\n\n  u32(): number {\n    return (this.u16() | (this.u16() << 16)) >>> 0;\n  }\n\n  // Reads a run of `count` characters, honoring the fresh grbit at every chunk\n  // boundary crossed mid-run. `wide` is the compression of the first segment.\n  readChars(count: number, wide: boolean): string {\n    let text = \"\";\n    let isWide = wide;\n    for (let i = 0; i < count; i++) {\n      if (this.atChunkEnd()) isWide = (this.crossToNextChunk() & 0x01) !== 0;\n      text += String.fromCharCode(isWide ? this.rawByte() | (this.rawByte() << 8) : this.rawByte());\n    }\n    return text;\n  }\n\n  // Skips `length` bytes of trailing data (rich-text runs, phonetic block). These\n  // do not re-read a grbit at boundaries — only the character array does.\n  skip(length: number): void {\n    let left = length;\n    while (left > 0) {\n      this.settle();\n      const chunk = this.currentChunk();\n      const take = Math.min(left, chunk.length - this.offset);\n      this.offset += take;\n      left -= take;\n    }\n  }\n\n  // Advance past any fully-consumed chunks so the cursor sits on real data.\n  private settle(): void {\n    while (this.chunkIndex < this.chunks.length && this.offset >= this.chunkLength()) {\n      this.chunkIndex += 1;\n      this.offset = 0;\n    }\n  }\n\n  private atChunkEnd(): boolean {\n    return this.chunkIndex < this.chunks.length && this.offset >= this.chunkLength();\n  }\n\n  private crossToNextChunk(): number {\n    this.chunkIndex += 1;\n    this.offset = 0;\n    return this.rawByte(); // the continuation's fresh grbit\n  }\n\n  private rawByte(): number {\n    const chunk = this.currentChunk();\n    const value = chunk[this.offset];\n    if (value === undefined)\n      throw new XlsError(`SST cursor past end of chunk ${this.chunkIndex} (offset ${this.offset})`);\n    this.offset += 1;\n    return value;\n  }\n\n  private chunkLength(): number {\n    return this.currentChunk().length;\n  }\n\n  private currentChunk(): Uint8Array {\n    const chunk = this.chunks[this.chunkIndex];\n    if (chunk === undefined)\n      throw new XlsError(`SST reader ran past its ${this.chunks.length} chunk(s)`);\n    return chunk;\n  }\n}\n","import { ContinuedReader } from \"./continued-reader\";\n\n// Grbit flags on an SST string (BIFF8 XLUnicodeRichExtendedString).\nconst F_WIDE = 0x01; // fHighByte: characters are 16-bit, not compressed 8-bit\nconst F_EXT = 0x04; // fExtSt: a phonetic (Asian) block follows the text\nconst F_RICH = 0x08; // fRichSt: rich-text formatting runs follow the text\n\nconst BYTES_PER_RUN = 4; // each rich-text run is a (char index, font index) pair\n\n// Parses the Shared String Table into an ordered array. String cells (LABELSST)\n// reference these by index. `chunks` is the SST record's data followed by each\n// CONTINUE record's data, in order.\n//\n// @example parseSharedStrings([sstData, continueData]) // [\"Emitente\", \"CDB\", ...]\nexport function parseSharedStrings(chunks: readonly Uint8Array[]): string[] {\n  const reader = new ContinuedReader(chunks);\n  reader.u32(); // cstTotal: total references, including repeats — not needed here\n  const unique = reader.u32();\n  const strings: string[] = [];\n  for (let i = 0; i < unique; i++) strings.push(readString(reader));\n  return strings;\n}\n\nfunction readString(reader: ContinuedReader): string {\n  const charCount = reader.u16();\n  const flags = reader.u8();\n  const runCount = (flags & F_RICH) !== 0 ? reader.u16() : 0;\n  const extSize = (flags & F_EXT) !== 0 ? reader.u32() : 0;\n  const text = reader.readChars(charCount, (flags & F_WIDE) !== 0);\n  reader.skip(runCount * BYTES_PER_RUN + extSize);\n  return text;\n}\n","import { ByteReader } from \"../byte-reader\";\nimport { excelSerialToDate } from \"../excel-serial-date\";\nimport type { SheetVisibility } from \"../types\";\nimport { isDateFormatIndex } from \"./number-format\";\nimport type { BiffRecord } from \"./record-stream\";\nimport { RecordType } from \"./record-types\";\nimport { parseSharedStrings } from \"./shared-strings\";\nimport { readUnicodeString } from \"./unicode-string\";\n\n// A sheet as advertised by the globals: its name, visibility, whether it is a\n// worksheet (vs a chart/macro/VBA substream), and the byte offset of its BOF\n// within the Workbook stream.\nexport interface BoundSheet {\n  readonly name: string;\n  readonly offset: number;\n  readonly visibility: SheetVisibility;\n  readonly isWorksheet: boolean;\n}\n\n// Everything from the workbook-globals substream that the sheets need to decode:\n// the shared strings, how to interpret a numeric cell (number vs date), and the\n// list of sheets.\nexport interface WorkbookGlobals {\n  readonly sharedStrings: readonly string[];\n  readonly boundSheets: readonly BoundSheet[];\n  readonly numeric: (xfIndex: number, value: number) => number | Date;\n}\n\n// Parses the globals substream (records 0..first EOF): date system, custom\n// number formats, XF→format map, shared strings, and the sheet directory.\nexport function parseGlobals(records: readonly BiffRecord[]): WorkbookGlobals {\n  let date1904 = false;\n  const customFormats = new Map<number, string>();\n  const xfFormatIndex: number[] = [];\n  let sharedStrings: string[] = [];\n  const boundSheets: BoundSheet[] = [];\n\n  for (let i = 0; i < records.length; i++) {\n    const record = records[i];\n    if (record === undefined || record.type === RecordType.EOF) break;\n    if (record.type === RecordType.DATEMODE) date1904 = new ByteReader(record.data).u16() === 1;\n    else if (record.type === RecordType.FORMAT) addFormat(record.data, customFormats);\n    else if (record.type === RecordType.XF)\n      xfFormatIndex.push(new ByteReader(record.data, 2).u16());\n    else if (record.type === RecordType.SST)\n      sharedStrings = parseSharedStrings(collectSstChunks(records, i));\n    else if (record.type === RecordType.BOUNDSHEET8) boundSheets.push(parseBoundSheet(record.data));\n  }\n\n  return {\n    sharedStrings,\n    boundSheets,\n    numeric: makeNumeric(xfFormatIndex, customFormats, date1904),\n  };\n}\n\nfunction addFormat(data: Uint8Array, into: Map<number, string>): void {\n  const reader = new ByteReader(data);\n  const formatIndex = reader.u16();\n  into.set(formatIndex, readUnicodeString(reader, false));\n}\n\n// The SST record plus every CONTINUE record immediately after it form one string\n// table; return their data as ordered chunks for parseSharedStrings.\nfunction collectSstChunks(records: readonly BiffRecord[], sstIndex: number): Uint8Array[] {\n  const first = records[sstIndex];\n  const chunks: Uint8Array[] = first ? [first.data] : [];\n  for (let j = sstIndex + 1; j < records.length; j++) {\n    const record = records[j];\n    if (record === undefined || record.type !== RecordType.CONTINUE) break;\n    chunks.push(record.data);\n  }\n  return chunks;\n}\n\n// BOUNDSHEET8: byte offset of the sheet's BOF (u32), grbit (u16), then a short\n// (1-byte length) unicode name. The grbit low byte carries the hidden state and\n// its high byte the sheet type — see decodeSheetGrbit.\nexport function parseBoundSheet(data: Uint8Array): BoundSheet {\n  const reader = new ByteReader(data);\n  const offset = reader.u32();\n  const grbit = reader.u16();\n  const name = readUnicodeString(reader, true);\n  return { name, offset, ...decodeSheetGrbit(grbit) };\n}\n\n// BOUNDSHEET8 grbit ([MS-XLS] 2.4.28): the low byte's low 2 bits are hsState\n// (0 visible, 1 hidden, 2 very-hidden) and the high byte is dt, the sheet type\n// (0 worksheet/dialog, 1 Excel-4 macro, 2 chart, 6 VBA module). Only dt 0 holds\n// cells; the rest are separate substreams we don't return as sheets.\nfunction decodeSheetGrbit(grbit: number): {\n  visibility: SheetVisibility;\n  isWorksheet: boolean;\n} {\n  const visibility = VISIBILITY_BY_STATE[grbit & 0x03] ?? \"visible\";\n  return { visibility, isWorksheet: ((grbit >> 8) & 0xff) === 0x00 };\n}\n\nconst VISIBILITY_BY_STATE: Record<number, SheetVisibility> = {\n  0: \"visible\",\n  1: \"hidden\",\n  2: \"very-hidden\",\n};\n\n// Builds the number/date interpreter: a cell's xf index selects a format index,\n// and a date format means the raw serial becomes a Date.\nfunction makeNumeric(\n  xfFormatIndex: readonly number[],\n  customFormats: ReadonlyMap<number, string>,\n  date1904: boolean,\n): (xfIndex: number, value: number) => number | Date {\n  return (xfIndex, value) => {\n    const formatIndex = xfFormatIndex[xfIndex] ?? 0;\n    return isDateFormatIndex(formatIndex, customFormats)\n      ? excelSerialToDate(value, date1904)\n      : value;\n  };\n}\n","import type { Workbook } from \"../types\";\nimport { readRecords } from \"./record-stream\";\nimport { decodeSheet } from \"./sheet-decoder\";\nimport { parseGlobals } from \"./workbook-globals\";\n\n// Turns a raw Workbook/Book BIFF8 stream into a Workbook: parse the globals\n// substream, then decode each worksheet the globals point to. Sheets are located\n// by the byte offset of their BOF, so we index records by offset once. Chart,\n// macro, and VBA substreams are bound sheets too but hold no cells, so we skip\n// them rather than return empty phantom sheets.\nexport function parseWorkbook(stream: Uint8Array): Workbook {\n  const records = readRecords(stream);\n  const globals = parseGlobals(records);\n  const offsetToIndex = new Map(records.map((record, index) => [record.offset, index]));\n  const sheets = globals.boundSheets\n    .filter((sheet) => sheet.isWorksheet)\n    .map((sheet) => decodeSheet(records, sheet, offsetToIndex, globals));\n  return { sheets };\n}\n","import { ByteReader } from \"../byte-reader\";\nimport { XlsError } from \"../errors\";\n\n// The 8-byte OLE2 / Compound File magic number (D0 CF 11 E0 A1 B1 1A E1).\nconst SIGNATURE = [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1];\n\n// The 512-byte header of a Compound File, decoded to the fields we need to walk\n// its sector chains. See [MS-CFB] §2.2.\nexport interface CfbHeader {\n  readonly sectorSize: number;\n  readonly miniSectorSize: number;\n  readonly firstDirSector: number;\n  readonly miniStreamCutoff: number;\n  readonly firstMiniFatSector: number;\n  readonly firstDifatSector: number;\n  readonly numDifatSectors: number;\n  readonly initialDifat: readonly number[]; // first 109 FAT sector ids, from the header\n}\n\nexport function parseCfbHeader(bytes: Uint8Array): CfbHeader {\n  assertSignature(bytes);\n  const reader = new ByteReader(bytes, 30);\n  const sectorSize = powerOfTwoSize(reader.u16(), \"sector\", [9, 12]);\n  const miniSectorSize = powerOfTwoSize(reader.u16(), \"mini-sector\", [6]);\n  reader.position = 44;\n  reader.u32(); // number of FAT sectors — we derive the FAT from the DIFAT instead\n  const firstDirSector = reader.u32();\n  reader.u32(); // transaction signature (unused)\n  const miniStreamCutoff = reader.u32();\n  const firstMiniFatSector = reader.u32();\n  reader.u32(); // number of mini-FAT sectors (chain is self-terminating)\n  const firstDifatSector = reader.u32();\n  const numDifatSectors = reader.u32();\n  return {\n    sectorSize,\n    miniSectorSize,\n    firstDirSector,\n    miniStreamCutoff,\n    firstMiniFatSector,\n    firstDifatSector,\n    numDifatSectors,\n    initialDifat: readInitialDifat(bytes),\n  };\n}\n\n// Sector sizes are stored as a power-of-two shift ([MS-CFB] §2.2). Only a fixed\n// set is legal (9→512 or 12→4096 for sectors, 6→64 for mini sectors). Validating\n// here is essential, not cosmetic: an unchecked `1 << shift` can go negative\n// (e.g. `1 << 31`) or huge, turning later sector offsets into out-of-bounds or\n// OOM-sized allocations on a crafted file.\nfunction powerOfTwoSize(shift: number, kind: string, allowed: readonly number[]): number {\n  if (!allowed.includes(shift)) {\n    throw new XlsError(\n      `Invalid CFB ${kind} shift ${shift}: expected one of [${allowed.join(\", \")}]`,\n    );\n  }\n  return 1 << shift;\n}\n\n// The header's tail (offset 76..512) holds the first 109 DIFAT entries — the\n// sector ids that make up the start of the FAT.\nfunction readInitialDifat(bytes: Uint8Array): number[] {\n  const reader = new ByteReader(bytes, 76);\n  const entries: number[] = [];\n  for (let i = 0; i < 109; i++) entries.push(reader.u32());\n  return entries;\n}\n\nfunction assertSignature(bytes: Uint8Array): void {\n  if (bytes.length < 512) {\n    throw new XlsError(\n      `File too small to be an OLE2 container: ${bytes.length} bytes (need >= 512)`,\n    );\n  }\n  for (let i = 0; i < SIGNATURE.length; i++) {\n    if (bytes[i] !== SIGNATURE[i]) {\n      const got = Array.from(bytes.slice(0, 8), (b) => b.toString(16).padStart(2, \"0\")).join(\" \");\n      throw new XlsError(`Not an OLE2 / .xls file: expected magic D0CF11E0A1B11AE1, got ${got}`);\n    }\n  }\n}\n","import { ByteReader } from \"../byte-reader\";\n\nconst DIRECTORY_ENTRY_SIZE = 128;\nconst OBJECT_TYPE_ROOT = 5;\n\n// One entry in the Compound File directory: a named stream or storage. We keep\n// the fields needed to locate a stream's bytes ([MS-CFB] §2.6.1).\nexport interface DirectoryEntry {\n  readonly name: string;\n  readonly objectType: number; // 1 = storage, 2 = stream, 5 = root\n  readonly startSector: number;\n  readonly size: number;\n}\n\n// Parses the directory bytes into entries. Names are UTF-16LE, length-prefixed\n// by a byte count that includes the terminating NUL.\nexport function parseDirectory(directoryBytes: Uint8Array): DirectoryEntry[] {\n  const entries: DirectoryEntry[] = [];\n  const count = Math.floor(directoryBytes.length / DIRECTORY_ENTRY_SIZE);\n  for (let i = 0; i < count; i++) {\n    const entry = parseEntry(directoryBytes.subarray(i * DIRECTORY_ENTRY_SIZE));\n    if (entry) entries.push(entry);\n  }\n  return entries;\n}\n\n// The root entry's own chain holds the mini-stream container, and its size is\n// the mini stream's length — both needed to read small streams.\nexport function findRoot(entries: readonly DirectoryEntry[]): DirectoryEntry | undefined {\n  return entries.find((entry) => entry.objectType === OBJECT_TYPE_ROOT);\n}\n\nfunction parseEntry(entryBytes: Uint8Array): DirectoryEntry | null {\n  const reader = new ByteReader(entryBytes);\n  const nameBytes = reader.slice(64);\n  const nameLength = reader.u16(); // byte length including the NUL terminator\n  const objectType = reader.u8();\n  if (objectType === 0) return null; // unused slot\n  reader.position = 116;\n  const startSector = reader.u32();\n  const size = reader.u32(); // low 32 bits; .xls streams are far below 4 GB\n  return { name: decodeName(nameBytes, nameLength), objectType, startSector, size };\n}\n\nfunction decodeName(nameBytes: Uint8Array, byteLength: number): string {\n  const chars = Math.max(0, byteLength / 2 - 1);\n  const reader = new ByteReader(nameBytes);\n  let name = \"\";\n  for (let i = 0; i < chars; i++) name += String.fromCharCode(reader.u16());\n  return name;\n}\n","import { ByteReader } from \"../byte-reader\";\nimport type { CfbHeader } from \"./cfb-header\";\n\n// Special FAT sector markers ([MS-CFB] §2.2). ENDOFCHAIN terminates a chain;\n// the others tag sectors that aren't part of a stream chain.\nconst ENDOFCHAIN = 0xfffffffe;\nconst FREESECT = 0xffffffff;\n\n// Byte offset of sector `id` in the file. Sector 0 begins right after the\n// 512-byte header, so sector `id` starts at (id + 1) * sectorSize.\nfunction sectorOffset(id: number, sectorSize: number): number {\n  return (id + 1) * sectorSize;\n}\n\n// Reassembles the full FAT (File Allocation Table): a flat array where FAT[i] is\n// the next sector after sector i, or ENDOFCHAIN. Built by concatenating every\n// sector the DIFAT points to.\nexport function buildFat(bytes: Uint8Array, header: CfbHeader): number[] {\n  const fatSectorIds = collectFatSectorIds(bytes, header);\n  const fat: number[] = [];\n  const perSector = header.sectorSize / 4;\n  for (const id of fatSectorIds) {\n    const reader = new ByteReader(bytes, sectorOffset(id, header.sectorSize));\n    for (let i = 0; i < perSector; i++) fat.push(reader.u32());\n  }\n  return fat;\n}\n\n// The ordered list of sector ids that hold the FAT: the header's first 109, then\n// any extra ones chained through DIFAT sectors. The DIFAT chain is walked with a\n// cycle guard (`seen`): a crafted file can set numDifatSectors near 2^32 and\n// point DIFAT sectors back in-bounds, which without the guard grows `ids`\n// without bound and exhausts memory. Distinct in-file sectors is a natural cap.\nfunction collectFatSectorIds(bytes: Uint8Array, header: CfbHeader): number[] {\n  const ids = header.initialDifat.filter((id) => id !== FREESECT && id !== ENDOFCHAIN);\n  const perSector = header.sectorSize / 4;\n  const seen = new Set<number>();\n  let difatSector = header.firstDifatSector;\n  for (\n    let n = 0;\n    n < header.numDifatSectors && difatSector !== ENDOFCHAIN && !seen.has(difatSector);\n    n++\n  ) {\n    seen.add(difatSector);\n    const reader = new ByteReader(bytes, sectorOffset(difatSector, header.sectorSize));\n    for (let i = 0; i < perSector - 1; i++) {\n      const id = reader.u32();\n      if (id !== FREESECT && id !== ENDOFCHAIN) ids.push(id);\n    }\n    difatSector = reader.u32(); // last entry links to the next DIFAT sector\n  }\n  return ids;\n}\n\n// Walks a sector chain from `start` through the FAT, returning the sector ids in\n// order. Guards against cycles in a corrupt FAT.\nexport function followChain(fat: readonly number[], start: number): number[] {\n  const chain: number[] = [];\n  const seen = new Set<number>();\n  let current = start;\n  while (current !== ENDOFCHAIN && current < fat.length && !seen.has(current)) {\n    seen.add(current);\n    chain.push(current);\n    current = fat[current] ?? ENDOFCHAIN;\n  }\n  return chain;\n}\n\n// Concatenates the bytes of a sector chain, then trims to `size`. Used for both\n// the directory and any regular (non-mini) stream.\nexport function readChainBytes(\n  bytes: Uint8Array,\n  chain: readonly number[],\n  sectorSize: number,\n  size: number,\n): Uint8Array {\n  const out = new Uint8Array(chain.length * sectorSize);\n  chain.forEach((id, index) => {\n    const start = sectorOffset(id, sectorSize);\n    out.set(bytes.subarray(start, start + sectorSize), index * sectorSize);\n  });\n  return out.subarray(0, size);\n}\n","import { ByteReader } from \"../byte-reader\";\nimport { parseCfbHeader, type CfbHeader } from \"./cfb-header\";\nimport { parseDirectory, findRoot, type DirectoryEntry } from \"./directory\";\nimport { buildFat, followChain, readChainBytes } from \"./sector-chains\";\n\n// A read-only view over an opened Compound File: look up a named stream and get\n// its raw bytes. This is the OLE2 container layer only — it knows nothing about\n// BIFF/Excel; it just extracts streams like \"Workbook\".\nexport interface CompoundFile {\n  readStream(name: string): Uint8Array | undefined;\n}\n\n// Everything derived once when the file is opened, so each readStream call is a\n// cheap lookup rather than a re-parse.\ninterface OpenedFile {\n  readonly bytes: Uint8Array;\n  readonly header: CfbHeader;\n  readonly fat: number[];\n  readonly directory: readonly DirectoryEntry[];\n  readonly miniStream: Uint8Array;\n  readonly miniFat: number[];\n}\n\nexport function openCompoundFile(bytes: Uint8Array): CompoundFile {\n  const header = parseCfbHeader(bytes);\n  const fat = buildFat(bytes, header);\n  const directory = parseDirectory(directoryBytes(bytes, header, fat));\n  const file: OpenedFile = {\n    bytes,\n    header,\n    fat,\n    directory,\n    miniStream: readMiniStreamContainer(bytes, header, fat, directory),\n    miniFat: buildMiniFat(bytes, header, fat),\n  };\n\n  return {\n    readStream(name) {\n      const entry = directory.find((e) => e.name === name);\n      if (!entry) return undefined;\n      return entry.size < header.miniStreamCutoff\n        ? readMiniStream(file, entry)\n        : readRegularStream(file, entry);\n    },\n  };\n}\n\nfunction directoryBytes(bytes: Uint8Array, header: CfbHeader, fat: number[]): Uint8Array {\n  const chain = followChain(fat, header.firstDirSector);\n  return readChainBytes(bytes, chain, header.sectorSize, chain.length * header.sectorSize);\n}\n\n// A stream at or above the cutoff lives directly in the main FAT sectors.\nfunction readRegularStream(file: OpenedFile, entry: DirectoryEntry): Uint8Array {\n  const chain = followChain(file.fat, entry.startSector);\n  return readChainBytes(file.bytes, chain, file.header.sectorSize, entry.size);\n}\n\n// The root entry's chain is the container that holds all small streams packed\n// into mini sectors; it is itself a regular stream in the main FAT.\nfunction readMiniStreamContainer(\n  bytes: Uint8Array,\n  header: CfbHeader,\n  fat: number[],\n  directory: readonly DirectoryEntry[],\n): Uint8Array {\n  const root = findRoot(directory);\n  if (!root) return new Uint8Array(0);\n  const chain = followChain(fat, root.startSector);\n  return readChainBytes(bytes, chain, header.sectorSize, root.size);\n}\n\n// The mini-FAT is a regular stream chain in the main file; each 4-byte entry\n// links mini sectors the way the FAT links normal sectors.\nfunction buildMiniFat(bytes: Uint8Array, header: CfbHeader, fat: number[]): number[] {\n  const chain = followChain(fat, header.firstMiniFatSector);\n  const raw = readChainBytes(bytes, chain, header.sectorSize, chain.length * header.sectorSize);\n  return toU32Array(raw);\n}\n\n// A stream below the cutoff is stored in mini sectors within the mini-stream\n// container, chained through the mini-FAT.\nfunction readMiniStream(file: OpenedFile, entry: DirectoryEntry): Uint8Array {\n  const { miniStream, miniFat, header } = file;\n  const chain = followChain(miniFat, entry.startSector);\n  const out = new Uint8Array(chain.length * header.miniSectorSize);\n  chain.forEach((id, index) => {\n    const start = id * header.miniSectorSize;\n    out.set(\n      miniStream.subarray(start, start + header.miniSectorSize),\n      index * header.miniSectorSize,\n    );\n  });\n  return out.subarray(0, entry.size);\n}\n\nfunction toU32Array(raw: Uint8Array): number[] {\n  const reader = new ByteReader(raw);\n  const values: number[] = [];\n  const count = Math.floor(raw.length / 4);\n  for (let i = 0; i < count; i++) values.push(reader.u32());\n  return values;\n}\n","import { parseWorkbook } from \"./biff/parse-workbook\";\nimport { openCompoundFile } from \"./cfb/compound-file\";\nimport { XlsError } from \"./errors\";\nimport type { Sheet, Workbook } from \"./types\";\n\n// Reads a legacy .xls (BIFF8 / Excel 97-2003) file into a Workbook. Accepts the\n// file bytes as an ArrayBuffer or Uint8Array (e.g. from fs.readFile or an\n// upload). Throws XlsError if the bytes aren't a BIFF .xls workbook.\n//\n// @example\n//   const wb = readXls(await readFile(\"posicao.xls\"));\n//   wb.sheets[1].rows.forEach((row) => console.log(row));\nexport function readXls(data: ArrayBuffer | Uint8Array): Workbook {\n  const cfb = openCompoundFile(toBytes(data));\n  const stream = cfb.readStream(\"Workbook\") ?? cfb.readStream(\"Book\");\n  if (!stream) {\n    throw new XlsError(\n      \"No 'Workbook' or 'Book' stream in the OLE2 file — not a BIFF .xls workbook\",\n    );\n  }\n  return parseWorkbook(stream);\n}\n\n// Convenience for the common single-sheet case: the first worksheet, or\n// undefined if the workbook has none.\nexport function readFirstSheet(data: ArrayBuffer | Uint8Array): Sheet | undefined {\n  return readXls(data).sheets[0];\n}\n\nfunction toBytes(data: ArrayBuffer | Uint8Array): Uint8Array {\n  return data instanceof Uint8Array ? data : new Uint8Array(data);\n}\n","import { XlsError } from \"./errors\";\nimport type { Cell, RowObject, Sheet } from \"./types\";\n\n// Options for `sheetToObjects`. `headerRow` picks which 0-based row supplies the\n// keys; every row after it becomes one data object.\nexport interface SheetToObjectsOptions {\n  readonly headerRow?: number;\n}\n\n// Turns a sheet's dense grid into objects keyed by a header row — the shape most\n// callers want when they say \"read the .xls into JSON\". Columns whose header\n// cell is blank are skipped; when two headers share a name the rightmost column\n// wins. Returns [] when there is no row after the header.\n//\n// @example\n//   const rows = sheetToObjects(readFirstSheet(bytes)!);\n//   // [{ Name: \"Ada\", Age: 36 }, { Name: \"Alan\", Age: 41 }]\nexport function sheetToObjects(sheet: Sheet, options: SheetToObjectsOptions = {}): RowObject[] {\n  const headerRow = options.headerRow ?? 0;\n  assertHeaderRow(headerRow);\n  const header = sheet.rows[headerRow];\n  if (header === undefined) return [];\n  const keys = headerKeys(header);\n  return sheet.rows.slice(headerRow + 1).map((row) => rowToObject(row, keys));\n}\n\n// The header row as lookup keys, with a `null` slot for every blank column so\n// `rowToObject` can skip it while keeping column alignment.\nfunction headerKeys(row: ReadonlyArray<Cell>): (string | null)[] {\n  return row.map((cell) => toKey(cell));\n}\n\nfunction toKey(cell: Cell): string | null {\n  if (cell === null) return null;\n  const key = String(cell).trim();\n  return key.length === 0 ? null : key;\n}\n\nfunction rowToObject(row: ReadonlyArray<Cell>, keys: ReadonlyArray<string | null>): RowObject {\n  const object: RowObject = {};\n  keys.forEach((key, col) => {\n    if (key === null) return;\n    // `?? null` covers both an out-of-range column and a genuine blank cell.\n    object[key] = row[col] ?? null;\n  });\n  return object;\n}\n\nfunction assertHeaderRow(headerRow: number): void {\n  if (Number.isInteger(headerRow) && headerRow >= 0) return;\n  throw new XlsError(`headerRow must be a non-negative integer, got ${JSON.stringify(headerRow)}`);\n}\n","import { XlsError } from \"./errors\";\nimport type { Cell, Sheet } from \"./types\";\nimport { CellError } from \"./types\";\n\n// Options for `sheetToCsv`. `delimiter` is the field separator (default `,`);\n// `eol` is the line terminator between rows (default `\\n` — pass `\\r\\n` for\n// strict RFC-4180 / Excel-style output).\nexport interface SheetToCsvOptions {\n  readonly delimiter?: string;\n  readonly eol?: string;\n}\n\n// Serializes a sheet's dense grid to a CSV string with RFC-4180 quoting. Each\n// row becomes one line and every cell is rendered as text — a `Date` as a UTC\n// ISO-8601 string, a `CellError` as its code (e.g. `#DIV/0!`), and a blank cell\n// (`null`) as an empty field. Fields containing the delimiter, a double quote,\n// or a newline are wrapped in quotes with inner quotes doubled.\n//\n// @example\n//   const csv = sheetToCsv(readFirstSheet(bytes)!);\n//   // \"Name,Age\\nAda,36\\nAlan,41\"\nexport function sheetToCsv(sheet: Sheet, options: SheetToCsvOptions = {}): string {\n  const delimiter = options.delimiter ?? \",\";\n  const eol = options.eol ?? \"\\n\";\n  assertDelimiter(delimiter);\n  return sheet.rows.map((row) => encodeRow(row, delimiter)).join(eol);\n}\n\nfunction encodeRow(row: ReadonlyArray<Cell>, delimiter: string): string {\n  return row.map((cell) => encodeField(cellToText(cell), delimiter)).join(delimiter);\n}\n\n// A cell as plain text: blank → empty, Date → UTC ISO-8601, CellError → its\n// code, everything else via its JS string form.\nfunction cellToText(cell: Cell): string {\n  if (cell === null) return \"\";\n  if (cell instanceof Date) return cell.toISOString();\n  if (cell instanceof CellError) return cell.code;\n  return String(cell);\n}\n\n// RFC-4180: quote a field only when it holds the delimiter, a quote, or a\n// newline; inside quotes a `\"` is escaped by doubling it.\nfunction encodeField(text: string, delimiter: string): string {\n  if (!text.includes(delimiter) && !/[\"\\r\\n]/.test(text)) return text;\n  return `\"${text.replace(/\"/g, '\"\"')}\"`;\n}\n\nfunction assertDelimiter(delimiter: string): void {\n  if (delimiter.length === 1 && !/[\"\\r\\n]/.test(delimiter)) return;\n  throw new XlsError(\n    `delimiter must be a single character other than '\"', CR, or LF, got ${JSON.stringify(delimiter)}`,\n  );\n}\n"],"mappings":"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"}