@office-kit/xlsx 0.9.1 → 0.10.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.
Files changed (61) hide show
  1. package/dist/{cell-style-CN9JXOwm.mjs → cell-style-DuvS_Lsg.mjs} +2 -2
  2. package/dist/cell-style-DuvS_Lsg.mjs.map +1 -0
  3. package/dist/{differential-YEjxNScf.mjs → differential-DvKU8fJt.mjs} +2 -2
  4. package/dist/{differential-YEjxNScf.mjs.map → differential-DvKU8fJt.mjs.map} +1 -1
  5. package/dist/drawing/drawing-xml.d.ts +7 -0
  6. package/dist/drawing/drawing.d.ts +25 -0
  7. package/dist/drawing-BxzLuryn.mjs.map +1 -1
  8. package/dist/io.mjs +2 -2
  9. package/dist/{load-DeAQKGQN.mjs → load-CnPfhGo3.mjs} +93 -26
  10. package/dist/load-CnPfhGo3.mjs.map +1 -0
  11. package/dist/{manifest-CVL1_t0O.mjs → manifest-Cm9K7D62.mjs} +5 -5
  12. package/dist/{manifest-CVL1_t0O.mjs.map → manifest-Cm9K7D62.mjs.map} +1 -1
  13. package/dist/node.mjs +1 -1
  14. package/dist/packaging.mjs +1 -1
  15. package/dist/{parser-nk0Lqmcb.mjs → parser-D3SLaOFe.mjs} +27 -4
  16. package/dist/parser-D3SLaOFe.mjs.map +1 -0
  17. package/dist/{save-OTuS72yI.mjs → save-2moCT3Af.mjs} +68 -34
  18. package/dist/save-2moCT3Af.mjs.map +1 -0
  19. package/dist/schema.mjs +1 -1
  20. package/dist/{serialize-55EnT30e.mjs → serialize-BC2Wu3bR.mjs} +2 -2
  21. package/dist/{serialize-55EnT30e.mjs.map → serialize-BC2Wu3bR.mjs.map} +1 -1
  22. package/dist/{serializer-DQzTTNOS.mjs → serializer-BtO2TrI7.mjs} +21 -9
  23. package/dist/serializer-BtO2TrI7.mjs.map +1 -0
  24. package/dist/streaming.mjs +9 -12
  25. package/dist/streaming.mjs.map +1 -1
  26. package/dist/styles/stylesheet.d.ts +8 -0
  27. package/dist/styles.mjs +3 -3
  28. package/dist/{stylesheet-writer-P1Hxoqzm.mjs → stylesheet-writer-BrOw4jMY.mjs} +133 -51
  29. package/dist/stylesheet-writer-BrOw4jMY.mjs.map +1 -0
  30. package/dist/{table-BifavDVW.mjs → table-1P8we2gS.mjs} +2 -2
  31. package/dist/{table-BifavDVW.mjs.map → table-1P8we2gS.mjs.map} +1 -1
  32. package/dist/{tree-Bbs1C8Rc.mjs → tree-BX-sRRVp.mjs} +3 -1
  33. package/dist/tree-BX-sRRVp.mjs.map +1 -0
  34. package/dist/{utf8-D91g1XTG.mjs → utf8-Tn3nzyik.mjs} +2 -2
  35. package/dist/{utf8-D91g1XTG.mjs.map → utf8-Tn3nzyik.mjs.map} +1 -1
  36. package/dist/workbook/shared-strings.d.ts +15 -5
  37. package/dist/workbook/views.d.ts +7 -0
  38. package/dist/workbook/workbook.d.ts +15 -0
  39. package/dist/{workbook-T1Y3lstQ.mjs → workbook-CARZS94U.mjs} +39 -14
  40. package/dist/workbook-CARZS94U.mjs.map +1 -0
  41. package/dist/workbook.mjs +1 -1
  42. package/dist/workbook.mjs.map +1 -1
  43. package/dist/worksheet/hyperlinks.d.ts +5 -0
  44. package/dist/worksheet/reader.d.ts +7 -2
  45. package/dist/worksheet/worksheet.d.ts +14 -2
  46. package/dist/{worksheet-C6CWgvP5.mjs → worksheet-C5Ensf_j.mjs} +167 -135
  47. package/dist/worksheet-C5Ensf_j.mjs.map +1 -0
  48. package/dist/worksheet.mjs +2 -2
  49. package/dist/xml/parser.d.ts +20 -0
  50. package/dist/xml/serializer.d.ts +8 -0
  51. package/dist/xml.mjs +4 -4
  52. package/package.json +1 -1
  53. package/dist/cell-style-CN9JXOwm.mjs.map +0 -1
  54. package/dist/load-DeAQKGQN.mjs.map +0 -1
  55. package/dist/parser-nk0Lqmcb.mjs.map +0 -1
  56. package/dist/save-OTuS72yI.mjs.map +0 -1
  57. package/dist/serializer-DQzTTNOS.mjs.map +0 -1
  58. package/dist/stylesheet-writer-P1Hxoqzm.mjs.map +0 -1
  59. package/dist/tree-Bbs1C8Rc.mjs.map +0 -1
  60. package/dist/workbook-T1Y3lstQ.mjs.map +0 -1
  61. package/dist/worksheet-C6CWgvP5.mjs.map +0 -1
