@bendyline/squisq-formats 2.5.1 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/NOTICE.md +10 -9
  2. package/dist/{chunk-TVUX3RUC.js → chunk-2OCP46K5.js} +10 -3
  3. package/dist/{chunk-2LT3JL7U.js → chunk-3ITGQRL5.js} +8 -8
  4. package/dist/{chunk-FMQWNPCV.js → chunk-AGGNLRHV.js} +6 -6
  5. package/dist/{chunk-AONELFLA.js → chunk-B7GEAZBI.js} +6 -1
  6. package/dist/chunk-CKSTGNVZ.js +724 -0
  7. package/dist/chunk-DXYWKZ52.js +57 -0
  8. package/dist/chunk-FLR2ARKC.js +240 -0
  9. package/dist/{chunk-5JQ5NDRC.js → chunk-JPU5GPGG.js} +64 -12
  10. package/dist/{chunk-RX55T5HO.js → chunk-OBADJV7C.js} +136 -415
  11. package/dist/{chunk-T4PX33AG.js → chunk-POO3PJFH.js} +23 -3
  12. package/dist/{chunk-AD2WT564.js → chunk-Q77KNJIN.js} +45 -0
  13. package/dist/{chunk-6RQOV3B3.js → chunk-VPWPEMZJ.js} +1 -1
  14. package/dist/{chunk-FIOSE4BO.js → chunk-XJNOZTAY.js} +6 -6
  15. package/dist/csv/index.d.ts +67 -1
  16. package/dist/csv/index.js +10 -3
  17. package/dist/data/index.d.ts +78 -0
  18. package/dist/data/index.js +30 -0
  19. package/dist/docx/index.js +3 -3
  20. package/dist/epub/index.js +4 -4
  21. package/dist/{export-Boq78GMq.d.ts → export-6iQXd-lQ.d.ts} +98 -2
  22. package/dist/html/index.d.ts +2 -8
  23. package/dist/html/index.js +3 -3
  24. package/dist/{images-ESPQKVTW.js → images-JLBFCDD4.js} +1 -1
  25. package/dist/{import-B0gBYUmd.d.ts → import-D59rxNTj.d.ts} +11 -3
  26. package/dist/index.d.ts +3 -3
  27. package/dist/index.js +29 -26
  28. package/dist/infer/index.js +6 -6
  29. package/dist/materialize-A34OZGEU.js +11 -0
  30. package/dist/outside-in/index.d.ts +4 -4
  31. package/dist/outside-in/index.js +2 -2
  32. package/dist/pdf/index.js +2 -2
  33. package/dist/pptx/index.js +3 -3
  34. package/dist/registry/index.d.ts +4 -4
  35. package/dist/registry/index.js +1 -1
  36. package/dist/{types-bwP9PBSk.d.ts → types-BD23kHNG.d.ts} +5 -5
  37. package/dist/xlsx/index.d.ts +85 -4
  38. package/dist/xlsx/index.js +21 -4
  39. package/package.json +17 -2
  40. package/dist/{chunk-KMBBO5H7.js → chunk-7DQP2I57.js} +4 -4
  41. package/dist/{chunk-M7XPXGXW.js → chunk-ROF7SSQP.js} +3 -3
