@alosha/xlsx 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/compat.js CHANGED
@@ -1,5 +1,5 @@
1
- import { UnsupportedFeatureError, FormulaType, Workbook, Cell, Row, Column, Worksheet } from './chunk-6XXKAKLS.js';
2
- export { AloshaXlsxError, Cell, CellType, Column, DEFAULT_COLUMN_WIDTH, DuplicateWorksheetNameError, FormulaType, InvalidAddressError, InvalidCellValueError, InvalidPackageError, InvalidRangeError, InvalidRowNumberError, InvalidWorksheetNameError, MergeConflictError, Range, ReservedWorksheetNameError, Row, UnsupportedFeatureError, Worksheet, WorksheetNameTooLongError, colLetterToNumber, colNumberToLetter, createSharedStrings, createStyles, dateToSerial, decodeAddress, decodeEx, detectType, effectiveType, encodeAddress, fromStored, isAloshaXlsxError, readWorkbookBuffer, readWorkbookFile, resolveCellStyle, serialToDate, toCsv, toStored, toText, validateAddress, version, writeWorkbookBuffer, writeWorkbookFile } from './chunk-6XXKAKLS.js';
1
+ import { UnsupportedFeatureError, FormulaType, Workbook, Cell, Row, Column, Worksheet } from './chunk-C67HH2MR.js';
2
+ export { AloshaXlsxError, Cell, CellType, Column, DEFAULT_COLUMN_WIDTH, DuplicateWorksheetNameError, FormulaType, InvalidAddressError, InvalidCellValueError, InvalidPackageError, InvalidRangeError, InvalidRowNumberError, InvalidWorksheetNameError, MergeConflictError, Range, ReservedWorksheetNameError, Row, UnsupportedFeatureError, Worksheet, WorksheetNameTooLongError, colLetterToNumber, colNumberToLetter, createSharedStrings, createStyles, dateToSerial, decodeAddress, decodeEx, detectType, effectiveType, encodeAddress, fromStored, isAloshaXlsxError, readWorkbookBuffer, readWorkbookFile, resolveCellStyle, serialToDate, toCsv, toStored, toText, validateAddress, version, writeWorkbookBuffer, writeWorkbookFile } from './chunk-C67HH2MR.js';
3
3
 
4
4
  // src/compat/value-type.ts
5
5
  var ValueType = {
@@ -153,6 +153,14 @@ function reflectGet(target, prop) {
153
153
  }
154
154
  return wrap(value);
155
155
  }