@@ -7,17 +7,17 @@ import { t as makeChartsheet } from "./chartsheet-C3-tqkPy.mjs";
7
7
  import { o as makeDrawing } from "./drawing-BxzLuryn.mjs";
8
8
  import { n as VALUED_COLOR_MOD_KINDS, r as VALUELESS_COLOR_MOD_KINDS, t as SCHEME_COLOR_NAMES } from "./colors-ovWAwnZI.mjs";
9
9
  import { n as escapeXmlAttr$1, r as escapeXmlText$1, t as escapeCellString } from "./escape-DFTE7ZJc.mjs";
10
- import { H as DRAWING_NS, I as CX_NS, T as CHART_NS, a as findChildren, dt as SHEET_DRAWING_NS, ft as SHEET_MAIN_NS, i as findChild, jt as qname, lt as REL_NS, n as el, w as CHART_DRAWING_NS } from "./tree-Bbs1C8Rc.mjs";
11
- import { t as parseXml } from "./parser-nk0Lqmcb.mjs";
12
- import { n as toTree, r as defineSchema, t as fromTree } from "./serialize-55EnT30e.mjs";
13
- import { t as serializeXml } from "./serializer-DQzTTNOS.mjs";
14
- import { Q as findById } from "./manifest-CVL1_t0O.mjs";
15
- import { $t as makeRowDimension, Cn as parseRange, Dn as rangeToString, Qt as makeColumnDimension, Sn as parseMultiCellRange, Xt as makeSheetView, Zt as makeHyperlink, at as makeWorksheet, bt as setCell, ln as makeColor, qt as makeLegacyComment, xn as multiCellRangeToString } from "./worksheet-C6CWgvP5.mjs";
16
- import { a as makeCfRule, i as makeDataValidation, n as makeTableColumn, o as makeConditionalFormatting, r as makeTableDefinition } from "./table-BifavDVW.mjs";
10
+ import { H as DRAWING_NS, I as CX_NS, T as CHART_NS, a as findChildren, bt as X14_NS, dt as SHEET_DRAWING_NS, ft as SHEET_MAIN_NS, i as findChild, jt as qname, lt as REL_NS, n as el, q as MARKUP_COMPAT_NS, w as CHART_DRAWING_NS } from "./tree-BX-sRRVp.mjs";
11
+ import { t as parseXml } from "./parser-D3SLaOFe.mjs";
12
+ import { n as toTree, r as defineSchema, t as fromTree } from "./serialize-BC2Wu3bR.mjs";
13
+ import { t as serializeXml } from "./serializer-BtO2TrI7.mjs";
14
+ import { Q as findById } from "./manifest-Cm9K7D62.mjs";
15
+ import { $t as makeRowDimension, Jt as makeLegacyComment, Qt as makeColumnDimension, Zt as makeSheetView, an as multiCellRangeToString, at as makeWorksheet, bt as setCell, dn as rangeToString, on as parseMultiCellRange, sn as parseRange, wn as makeColor } from "./worksheet-C5Ensf_j.mjs";
16
+ import { Jt as VERTICAL_ALIGNMENTS, Lt as PATTERN_TYPES, Mt as FONT_SCHEMES, Nt as UNDERLINE_STYLES, Pt as VERT_ALIGNS, Ut as SIDE_STYLES, qt as HORIZONTAL_ALIGNMENTS } from "./cell-style-DuvS_Lsg.mjs";
17
+ import { C as addSharedRichText, O as parseRichString, w as addSharedString } from "./workbook-CARZS94U.mjs";
18
+ import { a as makeCfRule, i as makeDataValidation, n as makeTableColumn, o as makeConditionalFormatting, r as makeTableDefinition } from "./table-1P8we2gS.mjs";
17
19
  import { i as durationToExcel, r as dateToExcel } from "./datetime-B2ySVlXt.mjs";