@@ -1,23 +1,9 @@
1
1
  import {
2
- extractPlainText,
3
- inlineToPlainText
4
- } from "./chunk-AVOZAKGP.js";
2
+ planDataSidecar
3
+ } from "./chunk-DXYWKZ52.js";
5
4
  import {
6
- createPackage
7
- } from "./chunk-ILCJ3WFD.js";
8
- import {
9
- escapeXml,
10
- xmlDeclaration
11
- } from "./chunk-JU2RHXUB.js";
12
- import {
13
- CONTENT_TYPE_XLSX_STYLES,
14
- CONTENT_TYPE_XLSX_WORKBOOK,
15
- CONTENT_TYPE_XLSX_WORKSHEET,
16
5
  NS_R,
17
6
  NS_SML,
18
- REL_OFFICE_DOCUMENT,
19
- REL_STYLES,
20
- REL_WORKSHEET,
21
7
  baseDirOf,
22
8
  getPartRelationships,
23
9
  getPartXml,
@@ -25,9 +11,6 @@ import {
25
11
  requireMainPartPath
26
12
  } from "./chunk-S5PCVMKU.js";
27
13
 
28
- // src/xlsx/index.ts
29
- import { markdownToDoc } from "@bendyline/squisq/doc";
30
-
31
14
  // src/xlsx/cells.ts
32
15
  var MAX_COL_INDEX = 16383;
33
16
  var MAX_ROW_INDEX = 1048575;
@@ -495,6 +478,8 @@ function gridToTables(sheet, grid, merges = [], options = {}) {
495
478
  }
496
479
 
497
480
  // src/xlsx/import.ts
481
+ import { stringifyMarkdown } from "@bendyline/squisq/markdown";
482
+ import { MemoryContentContainer } from "@bendyline/squisq/storage";
498
483
  var XLSX_MAIN_PART = "xl/workbook.xml";
499
484
  function attrNS(el, ns, local, fallback) {
500
485
  return el.getAttributeNS(ns, local) ?? el.getAttribute(fallback);
@@ -508,7 +493,7 @@ function resolveTarget(baseDir, target) {
508
493
  }
509
494
  return stack.join("/");
510
495
  }
511
- async function readWorkbook(pkg, mainPart) {
496
+ async function listSheetParts(pkg, mainPart) {
512
497
  const wb = await getPartXml(pkg, mainPart);
513
498
  if (!wb) {
514
499
  throw new Error(`Invalid XLSX package: workbook part "${mainPart}" could not be parsed.`);
@@ -524,11 +509,22 @@ async function readWorkbook(pkg, mainPart) {
524
509
  const target = rid ? relById.get(rid) : void 0;
525
510
  if (target) out.push({ name, path: resolveTarget(baseDirOf(mainPart), target) });
526
511
  }
512
+ return out;
513
+ }
514
+ async function readWorkbook(pkg, mainPart) {
515
+ const wb = await getPartXml(pkg, mainPart);
516
+ if (!wb) {
517
+ throw new Error(`Invalid XLSX package: workbook part "${mainPart}" could not be parsed.`);
518
+ }
519
+ const sheets = await listSheetParts(pkg, mainPart);
527
520
  const workbookPr = wb.getElementsByTagNameNS(NS_SML, "workbookPr")[0];
528
521
  const date1904Value = workbookPr?.getAttribute("date1904");
522
+ const calcPr = wb.getElementsByTagNameNS(NS_SML, "calcPr")[0];
523
+ const fullCalcValue = calcPr?.getAttribute("fullCalcOnLoad");
529
524
  return {
530
- sheets: out,
531
- date1904: date1904Value === "1" || date1904Value === "true"
525
+ sheets,
526
+ date1904: date1904Value === "1" || date1904Value === "true",
527
+ fullCalcOnLoad: fullCalcValue === "1" || fullCalcValue === "true"
532
528
  };
533
529
  }
534
530
  function isPhonetic(el, root) {
@@ -698,28 +694,32 @@ function formattedNumberText(raw, style, date1904) {
698
694
  function readFormula(cell, row, col, ctx) {
699
695
  const fEls = cell.getElementsByTagNameNS(NS_SML, "f");
700
696
  const f = fEls.length ? fEls[0] : null;
701
- if (!f) return "";
697
+ if (!f) return { text: "" };
702
698
  const text = (f.textContent ?? "").trim();
703
- if (f.getAttribute("t") !== "shared") return text;
699
+ if (f.getAttribute("t") !== "shared") return { text };
704
700
  const si = f.getAttribute("si");
705
- if (si === null) return text;
701
+ if (si === null) return { text };
706
702
  if (text !== "") {
707
703
  ctx.sharedFormulas.set(si, { text, row, col });
708
- return text;
704
+ return { text, sharedRole: "master" };
709
705
  }
710
706
  const master = ctx.sharedFormulas.get(si);
711
- if (!master) return "";
707
+ if (!master) return { text: "", sharedRole: "follower" };
712
708
  try {
713
- return translateFormula(master.text, row - master.row, col - master.col);
709
+ return {
710
+ text: translateFormula(master.text, row - master.row, col - master.col),
711
+ sharedRole: "follower"
712
+ };
714
713
  } catch {
715
- return "";
714
+ return { text: "", sharedRole: "follower" };
716
715
  }
717
716
  }
718
717
  function readCell(cell, row, col, ctx) {
719
- const formula = readFormula(cell, row, col, ctx);
718
+ const { text: formula, sharedRole } = readFormula(cell, row, col, ctx);
720
719
  const withFormula = (text2, kind2, value) => {
721
720
  const out = { text: text2, kind: text2 === "" ? "empty" : kind2 };
722
721
  if (formula !== "") out.formula = formula;
722
+ if (sharedRole !== void 0) out.sharedFormulaRole = sharedRole;
723
723
  if (value !== void 0 && out.kind !== "empty") out.value = value;
724
724
  return out;
725
725
  };
@@ -866,7 +866,50 @@ async function xlsxToTables(data, options = {}) {
866
866
  }
867
867
  return out;
868
868
  }
869
+ async function xlsxToCellGrids(data, options = {}) {
870
+ const pkg = await openPackage(data, options);
871
+ const mainPart = requireMainPartPath(pkg, XLSX_MAIN_PART, "XLSX");
872
+ const [{ sheets, date1904, fullCalcOnLoad }, shared, styles] = await Promise.all([
873
+ readWorkbook(pkg, mainPart),
874
+ readSharedStrings(pkg),
875
+ readCellStyles(pkg)
876
+ ]);
877
+ let selected = sheets;
878
+ if (options.sheet !== void 0) {
879
+ const picked = typeof options.sheet === "number" ? sheets[options.sheet] : sheets.find((s) => s.name === options.sheet);
880
+ selected = picked ? [picked] : [];
881
+ }
882
+ const out = [];
883
+ for (const sheet of selected) {
884
+ const { cells, merges } = await sheetToCells(pkg, sheet.path, shared, styles, date1904);
885
+ out.push({ name: sheet.name, cells, merges });
886
+ }
887
+ return { sheets: out, date1904, fullCalcOnLoad };
888
+ }
869
889
  async function xlsxToMarkdownDoc(data, options = {}) {
890
+ return workbookToMarkdown(data, options, void 0);
891
+ }
892
+ function shouldSpillRegion(spill, rect, hasHeader) {
893
+ if (spill.mode === "always") return true;
894
+ const height = rect.bottom - rect.top + 1;
895
+ const width = rect.right - rect.left + 1;
896
+ const dataRows = height - (hasHeader ? 1 : 0);
897
+ return dataRows > spill.maxInlineRows || height * width > spill.maxInlineCells;
898
+ }
899
+ function shouldSpillGrid(spill, cells) {
900
+ if (spill.mode === "always") return true;
901
+ const width = cells.reduce((max, row) => Math.max(max, row.length), 0);
902
+ return cells.length - 1 > spill.maxInlineRows || cells.length * width > spill.maxInlineCells;
903
+ }
904
+ function sidecarLinkParagraph(spill) {
905
+ return {
906
+ type: "paragraph",
907
+ children: [
908
+ { type: "link", url: spill.src, children: [{ type: "text", value: spill.fileName }] }
909
+ ]
910
+ };
911
+ }
912
+ async function workbookToMarkdown(data, options, spill) {
870
913
  const pkg = await openPackage(data, options);
871
914
  const mainPart = requireMainPartPath(pkg, XLSX_MAIN_PART, "XLSX");
872
915
  const [{ sheets, date1904 }, shared, styles] = await Promise.all([
@@ -890,6 +933,14 @@ async function xlsxToMarkdownDoc(data, options = {}) {
890
933
  }
891
934
  if (cells.length === 0) continue;
892
935
  if (!useRegions) {
936
+ if (spill && shouldSpillGrid(spill, cells)) {
937
+ children.push(
938
+ annotatedHeading(single ? 1 : 2, sheet.name, { src: spill.src, sheet: sheet.name }),
939
+ sidecarLinkParagraph(spill)
940
+ );
941
+ spill.used = true;
942
+ continue;
943
+ }
893
944
  children.push(cellsToTable(cells));
894
945
  continue;
895
946
  }
@@ -900,6 +951,14 @@ async function xlsxToMarkdownDoc(data, options = {}) {
900
951
  });
901
952
  for (const warning of plan.warnings) console.warn(`XLSX import: ${sheet.name}: ${warning}`);
902
953
  if (plan.degraded || plan.regions.length === 0 && plan.strays.length === 0) {
954
+ if (spill && shouldSpillGrid(spill, cells)) {
955
+ children.push(
956
+ annotatedHeading(single ? 1 : 2, sheet.name, { src: spill.src, sheet: sheet.name }),
957
+ sidecarLinkParagraph(spill)
958
+ );
959
+ spill.used = true;
960
+ continue;
961
+ }
903
962
  children.push(cellsToTable(cells));
904
963
  continue;
905
964
  }
@@ -908,6 +967,21 @@ async function xlsxToMarkdownDoc(data, options = {}) {
908
967
  const slice = sliceRect(cells, region.rect, EMPTY_CELL);
909
968
  const anchor = formatCellRef(region.rect.top, region.rect.left);
910
969
  const title = region.title ?? `${sheet.name} \u2014 ${anchor}`;
970
+ const hasHeaderRow = inferHeader(slice);
971
+ if (spill && shouldSpillRegion(spill, region.rect, hasHeaderRow)) {
972
+ children.push(
973
+ annotatedHeading(depth, title, {
974
+ src: spill.src,
975
+ sheet: sheet.name,
976
+ anchor,
977
+ ...hasHeaderRow ? {} : { headerRow: "false" },
978
+ ...region.titleCell ? { titleAnchor: formatCellRef(region.titleCell.row, region.titleCell.col) } : {}
979
+ }),
980
+ sidecarLinkParagraph(spill)
981
+ );
982
+ spill.used = true;
983
+ continue;
984
+ }
911
985
  children.push(
912
986
  annotatedHeading(depth, title, {
913
987
  sheet: sheet.name,
@@ -916,7 +990,7 @@ async function xlsxToMarkdownDoc(data, options = {}) {
916
990
  // says. (`headerRow`, not `header` — `dataTable` already declares a
917
991
  // `headers` input, and two params one letter apart in the same
918
992
  // annotation is a trap for anyone reading or editing the markdown.)
919
- ...inferHeader(slice) ? {} : { headerRow: "false" },
993
+ ...hasHeaderRow ? {} : { headerRow: "false" },
920
994
  // A caption promoted into the heading has left its cell behind;
921
995
  // record where, so the reverse path can put the text back.
922
996
  ...region.titleCell ? { titleAnchor: formatCellRef(region.titleCell.row, region.titleCell.col) } : {}
@@ -947,396 +1021,43 @@ async function xlsxToMarkdownDoc(data, options = {}) {
947
1021
  }
948
1022
  return { type: "document", children };
949
1023
  }
950
-
951
- // src/xlsx/export.ts
952
- import { docToMarkdown } from "@bendyline/squisq/doc";
953
-
954
- // src/xlsx/workbookPlan.ts
955
- function hasRichCellContent(nodes) {
956
- return nodes.some(
957
- (n) => n.type === "superscript" || n.type === "subscript" || "children" in n && Array.isArray(n.children) && hasRichCellContent(n.children)
958
- );
959
- }
960
- var KEY_STRIDE = MAX_COL_INDEX + 1;
961
- function cellKey(row, col) {
962
- return row * KEY_STRIDE + col;
963
- }
964
- function keyRow(key) {
965
- return Math.floor(key / KEY_STRIDE);
966
- }
967
- function keyCol(key) {
968
- return key - keyRow(key) * KEY_STRIDE;
969
- }
970
- function tableToGrid(table) {
971
- return table.children.map(
972
- (row) => row.children.map((cell) => extractPlainText(cell.children))
973
- );
974
- }
975
- function tableToRichGrid(table) {
976
- return table.children.map(
977
- (row) => row.children.map((cell) => hasRichCellContent(cell.children) ? cell.children : void 0)
978
- );
979
- }
980
- function readRole(raw) {
981
- return raw === "formulas" || raw === "loose" ? raw : "values";
982
- }
983
- function collectEntries(nodes) {
984
- const entries = [];
985
- let pending = null;
986
- for (const node of nodes) {
987
- if (node.type === "heading") {
988
- pending = node;
989
- continue;
990
- }
991
- if (node.type !== "table") continue;
992
- const params = pending?.templateAnnotation?.params ?? {};
993
- const sheetKey = typeof params.sheet === "string" && params.sheet !== "" ? params.sheet : null;
994
- entries.push({
995
- table: node,
996
- headingText: pending ? extractPlainText(pending.children) : "",
997
- params,
998
- sheetKey,
999
- role: readRole(params.role)
1000
- });
1001
- pending = null;
1002
- }
1003
- return entries;
1004
- }
1005
- function groupEntries(entries) {
1006
- const groups = [];
1007
- const bySheet = /* @__PURE__ */ new Map();
1008
- for (const entry of entries) {
1009
- if (entry.sheetKey !== null) {
1010
- let group = bySheet.get(entry.sheetKey);
1011
- if (!group) {
1012
- group = { candidate: entry.sheetKey, entries: [], anchored: true };
1013
- bySheet.set(entry.sheetKey, group);
1014
- groups.push(group);
1015
- }
1016
- group.entries.push(entry);
1017
- continue;
1018
- }
1019
- groups.push({ candidate: entry.headingText || null, entries: [entry], anchored: false });
1020
- }
1021
- return groups;
1022
- }
1023
- function place(cells, row, col, cell, clashes) {
1024
- const key = cellKey(row, col);
1025
- if (cells.has(key)) clashes.push(formatCellRef(row, col));
1026
- cells.set(key, cell);
1027
- }
1028
- function overlayFormula(cells, row, col, formula) {
1029
- const key = cellKey(row, col);
1030
- const existing = cells.get(key);
1031
- cells.set(key, { text: existing?.text ?? "", formula });
1032
- }
1033
- function formulaSource(raw) {
1034
- const trimmed = raw.trim();
1035
- return trimmed.startsWith("=") ? trimmed.slice(1) : trimmed;
1036
- }
1037
- function placeValues(entry, cells, warnings, sheetName, clashes) {
1038
- const grid = tableToGrid(entry.table);
1039
- const richGrid = tableToRichGrid(entry.table);
1040
- const anchorRaw = entry.params.anchor ?? "A1";
1041
- let anchor = parseCellRef(anchorRaw);
1042
- if (!anchor) {
1043
- warnings.push(
1044
- `Sheet "${sheetName}": anchor "${anchorRaw}" is not a valid cell reference; placed at A1 instead.`
1045
- );
1046
- anchor = { row: 0, col: 0 };
1047
- }
1048
- const height = grid.length;
1049
- const width = grid.reduce((m, r) => Math.max(m, r.length), 0);
1050
- if (anchor.row + height - 1 > MAX_ROW_INDEX || anchor.col + width - 1 > MAX_COL_INDEX) {
1051
- warnings.push(
1052
- `Sheet "${sheetName}": a table anchored at ${anchorRaw} runs past the end of the sheet; placed at A1 instead.`
1053
- );
1054
- anchor = { row: 0, col: 0 };
1055
- }
1056
- const titleRef = entry.params.titleAnchor;
1057
- if (titleRef !== void 0 && entry.headingText !== "") {
1058
- const at = parseCellRef(titleRef);
1059
- if (at) place(cells, at.row, at.col, { text: entry.headingText }, clashes);
1060
- }
1061
- for (let r = 0; r < grid.length; r++) {
1062
- const row = grid[r];
1063
- for (let c = 0; c < row.length; c++) {
1064
- const text = row[c];
1065
- if (text === "") continue;
1066
- const rich = richGrid[r]?.[c];
1067
- place(cells, anchor.row + r, anchor.col + c, rich ? { text, rich } : { text }, clashes);
1068
- }
1069
- }
1070
- }
1071
- function placeFormulas(entry, cells, warnings, sheetName) {
1072
- const grid = tableToGrid(entry.table);
1073
- if (grid.length < 2) return;
1074
- const anchorRaw = entry.params.anchor ?? "A1";
1075
- const anchor = parseCellRef(anchorRaw);
1076
- if (!anchor) {
1077
- warnings.push(
1078
- `Sheet "${sheetName}": formulas block anchor "${anchorRaw}" is not a valid cell reference; skipped.`
1079
- );
1080
- return;
1081
- }
1082
- const columns = grid[0].map((letters) => {
1083
- const trimmed = letters.trim();
1084
- if (!/^[A-Za-z]{1,3}$/.test(trimmed)) return -1;
1085
- const col = columnIndexFromLetters(trimmed);
1086
- return col >= 0 && col <= MAX_COL_INDEX ? col : -1;
1087
- });
1088
- for (let r = 1; r < grid.length; r++) {
1089
- const row = grid[r];
1090
- for (let c = 0; c < row.length; c++) {
1091
- const raw = row[c];
1092
- if (raw.trim() === "") continue;
1093
- const mapped = columns[c];
1094
- const col = mapped !== void 0 && mapped >= 0 ? mapped : anchor.col + c;
1095
- const targetRow = anchor.row + r - 1;
1096
- if (targetRow > MAX_ROW_INDEX) continue;
1097
- overlayFormula(cells, targetRow, col, formulaSource(raw));
1098
- }
1099
- }
1100
- }
1101
- function placeLoose(entry, cells, warnings, sheetName, clashes) {
1102
- const grid = tableToGrid(entry.table);
1103
- const richGrid = tableToRichGrid(entry.table);
1104
- let skipped = 0;
1105
- for (let r = 1; r < grid.length; r++) {
1106
- const row = grid[r];
1107
- const ref = (row[0] ?? "").trim();
1108
- if (ref === "") continue;
1109
- const at = parseCellRef(ref);
1110
- if (!at) {
1111
- skipped++;
1112
- continue;
1113
- }
1114
- const text = row[1] ?? "";
1115
- const formula = formulaSource(row[2] ?? "");
1116
- const rich = richGrid[r]?.[1];
1117
- const planned = { text };
1118
- if (formula !== "") planned.formula = formula;
1119
- if (rich) planned.rich = rich;
1120
- place(cells, at.row, at.col, planned, clashes);
1121
- }
1122
- if (skipped > 0) {
1123
- warnings.push(
1124
- `Sheet "${sheetName}": ${skipped} loose-cell row(s) had an invalid cell reference and were skipped.`
1125
- );
1126
- }
1127
- }
1128
- function planWorkbook(doc, options) {
1129
- const warnings = [];
1130
- const groups = groupEntries(collectEntries(doc.children));
1131
- const used = /* @__PURE__ */ new Set();
1132
- const sheets = [];
1133
- groups.forEach((group, index) => {
1134
- const fallback = `${options.sheetNamePrefix}${index + 1}`;
1135
- const name = options.sanitize(group.candidate ?? fallback, used, fallback);
1136
- const cells = /* @__PURE__ */ new Map();
1137
- const clashes = [];
1138
- for (const entry of group.entries) {
1139
- if (entry.role === "values") placeValues(entry, cells, warnings, name, clashes);
1140
- }
1141
- for (const entry of group.entries) {
1142
- if (entry.role === "formulas") placeFormulas(entry, cells, warnings, name);
1143
- }
1144
- for (const entry of group.entries) {
1145
- if (entry.role === "loose") placeLoose(entry, cells, warnings, name, clashes);
1146
- }
1147
- if (clashes.length > 0) {
1148
- const shown = clashes.slice(0, 5).join(", ");
1149
- const rest = clashes.length > 5 ? ", and more" : "";
1150
- warnings.push(
1151
- `Sheet "${name}": ${clashes.length} overlapping cell(s) (${shown}${rest}); the later block won.`
1152
- );
1153
- }
1154
- sheets.push({ name, cells, anchored: group.anchored });
1155
- });
1156
- let cellCount = 0;
1157
- for (const sheet of sheets) cellCount += sheet.cells.size;
1158
- return { sheets, warnings, cellCount };
1159
- }
1160
-
1161
- // src/xlsx/export.ts
1162
- var NUMERIC_RE = /^-?\d+(\.\d+)?$/;
1163
- function isSafeNumericCell(value) {
1164
- if (!NUMERIC_RE.test(value)) return false;
1165
- const unsigned = value.startsWith("-") ? value.slice(1) : value;
1166
- const [integer] = unsigned.split(".");
1167
- if (integer.length > 1 && integer.startsWith("0")) return false;
1168
- const significantDigits = unsigned.replace(".", "").replace(/^0+/, "");
1169
- if (significantDigits.length > 15) return false;
1170
- return Number.isFinite(Number(value));
1171
- }
1172
- function cleanSheetName(raw) {
1173
- return raw.replace(/[[\]:*?/\\]/g, "").trim().slice(0, 31).trim().replace(/^'+|'+$/g, "");
1174
- }
1175
- function sanitizeSheetName(candidate, used, fallback) {
1176
- let base = cleanSheetName(candidate) || cleanSheetName(fallback) || "Sheet";
1177
- let name = base;
1178
- let n = 2;
1179
- while (used.has(name.toLocaleLowerCase("en-US"))) {
1180
- const suffix = String(n++);
1181
- base = base.slice(0, 31 - suffix.length);
1182
- name = `${base}${suffix}`;
1183
- }
1184
- used.add(name.toLocaleLowerCase("en-US"));
1185
- return name;
1186
- }
1187
- var ERROR_VALUE_RE = /^#[A-Z0-9_/]+[!?]?$/;
1188
- function cellXml(cell, ref, inferNumericCells) {
1189
- const { text, formula } = cell;
1190
- if (formula !== void 0 && formula !== "") {
1191
- const f = `<f>${escapeXml(formula)}</f>`;
1192
- if (text === "") return `<c r="${ref}">${f}</c>`;
1193
- if (isSafeNumericCell(text)) return `<c r="${ref}">${f}<v>${escapeXml(text)}</v></c>`;
1194
- if (ERROR_VALUE_RE.test(text)) return `<c r="${ref}" t="e">${f}<v>${escapeXml(text)}</v></c>`;
1195
- return `<c r="${ref}" t="str">${f}<v>${escapeXml(text)}</v></c>`;
1196
- }
1197
- if (inferNumericCells && isSafeNumericCell(text)) {
1198
- return `<c r="${ref}"><v>${escapeXml(text)}</v></c>`;
1199
- }
1200
- if (cell.rich) {
1201
- return `<c r="${ref}" t="inlineStr"><is>${richRunsXml(cell.rich)}</is></c>`;
1202
- }
1203
- return `<c r="${ref}" t="inlineStr"><is><t xml:space="preserve">${escapeXml(text)}</t></is></c>`;
1204
- }
1205
- function richRunsXml(nodes) {
1206
- const runs = [];
1207
- const emit = (text, vertAlign) => {
1208
- if (text === "") return;
1209
- const rPr = vertAlign ? `<rPr><vertAlign val="${vertAlign}"/></rPr>` : "";
1210
- runs.push(`<r>${rPr}<t xml:space="preserve">${escapeXml(text)}</t></r>`);
1024
+ var XLSX_MIME = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
1025
+ async function xlsxToContainer(data, options = {}) {
1026
+ const plan = planDataSidecar(options.sourceName, "workbook.xlsx");
1027
+ const mode = options.sidecar ?? "auto";
1028
+ const spill = mode === "never" ? void 0 : {
1029
+ src: plan.sidecarPath,
1030
+ fileName: plan.fileName,
1031
+ mode,
1032
+ maxInlineRows: options.maxInlineRows ?? 100,
1033
+ maxInlineCells: options.maxInlineCells ?? 2e3,
1034
+ used: false
1211
1035
  };
1212
- const walk = (list, vertAlign) => {
1213
- for (const node of list) {
1214
- if (node.type === "superscript" || node.type === "subscript") {
1215
- walk(node.children, node.type === "superscript" ? "superscript" : "subscript");
1216
- } else if ("children" in node && Array.isArray(node.children)) {
1217
- walk(node.children, vertAlign);
1218
- } else {
1219
- emit(inlineToPlainText(node), vertAlign);
1220
- }
1221
- }
1222
- };
1223
- walk(nodes, null);
1224
- return runs.join("");
1225
- }
1226
- function worksheetXml(sheet, inferNumericCells) {
1227
- const keys = [...sheet.cells.keys()].sort((a, b) => a - b);
1228
- const rows = [];
1229
- let maxRow = 0;
1230
- let maxCol = 0;
1231
- let i = 0;
1232
- while (i < keys.length) {
1233
- const rowIdx = keyRow(keys[i]);
1234
- let cellsXml = "";
1235
- while (i < keys.length && keyRow(keys[i]) === rowIdx) {
1236
- const key = keys[i];
1237
- const col = keyCol(key);
1238
- if (col > maxCol) maxCol = col;
1239
- cellsXml += cellXml(
1240
- sheet.cells.get(key),
1241
- `${columnLetter(col)}${rowIdx + 1}`,
1242
- inferNumericCells
1243
- );
1244
- i++;
1245
- }
1246
- if (rowIdx > maxRow) maxRow = rowIdx;
1247
- rows.push(`<row r="${rowIdx + 1}">${cellsXml}</row>`);
1036
+ const markdownDoc = await workbookToMarkdown(data, options, spill);
1037
+ const container = new MemoryContentContainer();
1038
+ await container.writeDocument(stringifyMarkdown(markdownDoc), plan.markdownFilename);
1039
+ if (spill?.used) {
1040
+ const bytes = data instanceof Blob ? await data.arrayBuffer() : data;
1041
+ await container.writeFile(plan.sidecarPath, bytes, XLSX_MIME);
1248
1042
  }
1249
- const dimension = keys.length > 0 ? `A1:${columnLetter(maxCol)}${maxRow + 1}` : "A1";
1250
- return `${xmlDeclaration()}
1251
- <worksheet xmlns="${NS_SML}" xmlns:r="${NS_R}"><dimension ref="${dimension}"/><sheetData>${rows.join("")}</sheetData></worksheet>`;
1252
- }
1253
- function workbookXml(sheets, hasFormulas) {
1254
- const sheetEls = sheets.map(
1255
- (sheet, i) => `<sheet name="${escapeXml(sheet.name)}" sheetId="${i + 1}" r:id="rId${i + 1}"/>`
1256
- ).join("");
1257
- const calcPr = hasFormulas ? `<calcPr calcId="0" fullCalcOnLoad="1"/>` : "";
1258
- return `${xmlDeclaration()}
1259
- <workbook xmlns="${NS_SML}" xmlns:r="${NS_R}"><sheets>${sheetEls}</sheets>${calcPr}</workbook>`;
1260
- }
1261
- function stylesXml() {
1262
- return `${xmlDeclaration()}
1263
- <styleSheet xmlns="${NS_SML}"><fonts count="1"><font><sz val="11"/><name val="Calibri"/></font></fonts><fills count="1"><fill><patternFill patternType="none"/></fill></fills><borders count="1"><border/></borders><cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs><cellXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/></cellXfs></styleSheet>`;
1264
- }
1265
- async function markdownDocToXlsx(doc, options = {}) {
1266
- options.signal?.throwIfAborted();
1267
- const prefix = cleanSheetName(options.sheetNamePrefix ?? "Sheet") || "Sheet";
1268
- const maxCells = options.maxCells ?? 1e5;
1269
- if (!Number.isSafeInteger(maxCells) || maxCells < 0) {
1270
- throw new RangeError("maxCells must be a non-negative safe integer");
1271
- }
1272
- const plan = planWorkbook(doc, { sheetNamePrefix: prefix, sanitize: sanitizeSheetName });
1273
- for (const warning of plan.warnings) options.onWarning?.(warning);
1274
- if (plan.cellCount > maxCells) {
1275
- throw new RangeError(`XLSX export exceeds the ${maxCells}-cell safety limit`);
1276
- }
1277
- let sheets = plan.sheets;
1278
- if (sheets.length === 0) {
1279
- sheets = [
1280
- {
1281
- name: sanitizeSheetName(`${prefix}1`, /* @__PURE__ */ new Set(), "Sheet1"),
1282
- cells: /* @__PURE__ */ new Map(),
1283
- anchored: false
1284
- }
1285
- ];
1286
- }
1287
- const anchored = sheets.some((sheet) => sheet.anchored);
1288
- const inferNumericCells = options.inferNumericCells ?? anchored;
1289
- const hasFormulas = sheets.some((sheet) => {
1290
- for (const cell of sheet.cells.values()) if (cell.formula) return true;
1291
- return false;
1292
- });
1293
- const pkg = createPackage();
1294
- sheets.forEach((sheet, i) => {
1295
- if ((i & 31) === 0) options.signal?.throwIfAborted();
1296
- const sheetPath = `xl/worksheets/sheet${i + 1}.xml`;
1297
- pkg.addPart(sheetPath, worksheetXml(sheet, inferNumericCells), CONTENT_TYPE_XLSX_WORKSHEET);
1298
- pkg.addRelationship("xl/workbook.xml", {
1299
- id: `rId${i + 1}`,
1300
- type: REL_WORKSHEET,
1301
- target: `worksheets/sheet${i + 1}.xml`
1302
- });
1303
- });
1304
- pkg.addPart("xl/styles.xml", stylesXml(), CONTENT_TYPE_XLSX_STYLES);
1305
- pkg.addRelationship("xl/workbook.xml", {
1306
- id: `rId${sheets.length + 1}`,
1307
- type: REL_STYLES,
1308
- target: "styles.xml"
1309
- });
1310
- pkg.addPart("xl/workbook.xml", workbookXml(sheets, hasFormulas), CONTENT_TYPE_XLSX_WORKBOOK);
1311
- pkg.addRelationship("", {
1312
- id: "rId1",
1313
- type: REL_OFFICE_DOCUMENT,
1314
- target: "xl/workbook.xml"
1315
- });
1316
- if (options.title || options.author) {
1317
- pkg.setCoreProperties({
1318
- title: options.title,
1319
- creator: options.author,
1320
- created: (/* @__PURE__ */ new Date()).toISOString(),
1321
- modified: (/* @__PURE__ */ new Date()).toISOString()
1322
- });
1323
- }
1324
- return pkg.toArrayBuffer();
1325
- }
1326
- async function docToXlsx(doc, options) {
1327
- return markdownDocToXlsx(docToMarkdown(doc), options);
1328
- }
1329
-
1330
- // src/xlsx/index.ts
1331
- async function xlsxToDoc(data, options) {
1332
- return markdownToDoc(await xlsxToMarkdownDoc(data, options));
1043
+ return container;
1333
1044
  }
1334
1045
 
1335
1046
  export {
1047
+ MAX_COL_INDEX,
1048
+ MAX_ROW_INDEX,
1049
+ columnLetter,
1050
+ columnIndexFromLetters,
1051
+ colIndex,
1052
+ parseCellRef,
1053
+ formatCellRef,
1054
+ columnLetter2,
1336
1055
  gridToTables,
1056
+ listSheetParts,
1057
+ readCellStyles,
1058
+ numberFormatKind,
1337
1059
  xlsxToTables,
1060
+ xlsxToCellGrids,
1338
1061
  xlsxToMarkdownDoc,
1339
- markdownDocToXlsx,
1340
- docToXlsx,
1341
- xlsxToDoc
1062
+ xlsxToContainer
1342
1063
  };