@extend-ai/react-xlsx 0.13.2 → 0.13.3

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.
@@ -1,3 +1,6 @@
1
+ // src/xlsx-worker.ts
2
+ import { strFromU8 as strFromU83, unzipSync as unzipSync2 } from "fflate";
3
+
1
4
  // src/charts.ts
2
5
  import { strFromU8, strToU8 } from "fflate";
3
6
  var CHART_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart";
@@ -3108,30 +3111,6 @@ function resolveWorksheetDefaultRowHeightPixels(worksheet, fallbackPx = Math.max
3108
3111
  const height = typeof worksheet.defaultRowHeight === "number" ? worksheet.defaultRowHeight : Number.NaN;
3109
3112
  return Number.isFinite(height) && height > 0 ? Math.max(MIN_ROW_HEIGHT_PX, Math.round(height * 1.33)) : fallbackPx;
3110
3113
  }
3111
- function resolveWorksheetHiddenRows(worksheet, maxRow) {
3112
- if (!Number.isFinite(maxRow) || maxRow < 0 || typeof worksheet.isRowHidden !== "function") {
3113
- return [];
3114
- }
3115
- const hiddenRows = [];
3116
- for (let row = 0; row <= maxRow; row += 1) {
3117
- if (worksheet.isRowHidden(row)) {
3118
- hiddenRows.push(row);
3119
- }
3120
- }
3121
- return hiddenRows;
3122
- }
3123
- function resolveWorksheetHiddenCols(worksheet, maxCol) {
3124
- if (!Number.isFinite(maxCol) || maxCol < 0 || typeof worksheet.isColumnHidden !== "function") {
3125
- return [];
3126
- }
3127
- const hiddenCols = [];
3128
- for (let col = 0; col <= maxCol; col += 1) {
3129
- if (worksheet.isColumnHidden(col)) {
3130
- hiddenCols.push(col);
3131
- }
3132
- }
3133
- return hiddenCols;
3134
- }
3135
3114
  function resolveWorksheetMergeMetadata(worksheet) {
3136
3115
  const mergeMetadata = {
3137
3116
  hasHorizontalMerges: false,
@@ -4453,6 +4432,7 @@ var DEFAULT_COL_WIDTH = 80;
4453
4432
  var DEFAULT_ZOOM_SCALE = 100;
4454
4433
  var FORMULA_COUNT_THRESHOLD = 1e3;
4455
4434
  var FAST_STRUCTURE_PARSE_THRESHOLD_BYTES = 5 * 1024 * 1024;
4435
+ var MIN_ROW_HEIGHT_PX2 = 16;
4456
4436
  function isLegacyXlsWorkbook(bytes) {
4457
4437
  return bytes.byteLength >= 8 && bytes[0] === 208 && bytes[1] === 207 && bytes[2] === 17 && bytes[3] === 224 && bytes[4] === 161 && bytes[5] === 177 && bytes[6] === 26 && bytes[7] === 225;
4458
4438
  }
@@ -4468,6 +4448,79 @@ var chartsheets = [];
4468
4448
  var sheets = [];
4469
4449
  var tablesByWorkbookSheetIndex = [];
4470
4450
  var tabs = [];
4451
+ function canParseXmlInWorker() {
4452
+ return typeof DOMParser !== "undefined";
4453
+ }
4454
+ function decodeXmlAttribute(value) {
4455
+ return value.replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
4456
+ }
4457
+ function readXmlAttribute(tag, name) {
4458
+ const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4459
+ const match = new RegExp(`(?:^|\\s)${escapedName}="([^"]*)"`).exec(tag);
4460
+ return match ? decodeXmlAttribute(match[1] ?? "") : null;
4461
+ }
4462
+ function readArchiveText3(archive, path) {
4463
+ const entry = archive[path];
4464
+ return entry ? strFromU83(entry) : "";
4465
+ }
4466
+ function normalizeWorkbookRelationshipTarget(target) {
4467
+ if (target.startsWith("/")) {
4468
+ return target.replace(/^\/+/, "");
4469
+ }
4470
+ return target.startsWith("xl/") ? target : `xl/${target.replace(/^\.?\//, "")}`;
4471
+ }
4472
+ function parseWorkbookSheetPathsFromArchive(archive) {
4473
+ const workbookXml = readArchiveText3(archive, "xl/workbook.xml");
4474
+ const workbookRelationshipsXml = readArchiveText3(archive, "xl/_rels/workbook.xml.rels");
4475
+ if (!workbookXml || !workbookRelationshipsXml) {
4476
+ return [];
4477
+ }
4478
+ const relationshipTargetById = /* @__PURE__ */ new Map();
4479
+ for (const match of workbookRelationshipsXml.matchAll(/<Relationship\b[^>]*>/g)) {
4480
+ const tag = match[0];
4481
+ const id = readXmlAttribute(tag, "Id");
4482
+ const target = readXmlAttribute(tag, "Target");
4483
+ if (id && target) {
4484
+ relationshipTargetById.set(id, normalizeWorkbookRelationshipTarget(target));
4485
+ }
4486
+ }
4487
+ const paths = [];
4488
+ for (const match of workbookXml.matchAll(/<sheet\b[^>]*>/g)) {
4489
+ const tag = match[0];
4490
+ const relationshipId = readXmlAttribute(tag, "r:id") ?? readXmlAttribute(tag, "id");
4491
+ const target = relationshipId ? relationshipTargetById.get(relationshipId) : null;
4492
+ if (target) {
4493
+ paths.push(target);
4494
+ }
4495
+ }
4496
+ return paths;
4497
+ }
4498
+ function parseWorkerSheetLayoutAssets(bytes, sheetCount) {
4499
+ try {
4500
+ const archive = unzipSync2(bytes);
4501
+ const workbookSheetPaths = parseWorkbookSheetPathsFromArchive(archive);
4502
+ const sheetPaths = workbookSheetPaths.length > 0 ? workbookSheetPaths : Array.from({ length: sheetCount }, (_, index) => `xl/worksheets/sheet${index + 1}.xml`);
4503
+ return sheetPaths.slice(0, sheetCount).map((path) => {
4504
+ const xml = readArchiveText3(archive, path);
4505
+ if (!xml) {
4506
+ return null;
4507
+ }
4508
+ const rowHeightOverridesPx = {};
4509
+ for (const match of xml.matchAll(/<row\b[^>]*>/g)) {
4510
+ const tag = match[0];
4511
+ const rowNumber = Number(readXmlAttribute(tag, "r") ?? Number.NaN);
4512
+ const height = Number(readXmlAttribute(tag, "ht") ?? Number.NaN);
4513
+ const rowIndex = rowNumber - 1;
4514
+ if (rowIndex >= 0 && Number.isFinite(height)) {
4515
+ rowHeightOverridesPx[rowIndex] = Math.max(MIN_ROW_HEIGHT_PX2, Math.round(height * 1.33));
4516
+ }
4517
+ }
4518
+ return { rowHeightOverridesPx };
4519
+ });
4520
+ } catch {
4521
+ return [];
4522
+ }
4523
+ }
4471
4524
  function buildVisibleSheetIndexByWorkbookSheetIndex(nextWorkbook, showHiddenSheets = false) {
4472
4525
  const mapping = /* @__PURE__ */ new Map();
4473
4526
  let visibleIndex = 0;
@@ -4588,11 +4641,11 @@ function resolveSheetDisplayUsedRange(usedRange, sheetState) {
4588
4641
  maxMeaningfulCol >= 0 ? maxContentCol >= 0 ? Math.min(maxCol, maxMeaningfulCol) : Math.max(maxCol, maxMeaningfulCol) : maxCol
4589
4642
  ];
4590
4643
  }
4591
- function buildSheetList(nextWorkbook, structureAssets, showHiddenSheets = false) {
4644
+ function buildSheetList(nextWorkbook, structureAssets, sheetLayoutStates, showHiddenSheets = false) {
4592
4645
  const sheetsByWorkbookSheetIndex = [];
4593
4646
  for (let index = 0; index < nextWorkbook.sheetCount; index += 1) {
4594
4647
  const worksheet = nextWorkbook.getSheet(index);
4595
- const sheetState = structureAssets?.sheetStatesByWorkbookSheetIndex[index] ?? null;
4648
+ const sheetState = structureAssets?.sheetStatesByWorkbookSheetIndex[index] ?? sheetLayoutStates?.[index] ?? null;
4596
4649
  const mergeMetadata = resolveWorksheetMergeMetadata(worksheet);
4597
4650
  const effectiveSheetState = {
4598
4651
  ...sheetState,
@@ -4669,15 +4722,31 @@ function buildSheetList(nextWorkbook, structureAssets, showHiddenSheets = false)
4669
4722
  continue;
4670
4723
  }
4671
4724
  const [minRow, minCol, maxRow, maxCol] = resolveSheetDisplayUsedRange(usedRange, effectiveSheetState);
4672
- const hiddenRows = resolveWorksheetHiddenRows(worksheet, maxRow);
4673
- const hiddenCols = resolveWorksheetHiddenCols(worksheet, maxCol);
4725
+ const visibleRows = [];
4726
+ const hiddenRows = [];
4727
+ for (let row = 0; row <= maxRow; row += 1) {
4728
+ if (worksheet.isRowHidden(row)) {
4729
+ hiddenRows.push(row);
4730
+ } else {
4731
+ visibleRows.push(row);
4732
+ }
4733
+ }
4734
+ const visibleCols = [];
4735
+ const hiddenCols = [];
4736
+ for (let col = 0; col <= maxCol; col += 1) {
4737
+ if (worksheet.isColumnHidden(col)) {
4738
+ hiddenCols.push(col);
4739
+ } else {
4740
+ visibleCols.push(col);
4741
+ }
4742
+ }
4674
4743
  sheetsByWorkbookSheetIndex.push({
4675
4744
  cachedFormulaValues: sheetState?.cachedFormulaValues ?? {},
4676
4745
  columnWidthCharacterWidthPx: sheetState?.columnWidthCharacterWidthPx,
4677
- colCount: Math.max(0, maxCol + 1 - hiddenCols.length),
4746
+ colCount: visibleCols.length,
4678
4747
  colStyleIds: sheetState?.colStyleIds ?? {},
4679
4748
  colWidthOverridesPx: sheetState?.colWidthOverridesPx ?? {},
4680
- colWidths: [],
4749
+ colWidths: visibleCols.map(resolveColumnWidthPx),
4681
4750
  conditionalFormatRules: sheetState?.conditionalFormatRules ?? [],
4682
4751
  dataValidations: parseWorksheetDataValidations(worksheet),
4683
4752
  defaultColWidthPx,
@@ -4696,17 +4765,17 @@ function buildSheetList(nextWorkbook, structureAssets, showHiddenSheets = false)
4696
4765
  name: worksheet.name,
4697
4766
  visibility,
4698
4767
  namedCellStyleByName: structureAssets?.namedCellStyleByName ?? {},
4699
- rowCount: Math.max(0, maxRow + 1 - hiddenRows.length),
4768
+ rowCount: visibleRows.length,
4700
4769
  rowHeightOverridesPx: sheetState?.rowHeightOverridesPx ?? {},
4701
- rowHeights: [],
4770
+ rowHeights: visibleRows.map(resolveRowHeightPx),
4702
4771
  rowStyleIds: sheetState?.rowStyleIds ?? {},
4703
4772
  showGridLines: sheetState?.showGridLines ?? true,
4704
4773
  sparklines: sheetState?.sparklines ?? [],
4705
4774
  styleById: structureAssets?.styleById ?? {},
4706
4775
  tableStyleByName: structureAssets?.tableStyleByName ?? {},
4707
4776
  themePalette: structureAssets?.themePalette ?? { colorsByIndex: {} },
4708
- visibleCols: [],
4709
- visibleRows: [],
4777
+ visibleCols,
4778
+ visibleRows,
4710
4779
  workbookSheetIndex: index,
4711
4780
  zoomScale: resolveWorksheetZoomScale(worksheet, sheetState)
4712
4781
  });
@@ -4823,11 +4892,12 @@ async function loadWorkbook(buffer, skipXmlParsing = false, showHiddenSheets = f
4823
4892
  }
4824
4893
  const nextWorkbook = activeWorkbook;
4825
4894
  const shouldUseFastStructureParse = bytes.byteLength >= FAST_STRUCTURE_PARSE_THRESHOLD_BYTES && totalFormulas <= FORMULA_COUNT_THRESHOLD;
4826
- const structureAssets = effectiveSkipXmlParsing || shouldUseFastStructureParse ? null : parseWorkbookStructureAssets(bytes, {
4895
+ const structureAssets = effectiveSkipXmlParsing || shouldUseFastStructureParse || !canParseXmlInWorker() ? null : parseWorkbookStructureAssets(bytes, {
4827
4896
  includeCachedFormulaValues: true
4828
4897
  });
4898
+ const sheetLayoutStates = structureAssets ? void 0 : parseWorkerSheetLayoutAssets(bytes, nextWorkbook.sheetCount);
4829
4899
  workbook = nextWorkbook;
4830
- sheets = buildSheetList(nextWorkbook, structureAssets, showHiddenSheets);
4900
+ sheets = buildSheetList(nextWorkbook, structureAssets, sheetLayoutStates, showHiddenSheets);
4831
4901
  tablesByWorkbookSheetIndex = Array.from(
4832
4902
  { length: nextWorkbook.sheetCount },
4833
4903
  (_, workbookSheetIndex) => mapWorksheetTables(nextWorkbook.getSheet(workbookSheetIndex))
@@ -4839,7 +4909,7 @@ async function loadWorkbook(buffer, skipXmlParsing = false, showHiddenSheets = f
4839
4909
  const hasModernCharts = Array.isArray(worksheet.chartsEx) && worksheet.chartsEx.length > 0;
4840
4910
  return hasClassicCharts || hasModernCharts;
4841
4911
  }).some(Boolean);
4842
- const chartStyleAssets = effectiveSkipXmlParsing || !hasCharts ? null : parseWorkbookChartStyleAssets(bytes);
4912
+ const chartStyleAssets = effectiveSkipXmlParsing || !hasCharts || !canParseXmlInWorker() ? null : parseWorkbookChartStyleAssets(bytes);
4843
4913
  const chartAssets = loadWorkbookChartAssets(
4844
4914
  nextWorkbook,
4845
4915
  chartStyleAssets,
@@ -4874,7 +4944,7 @@ async function parseCharts(buffer, skipXmlParsing = false, showHiddenSheets = fa
4874
4944
  }
4875
4945
  const nextWorkbook = activeWorkbook;
4876
4946
  const visibleSheetIndexByWorkbookSheetIndex = buildVisibleSheetIndexByWorkbookSheetIndex(nextWorkbook, showHiddenSheets);
4877
- const chartStyleAssets = effectiveSkipXmlParsing ? null : parseWorkbookChartStyleAssets(bytes);
4947
+ const chartStyleAssets = effectiveSkipXmlParsing || !canParseXmlInWorker() ? null : parseWorkbookChartStyleAssets(bytes);
4878
4948
  const chartAssets = loadWorkbookChartAssets(
4879
4949
  nextWorkbook,
4880
4950
  chartStyleAssets,