156
+ function eachWithEmptyFilter(each, isEmpty, optsOrCb, maybeCb) {
157
+ const includeEmpty = typeof optsOrCb === "object" ? optsOrCb.includeEmpty === true : false;
158
+ const cb = typeof optsOrCb === "function" ? optsOrCb : maybeCb;
159
+ each({ includeEmpty }, (item, n) => {
160
+ if (!includeEmpty && isEmpty(item)) return;
161
+ cb(wrap(item), n);
162
+ });
163
+ }
156
164
  function proxyCell(cell) {
157
165
  const cached = cellProxies.get(cell);
158
166
  if (cached) return cached;
@@ -188,6 +196,14 @@ function proxyRow(row) {
188
196
  const proxy = new Proxy(row, {
189
197
  get(target, prop) {
190
198
  if (prop === RAW) return target;
199
+ if (prop === "eachCell") {
200
+ return (optsOrCb, maybeCb) => eachWithEmptyFilter(
201
+ (o, cb) => target.eachCell(o, cb),
202
+ (cell) => cell.type === 0 /* Null */,
203
+ optsOrCb,
204
+ maybeCb
205
+ );
206
+ }
191
207
  return reflectGet(target, prop);
192
208
  },
193
209
  set(target, prop, value) {
@@ -203,6 +219,14 @@ function proxyColumn(column) {
203
219
  const proxy = new Proxy(column, {
204
220
  get(target, prop) {
205
221
  if (prop === RAW) return target;
222
+ if (prop === "eachCell") {
223
+ return (optsOrCb, maybeCb) => eachWithEmptyFilter(
224
+ (o, cb) => target.eachCell(o, cb),
225
+ (cell) => cell.type === 0 /* Null */,
226
+ optsOrCb,
227
+ maybeCb
228
+ );
229
+ }
206
230
  return reflectGet(target, prop);
207
231
  },
208
232
  set(target, prop, value) {
@@ -227,6 +251,14 @@ function proxyWorksheet(worksheet) {
227
251
  COMPAT_DEFER
228
252
  );
229
253
  }
254
+ if (prop === "eachRow") {
255
+ return (optsOrCb, maybeCb) => eachWithEmptyFilter(
256
+ (o, cb) => target.eachRow(o, cb),
257
+ (row) => !row.hasValues,
258
+ optsOrCb,
259
+ maybeCb
260
+ );
261
+ }
230
262
  return reflectGet(target, prop);
231
263
  },
232
264
  set(target, prop, value) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/compat/value-type.ts","../src/compat/style-compat.ts","../src/compat/workbook.ts","../src/compat/index.ts"],"names":[],"mappings":"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","file":"compat.js","sourcesContent":["// The ExcelJS `Enums.ValueType`/`FormulaType` bridge (docs/COMPAT-SPEC.md §3). Our `CellType`\n// shares names with ExcelJS's `ValueType` but not numbers; these maps translate between the two.\n// `FormulaType` numbering already matches ExcelJS 1:1, so it's a straight re-export.\n\nimport { CellType } from \"../model/index.js\";\n\n/** ExcelJS's `Enums.ValueType` numbering. */\nexport const ValueType = {\n Null: 0,\n Merge: 1,\n Number: 2,\n String: 3,\n Date: 4,\n Hyperlink: 5,\n Formula: 6,\n SharedString: 7,\n RichText: 8,\n Boolean: 9,\n Error: 10,\n} as const;\n\nexport type ValueType = (typeof ValueType)[keyof typeof ValueType];\n\nexport { FormulaType } from \"../model/index.js\";\n\nconst TO_EXCELJS_VALUE_TYPE: Record<CellType, ValueType> = {\n [CellType.Null]: ValueType.Null,\n [CellType.Number]: ValueType.Number,\n [CellType.String]: ValueType.String,\n [CellType.Boolean]: ValueType.Boolean,\n [CellType.Date]: ValueType.Date,\n [CellType.Error]: ValueType.Error,\n [CellType.RichText]: ValueType.RichText,\n [CellType.Hyperlink]: ValueType.Hyperlink,\n [CellType.Formula]: ValueType.Formula,\n [CellType.Merge]: ValueType.Merge,\n [CellType.SharedString]: ValueType.SharedString,\n};\n\nconst FROM_EXCELJS_VALUE_TYPE: Record<ValueType, CellType> = {\n [ValueType.Null]: CellType.Null,\n [ValueType.Merge]: CellType.Merge,\n [ValueType.Number]: CellType.Number,\n [ValueType.String]: CellType.String,\n [ValueType.Date]: CellType.Date,\n [ValueType.Hyperlink]: CellType.Hyperlink,\n [ValueType.Formula]: CellType.Formula,\n [ValueType.SharedString]: CellType.SharedString,\n [ValueType.RichText]: CellType.RichText,\n [ValueType.Boolean]: CellType.Boolean,\n [ValueType.Error]: CellType.Error,\n};\n\n/** `cell.type` in compat mode: our `CellType` → ExcelJS's `ValueType` number. */\nexport function toExcelJSValueType(cellType: CellType): ValueType {\n return TO_EXCELJS_VALUE_TYPE[cellType];\n}\n\n/** The inverse of {@link toExcelJSValueType}. */\nexport function fromExcelJSValueType(value: ValueType): CellType {\n return FROM_EXCELJS_VALUE_TYPE[value];\n}\n","// The style-precedence divergence the compat shim must emulate (docs/COMPAT-SPEC.md §4).\n//\n// The core resolver (`resolveCellStyle`) does a **deep field-level merge**: a lone `cell.font.bold`\n// coexists with an inherited `font.name`/`font.size`. ExcelJS instead replaces the **whole**\n// category — assigning `cell.font` discards every inherited font field. A migrated spreadsheet must\n// render identically, so the compat facade's style setters route through `applyExcelJsStyle`, which\n// applies ExcelJS whole-object-per-category semantics.\n//\n// This only affects the authoring path: on read, styles come back already fully-resolved per cell,\n// so there is no divergence to bridge there. The core `resolveCellStyle` is deliberately left\n// untouched — the divergence is emulated here, scoped to compat-constructed workbooks.\n\nimport type { Cell, Style } from \"../model/index.js\";\n\n/** The six independently-inheritable style categories, in the order the core resolver lists them. */\nconst STYLE_CATEGORIES = [\"numFmt\", \"font\", \"fill\", \"border\", \"alignment\", \"protection\"] as const;\n\n/**\n * Apply a style `patch` to `cell` with ExcelJS whole-object precedence: every category **present**\n * in the patch replaces the cell's inherited category **outright** (no field-level merge), while\n * categories absent from the patch keep their current (possibly inherited) value. A category set to\n * `undefined` in the patch clears it. The underlying model store is otherwise unchanged — the\n * serializer still dedups the final styles.\n */\nexport function applyExcelJsStyle(cell: Cell, patch: Style): void {\n const inherited = cell.style;\n const next: Style = {};\n for (const key of STYLE_CATEGORIES) {\n // A category the patch mentions comes from the patch (whole-object replacement); otherwise it is\n // inherited from the cell's current style. Either way we copy the value as-is, never merging its\n // fields into the inherited one — that field-merge is exactly the core behaviour we diverge from.\n copyCategory(next, Object.hasOwn(patch, key) ? patch : inherited, key);\n }\n cell.style = next;\n}\n\n/** Copy one style category from `source` to `target`, skipping it entirely when unset. */\nfunction copyCategory<K extends keyof Style>(target: Style, source: Style, key: K): void {\n const value = source[key];\n if (value !== undefined) target[key] = value;\n}\n","// The ExcelJS-faithful facade over the core model (docs/COMPAT-SPEC.md §5).\n//\n// Mechanism (§5 leaves it to the implementer, with one hard rule: it MUST NOT leak ExcelJS\n// semantics into the core `@alosha/xlsx` entry): a **Proxy tree**. `CompatWorkbook`'s constructor\n// returns a Proxy over a plain core `Workbook`; every model object reachable from it (worksheets,\n// rows, columns, cells) is wrapped on the way out. The proxies delegate everything by default and\n// override only the three documented divergences plus the deferred surface:\n//\n// 1. `cell.type` / `cell.effectiveType` report ExcelJS `ValueType` numbers (§3, Decision D1 = full\n// emulation) instead of our `CellType` numbers.\n// 2. cell style setters (`font`/`fill`/`border`/`alignment`/`protection`/`numFmt`) route through\n// `applyExcelJsStyle` — ExcelJS whole-object-per-category precedence (§4).\n// 3. the deferred surface (§6: stream/csv/images/tables/conditional-formatting/data-validation/\n// comments/defined-names/protection) throws `UnsupportedFeatureError` at the exact call, naming\n// the feature, rather than silently no-op'ing.\n//\n// Everything else — `addRow(array | object)`, `row.values` (1-based, empty `[0]`), `worksheet.columns\n// = [{header, key, width}]`, the `workbook.xlsx.*` I/O accessor — is already ExcelJS-shaped in the\n// core model (COMPAT-SPEC.md §2 \"already compatible\"), so the proxies pass it straight through. The\n// core classes are never mutated; the divergence lives entirely in these compat-only wrappers.\n\nimport { UnsupportedFeatureError } from \"../errors.js\";\nimport type { XlsxAccessor } from \"../index.js\";\nimport { Cell, Column, Row, Workbook, Worksheet } from \"../index.js\";\nimport type { Style } from \"../model/index.js\";\nimport { applyExcelJsStyle } from \"./style-compat.js\";\nimport { toExcelJSValueType } from \"./value-type.js\";\n\n/** The pointer appended to every compat `UnsupportedFeatureError` (§6). */\nexport const COMPAT_DEFER =\n \"not yet supported in @alosha/xlsx/compat; see https://github.com/avlisodraude/alosha-xlsx/issues\";\n\n/** Sentinel prop that unwraps a facade back to its raw target (used by {@link unwrap}). */\nconst RAW = Symbol(\"alosha.compat.raw\");\n\n/** The cell style categories whose setters must apply ExcelJS whole-object precedence (§4). */\nconst STYLE_SETTERS = new Set([\"numFmt\", \"font\", \"fill\", \"border\", \"alignment\", \"protection\"]);\n\n// --- deferred surface (§6) ----------------------------------------------------------------------\n\n/** A method stub that always throws, naming `feature`. */\nfunction thrower(feature: string): (...args: never[]) => never {\n return () => {\n throw new UnsupportedFeatureError(feature, COMPAT_DEFER);\n };\n}\n\n/** A namespace-shaped object (e.g. `workbook.csv`) whose every method throws. */\nfunction stubNamespace(prefix: string, methods: readonly string[]): Record<string, () => never> {\n const ns: Record<string, () => never> = {};\n for (const m of methods) ns[m] = thrower(`${prefix}.${m}`);\n return ns;\n}\n\nconst CSV_STUB = stubNamespace(\"workbook.csv\", [\n \"read\",\n \"readFile\",\n \"write\",\n \"writeFile\",\n \"writeBuffer\",\n]);\nconst DEFINED_NAMES_STUB = stubNamespace(\"workbook.definedNames\", [\n \"add\",\n \"remove\",\n \"getRanges\",\n \"forEach\",\n \"getNames\",\n]);\n\n/** Worksheet methods that don't exist in the core model and must fail loud in compat mode. */\nconst WORKSHEET_UNSUPPORTED = new Set([\n \"addImage\",\n \"getImages\",\n \"addBackgroundImage\",\n \"addTable\",\n \"getTable\",\n \"getTables\",\n \"addConditionalFormatting\",\n \"removeConditionalFormatting\",\n \"protect\",\n \"unprotect\",\n]);\n\n/** Streaming entry points hung off the ExcelJS namespace (`ExcelJS.stream.xlsx.*`); each throws. */\nexport const streamStub = {\n xlsx: {\n WorkbookWriter: class {\n constructor() {\n throw new UnsupportedFeatureError(\"stream.xlsx.WorkbookWriter\", COMPAT_DEFER);\n }\n },\n WorkbookReader: class {\n constructor() {\n throw new UnsupportedFeatureError(\"stream.xlsx.WorkbookReader\", COMPAT_DEFER);\n }\n },\n },\n} as const;\n\n// --- facade plumbing ----------------------------------------------------------------------------\n\n// One proxy per underlying object, so facade identity is stable (`ws.getCell('A1') === ws.getCell\n// ('A1')`) and re-wrapping is idempotent.\nconst workbookProxies = new WeakMap<Workbook, Workbook>();\nconst worksheetProxies = new WeakMap<Worksheet, Worksheet>();\nconst rowProxies = new WeakMap<Row, Row>();\nconst columnProxies = new WeakMap<Column, Column>();\nconst cellProxies = new WeakMap<Cell, Cell>();\n\n/** Wrap a value crossing the facade boundary on the way out: model objects become their proxies,\n * arrays are wrapped element-wise (preserving sparse holes, e.g. `row.values`), primitives pass. */\nfunction wrap(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(wrap);\n if (value instanceof Cell) return proxyCell(value);\n if (value instanceof Row) return proxyRow(value);\n if (value instanceof Column) return proxyColumn(value);\n if (value instanceof Worksheet) return proxyWorksheet(value);\n if (value instanceof Workbook) return proxyWorkbook(value);\n return value;\n}\n\n/** The inverse of {@link wrap} for a single value: a facade proxy back to its raw target. */\nfunction unwrap(value: unknown): unknown {\n if (value !== null && typeof value === \"object\") {\n const raw = (value as { [RAW]?: unknown })[RAW];\n if (raw !== undefined) return raw;\n }\n return value;\n}\n\n/** Transform one argument passed *into* a model method: unwrap facade args, and wrap the arguments\n * a user callback receives (so `eachRow`/`eachCell` hand back proxied rows/cells, not raw ones). */\nfunction mapArgIn(arg: unknown): unknown {\n if (typeof arg === \"function\") {\n const cb = arg as (...cbArgs: unknown[]) => unknown;\n return (...cbArgs: unknown[]) => cb(...cbArgs.map(wrap));\n }\n return unwrap(arg);\n}\n\n/** Default `get` behaviour shared by every facade: read the raw property, bind-and-wrap methods so\n * their return value (and callback args) cross the boundary, else wrap the plain value. */\nfunction reflectGet(target: object, prop: string | symbol): unknown {\n const value = Reflect.get(target, prop, target);\n if (typeof value === \"function\") {\n const fn = value as (...args: unknown[]) => unknown;\n return (...args: unknown[]) => wrap(fn.apply(target, args.map(mapArgIn)));\n }\n return wrap(value);\n}\n\n// --- the per-level proxies ----------------------------------------------------------------------\n\nfunction proxyCell(cell: Cell): Cell {\n const cached = cellProxies.get(cell);\n if (cached) return cached;\n const proxy = new Proxy(cell, {\n get(target, prop) {\n if (prop === RAW) return target;\n // Decision D1: compat cells always report ExcelJS ValueType numbers (§3).\n if (prop === \"type\") return toExcelJSValueType(target.type);\n if (prop === \"effectiveType\") return toExcelJSValueType(target.effectiveType);\n return reflectGet(target, prop);\n },\n set(target, prop, value) {\n // §4: assigning a style category replaces it whole-object, never field-merges.\n if (typeof prop === \"string\" && STYLE_SETTERS.has(prop)) {\n const patch: Style = {};\n (patch as Record<string, unknown>)[prop] = value;\n applyExcelJsStyle(target, patch);\n return true;\n }\n if (prop === \"note\") {\n throw new UnsupportedFeatureError(\"cell.note (comments)\", COMPAT_DEFER);\n }\n if (prop === \"dataValidation\") {\n throw new UnsupportedFeatureError(\"cell.dataValidation (data validation)\", COMPAT_DEFER);\n }\n return Reflect.set(target, prop, value, target);\n },\n });\n cellProxies.set(cell, proxy);\n return proxy;\n}\n\nfunction proxyRow(row: Row): Row {\n const cached = rowProxies.get(row);\n if (cached) return cached;\n const proxy = new Proxy(row, {\n get(target, prop) {\n if (prop === RAW) return target;\n return reflectGet(target, prop);\n },\n set(target, prop, value) {\n return Reflect.set(target, prop, value, target);\n },\n });\n rowProxies.set(row, proxy);\n return proxy;\n}\n\nfunction proxyColumn(column: Column): Column {\n const cached = columnProxies.get(column);\n if (cached) return cached;\n const proxy = new Proxy(column, {\n get(target, prop) {\n if (prop === RAW) return target;\n return reflectGet(target, prop);\n },\n set(target, prop, value) {\n return Reflect.set(target, prop, value, target);\n },\n });\n columnProxies.set(column, proxy);\n return proxy;\n}\n\nfunction proxyWorksheet(worksheet: Worksheet): Worksheet {\n const cached = worksheetProxies.get(worksheet);\n if (cached) return cached;\n const proxy = new Proxy(worksheet, {\n get(target, prop) {\n if (prop === RAW) return target;\n if (typeof prop === \"string\" && WORKSHEET_UNSUPPORTED.has(prop)) {\n return thrower(`worksheet.${prop}`);\n }\n if (prop === \"dataValidations\") {\n throw new UnsupportedFeatureError(\n \"worksheet.dataValidations (data validation)\",\n COMPAT_DEFER,\n );\n }\n return reflectGet(target, prop);\n },\n set(target, prop, value) {\n return Reflect.set(target, prop, value, target);\n },\n });\n worksheetProxies.set(worksheet, proxy);\n return proxy;\n}\n\nfunction proxyWorkbook(workbook: Workbook): Workbook {\n const cached = workbookProxies.get(workbook);\n if (cached) return cached;\n const proxy = new Proxy(workbook, {\n get(target, prop) {\n if (prop === RAW) return target;\n // The I/O accessor is already ExcelJS-shaped; only rebind load/read/readFile so they resolve\n // to the *facade* (not the raw workbook), keeping the returned handle inside compat mode.\n if (prop === \"xlsx\") {\n const acc = Reflect.get(target, \"xlsx\", target) as XlsxAccessor;\n return {\n writeBuffer: (...args: Parameters<XlsxAccessor[\"writeBuffer\"]>) =>\n acc.writeBuffer(...args),\n writeFile: (...args: Parameters<XlsxAccessor[\"writeFile\"]>) => acc.writeFile(...args),\n load: async (...args: Parameters<XlsxAccessor[\"load\"]>) => {\n await acc.load(...args);\n return proxy;\n },\n readFile: async (...args: Parameters<XlsxAccessor[\"readFile\"]>) => {\n await acc.readFile(...args);\n return proxy;\n },\n read: async (...args: Parameters<XlsxAccessor[\"read\"]>) => {\n await acc.read(...args);\n return proxy;\n },\n } satisfies XlsxAccessor;\n }\n if (prop === \"csv\") return CSV_STUB;\n if (prop === \"definedNames\") return DEFINED_NAMES_STUB;\n if (prop === \"addImage\" || prop === \"getImage\") return thrower(`workbook.${prop}`);\n if (prop === \"media\") {\n throw new UnsupportedFeatureError(\"workbook.media (images)\", COMPAT_DEFER);\n }\n return reflectGet(target, prop);\n },\n set(target, prop, value) {\n return Reflect.set(target, prop, value, target);\n },\n });\n workbookProxies.set(workbook, proxy);\n return proxy;\n}\n\n/**\n * The compat `Workbook`: an ExcelJS drop-in. `new CompatWorkbook()` builds a plain core workbook and\n * returns a facade Proxy over it — so `instanceof` still holds (the proxy's target *is* a Workbook),\n * while every reachable cell/row/column/worksheet reports ExcelJS semantics (§5).\n */\nexport class CompatWorkbook extends Workbook {\n constructor() {\n super();\n // A constructor may return an object in place of `this`; we deliberately return the facade\n // wrapping the fully-initialised core instance — the whole mechanism of the shim (§5). Cast:\n // the proxy's target is this CompatWorkbook, so `instanceof` still holds.\n // biome-ignore lint/correctness/noConstructorReturn: returning the facade Proxy is intentional.\n return proxyWorkbook(this) as CompatWorkbook;\n }\n}\n","/**\n * @alosha/xlsx/compat — the ExcelJS drop-in shim entry point (docs/COMPAT-SPEC.md).\n *\n * The default export is shaped like the `exceljs` namespace (`{ Workbook, ValueType, Enums, stream }`)\n * and the named `Workbook` is the ExcelJS-faithful facade (`CompatWorkbook`, §5): compat-constructed\n * workbooks report ExcelJS `ValueType` numbers, apply whole-object style precedence, and throw\n * `UnsupportedFeatureError` on the deferred surface (§6). An ExcelJS user changes one import.\n *\n * Re-exports from `../index.js` (not `../model/index.js`) so the `workbook.xlsx` accessor — attached\n * to `Workbook.prototype` as a side effect of loading the main entry — is present on compat workbooks.\n * The star export's plain `Workbook` is deliberately shadowed by the explicit `CompatWorkbook as\n * Workbook` re-export below (explicit named exports win over `export *`).\n */\n\nimport { FormulaType, ValueType } from \"./value-type.js\";\nimport { CompatWorkbook, streamStub } from \"./workbook.js\";\n\nexport * from \"../index.js\";\nexport { fromExcelJSValueType, toExcelJSValueType, ValueType } from \"./value-type.js\";\nexport { CompatWorkbook, CompatWorkbook as Workbook } from \"./workbook.js\";\n\n/** ExcelJS's `Enums` grouping (`import { Enums } from \"exceljs\"`). */\nexport const Enums = {\n ValueType,\n FormulaType,\n} as const;\n\n/** The ExcelJS-shaped default export: `import ExcelJS from \"@alosha/xlsx/compat\"`. */\nconst ExcelJS = {\n Workbook: CompatWorkbook,\n ValueType,\n FormulaType,\n Enums,\n stream: streamStub,\n};\n\nexport default ExcelJS;\n"]}
1
+ {"version":3,"sources":["../src/compat/value-type.ts","../src/compat/style-compat.ts","../src/compat/workbook.ts","../src/compat/index.ts"],"names":[],"mappings":"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","file":"compat.js","sourcesContent":["// The ExcelJS `Enums.ValueType`/`FormulaType` bridge (docs/COMPAT-SPEC.md §3). Our `CellType`\n// shares names with ExcelJS's `ValueType` but not numbers; these maps translate between the two.\n// `FormulaType` numbering already matches ExcelJS 1:1, so it's a straight re-export.\n\nimport { CellType } from \"../model/index.js\";\n\n/** ExcelJS's `Enums.ValueType` numbering. */\nexport const ValueType = {\n Null: 0,\n Merge: 1,\n Number: 2,\n String: 3,\n Date: 4,\n Hyperlink: 5,\n Formula: 6,\n SharedString: 7,\n RichText: 8,\n Boolean: 9,\n Error: 10,\n} as const;\n\nexport type ValueType = (typeof ValueType)[keyof typeof ValueType];\n\nexport { FormulaType } from \"../model/index.js\";\n\nconst TO_EXCELJS_VALUE_TYPE: Record<CellType, ValueType> = {\n [CellType.Null]: ValueType.Null,\n [CellType.Number]: ValueType.Number,\n [CellType.String]: ValueType.String,\n [CellType.Boolean]: ValueType.Boolean,\n [CellType.Date]: ValueType.Date,\n [CellType.Error]: ValueType.Error,\n [CellType.RichText]: ValueType.RichText,\n [CellType.Hyperlink]: ValueType.Hyperlink,\n [CellType.Formula]: ValueType.Formula,\n [CellType.Merge]: ValueType.Merge,\n [CellType.SharedString]: ValueType.SharedString,\n};\n\nconst FROM_EXCELJS_VALUE_TYPE: Record<ValueType, CellType> = {\n [ValueType.Null]: CellType.Null,\n [ValueType.Merge]: CellType.Merge,\n [ValueType.Number]: CellType.Number,\n [ValueType.String]: CellType.String,\n [ValueType.Date]: CellType.Date,\n [ValueType.Hyperlink]: CellType.Hyperlink,\n [ValueType.Formula]: CellType.Formula,\n [ValueType.SharedString]: CellType.SharedString,\n [ValueType.RichText]: CellType.RichText,\n [ValueType.Boolean]: CellType.Boolean,\n [ValueType.Error]: CellType.Error,\n};\n\n/** `cell.type` in compat mode: our `CellType` → ExcelJS's `ValueType` number. */\nexport function toExcelJSValueType(cellType: CellType): ValueType {\n return TO_EXCELJS_VALUE_TYPE[cellType];\n}\n\n/** The inverse of {@link toExcelJSValueType}. */\nexport function fromExcelJSValueType(value: ValueType): CellType {\n return FROM_EXCELJS_VALUE_TYPE[value];\n}\n","// The style-precedence divergence the compat shim must emulate (docs/COMPAT-SPEC.md §4).\n//\n// The core resolver (`resolveCellStyle`) does a **deep field-level merge**: a lone `cell.font.bold`\n// coexists with an inherited `font.name`/`font.size`. ExcelJS instead replaces the **whole**\n// category — assigning `cell.font` discards every inherited font field. A migrated spreadsheet must\n// render identically, so the compat facade's style setters route through `applyExcelJsStyle`, which\n// applies ExcelJS whole-object-per-category semantics.\n//\n// This only affects the authoring path: on read, styles come back already fully-resolved per cell,\n// so there is no divergence to bridge there. The core `resolveCellStyle` is deliberately left\n// untouched — the divergence is emulated here, scoped to compat-constructed workbooks.\n\nimport type { Cell, Style } from \"../model/index.js\";\n\n/** The six independently-inheritable style categories, in the order the core resolver lists them. */\nconst STYLE_CATEGORIES = [\"numFmt\", \"font\", \"fill\", \"border\", \"alignment\", \"protection\"] as const;\n\n/**\n * Apply a style `patch` to `cell` with ExcelJS whole-object precedence: every category **present**\n * in the patch replaces the cell's inherited category **outright** (no field-level merge), while\n * categories absent from the patch keep their current (possibly inherited) value. A category set to\n * `undefined` in the patch clears it. The underlying model store is otherwise unchanged — the\n * serializer still dedups the final styles.\n */\nexport function applyExcelJsStyle(cell: Cell, patch: Style): void {\n const inherited = cell.style;\n const next: Style = {};\n for (const key of STYLE_CATEGORIES) {\n // A category the patch mentions comes from the patch (whole-object replacement); otherwise it is\n // inherited from the cell's current style. Either way we copy the value as-is, never merging its\n // fields into the inherited one — that field-merge is exactly the core behaviour we diverge from.\n copyCategory(next, Object.hasOwn(patch, key) ? patch : inherited, key);\n }\n cell.style = next;\n}\n\n/** Copy one style category from `source` to `target`, skipping it entirely when unset. */\nfunction copyCategory<K extends keyof Style>(target: Style, source: Style, key: K): void {\n const value = source[key];\n if (value !== undefined) target[key] = value;\n}\n","// The ExcelJS-faithful facade over the core model (docs/COMPAT-SPEC.md §5).\n//\n// Mechanism (§5 leaves it to the implementer, with one hard rule: it MUST NOT leak ExcelJS\n// semantics into the core `@alosha/xlsx` entry): a **Proxy tree**. `CompatWorkbook`'s constructor\n// returns a Proxy over a plain core `Workbook`; every model object reachable from it (worksheets,\n// rows, columns, cells) is wrapped on the way out. The proxies delegate everything by default and\n// override only the three documented divergences plus the deferred surface:\n//\n// 1. `cell.type` / `cell.effectiveType` report ExcelJS `ValueType` numbers (§3, Decision D1 = full\n// emulation) instead of our `CellType` numbers.\n// 2. cell style setters (`font`/`fill`/`border`/`alignment`/`protection`/`numFmt`) route through\n// `applyExcelJsStyle` — ExcelJS whole-object-per-category precedence (§4).\n// 3. the deferred surface (§6: stream/csv/images/tables/conditional-formatting/data-validation/\n// comments/defined-names/protection) throws `UnsupportedFeatureError` at the exact call, naming\n// the feature, rather than silently no-op'ing.\n//\n// Everything else — `addRow(array | object)`, `row.values` (1-based, empty `[0]`), `worksheet.columns\n// = [{header, key, width}]`, the `workbook.xlsx.*` I/O accessor — is already ExcelJS-shaped in the\n// core model (COMPAT-SPEC.md §2 \"already compatible\"), so the proxies pass it straight through. The\n// core classes are never mutated; the divergence lives entirely in these compat-only wrappers.\n\nimport { UnsupportedFeatureError } from \"../errors.js\";\nimport type { XlsxAccessor } from \"../index.js\";\nimport { Cell, Column, Row, Workbook, Worksheet } from \"../index.js\";\nimport { CellType, type Style } from \"../model/index.js\";\nimport { applyExcelJsStyle } from \"./style-compat.js\";\nimport { toExcelJSValueType } from \"./value-type.js\";\n\n/** The pointer appended to every compat `UnsupportedFeatureError` (§6). */\nexport const COMPAT_DEFER =\n \"not yet supported in @alosha/xlsx/compat; see https://github.com/avlisodraude/alosha-xlsx/issues\";\n\n/** Sentinel prop that unwraps a facade back to its raw target (used by {@link unwrap}). */\nconst RAW = Symbol(\"alosha.compat.raw\");\n\n/** The cell style categories whose setters must apply ExcelJS whole-object precedence (§4). */\nconst STYLE_SETTERS = new Set([\"numFmt\", \"font\", \"fill\", \"border\", \"alignment\", \"protection\"]);\n\n// --- deferred surface (§6) ----------------------------------------------------------------------\n\n/** A method stub that always throws, naming `feature`. */\nfunction thrower(feature: string): (...args: never[]) => never {\n return () => {\n throw new UnsupportedFeatureError(feature, COMPAT_DEFER);\n };\n}\n\n/** A namespace-shaped object (e.g. `workbook.csv`) whose every method throws. */\nfunction stubNamespace(prefix: string, methods: readonly string[]): Record<string, () => never> {\n const ns: Record<string, () => never> = {};\n for (const m of methods) ns[m] = thrower(`${prefix}.${m}`);\n return ns;\n}\n\nconst CSV_STUB = stubNamespace(\"workbook.csv\", [\n \"read\",\n \"readFile\",\n \"write\",\n \"writeFile\",\n \"writeBuffer\",\n]);\nconst DEFINED_NAMES_STUB = stubNamespace(\"workbook.definedNames\", [\n \"add\",\n \"remove\",\n \"getRanges\",\n \"forEach\",\n \"getNames\",\n]);\n\n/** Worksheet methods that don't exist in the core model and must fail loud in compat mode. */\nconst WORKSHEET_UNSUPPORTED = new Set([\n \"addImage\",\n \"getImages\",\n \"addBackgroundImage\",\n \"addTable\",\n \"getTable\",\n \"getTables\",\n \"addConditionalFormatting\",\n \"removeConditionalFormatting\",\n \"protect\",\n \"unprotect\",\n]);\n\n/** Streaming entry points hung off the ExcelJS namespace (`ExcelJS.stream.xlsx.*`); each throws. */\nexport const streamStub = {\n xlsx: {\n WorkbookWriter: class {\n constructor() {\n throw new UnsupportedFeatureError(\"stream.xlsx.WorkbookWriter\", COMPAT_DEFER);\n }\n },\n WorkbookReader: class {\n constructor() {\n throw new UnsupportedFeatureError(\"stream.xlsx.WorkbookReader\", COMPAT_DEFER);\n }\n },\n },\n} as const;\n\n// --- facade plumbing ----------------------------------------------------------------------------\n\n// One proxy per underlying object, so facade identity is stable (`ws.getCell('A1') === ws.getCell\n// ('A1')`) and re-wrapping is idempotent.\nconst workbookProxies = new WeakMap<Workbook, Workbook>();\nconst worksheetProxies = new WeakMap<Worksheet, Worksheet>();\nconst rowProxies = new WeakMap<Row, Row>();\nconst columnProxies = new WeakMap<Column, Column>();\nconst cellProxies = new WeakMap<Cell, Cell>();\n\n/** Wrap a value crossing the facade boundary on the way out: model objects become their proxies,\n * arrays are wrapped element-wise (preserving sparse holes, e.g. `row.values`), primitives pass. */\nfunction wrap(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(wrap);\n if (value instanceof Cell) return proxyCell(value);\n if (value instanceof Row) return proxyRow(value);\n if (value instanceof Column) return proxyColumn(value);\n if (value instanceof Worksheet) return proxyWorksheet(value);\n if (value instanceof Workbook) return proxyWorkbook(value);\n return value;\n}\n\n/** The inverse of {@link wrap} for a single value: a facade proxy back to its raw target. */\nfunction unwrap(value: unknown): unknown {\n if (value !== null && typeof value === \"object\") {\n const raw = (value as { [RAW]?: unknown })[RAW];\n if (raw !== undefined) return raw;\n }\n return value;\n}\n\n/** Transform one argument passed *into* a model method: unwrap facade args, and wrap the arguments\n * a user callback receives (so `eachRow`/`eachCell` hand back proxied rows/cells, not raw ones). */\nfunction mapArgIn(arg: unknown): unknown {\n if (typeof arg === \"function\") {\n const cb = arg as (...cbArgs: unknown[]) => unknown;\n return (...cbArgs: unknown[]) => cb(...cbArgs.map(wrap));\n }\n return unwrap(arg);\n}\n\n/** Default `get` behaviour shared by every facade: read the raw property, bind-and-wrap methods so\n * their return value (and callback args) cross the boundary, else wrap the plain value. */\nfunction reflectGet(target: object, prop: string | symbol): unknown {\n const value = Reflect.get(target, prop, target);\n if (typeof value === \"function\") {\n const fn = value as (...args: unknown[]) => unknown;\n return (...args: unknown[]) => wrap(fn.apply(target, args.map(mapArgIn)));\n }\n return wrap(value);\n}\n\n/** ExcelJS parity for `eachRow`/`eachCell`: without `includeEmpty`, ExcelJS drops rows/cells that are\n * empty (never held a value, or were explicitly set to `null`), while our core model still yields any\n * row/cell ever touched via `getRow`/`getCell`. This bridges that gap on the compat iteration path —\n * `isEmpty` tests the raw model item, and surviving items are wrapped like every other facade boundary\n * (so callbacks receive proxied rows/cells, not raw ones). `includeEmpty: true` passes straight through\n * to the core's full enumeration. */\nfunction eachWithEmptyFilter<T>(\n each: (opts: { includeEmpty: boolean }, cb: (item: T, n: number) => void) => void,\n isEmpty: (item: T) => boolean,\n optsOrCb: { includeEmpty?: boolean } | ((item: unknown, n: number) => void),\n maybeCb?: (item: unknown, n: number) => void,\n): void {\n const includeEmpty = typeof optsOrCb === \"object\" ? optsOrCb.includeEmpty === true : false;\n const cb = (typeof optsOrCb === \"function\" ? optsOrCb : maybeCb) as (\n item: unknown,\n n: number,\n ) => void;\n each({ includeEmpty }, (item, n) => {\n if (!includeEmpty && isEmpty(item)) return;\n cb(wrap(item), n);\n });\n}\n\n// --- the per-level proxies ----------------------------------------------------------------------\n\nfunction proxyCell(cell: Cell): Cell {\n const cached = cellProxies.get(cell);\n if (cached) return cached;\n const proxy = new Proxy(cell, {\n get(target, prop) {\n if (prop === RAW) return target;\n // Decision D1: compat cells always report ExcelJS ValueType numbers (§3).\n if (prop === \"type\") return toExcelJSValueType(target.type);\n if (prop === \"effectiveType\") return toExcelJSValueType(target.effectiveType);\n return reflectGet(target, prop);\n },\n set(target, prop, value) {\n // §4: assigning a style category replaces it whole-object, never field-merges.\n if (typeof prop === \"string\" && STYLE_SETTERS.has(prop)) {\n const patch: Style = {};\n (patch as Record<string, unknown>)[prop] = value;\n applyExcelJsStyle(target, patch);\n return true;\n }\n if (prop === \"note\") {\n throw new UnsupportedFeatureError(\"cell.note (comments)\", COMPAT_DEFER);\n }\n if (prop === \"dataValidation\") {\n throw new UnsupportedFeatureError(\"cell.dataValidation (data validation)\", COMPAT_DEFER);\n }\n return Reflect.set(target, prop, value, target);\n },\n });\n cellProxies.set(cell, proxy);\n return proxy;\n}\n\nfunction proxyRow(row: Row): Row {\n const cached = rowProxies.get(row);\n if (cached) return cached;\n const proxy = new Proxy(row, {\n get(target, prop) {\n if (prop === RAW) return target;\n // ExcelJS parity: default `eachCell` skips empty cells (§ MIGRATION \"eachRow/eachCell\").\n if (prop === \"eachCell\") {\n return (\n optsOrCb: { includeEmpty?: boolean } | ((cell: unknown, n: number) => void),\n maybeCb?: (cell: unknown, n: number) => void,\n ) =>\n eachWithEmptyFilter<Cell>(\n (o, cb) => target.eachCell(o, cb),\n (cell) => cell.type === CellType.Null,\n optsOrCb,\n maybeCb,\n );\n }\n return reflectGet(target, prop);\n },\n set(target, prop, value) {\n return Reflect.set(target, prop, value, target);\n },\n });\n rowProxies.set(row, proxy);\n return proxy;\n}\n\nfunction proxyColumn(column: Column): Column {\n const cached = columnProxies.get(column);\n if (cached) return cached;\n const proxy = new Proxy(column, {\n get(target, prop) {\n if (prop === RAW) return target;\n // ExcelJS parity: default `eachCell` skips empty cells (§ MIGRATION \"eachRow/eachCell\").\n if (prop === \"eachCell\") {\n return (\n optsOrCb: { includeEmpty?: boolean } | ((cell: unknown, n: number) => void),\n maybeCb?: (cell: unknown, n: number) => void,\n ) =>\n eachWithEmptyFilter<Cell>(\n (o, cb) => target.eachCell(o, cb),\n (cell) => cell.type === CellType.Null,\n optsOrCb,\n maybeCb,\n );\n }\n return reflectGet(target, prop);\n },\n set(target, prop, value) {\n return Reflect.set(target, prop, value, target);\n },\n });\n columnProxies.set(column, proxy);\n return proxy;\n}\n\nfunction proxyWorksheet(worksheet: Worksheet): Worksheet {\n const cached = worksheetProxies.get(worksheet);\n if (cached) return cached;\n const proxy = new Proxy(worksheet, {\n get(target, prop) {\n if (prop === RAW) return target;\n if (typeof prop === \"string\" && WORKSHEET_UNSUPPORTED.has(prop)) {\n return thrower(`worksheet.${prop}`);\n }\n if (prop === \"dataValidations\") {\n throw new UnsupportedFeatureError(\n \"worksheet.dataValidations (data validation)\",\n COMPAT_DEFER,\n );\n }\n // ExcelJS parity: default `eachRow` skips empty rows (§ MIGRATION \"eachRow/eachCell\").\n if (prop === \"eachRow\") {\n return (\n optsOrCb: { includeEmpty?: boolean } | ((row: unknown, n: number) => void),\n maybeCb?: (row: unknown, n: number) => void,\n ) =>\n eachWithEmptyFilter<Row>(\n (o, cb) => target.eachRow(o, cb),\n (row) => !row.hasValues,\n optsOrCb,\n maybeCb,\n );\n }\n return reflectGet(target, prop);\n },\n set(target, prop, value) {\n return Reflect.set(target, prop, value, target);\n },\n });\n worksheetProxies.set(worksheet, proxy);\n return proxy;\n}\n\nfunction proxyWorkbook(workbook: Workbook): Workbook {\n const cached = workbookProxies.get(workbook);\n if (cached) return cached;\n const proxy = new Proxy(workbook, {\n get(target, prop) {\n if (prop === RAW) return target;\n // The I/O accessor is already ExcelJS-shaped; only rebind load/read/readFile so they resolve\n // to the *facade* (not the raw workbook), keeping the returned handle inside compat mode.\n if (prop === \"xlsx\") {\n const acc = Reflect.get(target, \"xlsx\", target) as XlsxAccessor;\n return {\n writeBuffer: (...args: Parameters<XlsxAccessor[\"writeBuffer\"]>) =>\n acc.writeBuffer(...args),\n writeFile: (...args: Parameters<XlsxAccessor[\"writeFile\"]>) => acc.writeFile(...args),\n load: async (...args: Parameters<XlsxAccessor[\"load\"]>) => {\n await acc.load(...args);\n return proxy;\n },\n readFile: async (...args: Parameters<XlsxAccessor[\"readFile\"]>) => {\n await acc.readFile(...args);\n return proxy;\n },\n read: async (...args: Parameters<XlsxAccessor[\"read\"]>) => {\n await acc.read(...args);\n return proxy;\n },\n } satisfies XlsxAccessor;\n }\n if (prop === \"csv\") return CSV_STUB;\n if (prop === \"definedNames\") return DEFINED_NAMES_STUB;\n if (prop === \"addImage\" || prop === \"getImage\") return thrower(`workbook.${prop}`);\n if (prop === \"media\") {\n throw new UnsupportedFeatureError(\"workbook.media (images)\", COMPAT_DEFER);\n }\n return reflectGet(target, prop);\n },\n set(target, prop, value) {\n return Reflect.set(target, prop, value, target);\n },\n });\n workbookProxies.set(workbook, proxy);\n return proxy;\n}\n\n/**\n * The compat `Workbook`: an ExcelJS drop-in. `new CompatWorkbook()` builds a plain core workbook and\n * returns a facade Proxy over it — so `instanceof` still holds (the proxy's target *is* a Workbook),\n * while every reachable cell/row/column/worksheet reports ExcelJS semantics (§5).\n */\nexport class CompatWorkbook extends Workbook {\n constructor() {\n super();\n // A constructor may return an object in place of `this`; we deliberately return the facade\n // wrapping the fully-initialised core instance — the whole mechanism of the shim (§5). Cast:\n // the proxy's target is this CompatWorkbook, so `instanceof` still holds.\n // biome-ignore lint/correctness/noConstructorReturn: returning the facade Proxy is intentional.\n return proxyWorkbook(this) as CompatWorkbook;\n }\n}\n","/**\n * @alosha/xlsx/compat — the ExcelJS drop-in shim entry point (docs/COMPAT-SPEC.md).\n *\n * The default export is shaped like the `exceljs` namespace (`{ Workbook, ValueType, Enums, stream }`)\n * and the named `Workbook` is the ExcelJS-faithful facade (`CompatWorkbook`, §5): compat-constructed\n * workbooks report ExcelJS `ValueType` numbers, apply whole-object style precedence, and throw\n * `UnsupportedFeatureError` on the deferred surface (§6). An ExcelJS user changes one import.\n *\n * Re-exports from `../index.js` (not `../model/index.js`) so the `workbook.xlsx` accessor — attached\n * to `Workbook.prototype` as a side effect of loading the main entry — is present on compat workbooks.\n * The star export's plain `Workbook` is deliberately shadowed by the explicit `CompatWorkbook as\n * Workbook` re-export below (explicit named exports win over `export *`).\n */\n\nimport { FormulaType, ValueType } from \"./value-type.js\";\nimport { CompatWorkbook, streamStub } from \"./workbook.js\";\n\nexport * from \"../index.js\";\nexport { fromExcelJSValueType, toExcelJSValueType, ValueType } from \"./value-type.js\";\nexport { CompatWorkbook, CompatWorkbook as Workbook } from \"./workbook.js\";\n\n/** ExcelJS's `Enums` grouping (`import { Enums } from \"exceljs\"`). */\nexport const Enums = {\n ValueType,\n FormulaType,\n} as const;\n\n/** The ExcelJS-shaped default export: `import ExcelJS from \"@alosha/xlsx/compat\"`. */\nconst ExcelJS = {\n Workbook: CompatWorkbook,\n ValueType,\n FormulaType,\n Enums,\n stream: streamStub,\n};\n\nexport default ExcelJS;\n"]}
package/dist/index.cjs CHANGED
@@ -1694,7 +1694,8 @@ var REL_TYPE = {
1694
1694
  worksheet: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
1695
1695
  styles: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
1696
1696
  sharedStrings: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings",
1697
- theme: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
1697
+ theme: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
1698
+ hyperlink: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
1698
1699
  };
1699
1700
  var PART_PATH = {
1700
1701
  contentTypes: "[Content_Types].xml",
@@ -1995,11 +1996,23 @@ function openPackage(bytes) {
1995
1996
  relsMap.set(rel.id, { type: rel.type, target: resolveRelTarget(workbookDir, rel.target) });
1996
1997
  }
1997
1998
  }
1999
+ const partRels = (partPath) => {
2000
+ const dir = dirname(partPath);
2001
+ const relsXml = text(relsPathFor(partPath));
2002
+ const map = /* @__PURE__ */ new Map();
2003
+ if (relsXml === void 0) return map;
2004
+ for (const rel of parseRels(relsXml)) {
2005
+ const target = rel.mode === "External" ? rel.target : resolveRelTarget(dir, rel.target);
2006
+ map.set(rel.id, { type: rel.type, target, mode: rel.mode });
2007
+ }
2008
+ return map;
2009
+ };
1998
2010
  return {
1999
2011
  entry,
2000
2012
  text,
2001
2013
  workbookRels: () => relsMap,
2002
- workbookPath: () => workbookPath
2014
+ workbookPath: () => workbookPath,
2015
+ partRels
2003
2016
  };
2004
2017
  }
2005
2018
  function readZip(bytes) {
@@ -2021,7 +2034,8 @@ function parseRels(xml) {
2021
2034
  rels.push({
2022
2035
  id: child.attrs.Id ?? "",
2023
2036
  type: child.attrs.Type ?? "",
2024
- target: child.attrs.Target ?? ""
2037
+ target: child.attrs.Target ?? "",
2038
+ mode: child.attrs.TargetMode === "External" ? "External" : "Internal"
2025
2039
  });
2026
2040
  });
2027
2041
  }
@@ -2925,6 +2939,7 @@ function parseWorksheet(ws, xml, ctx) {
2925
2939
  while (ev && !(ev.kind === "open" && localName(ev.name) === "worksheet")) ev = c.next();
2926
2940
  if (ev?.kind !== "open" || ev.selfClosing) return;
2927
2941
  const merges = [];
2942
+ const hyperlinks = [];
2928
2943
  c.eachChild(ev.name, (child) => {
2929
2944
  switch (localName(child.name)) {
2930
2945
  case "cols":
@@ -2936,11 +2951,17 @@ function parseWorksheet(ws, xml, ctx) {
2936
2951
  case "mergeCells":
2937
2952
  if (!child.selfClosing) collectMerges(c, child.name, merges);
2938
2953
  break;
2954
+ case "hyperlinks":
2955
+ if (!child.selfClosing) collectHyperlinks(c, child.name, hyperlinks);
2956
+ break;
2939
2957
  default:
2940
2958
  if (!child.selfClosing) c.textUntilClose(child.name);
2941
2959
  }
2942
2960
  });
2943
2961
  for (const ref of merges) ws.mergeCells(ref);
2962
+ if (ctx.rels) {
2963
+ for (const link of hyperlinks) applyHyperlink(ws, link, ctx.rels);
2964
+ }
2944
2965
  }
2945
2966
  function parseCols(c, container, ws, ctx) {
2946
2967
  c.eachChild(container, (col) => {
@@ -3081,6 +3102,35 @@ function collectMerges(c, container, merges) {
3081
3102
  }
3082
3103
  });
3083
3104
  }
3105
+ function collectHyperlinks(c, container, hyperlinks) {
3106
+ c.eachChild(container, (child) => {
3107
+ if (localName(child.name) !== "hyperlink") {
3108
+ if (!child.selfClosing) c.textUntilClose(child.name);
3109
+ return;
3110
+ }
3111
+ const ref = child.attrs.ref;
3112
+ const rId = relId2(child);
3113
+ if (ref === void 0 || rId === "") return;
3114
+ const tooltip = child.attrs.tooltip;
3115
+ hyperlinks.push(tooltip !== void 0 ? { ref, rId, tooltip } : { ref, rId });
3116
+ });
3117
+ }
3118
+ function applyHyperlink(ws, link, rels) {
3119
+ const rel = rels.get(link.rId);
3120
+ if (!rel) return;
3121
+ const topLeft = link.ref.split(":")[0] ?? link.ref;
3122
+ const cell = ws.getCell(topLeft);
3123
+ const text = typeof cell.value === "string" ? cell.value : "";
3124
+ cell.value = link.tooltip !== void 0 ? { text, hyperlink: rel.target, tooltip: link.tooltip } : { text, hyperlink: rel.target };
3125
+ }
3126
+ function relId2(el) {
3127
+ const direct = el.attrs["r:id"];
3128
+ if (direct !== void 0) return direct;
3129
+ for (const key of Object.keys(el.attrs)) {
3130
+ if (localName(key) === "id") return el.attrs[key] ?? "";
3131
+ }
3132
+ return "";
3133
+ }
3084
3134
  function decodeBool(raw) {
3085
3135
  if (raw === "1" || raw === "true" || raw === "TRUE") return true;
3086
3136
  if (raw === "0" || raw === "false" || raw === "FALSE") return false;
@@ -3118,7 +3168,9 @@ function readWorkbookBuffer(bytes, _options) {
3118
3168
  const target = rels.get(sheet.rId)?.target;
3119
3169
  if (target === void 0) continue;
3120
3170
  const sheetXml = pkg.text(target);
3121
- if (sheetXml !== void 0) parseWorksheet(ws, sheetXml, ctx);
3171
+ if (sheetXml !== void 0) {
3172
+ parseWorksheet(ws, sheetXml, { ...ctx, rels: pkg.partRels(target) });
3173
+ }
3122
3174
  }
3123
3175
  const coreXml = pkg.text(PART_PATH.coreProps);
3124
3176
  if (coreXml !== void 0) applyCoreProps(wb, coreXml);
@@ -3384,6 +3436,22 @@ function renderWorkbookRels(rels) {
3384
3436
  return w.toString();
3385
3437
  }
3386
3438
 
3439
+ // src/xlsx/parts/worksheet-rels.ts
3440
+ function renderWorksheetRels(rels) {
3441
+ const w = new XmlWriter();
3442
+ w.open("Relationships", { xmlns: NS.packageRels });
3443
+ for (const rel of rels) {
3444
+ w.leaf("Relationship", {
3445
+ Id: rel.rId,
3446
+ Type: REL_TYPE.hyperlink,
3447
+ Target: rel.target,
3448
+ TargetMode: rel.mode
3449
+ });
3450
+ }
3451
+ w.close("Relationships");
3452
+ return w.toString();
3453
+ }
3454
+
3387
3455
  // src/xlsx/parts/worksheet.ts
3388
3456
  var DEFAULT_DATE_NUMFMT = "mm-dd-yy";
3389
3457
  function renderWorksheet(ws, ctx) {
@@ -3401,11 +3469,13 @@ function renderWorksheet(ws, ctx) {
3401
3469
  defaultRowHeight: model.properties.defaultRowHeight ?? 15,
3402
3470
  defaultColWidth: model.properties.defaultColWidth
3403
3471
  });
3472
+ const hyperlinks = [];
3404
3473
  renderCols(w, model.columns, ctx);
3405
- renderSheetData(w, model.rows, ctx);
3474
+ renderSheetData(w, model.rows, ctx, hyperlinks);
3406
3475
  renderMergeCells(w, model.merges);
3476
+ const rels = renderHyperlinks(w, hyperlinks);
3407
3477
  w.close("worksheet");
3408
- return w.toString();
3478
+ return { xml: w.toString(), rels };
3409
3479
  }
3410
3480
  function renderCols(w, columns, ctx) {
3411
3481
  if (!columns || columns.length === 0) return;
@@ -3431,13 +3501,13 @@ function renderCols(w, columns, ctx) {
3431
3501
  for (const f of fragments) w.raw(f);
3432
3502
  w.close("cols");
3433
3503
  }
3434
- function renderSheetData(w, rows, ctx) {
3504
+ function renderSheetData(w, rows, ctx, hyperlinks) {
3435
3505
  w.open("sheetData");
3436
3506
  for (const row of rows) {
3437
3507
  const styleId = row.style ? ctx.styles.addStyle(row.style) : 0;
3438
3508
  let cellsXml = "";
3439
3509
  for (const cell of row.cells) {
3440
- cellsXml += renderCell(cell, ctx);
3510
+ cellsXml += renderCell(cell, ctx, hyperlinks);
3441
3511
  }
3442
3512
  const hasAttrs = row.height !== void 0 || row.hidden || (row.outlineLevel ?? 0) !== 0 || styleId !== 0;
3443
3513
  if (cellsXml === "" && !hasAttrs) continue;
@@ -3455,7 +3525,7 @@ function renderSheetData(w, rows, ctx) {
3455
3525
  }
3456
3526
  w.close("sheetData");
3457
3527
  }
3458
- function renderCell(cell, ctx) {
3528
+ function renderCell(cell, ctx, hyperlinks) {
3459
3529
  const styleId = cell.style ? ctx.styles.addStyle(cell.style) : 0;
3460
3530
  const r = cell.address;
3461
3531
  switch (cell.type) {
@@ -3474,8 +3544,11 @@ function renderCell(cell, ctx) {
3474
3544
  return valueCell(r, styleId, "e", cell.value.error);
3475
3545
  case 2 /* String */:
3476
3546
  return stringCell(r, styleId, cell.value, ctx);
3477
- case 7 /* Hyperlink */:
3478
- return stringCell(r, styleId, cell.value.text, ctx);
3547
+ case 7 /* Hyperlink */: {
3548
+ const link = cell.value;
3549
+ hyperlinks.push({ ref: r, target: link.hyperlink, tooltip: link.tooltip });
3550
+ return stringCell(r, styleId, link.text, ctx);
3551
+ }
3479
3552
  case 6 /* RichText */:
3480
3553
  return richTextCell(r, styleId, cell.value, ctx);
3481
3554
  case 8 /* Formula */:
@@ -3549,6 +3622,18 @@ function renderMergeCells(w, merges) {
3549
3622
  for (const ref of merges) w.leaf("mergeCell", { ref });
3550
3623
  w.close("mergeCells");
3551
3624
  }
3625
+ function renderHyperlinks(w, hyperlinks) {
3626
+ if (hyperlinks.length === 0) return void 0;
3627
+ const rels = [];
3628
+ w.open("hyperlinks");
3629
+ hyperlinks.forEach((h, i) => {
3630
+ const rId = `rId${i + 1}`;
3631
+ w.leaf("hyperlink", { ref: h.ref, "r:id": rId, tooltip: h.tooltip });
3632
+ rels.push({ rId, target: h.target, mode: "External" });
3633
+ });
3634
+ w.close("hyperlinks");
3635
+ return renderWorksheetRels(rels);
3636
+ }
3552
3637
 
3553
3638
  // src/xlsx/write-workbook.ts
3554
3639
  function writeWorkbookBuffer(wb, options) {
@@ -3612,7 +3697,10 @@ function writeWorkbookBuffer(wb, options) {
3612
3697
  put(PART_PATH.styles, styles.toXml());
3613
3698
  if (sharedStringsXml !== void 0) put(PART_PATH.sharedStrings, sharedStringsXml);
3614
3699
  put(PART_PATH.theme, renderTheme());
3615
- for (const [file, xml] of worksheetXml) put(`xl/worksheets/${file}`, xml);
3700
+ for (const [file, { xml, rels }] of worksheetXml) {
3701
+ put(`xl/worksheets/${file}`, xml);
3702
+ if (rels !== void 0) put(`xl/worksheets/_rels/${file}.rels`, rels);
3703
+ }
3616
3704
  return writeZipArchive(entries);
3617
3705
  }
3618
3706
  async function writeWorkbookFile(wb, path, options) {