18
- import { C as addSharedString, O as serializeRichTextRuns } from "./workbook-T1Y3lstQ.mjs";
19
- import { Jt as VERTICAL_ALIGNMENTS, Lt as PATTERN_TYPES, Mt as FONT_SCHEMES, Nt as UNDERLINE_STYLES, Pt as VERT_ALIGNS, Ut as SIDE_STYLES, qt as HORIZONTAL_ALIGNMENTS } from "./cell-style-CN9JXOwm.mjs";
20
- import { n as getDxfs } from "./differential-YEjxNScf.mjs";
20
+ import { n as getDxfs } from "./differential-DvKU8fJt.mjs";
21
21
  //#region src/drawing/dml/effect.ts
22
22
  const PRESET_SHADOW_NAMES = [
23
23
  "shdw1",
@@ -4976,7 +4976,6 @@ const C_TAG = `{${SHEET_MAIN_NS}}c`;
4976
4976
  const V_TAG = `{${SHEET_MAIN_NS}}v`;
4977
4977
  const F_TAG = `{${SHEET_MAIN_NS}}f`;
4978
4978
  const IS_TAG = `{${SHEET_MAIN_NS}}is`;
4979
- const T_TAG$1 = `{${SHEET_MAIN_NS}}t`;
4980
4979
  const MERGE_CELLS_TAG = `{${SHEET_MAIN_NS}}mergeCells`;
4981
4980
  const MERGE_CELL_TAG = `{${SHEET_MAIN_NS}}mergeCell`;
4982
4981
  const SHEET_VIEWS_TAG$1 = `{${SHEET_MAIN_NS}}sheetViews`;
@@ -5016,7 +5015,10 @@ const PROTECTED_RANGE_TAG = `{${SHEET_MAIN_NS}}protectedRange`;
5016
5015
  const SORT_STATE_TAG = `{${SHEET_MAIN_NS}}sortState`;
5017
5016
  const SORT_CONDITION_TAG = `{${SHEET_MAIN_NS}}sortCondition`;
5018
5017
  const PICTURE_TAG$1 = `{${SHEET_MAIN_NS}}picture`;
5018
+ const LEGACY_DRAWING_TAG$1 = `{${SHEET_MAIN_NS}}legacyDrawing`;
5019
5019
  const LEGACY_DRAWING_HF_TAG$1 = `{${SHEET_MAIN_NS}}legacyDrawingHF`;
5020
+ const MC_ALTERNATE_CONTENT_TAG = `{${MARKUP_COMPAT_NS}}AlternateContent`;
5021
+ const MC_CHOICE_TAG = `{${MARKUP_COMPAT_NS}}Choice`;
5020
5022
  const CUSTOM_SHEET_VIEWS_TAG$1 = `{${SHEET_MAIN_NS}}customSheetViews`;
5021
5023
  const CUSTOM_SHEET_VIEW_TAG$1 = `{${SHEET_MAIN_NS}}customSheetView`;
5022
5024
  const OLE_OBJECTS_TAG = `{${SHEET_MAIN_NS}}oleObjects`;
@@ -5176,6 +5178,11 @@ function parseWorksheetXml(bytes, title, ctx) {
5176
5178
  const rId = pictureEl.attrs[`{${REL_NS}}id`];
5177
5179
  if (rId) ws.backgroundPictureRId = rId;
5178
5180
  }
5181
+ const ldEl = findChild(root, LEGACY_DRAWING_TAG$1);
5182
+ if (ldEl) {
5183
+ const rId = ldEl.attrs[`{${REL_NS}}id`];
5184
+ if (rId) ws.legacyDrawingRId = rId;
5185
+ }
5179
5186
  const lhfEl = findChild(root, LEGACY_DRAWING_HF_TAG$1);
5180
5187
  if (lhfEl) {
5181
5188
  const rId = lhfEl.attrs[`{${REL_NS}}id`];
@@ -5186,13 +5193,11 @@ function parseWorksheetXml(bytes, title, ctx) {
5186
5193
  const view = parseCustomSheetView(v);
5187
5194
  if (view) ws.customSheetViews.push(view);
5188
5195
  }
5189
- const ooWrap = findChild(root, OLE_OBJECTS_TAG);
5190
- if (ooWrap) for (const oo of findChildren(ooWrap, OLE_OBJECT_TAG)) {
5196
+ for (const ooWrap of findChildrenThroughMc(root, OLE_OBJECTS_TAG)) for (const oo of findChildrenThroughMc(ooWrap, OLE_OBJECT_TAG)) {
5191
5197
  const parsed = parseOleObject(oo);
5192
5198
  if (parsed) ws.oleObjects.push(parsed);
5193
5199
  }
5194
- const cWrap = findChild(root, CONTROLS_TAG);
5195
- if (cWrap) for (const c of findChildren(cWrap, CONTROL_TAG)) {
5200
+ for (const cWrap of findChildrenThroughMc(root, CONTROLS_TAG)) for (const c of findChildrenThroughMc(cWrap, CONTROL_TAG)) {
5196
5201
  const parsed = parseFormControl(c);
5197
5202
  if (parsed) ws.controls.push(parsed);
5198
5203
  }
@@ -5896,7 +5901,7 @@ function captureWorksheetBodyExtras(root, ws) {
5896
5901
  const afterSheetData = [];
5897
5902
  let seenSheetData = false;
5898
5903
  for (const child of root.children) {
5899
- if (MODELED_WORKSHEET_TAGS.has(child.name)) {
5904
+ if (MODELED_WORKSHEET_TAGS.has(child.name) || wrapsModeledElement(child)) {
5900
5905
  if (child.name === SHEETDATA_TAG) seenSheetData = true;
5901
5906
  continue;
5902
5907
  }
@@ -5908,6 +5913,28 @@ function captureWorksheetBodyExtras(root, ws) {
5908
5913
  afterSheetData
5909
5914
  };
5910
5915
  }
5916
+ /**
5917
+ * Excel 2010+ gates `<controls>` / `<oleObjects>` (and each entry inside them)
5918
+ * behind `<mc:AlternateContent><mc:Choice Requires="x14">` so Excel 2007
5919
+ * skips the `<controlPr>` / `<objectPr>` children it predates. Collect the
5920
+ * named children whether they sit directly under `parent` or inside such a
5921
+ * wrapper. `mc:Fallback` only carries a degraded copy of the same entry, so it
5922
+ * is not consulted.
5923
+ */
5924
+ const findChildrenThroughMc = (parent, name) => {
5925
+ const out = [];
5926
+ for (const child of parent.children) if (child.name === name) out.push(child);
5927
+ else if (child.name === MC_ALTERNATE_CONTENT_TAG) for (const choice of findChildren(child, MC_CHOICE_TAG)) out.push(...findChildren(choice, name));
5928
+ return out;
5929
+ };
5930
+ /** The only worksheet children the reader collects through an `mc:AlternateContent` wrapper. */
5931
+ const MC_WRAPPED_TAGS = /* @__PURE__ */ new Set([OLE_OBJECTS_TAG, CONTROLS_TAG]);
5932
+ /**
5933
+ * True for an `mc:AlternateContent` whose Choice holds one of `MC_WRAPPED_TAGS`
5934
+ * — those are re-emitted from the typed model, so the wrapper must not also
5935
+ * land in bodyExtras. A wrapper around anything else is still a body extra.
5936
+ */
5937
+ const wrapsModeledElement = (node) => node.name === MC_ALTERNATE_CONTENT_TAG && findChildren(node, MC_CHOICE_TAG).some((choice) => choice.children.some((c) => MC_WRAPPED_TAGS.has(c.name)));
5911
5938
  const MODELED_WORKSHEET_TAGS = /* @__PURE__ */ new Set([
5912
5939
  `{${SHEET_MAIN_NS}}dimension`,
5913
5940
  SHEETDATA_TAG,
@@ -5944,7 +5971,7 @@ const MODELED_WORKSHEET_TAGS = /* @__PURE__ */ new Set([
5944
5971
  PHONETIC_PR_TAG,
5945
5972
  DATA_CONSOLIDATE_TAG,
5946
5973
  SCENARIOS_TAG,
5947
- `{${SHEET_MAIN_NS}}legacyDrawing`
5974
+ LEGACY_DRAWING_TAG$1
5948
5975
  ]);
5949
5976
  const PANE_TYPES = [
5950
5977
  "bottomRight",
@@ -6053,7 +6080,7 @@ const readCell = (ws, cNode, coord, ctx, sharedFormulas) => {
6053
6080
  const isNode = findChild(cNode, IS_TAG);
6054
6081
  if (fNode) {
6055
6082
  const cell = setCell(ws, coord.row, coord.col, null, styleId);
6056
- const cachedRaw = vNode?.text;
6083
+ const cachedRaw = vNode === void 0 ? void 0 : vNode.text ?? "";
6057
6084
  const cached = decodeCachedValue(cachedRaw, t);
6058
6085
  handleFormula(cell, fNode, coord, cached, sharedFormulas);
6059
6086
  return;
@@ -6069,7 +6096,10 @@ const readCell = (ws, cNode, coord, ctx, sharedFormulas) => {
6069
6096
  if (!Number.isInteger(idx) || idx < 0) throw new OpenXmlSchemaError(`worksheet: <c t="s"><v>${vNode.text}</v> is not a valid index`);
6070
6097
  const sst = ctx.sharedStrings[idx];
6071
6098
  if (sst === void 0) throw new OpenXmlSchemaError(`worksheet: shared-string index ${idx} out of range [0, ${ctx.sharedStrings.length})`);
6072
- value = sst;
6099
+ value = typeof sst === "string" ? sst : {
6100
+ kind: "rich-text",
6101
+ runs: sst.runs
6102
+ };
6073
6103
  break;
6074
6104
  }
6075
6105
  case "b":
@@ -6099,23 +6129,25 @@ const parseStyleId = (raw) => {
6099
6129
  if (!Number.isInteger(n) || n < 0) throw new OpenXmlSchemaError(`worksheet: <c s="${raw}"> is not a non-negative integer`);
6100
6130
  return n;
6101
6131
  };
6102
- /** Inline-string body — concatenates `<is>/<t>` text runs. Rich runs lose formatting in stage-1. */
6132
+ /**
6133
+ * Inline-string body (`<c t="inlineStr"><is>…</is></c>`). `<is>` is a CT_Rst —
6134
+ * the same shape as an `<si>` in sharedStrings.xml — so it goes through the
6135
+ * same parser, and a body built from `<r>` runs keeps its per-run formatting
6136
+ * instead of collapsing to the concatenated text.
6137
+ */
6103
6138
  const readInlineString = (isNode) => {
6104
6139
  if (!isNode) return "";
6105
- const direct = findChild(isNode, T_TAG$1);
6106
- if (direct) return direct.text ?? "";
6107
- let out = "";
6108
- for (const child of isNode.children) {
6109
- const t = findChild(child, T_TAG$1);
6110
- if (t?.text) out += t.text;
6111
- }
6112
- return out;
6140
+ const entry = parseRichString(isNode);
6141
+ return typeof entry === "string" ? entry : {
6142
+ kind: "rich-text",
6143
+ runs: entry.runs
6144
+ };
6113
6145
  };
6114
6146
  const decodeCachedValue = (raw, t) => {
6115
- if (raw === void 0 || raw === "") return void 0;
6147
+ if (raw === void 0) return void 0;
6116
6148
  switch (t) {
6117
- case "n": return Number.parseFloat(raw);
6118
- case "b": return raw === "1";
6149
+ case "n": return raw === "" ? void 0 : Number.parseFloat(raw);
6150
+ case "b": return raw === "" ? void 0 : raw === "1";
6119
6151
  case "str": return raw;
6120
6152
  case "e": return raw;
6121
6153
  case "s": return raw;
@@ -6394,7 +6426,7 @@ const parseHyperlink = (node, rels) => {
6394
6426
  if (node.attrs["location"]) opts.location = node.attrs["location"];
6395
6427
  if (node.attrs["tooltip"]) opts.tooltip = node.attrs["tooltip"];
6396
6428
  if (node.attrs["display"]) opts.display = node.attrs["display"];
6397
- return makeHyperlink(opts);
6429
+ return opts;
6398
6430
  };
6399
6431
  const maybeRecordRowDimension = (ws, node, rowIdx) => {
6400
6432
  const opts = {};
@@ -6427,7 +6459,8 @@ function worksheetToBytes(ws, ctx) {
6427
6459
  return new TextEncoder().encode(serializeWorksheet(ws, ctx));
6428
6460
  }
6429
6461
  function serializeWorksheet(ws, ctx) {
6430
- const parts = [XML_HEADER$4, `<worksheet xmlns="${SHEET_MAIN_NS}" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">`];
6462
+ const x14Decl = ws.oleObjects.length > 0 || ws.controls.length > 0 ? ` xmlns:mc="${MARKUP_COMPAT_NS}" xmlns:x14="${X14_NS}"` : "";
6463
+ const parts = [XML_HEADER$4, `<worksheet xmlns="${SHEET_MAIN_NS}" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"${x14Decl}>`];
6431
6464
  if (ws.sheetProperties) {
6432
6465
  const sp = serializeSheetProperties(ws.sheetProperties);
6433
6466
  if (sp) parts.push(sp);
@@ -6516,10 +6549,10 @@ function serializeWorksheet(ws, ctx) {
6516
6549
  if (ws.legacyComments.length > 0 && ctx.registerComments) {
6517
6550
  const { vmlRelId } = ctx.registerComments(ws.legacyComments);
6518
6551
  parts.push(`<legacyDrawing r:id="${escapeXmlAttr(vmlRelId)}"/>`);
6519
- }
6552
+ } else if (ws.legacyDrawingRId !== void 0) parts.push(`<legacyDrawing r:id="${escapeXmlAttr(ws.legacyDrawingRId)}"/>`);
6520
6553
  if (ws.legacyDrawingHFRId !== void 0) parts.push(`<legacyDrawingHF r:id="${escapeXmlAttr(ws.legacyDrawingHFRId)}"/>`);
6521
- if (ws.oleObjects.length > 0) parts.push(serializeOleObjects(ws.oleObjects));
6522
- if (ws.controls.length > 0) parts.push(serializeControls(ws.controls));
6554
+ if (ws.oleObjects.length > 0) parts.push(wrapInX14Choice(serializeOleObjects(ws.oleObjects)));
6555
+ if (ws.controls.length > 0) parts.push(wrapInX14Choice(serializeControls(ws.controls)));
6523
6556
  if (ws.backgroundPictureRId !== void 0) parts.push(`<picture r:id="${escapeXmlAttr(ws.backgroundPictureRId)}"/>`);
6524
6557
  if (ws.webPublishItems.length > 0) parts.push(serializeWebPublishItems(ws.webPublishItems));
6525
6558
  if (ws.tables.length > 0 && ctx.registerTable) {
@@ -6577,15 +6610,12 @@ const serializeCell = (cell, ctx) => {
6577
6610
  const ref = getCoordinate(cell);
6578
6611
  const styleAttr = cell.styleId === 0 ? "" : ` s="${cell.styleId}"`;
6579
6612
  const value = cell.value;
6580
- if (value === null) {
6581
- if (cell.styleId === 0) return "";
6582
- return `<c r="${ref}"${styleAttr}/>`;
6583
- }
6613
+ if (value === null) return `<c r="${ref}"${styleAttr}/>`;
6584
6614
  if (typeof value === "object" && value !== null && value.kind === "formula") return serializeFormulaCell(ref, styleAttr, value);
6585
6615
  if (typeof value === "object" && value !== null && value.kind === "error") return `<c r="${ref}"${styleAttr} t="e"><v>${value.code}</v></c>`;
6586
6616
  if (typeof value === "object" && value !== null && value.kind === "rich-text") {
6587
6617
  const runs = value.runs;
6588
- return `<c r="${ref}"${styleAttr} t="inlineStr"><is>${serializeRichTextRuns(runs)}</is></c>`;
6618
+ return `<c r="${ref}"${styleAttr} t="s"><v>${addSharedRichText(ctx.sharedStrings, runs)}</v></c>`;
6589
6619
  }
6590
6620
  if (typeof value === "number") {
6591
6621
  if (!Number.isFinite(value)) throw new OpenXmlSchemaError(`worksheet: cannot serialise non-finite number at ${ref}`);
@@ -6632,7 +6662,8 @@ const serializeFormulaCell = (ref, styleAttr, f) => {
6632
6662
  vEl = `<v>${cached ? "1" : "0"}</v>`;
6633
6663
  } else {
6634
6664
  valueAttr = " t=\"str\"";
6635
- vEl = `<v>${escapeXmlText(escapeCellString(cached))}</v>`;
6665
+ const text = escapeXmlText(escapeCellString(cached));
6666
+ vEl = text.length > 0 ? `<v>${text}</v>` : "<v/>";
6636
6667
  }
6637
6668
  return `<c r="${ref}"${styleAttr}${valueAttr}>${fEl}${vEl}</c>`;
6638
6669
  };
@@ -7232,6 +7263,13 @@ const serializeOleObjects = (objs) => {
7232
7263
  parts.push("</oleObjects>");
7233
7264
  return parts.join("");
7234
7265
  };
7266
+ /**
7267
+ * Excel 2007 predates `<objectPr>` / `<controlPr>`, so Excel 2010+ gates the
7268
+ * whole oleObjects / controls block behind `mc:Choice Requires="x14"`. Mirror
7269
+ * that so older readers skip the block instead of rejecting the part. The
7270
+ * `x14` (and `mc`) prefixes are declared on the worksheet root.
7271
+ */
7272
+ const wrapInX14Choice = (xml) => `<mc:AlternateContent><mc:Choice Requires="x14">${xml}</mc:Choice></mc:AlternateContent>`;
7235
7273
  const serializeControls = (ctrls) => {
7236
7274
  const parts = ["<controls>"];
7237
7275
  for (const c of ctrls) {
@@ -7734,7 +7772,8 @@ const parseAnchor = (node) => {
7734
7772
  content: {
7735
7773
  kind: "unsupported",
7736
7774
  rawTag: child.name
7737
- }
7775
+ },
7776
+ raw: node
7738
7777
  };
7739
7778
  }
7740
7779
  return {
@@ -7742,7 +7781,8 @@ const parseAnchor = (node) => {
7742
7781
  content: {
7743
7782
  kind: "unsupported",
7744
7783
  rawTag: ""
7745
- }
7784
+ },
7785
+ raw: node
7746
7786
  };
7747
7787
  };
7748
7788
  /** Parse a `xl/drawings/drawingN.xml` payload into a Drawing object. */
@@ -7750,12 +7790,46 @@ function parseDrawingXml(bytes) {
7750
7790
  const root = parseXml(bytes);
7751
7791
  if (root.name !== WS_DRAWING_TAG) throw new OpenXmlSchemaError(`parseDrawingXml: root is "${root.name}", expected wsDr`);
7752
7792
  const items = [];
7793
+ const rawChildren = [];
7753
7794
  for (const child of root.children) {
7754
- if (child.name !== ABSOLUTE_ANCHOR_TAG && child.name !== ONE_CELL_ANCHOR_TAG && child.name !== TWO_CELL_ANCHOR_TAG) continue;
7755
- const item = parseAnchor(child);
7756
- if (item) items.push(item);
7795
+ if (child.name === ABSOLUTE_ANCHOR_TAG || child.name === ONE_CELL_ANCHOR_TAG || child.name === TWO_CELL_ANCHOR_TAG) {
7796
+ const item = parseAnchor(child);
7797
+ if (item) items.push(item);
7798
+ continue;
7799
+ }
7800
+ rawChildren.push({
7801
+ beforeItem: items.length,
7802
+ node: child
7803
+ });
7757
7804
  }
7758
- return makeDrawing(items);
7805
+ const drawing = makeDrawing(items);
7806
+ if (rawChildren.length > 0) drawing.rawChildren = rawChildren;
7807
+ return drawing;
7808
+ }
7809
+ const WS_DR_PREFIXES = {
7810
+ [SHEET_DRAWING_NS]: "xdr",
7811
+ [DRAWING_NS]: "a"
7812
+ };
7813
+ /** Re-emit a captured node inline, verbatim. */
7814
+ const serializeRawNode = (node) => new TextDecoder().decode(serializeXml(node, {
7815
+ xmlDeclaration: false,
7816
+ inScopePrefixes: WS_DR_PREFIXES
7817
+ }));
7818
+ /**
7819
+ * Every relationship id referenced inside the drawing's verbatim nodes —
7820
+ * `r:embed` on a picture nested in a group, `r:id` on a shape's hyperlink, and
7821
+ * whatever else sits under an `<mc:AlternateContent>` wrapper. The loader uses
7822
+ * this to carry the matching rels (and their target parts) across a re-save.
7823
+ */
7824
+ function collectRawRelIds(drawing) {
7825
+ const ids = /* @__PURE__ */ new Set();
7826
+ const walk = (node) => {
7827
+ for (const [name, value] of Object.entries(node.attrs)) if (name.startsWith(`{${REL_NS}}`) && value.length > 0) ids.add(value);
7828
+ for (const child of node.children) walk(child);
7829
+ };
7830
+ for (const item of drawing.items) if (item.raw) walk(item.raw);
7831
+ for (const rc of drawing.rawChildren ?? []) walk(rc.node);
7832
+ return ids;
7759
7833
  }
7760
7834
  const serializeMarker = (tag, m) => `<xdr:${tag}><xdr:col>${m.col}</xdr:col><xdr:colOff>${m.colOff}</xdr:colOff><xdr:row>${m.row}</xdr:row><xdr:rowOff>${m.rowOff}</xdr:rowOff></xdr:${tag}>`;
7761
7835
  const serializePictureFrame = (picture, anchorIdx) => {
@@ -7795,6 +7869,7 @@ const serializeChartGraphicFrame = (chart, anchorIdx, ext) => {
7795
7869
  ].join("");
7796
7870
  };
7797
7871
  const serializeAnchor = (item, idx) => {
7872
+ if (item.raw) return serializeRawNode(item.raw);
7798
7873
  const a = item.anchor;
7799
7874
  let body = "";
7800
7875
  let chartExt = {
@@ -7822,10 +7897,16 @@ function drawingToBytes(drawing) {
7822
7897
  }
7823
7898
  function serializeDrawing(drawing) {
7824
7899
  const parts = [XML_HEADER$2, `<xdr:wsDr xmlns:xdr="${SHEET_DRAWING_NS}" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">`];
7900
+ const rawChildren = drawing.rawChildren ?? [];
7901
+ const emitRawBefore = (index) => {
7902
+ for (const rc of rawChildren) if (rc.beforeItem === index) parts.push(serializeRawNode(rc.node));
7903
+ };
7825
7904
  for (let i = 0; i < drawing.items.length; i++) {
7905
+ emitRawBefore(i);
7826
7906
  const item = drawing.items[i];
7827
7907
  if (item) parts.push(serializeAnchor(item, i));
7828
7908
  }
7909
+ emitRawBefore(drawing.items.length);
7829
7910
  parts.push("</xdr:wsDr>");
7830
7911
  return parts.join("");
7831
7912
  }
@@ -8587,7 +8668,7 @@ function buildStylesheetTree(ss) {
8587
8668
  root.children.push(cellStylesEl);
8588
8669
  }
8589
8670
  const dxfs = getDxfs(ss);
8590
- if (dxfs.length > 0) {
8671
+ {
8591
8672
  const dxfsEl = el(DXFS_TAG, { count: String(dxfs.length) });
8592
8673
  for (const dxf of dxfs) {
8593
8674
  const dxfEl = el(DXF_TAG);
@@ -8601,6 +8682,7 @@ function buildStylesheetTree(ss) {
8601
8682
  }
8602
8683
  root.children.push(dxfsEl);
8603
8684
  }
8685
+ if (ss.stylesXmlTail) for (const node of ss.stylesXmlTail) root.children.push(node);
8604
8686
  return root;
8605
8687
  }
8606
8688
  const cellXfToTree = (xf) => {
@@ -8625,6 +8707,6 @@ const cellXfToTree = (xf) => {
8625
8707
  return node;
8626
8708
  };
8627
8709
  //#endregion
8628
- export { isChartExBytes as C, parseChartXml as D, findUserShapesRId as E, chartExToBytes as S, chartToBytes as T, serializeCell as _, parseCommentsXml as a, parseUserShapesXml as b, NumberFormatSchema as c, BorderSchema as d, AlignmentSchema as f, parseChartsheetXml as g, chartsheetToBytes as h, commentsToBytes as i, FontSchema as l, parseDrawingXml as m, parseTableXml as n, placeholderVmlDrawing as o, drawingToBytes as p, tableToBytes as r, ProtectionSchema as s, stylesheetToBytes as t, fillFromTree as u, worksheetToBytes as v, parseChartExXml as w, userShapesToBytes as x, parseWorksheetXml as y };
8710
+ export { chartExToBytes as C, findUserShapesRId as D, chartToBytes as E, parseChartXml as O, userShapesToBytes as S, parseChartExXml as T, parseChartsheetXml as _, parseCommentsXml as a, parseWorksheetXml as b, NumberFormatSchema as c, BorderSchema as d, AlignmentSchema as f, chartsheetToBytes as g, parseDrawingXml as h, commentsToBytes as i, FontSchema as l, drawingToBytes as m, parseTableXml as n, placeholderVmlDrawing as o, collectRawRelIds as p, tableToBytes as r, ProtectionSchema as s, stylesheetToBytes as t, fillFromTree as u, serializeCell as v, isChartExBytes as w, parseUserShapesXml as x, worksheetToBytes as y };
8629
8711
 
8630
- //# sourceMappingURL=stylesheet-writer-P1Hxoqzm.mjs.map
8712
+ //# sourceMappingURL=stylesheet-writer-BrOw4jMY.mjs.map