@office-open/xlsx 0.14.2 → 0.14.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.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { ChartCollection, IMAGE_MEDIA_CONTENT_TYPES, Media, OoxmlMimeType, ParsedArchive, Relationships, TargetModeType, XLSX_PARTS, ZIP_DEFLATE_LEVEL, ZipStreamWriter, appPropertiesDesc, appendContentType, appendOverride, appendRelationship, applyCorePropertiesOverride, assertEncryptedExclusive, buildCorePropertiesXmlString, buildRootRelationships, collectPassthroughParts, compileMapping, contentTypesDesc, convertToEmu, convertToInch, convertToPt, createPacker, customPropertiesDesc, deriveContentTypes, derivePasswordHash, dropDanglingPassthroughRels, encryptedContainerOutput, encryptedContainerStream, getNextRelationshipIndex, isEncryptedContainer, nextNumericId, parseArchive, parseCorePropsElement, parseOnOff, parseVmlShape, partPathToRelsPath, pickNonVisualDrawingProperties, removeOverride, resolveRelationshipTarget, resolverFromRegistry, strFromU8, stringifyVmlShape, stringifyVmlShapeLayout, stringifyVmlShapetype, toJson, toUint8Array, toUint8ArrayAsync, unzipSync, xsdComments, xsdConsolidateFunction, xsdTotalsRowFunction, zipAndConvert } from "@office-open/core";
1
+ import { ChartCollection, IMAGE_MEDIA_CONTENT_TYPES, Media, OoxmlMimeType, ParsedArchive, RELATIONSHIP_TYPES, Relationships, TargetModeType, XLSX_PARTS, ZIP_DEFLATE_LEVEL, ZipStreamWriter, appPropertiesDesc, appendContentType, appendOverride, appendRelationship, applyCorePropertiesOverride, assertEncryptedExclusive, buildCorePropertiesXmlString, buildRootRelationships, collectPassthroughParts, compileMapping, contentTypesDesc, convertToEmu, convertToInch, convertToPt, createPacker, customPropertiesDesc, deriveContentTypes, derivePasswordHash, dropDanglingPassthroughRels, encryptedContainerOutput, encryptedContainerStream, finalizeContentTypes, getNextRelationshipIndex, isEncryptedContainer, nextNumericId, parseArchive, parseCorePropsElement, parseOnOff, parseVmlShape, partPathToRelsPath, pickNonVisualDrawingProperties, removeOverride, resolveRelationshipTarget, resolverFromRegistry, strFromU8, stringifyVmlShape, stringifyVmlShapeLayout, stringifyVmlShapetype, toJson, toUint8Array, toUint8ArrayAsync, unzipSync, xsdComments, xsdConsolidateFunction, xsdTotalsRowFunction, zipAndConvert } from "@office-open/core";
2
2
  import { OOXML_XML_DECLARATION, attr, attrMeasure, attrNum, attrs, children, escapeXml, findChild, selfCloseElement, stringify, stringifyElement, textOf, unescapeXml } from "@office-open/xml";
3
3
  import { blipDesc, buildHyperlinkElement, connectorLockingDesc, createSourceRectangle, graphicFrameLockingDesc, groupShapePropertiesDesc, parseEndpointConnection, parseNonVisualDrawingProperties, pictureLockingDesc, readHyperlink, registerHyperlink, shapeLockingDesc, shapePropertiesDesc, sourceRectangleDesc, stringifyBlipEffects, stringifyEndpointConnection, stringifyNonVisualDrawingProperties, textBodyDesc } from "@office-open/core/drawing";
4
4
  import { buildThemeXml, createThemeXml, createThemeXml as createThemeXml$1, parseShapeStyle, stringifyShapeStyle, themeDesc } from "@office-open/core/theme";
@@ -1687,10 +1687,11 @@ function scanAttrs(src, from, to, visit) {
1687
1687
  i++;
1688
1688
  }
1689
1689
  }
1690
- /** parseOnOff truthiness for on/off attribute values ("1"/"true"/"on"). */
1690
+ /** parseOnOff truthiness for on/off attribute values ("1"/"true"/"on" plus the
1691
+ * single-letter t/f Word 2007 wrote). */
1691
1692
  function isOn(value) {
1692
1693
  const lower = value.length <= 5 ? value.toLowerCase() : value;
1693
- return lower === "1" || lower === "true" || lower === "on";
1694
+ return lower === "1" || lower === "true" || lower === "on" || lower === "t";
1694
1695
  }
1695
1696
  /**
1696
1697
  * Text content of a leaf element's inner XML slice, matching the Element-tree
@@ -9906,9 +9907,9 @@ function parseWorkbookFromXlsx(xlsx) {
9906
9907
  /** Reusable TextEncoder (stateless, safe to share). */
9907
9908
  const encoder$1 = new TextEncoder();
9908
9909
  const WORKSHEET_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
9909
- const WORKSHEET_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet";
9910
- const COMMENTS_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
9911
- const VML_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing";
9910
+ const WORKSHEET_REL_TYPE = RELATIONSHIP_TYPES.worksheet;
9911
+ const COMMENTS_REL_TYPE = RELATIONSHIP_TYPES.comments;
9912
+ const VML_REL_TYPE = RELATIONSHIP_TYPES.vmlDrawing;
9912
9913
  const COMMENTS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml";
9913
9914
  const VML_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.vmlDrawing";
9914
9915
  /**
@@ -10402,17 +10403,16 @@ function appendCommentsToMap(xmlMap, vmlFiles, sheetName, commentOpts) {
10402
10403
  }
10403
10404
  }
10404
10405
  //#endregion
10405
- //#region src/compiler.ts
10406
+ //#region src/compile/sheet-drawing.ts
10406
10407
  /**
10407
- * XLSX Compiler compiles WorkbookOptions into a Zippable structure.
10408
- *
10409
- * Accepts pure JSON WorkbookOptions no intermediate File class needed.
10410
- * Uses XlsxWriteContext for shared state (strings, styles, media, charts).
10408
+ * Worksheet drawing compile phase: images, charts, SmartArt, shapes,
10409
+ * connectors, and groups on a sheet — the drawing part, its relationships,
10410
+ * and the `<drawing>` reference inserted into the sheet XML.
10411
10411
  *
10412
10412
  * @module
10413
10413
  */
10414
- const XML_DECL = OOXML_XML_DECLARATION;
10415
- const IMAGE_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
10414
+ const XML_DECL$2 = OOXML_XML_DECLARATION;
10415
+ const IMAGE_REL$1 = RELATIONSHIP_TYPES.image;
10416
10416
  /**
10417
10417
  * Replace `{fileName}` media placeholders in compiled part XML with
10418
10418
  * relationship ids. Core fill descriptors register blip-fill images through
@@ -10435,592 +10435,171 @@ function bindMediaPlaceholders(xml, media, rels) {
10435
10435
  let rid = ridByName.get(name);
10436
10436
  if (rid === void 0) {
10437
10437
  if (!names.has(name)) return whole;
10438
- rid = `rId${rels.add(IMAGE_REL, `../media/${name}`)}`;
10438
+ rid = `rId${rels.add(IMAGE_REL$1, `../media/${name}`)}`;
10439
10439
  ridByName.set(name, rid);
10440
10440
  }
10441
10441
  return rid;
10442
10442
  });
10443
10443
  }
10444
- /** XLSX part path content type, derived from the part registry. Matches
10445
- * actual file paths, so the dense/sequential xlsx part naming is handled. */
10446
- const XLSX_CONTENT_TYPE_RESOLVER$1 = resolverFromRegistry(XLSX_PARTS);
10447
- /** Chart part user-shapes part relationship (c:userShapes bridge). */
10448
- const CHART_USER_SHAPES_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartUserShapes";
10449
- const PKG_REL_NS = "http://schemas.openxmlformats.org/package/2006/relationships";
10450
- /** Extension MIME for image and VML Default entries. Declared only for
10451
- * extensions actually present in the package. VML backs legacy comment
10452
- * anchors (xl/drawings/vmlDrawing${i}.vml). */
10453
- const XLSX_MEDIA_CONTENT_TYPES = {
10454
- ...IMAGE_MEDIA_CONTENT_TYPES,
10455
- vml: "application/vnd.openxmlformats-officedocument.vmlDrawing"
10456
- };
10457
- /** UTF-8 encoder for serializing the derived [Content_Types].xml into the package. */
10458
- const encoder = new TextEncoder();
10459
- /**
10460
- * Compile workbook options into a Zippable structure.
10461
- */
10462
- function compileWorkbook(options, overrides = [], mediaLevel = 0) {
10463
- const ctx = new XlsxWriteContext();
10464
- const mapping = {};
10465
- if (options.sharedStrings) ctx.sharedStrings.loadEntries(options.sharedStrings);
10466
- const worksheetConfigs = options.worksheets ?? [];
10467
- const chartsheetConfigs = options.chartsheets ?? [];
10468
- const dialogsheetConfigs = options.dialogsheets ?? [];
10469
- const hasCustomProperties = !!options.customProperties && options.customProperties.length > 0;
10470
- mapping["Properties"] = {
10471
- data: XML_DECL + buildCorePropertiesXmlString(options),
10472
- path: "docProps/core.xml"
10473
- };
10474
- mapping["AppProperties"] = {
10475
- data: XML_DECL + (appPropertiesDesc.stringify(options.appProperties ?? {}, ctx) ?? ""),
10476
- path: "docProps/app.xml"
10477
- };
10478
- if (hasCustomProperties) mapping["CustomProperties"] = {
10479
- data: XML_DECL + (customPropertiesDesc.stringify({ properties: options.customProperties ?? [] }, ctx) ?? ""),
10480
- path: "docProps/custom.xml"
10481
- };
10482
- const fileRels = buildRootRelationships("xl/workbook.xml", hasCustomProperties, options.passthroughRelationships);
10483
- mapping["FileRelationships"] = {
10484
- data: XML_DECL + fileRels.serialize(),
10485
- path: "_rels/.rels"
10486
- };
10487
- if (options.dxfs !== void 0) ctx.styles.setDxfs(options.dxfs);
10488
- if (options.fonts !== void 0) ctx.styles.adopt({
10489
- fonts: options.fonts,
10490
- fills: options.fills ?? [],
10491
- borders: options.borders ?? [],
10492
- cellXfs: options.cellXfs ?? [],
10493
- numFmts: options.numFmts
10494
- });
10495
- if (options.colors) ctx.styles.setColors(options.colors);
10496
- if (options.tableStyles) ctx.styles.setTableStyles(options.tableStyles);
10497
- if (options.cellStyles !== void 0) ctx.styles.setCustomCellStyles(options.cellStyles);
10498
- if (options.cellStyleXfs !== void 0) ctx.styles.setCellStyleXfs(options.cellStyleXfs);
10499
- if (options.styleExtensions) ctx.styles.setExtensions(options.styleExtensions);
10500
- buildWorkbookRelationships(ctx.workbookRels, worksheetConfigs.length, chartsheetConfigs.length, dialogsheetConfigs.length);
10501
- const sheets = [];
10502
- let sheetId = 1;
10503
- const nextSheetId = (explicit) => {
10504
- const id = explicit ?? sheetId;
10505
- if (id >= sheetId) sheetId = id + 1;
10506
- return id;
10507
- };
10508
- let rId = 1;
10509
- for (const ws of worksheetConfigs) sheets.push({
10510
- name: ws.name ?? `Sheet${sheetId}`,
10511
- sheetId: nextSheetId(ws.sheetId),
10512
- state: ws.state,
10513
- rId: `rId${rId++}`
10514
- });
10515
- for (const cs of chartsheetConfigs) sheets.push({
10516
- name: cs.name ?? `Chart${sheetId}`,
10517
- sheetId: nextSheetId(cs.sheetId),
10518
- state: cs.state,
10519
- rId: `rId${rId++}`
10520
- });
10521
- for (const ds of dialogsheetConfigs) sheets.push({
10522
- name: ds.name ?? `Dialog${sheetId}`,
10523
- sheetId: nextSheetId(ds.sheetId),
10524
- state: ds.state,
10525
- rId: `rId${rId++}`
10526
- });
10527
- const wsContext = {
10528
- sharedStrings: ctx.sharedStrings,
10529
- styles: ctx.styles
10530
- };
10531
- const state = {
10532
- globalMediaIdx: 0,
10533
- globalChartIdx: 0,
10534
- globalPivotIdx: 0,
10535
- globalPivotCacheIdx: 0,
10536
- globalTableIdx: 0,
10537
- globalQueryTableIdx: 0,
10538
- globalSingleXmlCellsIdx: 0,
10539
- pivotCacheDataMap: /* @__PURE__ */ new Map(),
10540
- calcCells: [],
10541
- allTableParts: []
10542
- };
10543
- for (const [i, wsOpts] of worksheetConfigs.entries()) compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsContext, state, options.passthroughRelationships);
10544
- compileChartsheets(chartsheetConfigs, ctx, mapping, options.passthroughRelationships);
10545
- compileDialogsheets(dialogsheetConfigs, ctx, mapping);
10546
- let rtPivotRefs;
10547
- if (options.pivotCacheRefs && options.pivotCacheRefs.length > 0) {
10548
- rtPivotRefs = [];
10549
- for (const ref of options.pivotCacheRefs) {
10550
- const rel = (options.passthroughRelationships ?? []).find((r) => r.source === "xl/workbook.xml" && r.rId === ref.rId);
10551
- if (!rel) continue;
10552
- let rid = ctx.workbookRels.idOf(rel.relationshipType, rel.target);
10553
- if (rid === void 0) {
10554
- ctx.workbookRels.add(rel.relationshipType, rel.target);
10555
- rid = ctx.workbookRels.idOf(rel.relationshipType, rel.target);
10444
+ /** Compile a sheet's drawing: register image/chart/SmartArt media and
10445
+ * relationships, serialize the drawing part via the descriptor, bind media
10446
+ * and text-hyperlink placeholders, and splice the `<drawing r:id>` element
10447
+ * into the sheet XML at its CT_Worksheet position. Returns the updated XML. */
10448
+ function compileSheetDrawing(wsOpts, i, sheetXml, ctx, mapping, state, wsRels) {
10449
+ const imgOpts = wsOpts.images ?? [];
10450
+ const chartOpts = wsOpts.charts ?? [];
10451
+ const smartArtOpts = wsOpts.smartArts ?? [];
10452
+ const shapeOpts = wsOpts.shapes ?? [];
10453
+ const connectorOpts = wsOpts.connectors ?? [];
10454
+ const groupOpts = wsOpts.groups ?? [];
10455
+ const drawingImages = [];
10456
+ const drawingCharts = [];
10457
+ const drawingSmartArts = [];
10458
+ const drawingRels = new Relationships();
10459
+ let rid = 1;
10460
+ for (const img of imgOpts) {
10461
+ let embedRid;
10462
+ let linkRid;
10463
+ if (img.data !== void 0) {
10464
+ const ext = img.type === "jpg" ? "jpeg" : img.type;
10465
+ const rawBytes = toUint8Array(img.data, { encoding: "base64" });
10466
+ const target = `../media/${ctx.media.addMedia(rawBytes, ext, (fileName) => ({
10467
+ fileName,
10468
+ type: ext,
10469
+ data: rawBytes,
10470
+ width: 0,
10471
+ height: 0
10472
+ })).fileName}`;
10473
+ embedRid = drawingRels.idOf(IMAGE_REL$1, target);
10474
+ if (embedRid === void 0) {
10475
+ drawingRels.addRelationship(rid, IMAGE_REL$1, target);
10476
+ embedRid = `rId${rid}`;
10477
+ rid++;
10556
10478
  }
10557
- if (rid) rtPivotRefs.push({
10558
- cacheId: ref.cacheId,
10559
- rId: rid
10560
- });
10479
+ state.globalMediaIdx++;
10561
10480
  }
10481
+ if (img.sourceUrl !== void 0) {
10482
+ drawingRels.addRelationship(rid, IMAGE_REL$1, img.sourceUrl, "External");
10483
+ linkRid = `rId${rid}`;
10484
+ rid++;
10485
+ }
10486
+ drawingImages.push({
10487
+ ...pickAnchorOptions(img),
10488
+ rId: embedRid ?? "",
10489
+ ...linkRid ? { linkRId: linkRid } : {},
10490
+ ...pickNonVisualDrawingProperties(img),
10491
+ ...img.properties ? { properties: img.properties } : {},
10492
+ ...img.blackWhiteMode ? { blackWhiteMode: img.blackWhiteMode } : {},
10493
+ ...img.sourceRectangle ? { sourceRectangle: img.sourceRectangle } : {},
10494
+ ...img.preferRelativeResize !== void 0 ? { preferRelativeResize: img.preferRelativeResize } : {},
10495
+ ...img.blipEffects ? { blipEffects: img.blipEffects } : {},
10496
+ ...img.useLocalDpi !== void 0 ? { useLocalDpi: img.useLocalDpi } : {},
10497
+ ...img.blipExt !== void 0 ? { blipExt: img.blipExt } : {},
10498
+ ...img.locking ? { locking: img.locking } : {},
10499
+ ...img.hyperlink ? { hyperlink: img.hyperlink } : {},
10500
+ ...img.zOrder !== void 0 ? { zOrder: img.zOrder } : {},
10501
+ ...img.shapeId !== void 0 ? { shapeId: img.shapeId } : {}
10502
+ });
10562
10503
  }
10563
- let wbXml = workbookDesc.stringify({
10564
- sheets,
10565
- pivotCaches: ctx.pivotCacheRefs.length > 0 ? ctx.pivotCacheRefs : rtPivotRefs ?? [],
10566
- protection: options.workbookProtection,
10567
- customViews: options.customWorkbookViews,
10568
- fileRecovery: options.fileRecovery,
10569
- functionGroups: options.functionGroups,
10570
- webPublishing: options.webPublishing,
10571
- fileSharing: options.fileSharing,
10572
- webPublishObjects: options.webPublishObjects,
10573
- definedNames: options.definedNames,
10574
- properties: options.properties,
10575
- calculation: options.calculation,
10576
- oleSize: options.oleSize,
10577
- bookView: options.bookView,
10578
- ...options.absPath !== void 0 ? { absPath: options.absPath } : {},
10579
- ...options.revisionPtr ? { revisionPtr: options.revisionPtr } : {},
10580
- ...options.extensions ? { extensions: options.extensions } : {}
10581
- }, ctx) ?? "";
10582
- if (options.connections && options.connections.length > 0) {
10583
- const cRid = ctx.workbookRels.nextRelationshipId;
10584
- ctx.workbookRels.addRelationship(cRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/connections", "connections.xml");
10585
- mapping["Connections"] = {
10586
- data: XML_DECL + connectionsDesc.stringify({ connections: options.connections }, ctx),
10587
- path: "xl/connections.xml"
10588
- };
10589
- }
10590
- if (options.metadata && hasMetadataContent(options.metadata)) {
10591
- const mRid = ctx.workbookRels.nextRelationshipId;
10592
- ctx.workbookRels.addRelationship(mRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sheetMetadata", "metadata.xml");
10593
- mapping["Metadata"] = {
10594
- data: XML_DECL + metadataDesc.stringify(options.metadata, ctx),
10595
- path: "xl/metadata.xml"
10596
- };
10597
- }
10598
- if (options.xmlMaps) {
10599
- const xRid = ctx.workbookRels.nextRelationshipId;
10600
- ctx.workbookRels.addRelationship(xRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/xmlMaps", "xmlMaps.xml");
10601
- mapping["XmlMaps"] = {
10602
- data: XML_DECL + mapInfoDesc.stringify(options.xmlMaps, ctx),
10603
- path: "xl/xmlMaps.xml"
10604
- };
10605
- }
10606
- if (options.volTypes && options.volTypes.length > 0) {
10607
- const vRid = ctx.workbookRels.nextRelationshipId;
10608
- ctx.workbookRels.addRelationship(vRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/volTypes", "volTypes.xml");
10609
- mapping["VolTypes"] = {
10610
- data: XML_DECL + buildVolTypesXml(options.volTypes),
10611
- path: "xl/volTypes.xml"
10504
+ for (const chart of chartOpts) {
10505
+ const chartKey = `chart_${state.globalChartIdx}`;
10506
+ const userShapes = chart.userShapes ? buildUserShapesData(chart.userShapes) : void 0;
10507
+ ctx.charts.addChart(chartKey, {
10508
+ key: chartKey,
10509
+ chartSpaceXml: chartSpaceDesc.stringify(chart, ctx) ?? "",
10510
+ ...userShapes ? { userShapes } : {}
10511
+ });
10512
+ drawingRels.addRelationship(rid, RELATIONSHIP_TYPES.chart, `../charts/chart${state.globalChartIdx + 1}.xml`);
10513
+ const chartCnvPr = pickNonVisualDrawingProperties({
10514
+ ...chart,
10515
+ title: void 0,
10516
+ ext: void 0
10517
+ });
10518
+ drawingCharts.push({
10519
+ ...pickAnchorOptions(chart),
10520
+ ...chartCnvPr,
10521
+ rId: `rId${rid}`,
10522
+ ...chart.frameLocks ? { frameLocks: chart.frameLocks } : {},
10523
+ ...chart.macro !== void 0 ? { macro: chart.macro } : {},
10524
+ ...chart.hyperlink ? { hyperlink: chart.hyperlink } : {},
10525
+ ...chart.zOrder !== void 0 ? { zOrder: chart.zOrder } : {},
10526
+ ...chart.shapeId !== void 0 ? { shapeId: chart.shapeId } : {}
10527
+ });
10528
+ rid++;
10529
+ state.globalChartIdx++;
10530
+ }
10531
+ for (const sa of smartArtOpts) {
10532
+ const relTarget = (path) => path.startsWith("xl/") ? `../${path.slice(3)}` : path;
10533
+ const addDiagRel = (relType, path) => {
10534
+ const target = relTarget(path);
10535
+ const existing = drawingRels.idOf(relType, target);
10536
+ if (existing !== void 0) return existing;
10537
+ drawingRels.addRelationship(rid, relType, target);
10538
+ return `rId${rid++}`;
10612
10539
  };
10540
+ const relBase = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
10541
+ drawingSmartArts.push({
10542
+ ...pickAnchorOptions(sa),
10543
+ ...pickNonVisualDrawingProperties(sa),
10544
+ dataRId: addDiagRel(`${relBase}/diagramData`, sa.dataPath),
10545
+ layoutRId: addDiagRel(`${relBase}/diagramLayout`, sa.layoutPath),
10546
+ quickStyleRId: addDiagRel(`${relBase}/diagramQuickStyle`, sa.quickStylePath),
10547
+ colorsRId: addDiagRel(`${relBase}/diagramColors`, sa.colorsPath),
10548
+ ...sa.frameLocks ? { frameLocks: sa.frameLocks } : {},
10549
+ ...sa.macro !== void 0 ? { macro: sa.macro } : {},
10550
+ ...sa.zOrder !== void 0 ? { zOrder: sa.zOrder } : {},
10551
+ ...sa.shapeId !== void 0 ? { shapeId: sa.shapeId } : {}
10552
+ });
10613
10553
  }
10614
- const extLinks = options.externalLinks ?? [];
10615
- if (extLinks.length > 0) {
10616
- const extRefs = [];
10617
- for (let ei = 0; ei < extLinks.length; ei++) {
10618
- const elIdx = ei + 1;
10619
- const elRid = ctx.workbookRels.nextRelationshipId;
10620
- ctx.workbookRels.addRelationship(elRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLink", `externalLinks/externalLink${elIdx}.xml`);
10621
- const elOpts = extLinks[ei];
10622
- if (!elOpts) continue;
10623
- let bookRId;
10624
- if (elOpts.externalBook?.target) {
10625
- const elRels = new Relationships();
10626
- elRels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath", elOpts.externalBook.target, TargetModeType.EXTERNAL);
10627
- bookRId = "rId1";
10628
- mapping[`ExternalLinkRels${elIdx}`] = {
10629
- data: XML_DECL + elRels.serialize(),
10630
- path: `xl/externalLinks/_rels/externalLink${elIdx}.xml.rels`
10631
- };
10632
- }
10633
- mapping[`ExternalLink${elIdx}`] = {
10634
- data: XML_DECL + externalLinkDesc.stringify({
10635
- ...elOpts,
10636
- bookRId
10637
- }, ctx),
10638
- path: `xl/externalLinks/externalLink${elIdx}.xml`
10639
- };
10640
- extRefs.push({ rId: `rId${elRid}` });
10554
+ const hyperlinkBase = ctx.hyperlinks.length;
10555
+ let resolvedDrawingXml = drawingDesc.stringify({
10556
+ images: drawingImages,
10557
+ charts: drawingCharts,
10558
+ smartArts: drawingSmartArts,
10559
+ shapes: shapeOpts,
10560
+ connectors: connectorOpts,
10561
+ groups: groupOpts
10562
+ }, ctx);
10563
+ const hlinkRidByUrl = /* @__PURE__ */ new Map();
10564
+ for (const h of ctx.hyperlinks.slice(hyperlinkBase)) {
10565
+ let hlinkRid = hlinkRidByUrl.get(h.url);
10566
+ if (hlinkRid === void 0) {
10567
+ drawingRels.addRelationship(rid, RELATIONSHIP_TYPES.hyperlink, h.url, "External");
10568
+ hlinkRid = rid;
10569
+ hlinkRidByUrl.set(h.url, hlinkRid);
10570
+ rid++;
10641
10571
  }
10642
- const extRefsXml = buildExternalReferencesXml(extRefs);
10643
- wbXml = wbXml.replace("<!--EXTERNAL_REFS-->", extRefsXml);
10644
- } else wbXml = wbXml.replace("<!--EXTERNAL_REFS-->", "");
10645
- mapping["Workbook"] = {
10646
- data: XML_DECL + wbXml,
10647
- path: "xl/workbook.xml"
10648
- };
10649
- if (ctx.sharedStrings.count > 0) {
10650
- ctx.workbookRels.addRelationship(ctx.workbookRels.nextRelationshipId, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings", "sharedStrings.xml");
10651
- const ssXml = sharedStringsDesc.stringify(ctx.sharedStrings.toDescriptorOptions(), ctx);
10652
- mapping["SharedStrings"] = {
10653
- data: XML_DECL + ssXml,
10654
- path: "xl/sharedStrings.xml"
10655
- };
10572
+ resolvedDrawingXml = resolvedDrawingXml.split(`r:id="{hlink:${h.key}}"`).join(`r:id="rId${hlinkRid}"`);
10656
10573
  }
10657
- const stylesXml = stylesDesc.stringify({ styles: ctx.styles }, ctx);
10658
- mapping["Styles"] = {
10659
- data: XML_DECL + stylesXml,
10660
- path: "xl/styles.xml"
10574
+ resolvedDrawingXml = bindMediaPlaceholders(resolvedDrawingXml, ctx.media, drawingRels);
10575
+ const drawingIdx = i + 1;
10576
+ mapping[`Drawing${i}`] = {
10577
+ data: XML_DECL$2 + resolvedDrawingXml,
10578
+ path: `xl/drawings/drawing${drawingIdx}.xml`
10661
10579
  };
10662
- const themeRels = new Relationships();
10663
- const themeXml = options.theme ? bindMediaPlaceholders(buildThemeXml(options.theme, ctx), ctx.media, themeRels) : createThemeXml$1();
10664
- mapping["Theme"] = {
10665
- data: XML_DECL + themeXml,
10666
- path: "xl/theme/theme1.xml"
10667
- };
10668
- if (themeRels.relationshipCount > 0) mapping["ThemeRels"] = {
10669
- data: XML_DECL + themeRels.serialize(),
10670
- path: "xl/theme/_rels/theme1.xml.rels"
10580
+ mapping[`DrawingRels${i}`] = {
10581
+ data: XML_DECL$2 + drawingRels.serialize(),
10582
+ path: `xl/drawings/_rels/drawing${drawingIdx}.xml.rels`
10671
10583
  };
10672
- for (const [i, chartData] of ctx.charts.array.entries()) {
10673
- mapping[`Chart${i}`] = {
10674
- data: XML_DECL + chartData.chartSpaceXml,
10675
- path: `xl/charts/chart${i + 1}.xml`
10676
- };
10677
- if (chartData.userShapes) {
10678
- const rid = chartData.userShapes.relationshipId;
10679
- mapping[`ChartUserShapes${i}`] = {
10680
- data: XML_DECL + chartData.userShapes.xml,
10681
- path: `xl/charts/userShapes${i + 1}.xml`
10682
- };
10683
- mapping[`ChartRels${i}`] = {
10684
- data: XML_DECL + `<Relationships xmlns="${PKG_REL_NS}"><Relationship Id="${escapeXml(rid)}" Type="${CHART_USER_SHAPES_REL}" Target="userShapes${i + 1}.xml"/></Relationships>`,
10685
- path: `xl/charts/_rels/chart${i + 1}.xml.rels`
10686
- };
10687
- }
10688
- }
10689
- const calcChainCells = options.calcChain ?? state.calcCells;
10690
- const srcReferencesCalcChain = (options.passthroughRelationships ?? []).some((r) => r.source === "xl/workbook.xml" && r.relationshipType.endsWith("/calcChain"));
10691
- if (calcChainCells.length > 0 && !(srcReferencesCalcChain && options.calcChain === void 0)) {
10692
- mapping["CalcChain"] = {
10693
- data: calcChainDesc.stringify({ cells: calcChainCells }, ctx) ?? "",
10694
- path: "xl/calcChain.xml"
10695
- };
10696
- const calcChainRid = ctx.workbookRels.nextRelationshipId;
10697
- ctx.workbookRels.addRelationship(calcChainRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain", "calcChain.xml");
10698
- }
10699
- if (options.revisionLog) compileRevisionLogs(options.revisionLog, ctx, mapping);
10700
- for (const rel of options.passthroughRelationships ?? []) {
10701
- if (rel.source !== "xl/workbook.xml") continue;
10702
- if (ctx.workbookRels.hasRelationship(rel.relationshipType, rel.target)) continue;
10703
- ctx.workbookRels.add(rel.relationshipType, rel.target);
10704
- }
10705
- mapping["WorkbookRelationships"] = {
10706
- data: XML_DECL + ctx.workbookRels.serialize(),
10707
- path: "xl/_rels/workbook.xml.rels"
10708
- };
10709
- const mediaFiles = [];
10710
- for (const img of ctx.media.array) mediaFiles.push({
10711
- data: img.data,
10712
- path: `xl/media/${img.fileName}`
10713
- });
10714
- const files = compileMapping(mapping, overrides, mediaFiles, mediaLevel);
10715
- const passthroughSkipped = /* @__PURE__ */ new Set();
10716
- for (const part of options.rawParts ?? []) {
10717
- if (files[part.path] !== void 0) {
10718
- passthroughSkipped.add(part.path);
10719
- continue;
10720
- }
10721
- files[part.path] = toUint8Array(part.data);
10722
- }
10723
- const contentTypesInput = deriveContentTypes(Object.keys(files), {
10724
- resolve: XLSX_CONTENT_TYPE_RESOLVER$1,
10725
- mediaContentTypes: XLSX_MEDIA_CONTENT_TYPES,
10726
- source: options.contentTypes,
10727
- verbatimPaths: new Set((options.rawParts ?? []).map((p) => p.path))
10728
- });
10729
- const coveredExt = new Set(contentTypesInput.defaults.map((d) => d.extension.toLowerCase()));
10730
- for (const part of options.rawParts ?? []) {
10731
- if (part.contentType === void 0 || passthroughSkipped.has(part.path)) continue;
10732
- const dot = part.path.lastIndexOf(".");
10733
- const ext = dot > part.path.lastIndexOf("/") ? part.path.slice(dot + 1).toLowerCase() : void 0;
10734
- if (ext && coveredExt.has(ext)) continue;
10735
- contentTypesInput.overrides.push({
10736
- partName: `/${part.path}`,
10737
- contentType: part.contentType
10738
- });
10739
- }
10740
- files["[Content_Types].xml"] = encoder.encode(XML_DECL + (contentTypesDesc.stringify(contentTypesInput, ctx) ?? ""));
10741
- dropDanglingPassthroughRels(files, options.passthroughRelationships);
10742
- return files;
10584
+ return editSheetTailMarker(sheetXml, "<!--DRAWING-->", `<drawing r:id="rId${wsRels.add(RELATIONSHIP_TYPES.drawing, `../drawings/drawing${drawingIdx}.xml`)}"/>`);
10743
10585
  }
10586
+ //#endregion
10587
+ //#region src/compile/sheet-pivots.ts
10744
10588
  /**
10745
- * Compile one worksheet: sheet XML, calcChain cells, drawing/media,
10746
- * comments + VML, background, pivots, tables, query tables and
10747
- * single-cell XML tables, with their worksheet-level relationships.
10748
- * Rel registration order is significant (rIds are assigned sequentially).
10589
+ * Worksheet pivot compile phase: pivot cache definitions/records, pivot
10590
+ * table parts with their relationships, and the rendered pivot grid
10591
+ * spliced into the sheet's sheetData.
10592
+ *
10593
+ * @module
10749
10594
  */
10750
- function compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsContext, state, passthroughRelationships) {
10751
- const imgOpts = wsOpts.images ?? [];
10752
- const chartOpts = wsOpts.charts ?? [];
10753
- const smartArtOpts = wsOpts.smartArts ?? [];
10754
- const shapeOpts = wsOpts.shapes ?? [];
10755
- const connectorOpts = wsOpts.connectors ?? [];
10756
- const groupOpts = wsOpts.groups ?? [];
10757
- const hlOpts = wsOpts.hyperlinks ?? [];
10758
- const sheetName = wsOpts.name ?? `Sheet${i + 1}`;
10759
- const sheetIdx = wsOpts.sheetId ?? i + 1;
10760
- const wsRows = wsOpts.rows ?? [];
10761
- for (let ri = 0; ri < wsRows.length; ri++) {
10762
- const rowOpts = wsRows[ri];
10763
- const rowNumber = rowOpts.rowNumber ?? ri + 1;
10764
- const cells = rowOpts.cells;
10765
- if (!cells) continue;
10766
- for (let ci = 0; ci < cells.length; ci++) {
10767
- const cell = cells[ci];
10768
- if (!cell.formula) continue;
10769
- const ref = cell.reference ?? columnToLetter(ci + 1) + rowNumber;
10770
- state.calcCells.push({
10771
- reference: ref,
10772
- sheetIndex: sheetIdx,
10773
- array: typeof cell.formula === "object" && cell.formula.type === "array"
10774
- });
10775
- }
10776
- }
10777
- const hasMedia = imgOpts.length > 0 || chartOpts.length > 0 || smartArtOpts.length > 0 || shapeOpts.length > 0 || connectorOpts.length > 0 || groupOpts.length > 0;
10778
- const hasExternalHyperlinks = hlOpts.some((h) => h.url !== void 0);
10779
- const commentOpts = wsOpts.comments ?? [];
10780
- const hasComments = commentOpts.length > 0;
10595
+ const XML_DECL$1 = OOXML_XML_DECLARATION;
10596
+ /** Compile a sheet's pivot tables: cache parts (deduped by source reference),
10597
+ * pivot table parts with their rels, workbook-level cache registration, and
10598
+ * the worksheet rel entry. Rendering the grid into sheetData happens later
10599
+ * via renderPivotSheetData (it must run after the sheet XML is built). */
10600
+ function compileSheetPivots(wsOpts, worksheetConfigs, ctx, mapping, state, wsRels, sheetName) {
10781
10601
  const pivotOpts = wsOpts.pivotTables ?? [];
10782
- const hasPivots = pivotOpts.length > 0;
10783
- const tableOpts = wsOpts.tables ?? [];
10784
- const hasTables = tableOpts.length > 0;
10785
- const queryTableOpts = wsOpts.queryTables ?? [];
10786
- const hasQueryTables = queryTableOpts.length > 0;
10787
- const singleXmlCellOpts = wsOpts.singleXmlCells ?? [];
10788
- const bgImg = wsOpts.backgroundImage;
10789
- const wsPath = `xl/worksheets/sheet${i + 1}.xml`;
10790
- let wsRels;
10791
- if (hasMedia || hasExternalHyperlinks || hasComments || hasPivots || hasTables || hasQueryTables || singleXmlCellOpts.length > 0 || bgImg) {
10792
- wsRels = new Relationships();
10793
- wsRels.reserveSourceRids(wsPath, passthroughRelationships ?? []);
10794
- }
10795
- const resolvePassthroughRid = (typeFragment, originalRid) => {
10796
- if (!wsRels) return originalRid;
10797
- const rel = (passthroughRelationships ?? []).find((r) => r.source === wsPath && r.rId === originalRid && r.relationshipType.endsWith(typeFragment));
10798
- if (!rel) return originalRid;
10799
- const existing = wsRels.idOf(rel.relationshipType, rel.target);
10800
- if (existing) return existing;
10801
- if (wsRels.hasId(originalRid)) return `rId${wsRels.add(rel.relationshipType, rel.target)}`;
10802
- wsRels.addRelationship(originalRid, rel.relationshipType, rel.target);
10803
- return originalRid;
10804
- };
10805
- const resolveEmbeddingRid = (originalRid) => {
10806
- const rid = resolvePassthroughRid("/oleObject", originalRid);
10807
- return rid === originalRid ? resolvePassthroughRid("/package", originalRid) : rid;
10808
- };
10809
- let xmlOpts = wsOpts;
10810
- if (wsRels && (passthroughRelationships?.length ?? 0) > 0) {
10811
- const oleObjects = wsOpts.oleObjects?.map((ole) => ({
10812
- ...ole,
10813
- rId: ole.rId ? resolveEmbeddingRid(ole.rId) : ole.rId,
10814
- properties: ole.properties?.iconRid !== void 0 ? {
10815
- ...ole.properties,
10816
- iconRid: resolvePassthroughRid("/image", ole.properties.iconRid)
10817
- } : ole.properties
10818
- }));
10819
- const controls = wsOpts.controls?.map((c) => ({
10820
- ...c,
10821
- rId: resolvePassthroughRid("/controls", c.rId),
10822
- iconRid: c.iconRid !== void 0 ? resolvePassthroughRid("/image", c.iconRid) : c.iconRid
10823
- }));
10824
- const pageSetup = wsOpts.pageSetup?.printerSettingsRId ? {
10825
- ...wsOpts.pageSetup,
10826
- printerSettingsRId: resolvePassthroughRid("/printerSettings", wsOpts.pageSetup.printerSettingsRId)
10827
- } : wsOpts.pageSetup;
10828
- const pivotSelection = wsOpts.pivotSelection?.rId ? {
10829
- ...wsOpts.pivotSelection,
10830
- rId: resolvePassthroughRid("/pivotTable", wsOpts.pivotSelection.rId)
10831
- } : wsOpts.pivotSelection;
10832
- const legacyDrawingHF = wsOpts.legacyDrawingHF ? resolvePassthroughRid("/vmlDrawing", wsOpts.legacyDrawingHF) : wsOpts.legacyDrawingHF;
10833
- const customProperties = wsOpts.customProperties?.map((cp) => ({
10834
- ...cp,
10835
- rId: resolvePassthroughRid("/customXml", cp.rId)
10836
- }));
10837
- xmlOpts = {
10838
- ...wsOpts,
10839
- ...oleObjects ? { oleObjects } : {},
10840
- ...controls ? { controls } : {},
10841
- ...pageSetup !== wsOpts.pageSetup ? { pageSetup } : {},
10842
- ...pivotSelection !== wsOpts.pivotSelection ? { pivotSelection } : {},
10843
- ...legacyDrawingHF !== wsOpts.legacyDrawingHF ? { legacyDrawingHF } : {},
10844
- ...customProperties ? { customProperties } : {}
10845
- };
10846
- }
10847
- let sheetXml = stringifyWorksheet(xmlOpts, wsContext);
10848
- if (hasExternalHyperlinks) for (const hl of hlOpts) {
10849
- if (hl.url === void 0) continue;
10850
- wsRels.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", hl.url, "External");
10851
- }
10852
- if (hasMedia) {
10853
- const drawingImages = [];
10854
- const drawingCharts = [];
10855
- const drawingSmartArts = [];
10856
- const drawingRels = new Relationships();
10857
- let rid = 1;
10858
- for (const img of imgOpts) {
10859
- let embedRid;
10860
- let linkRid;
10861
- if (img.data !== void 0) {
10862
- const ext = img.type === "jpg" ? "jpeg" : img.type;
10863
- const rawBytes = toUint8Array(img.data, { encoding: "base64" });
10864
- const target = `../media/${ctx.media.addMedia(rawBytes, ext, (fileName) => ({
10865
- fileName,
10866
- type: ext,
10867
- data: rawBytes,
10868
- width: 0,
10869
- height: 0
10870
- })).fileName}`;
10871
- embedRid = drawingRels.idOf(IMAGE_REL, target);
10872
- if (embedRid === void 0) {
10873
- drawingRels.addRelationship(rid, IMAGE_REL, target);
10874
- embedRid = `rId${rid}`;
10875
- rid++;
10876
- }
10877
- state.globalMediaIdx++;
10878
- }
10879
- if (img.sourceUrl !== void 0) {
10880
- drawingRels.addRelationship(rid, IMAGE_REL, img.sourceUrl, "External");
10881
- linkRid = `rId${rid}`;
10882
- rid++;
10883
- }
10884
- drawingImages.push({
10885
- ...pickAnchorOptions(img),
10886
- rId: embedRid ?? "",
10887
- ...linkRid ? { linkRId: linkRid } : {},
10888
- ...pickNonVisualDrawingProperties(img),
10889
- ...img.properties ? { properties: img.properties } : {},
10890
- ...img.blackWhiteMode ? { blackWhiteMode: img.blackWhiteMode } : {},
10891
- ...img.sourceRectangle ? { sourceRectangle: img.sourceRectangle } : {},
10892
- ...img.preferRelativeResize !== void 0 ? { preferRelativeResize: img.preferRelativeResize } : {},
10893
- ...img.blipEffects ? { blipEffects: img.blipEffects } : {},
10894
- ...img.useLocalDpi !== void 0 ? { useLocalDpi: img.useLocalDpi } : {},
10895
- ...img.blipExt !== void 0 ? { blipExt: img.blipExt } : {},
10896
- ...img.locking ? { locking: img.locking } : {},
10897
- ...img.hyperlink ? { hyperlink: img.hyperlink } : {},
10898
- ...img.zOrder !== void 0 ? { zOrder: img.zOrder } : {},
10899
- ...img.shapeId !== void 0 ? { shapeId: img.shapeId } : {}
10900
- });
10901
- }
10902
- for (const chart of chartOpts) {
10903
- const chartKey = `chart_${state.globalChartIdx}`;
10904
- const userShapes = chart.userShapes ? buildUserShapesData(chart.userShapes) : void 0;
10905
- ctx.charts.addChart(chartKey, {
10906
- key: chartKey,
10907
- chartSpaceXml: chartSpaceDesc.stringify(chart, ctx) ?? "",
10908
- ...userShapes ? { userShapes } : {}
10909
- });
10910
- drawingRels.addRelationship(rid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart", `../charts/chart${state.globalChartIdx + 1}.xml`);
10911
- const chartCnvPr = pickNonVisualDrawingProperties({
10912
- ...chart,
10913
- title: void 0,
10914
- ext: void 0
10915
- });
10916
- drawingCharts.push({
10917
- ...pickAnchorOptions(chart),
10918
- ...chartCnvPr,
10919
- rId: `rId${rid}`,
10920
- ...chart.frameLocks ? { frameLocks: chart.frameLocks } : {},
10921
- ...chart.macro !== void 0 ? { macro: chart.macro } : {},
10922
- ...chart.hyperlink ? { hyperlink: chart.hyperlink } : {},
10923
- ...chart.zOrder !== void 0 ? { zOrder: chart.zOrder } : {},
10924
- ...chart.shapeId !== void 0 ? { shapeId: chart.shapeId } : {}
10925
- });
10926
- rid++;
10927
- state.globalChartIdx++;
10928
- }
10929
- for (const sa of smartArtOpts) {
10930
- const relTarget = (path) => path.startsWith("xl/") ? `../${path.slice(3)}` : path;
10931
- const addDiagRel = (relType, path) => {
10932
- const target = relTarget(path);
10933
- const existing = drawingRels.idOf(relType, target);
10934
- if (existing !== void 0) return existing;
10935
- drawingRels.addRelationship(rid, relType, target);
10936
- return `rId${rid++}`;
10937
- };
10938
- const relBase = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
10939
- drawingSmartArts.push({
10940
- ...pickAnchorOptions(sa),
10941
- ...pickNonVisualDrawingProperties(sa),
10942
- dataRId: addDiagRel(`${relBase}/diagramData`, sa.dataPath),
10943
- layoutRId: addDiagRel(`${relBase}/diagramLayout`, sa.layoutPath),
10944
- quickStyleRId: addDiagRel(`${relBase}/diagramQuickStyle`, sa.quickStylePath),
10945
- colorsRId: addDiagRel(`${relBase}/diagramColors`, sa.colorsPath),
10946
- ...sa.frameLocks ? { frameLocks: sa.frameLocks } : {},
10947
- ...sa.macro !== void 0 ? { macro: sa.macro } : {},
10948
- ...sa.zOrder !== void 0 ? { zOrder: sa.zOrder } : {},
10949
- ...sa.shapeId !== void 0 ? { shapeId: sa.shapeId } : {}
10950
- });
10951
- }
10952
- const hyperlinkBase = ctx.hyperlinks.length;
10953
- let resolvedDrawingXml = drawingDesc.stringify({
10954
- images: drawingImages,
10955
- charts: drawingCharts,
10956
- smartArts: drawingSmartArts,
10957
- shapes: shapeOpts,
10958
- connectors: connectorOpts,
10959
- groups: groupOpts
10960
- }, ctx);
10961
- const hlinkRidByUrl = /* @__PURE__ */ new Map();
10962
- for (const h of ctx.hyperlinks.slice(hyperlinkBase)) {
10963
- let hlinkRid = hlinkRidByUrl.get(h.url);
10964
- if (hlinkRid === void 0) {
10965
- drawingRels.addRelationship(rid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", h.url, "External");
10966
- hlinkRid = rid;
10967
- hlinkRidByUrl.set(h.url, hlinkRid);
10968
- rid++;
10969
- }
10970
- resolvedDrawingXml = resolvedDrawingXml.split(`r:id="{hlink:${h.key}}"`).join(`r:id="rId${hlinkRid}"`);
10971
- }
10972
- resolvedDrawingXml = bindMediaPlaceholders(resolvedDrawingXml, ctx.media, drawingRels);
10973
- const drawingIdx = i + 1;
10974
- mapping[`Drawing${i}`] = {
10975
- data: XML_DECL + resolvedDrawingXml,
10976
- path: `xl/drawings/drawing${drawingIdx}.xml`
10977
- };
10978
- mapping[`DrawingRels${i}`] = {
10979
- data: XML_DECL + drawingRels.serialize(),
10980
- path: `xl/drawings/_rels/drawing${drawingIdx}.xml.rels`
10981
- };
10982
- const drawingRid = wsRels.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing", `../drawings/drawing${drawingIdx}.xml`);
10983
- sheetXml = editSheetTailMarker(sheetXml, "<!--DRAWING-->", `<drawing r:id="rId${drawingRid}"/>`);
10984
- }
10985
- if (hasComments) {
10986
- const commentsIdx = i + 1;
10987
- const commentsXml = commentsDesc.stringify({ comments: commentOpts }, ctx);
10988
- mapping[`Comments${i}`] = {
10989
- data: XML_DECL + commentsXml,
10990
- path: `xl/comments${commentsIdx}.xml`
10991
- };
10992
- const vmlXml = vmlNotesDesc.stringify({ comments: commentOpts }, ctx);
10993
- mapping[`VmlDrawing${i}`] = {
10994
- data: XML_DECL + vmlXml,
10995
- path: `xl/drawings/vmlDrawing${commentsIdx}.vml`
10996
- };
10997
- wsRels.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments", `../comments${commentsIdx}.xml`);
10998
- const vmlRid = wsRels.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing", `../drawings/vmlDrawing${commentsIdx}.vml`);
10999
- sheetXml = editSheetTailMarker(sheetXml, "<!--LEGACY_DRAWING-->", `<legacyDrawing r:id="rId${vmlRid}"/>`);
11000
- }
11001
- if (bgImg) {
11002
- const ext = bgImg.type === "jpg" ? "jpeg" : bgImg.type;
11003
- const rawBytes = toUint8Array(bgImg.data, { encoding: "base64" });
11004
- const entry = ctx.media.addMedia(rawBytes, ext, (fileName) => ({
11005
- fileName,
11006
- type: ext,
11007
- data: rawBytes,
11008
- width: 0,
11009
- height: 0
11010
- }));
11011
- state.globalMediaIdx++;
11012
- const bgRid = wsRels.add(IMAGE_REL, `../media/${entry.fileName}`);
11013
- sheetXml = editSheetTailMarker(sheetXml, "<!--BACKGROUND_PICTURE-->", `<picture r:id="rId${bgRid}"/>`);
11014
- }
11015
- if (wsOpts.drawingRid) {
11016
- const rid = escapeXml(resolvePassthroughRid("/drawing", wsOpts.drawingRid));
11017
- sheetXml = editSheetTailMarker(sheetXml, "<!--DRAWING-->", `<drawing r:id="${rid}"/>`);
11018
- }
11019
- if (wsOpts.legacyDrawingRid) {
11020
- const rid = escapeXml(resolvePassthroughRid("/vmlDrawing", wsOpts.legacyDrawingRid));
11021
- sheetXml = editSheetTailMarker(sheetXml, "<!--LEGACY_DRAWING-->", `<legacyDrawing r:id="${rid}"/>`);
11022
- }
11023
- if (hasPivots) for (const pt of pivotOpts) {
10602
+ for (const pt of pivotOpts) {
11024
10603
  state.globalPivotIdx++;
11025
10604
  const pivotIdx = state.globalPivotIdx;
11026
10605
  const sourceSheet = pt.sourceSheet ?? sheetName;
@@ -11045,8 +10624,8 @@ function compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsConte
11045
10624
  cacheIdx
11046
10625
  });
11047
10626
  const cacheDefRels = new Relationships();
11048
- cacheDefRels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheRecords", "pivotCacheRecords1.xml");
11049
- const cacheDefXml = XML_DECL + pivotCacheDefDesc.stringify({
10627
+ cacheDefRels.addRelationship(1, RELATIONSHIP_TYPES.pivotCacheRecords, "pivotCacheRecords1.xml");
10628
+ const cacheDefXml = XML_DECL$1 + pivotCacheDefDesc.stringify({
11050
10629
  sourceRef: pt.source.split(":")[0] ? pt.source : "A1",
11051
10630
  sourceSheet,
11052
10631
  sourceData,
@@ -11057,22 +10636,22 @@ function compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsConte
11057
10636
  path: `xl/pivotCache/pivotCacheDefinition${cacheIdx}.xml`
11058
10637
  };
11059
10638
  mapping[`PivotCacheDefRels${cacheIdx}`] = {
11060
- data: XML_DECL + cacheDefRels.serialize(),
10639
+ data: XML_DECL$1 + cacheDefRels.serialize(),
11061
10640
  path: `xl/pivotCache/_rels/pivotCacheDefinition${cacheIdx}.xml.rels`
11062
10641
  };
11063
- const cacheRecordsXml = XML_DECL + pivotCacheRecordsDesc.stringify({ sourceData }, ctx);
10642
+ const cacheRecordsXml = XML_DECL$1 + pivotCacheRecordsDesc.stringify({ sourceData }, ctx);
11064
10643
  mapping[`PivotCacheRecords${cacheIdx}`] = {
11065
10644
  data: cacheRecordsXml,
11066
10645
  path: `xl/pivotCache/pivotCacheRecords${cacheIdx}.xml`
11067
10646
  };
11068
10647
  const wbPivotRid = ctx.workbookRels.nextRelationshipId;
11069
- ctx.workbookRels.addRelationship(wbPivotRid, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition", `pivotCache/pivotCacheDefinition${cacheIdx}.xml`);
10648
+ ctx.workbookRels.addRelationship(wbPivotRid, RELATIONSHIP_TYPES.pivotCacheDefinition, `pivotCache/pivotCacheDefinition${cacheIdx}.xml`);
11070
10649
  ctx.pivotCacheRefs.push({
11071
10650
  cacheId,
11072
10651
  rId: `rId${wbPivotRid}`
11073
10652
  });
11074
10653
  }
11075
- const pivotTableXml = XML_DECL + pivotTableDesc.stringify({
10654
+ const pivotTableXml = XML_DECL$1 + pivotTableDesc.stringify({
11076
10655
  options: pt,
11077
10656
  sourceData,
11078
10657
  cacheId
@@ -11082,225 +10661,43 @@ function compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsConte
11082
10661
  path: `xl/pivotTables/pivotTable${pivotIdx}.xml`
11083
10662
  };
11084
10663
  const ptRels = new Relationships();
11085
- ptRels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition", `../pivotCache/pivotCacheDefinition${cacheIdx}.xml`);
10664
+ ptRels.addRelationship(1, RELATIONSHIP_TYPES.pivotCacheDefinition, `../pivotCache/pivotCacheDefinition${cacheIdx}.xml`);
11086
10665
  mapping[`PivotTableRels${pivotIdx}`] = {
11087
- data: XML_DECL + ptRels.serialize(),
10666
+ data: XML_DECL$1 + ptRels.serialize(),
11088
10667
  path: `xl/pivotTables/_rels/pivotTable${pivotIdx}.xml.rels`
11089
10668
  };
11090
- wsRels.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable", `../pivotTables/pivotTable${pivotIdx}.xml`);
11091
- }
11092
- const wsTableParts = [];
11093
- if (hasTables) for (const tbl of tableOpts) {
11094
- state.globalTableIdx++;
11095
- const tableIdx = state.globalTableIdx;
11096
- if (!tbl.columns?.length) continue;
11097
- const tableXmlStr = XML_DECL + tableDesc.stringify({
11098
- ...tbl,
11099
- id: tbl.id ?? tableIdx
11100
- }, ctx);
11101
- mapping[`Table${tableIdx}`] = {
11102
- data: tableXmlStr,
11103
- path: `xl/tables/table${tableIdx}.xml`
11104
- };
11105
- const tblRid = wsRels.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/table", `../tables/table${tableIdx}.xml`);
11106
- wsTableParts.push({ rId: `rId${tblRid}` });
11107
- state.allTableParts.push({ rId: `rId${tblRid}` });
11108
- }
11109
- if (hasQueryTables) for (const qt of queryTableOpts) {
11110
- state.globalQueryTableIdx++;
11111
- mapping[`QueryTable${state.globalQueryTableIdx}`] = {
11112
- data: XML_DECL + queryTableDesc.stringify(qt, ctx),
11113
- path: `xl/queryTables/queryTable${state.globalQueryTableIdx}.xml`
11114
- };
11115
- wsRels.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/queryTable", `../queryTables/queryTable${state.globalQueryTableIdx}.xml`);
10669
+ wsRels.add(RELATIONSHIP_TYPES.pivotTable, `../pivotTables/pivotTable${pivotIdx}.xml`);
11116
10670
  }
11117
- if (singleXmlCellOpts.length > 0) {
11118
- state.globalSingleXmlCellsIdx++;
11119
- mapping[`TableSingleCells${state.globalSingleXmlCellsIdx}`] = {
11120
- data: XML_DECL + singleXmlCellsDesc.stringify({ cells: singleXmlCellOpts }, ctx),
11121
- path: `xl/tables/tableSingleCells${state.globalSingleXmlCellsIdx}.xml`
11122
- };
11123
- wsRels.add("http://schemas.openxmlformats.org/officeDocument/2006/relationships/tableSingleCells", `../tables/tableSingleCells${state.globalSingleXmlCellsIdx}.xml`);
10671
+ }
10672
+ function extractPivotSourceData(rows, sourceRef) {
10673
+ const parts = sourceRef.split(":");
10674
+ const start = parseA1Cell(parts[0] ?? "");
10675
+ if (!start) return {
10676
+ fieldNames: [],
10677
+ records: []
10678
+ };
10679
+ const end = parts[1] !== void 0 ? parseA1Cell(parts[1]) : void 0;
10680
+ const startRow = start.row - 1;
10681
+ const endRow = (end?.row ?? start.row) - 1;
10682
+ const startCol = start.col - 1;
10683
+ const endCol = (end?.col ?? start.col) - 1;
10684
+ const colCount = endCol - startCol + 1;
10685
+ const headerRow = rows[startRow];
10686
+ const fieldNames = [];
10687
+ if (headerRow?.cells) for (let c = startCol; c <= endCol && c < headerRow.cells.length; c++) {
10688
+ const hv = headerRow.cells[c]?.value;
10689
+ fieldNames.push(typeof hv === "string" ? hv : typeof hv === "number" || typeof hv === "boolean" ? String(hv) : `Col${c}`);
11124
10690
  }
11125
- if (hasPivots) {
11126
- const rendered = renderPivotSheetData(pivotOpts, worksheetConfigs, ctx.sharedStrings, sheetName);
11127
- if (rendered.sheetData.length > 0) {
11128
- sheetXml = sheetXml.replace(/<sheetData\/>|<sheetData><\/sheetData>/, rendered.sheetData);
11129
- if (!sheetXml.includes("<dimension")) sheetXml = sheetXml.replace("<sheetViews", `<dimension ref="${rendered.dimensionRef}"/><sheetViews`);
11130
- }
11131
- }
11132
- if (wsTableParts.length > 0) sheetXml = editSheetTailMarker(sheetXml, "<!--TABLE_PARTS-->", buildTablePartsXml(wsTableParts));
11133
- sheetXml = stripWorksheetPlaceholders(sheetXml);
11134
- if (wsRels) for (const rel of passthroughRelationships ?? []) {
11135
- if (rel.source !== wsPath) continue;
11136
- wsRels.claimSourceRel(rel);
11137
- }
11138
- if (wsRels) mapping[`WorksheetRels${i}`] = {
11139
- data: XML_DECL + wsRels.serialize(),
11140
- path: `xl/worksheets/_rels/sheet${i + 1}.xml.rels`
11141
- };
11142
- mapping[`Worksheet${i}`] = {
11143
- data: sheetXml,
11144
- path: `xl/worksheets/sheet${i + 1}.xml`
11145
- };
11146
- }
11147
- /** Full-page default frame for a fresh chartsheet chart (≈9.70×6.35 in). */
11148
- const CHARTSHEET_DEFAULT_CX = 9308969;
11149
- const CHARTSHEET_DEFAULT_CY = 6096e3;
11150
- /** Compile all chartsheets: chart part, chartsheet/drawing XML and rels. */
11151
- function compileChartsheets(chartsheetConfigs, ctx, mapping, passthroughRelationships) {
11152
- for (const [i, csOpts] of chartsheetConfigs.entries()) {
11153
- const chartDef = csOpts.chart;
11154
- if (!chartDef) continue;
11155
- const csChartGlobalIdx = ctx.charts.array.length;
11156
- const csChartKey = `cs_chart_${csChartGlobalIdx}`;
11157
- const csUserShapes = chartDef.userShapes ? buildUserShapesData(chartDef.userShapes) : void 0;
11158
- ctx.charts.addChart(csChartKey, {
11159
- key: csChartKey,
11160
- chartSpaceXml: chartSpaceDesc.stringify(chartDef, ctx) ?? "",
11161
- ...csUserShapes ? { userShapes: csUserShapes } : {}
11162
- });
11163
- const csRels = new Relationships();
11164
- const csDrawingIdx = i + 1;
11165
- csRels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing", `../drawings/drawing${csDrawingIdx}.xml`);
11166
- let csNextRid = 2;
11167
- for (const rel of passthroughRelationships ?? []) {
11168
- if (rel.source !== `xl/chartsheets/sheet${i + 1}.xml`) continue;
11169
- if (csRels.hasRelationship(rel.relationshipType, rel.target)) continue;
11170
- csRels.addRelationship(csNextRid++, rel.relationshipType, rel.target);
11171
- }
11172
- const csDrawingRels = new Relationships();
11173
- csDrawingRels.addRelationship(1, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart", `../charts/chart${csChartGlobalIdx + 1}.xml`);
11174
- const frame = graphicFrameXml(csOpts.shapeId ?? 1, void 0, `Chart ${i + 1}`, "rId1", 0, 0, ctx, {
11175
- frameLocks: csOpts.frameLocks,
11176
- macro: csOpts.macro
11177
- });
11178
- const anchor = wrapAnchor({
11179
- anchorType: "absolute",
11180
- col: 1,
11181
- row: 1,
11182
- absoluteX: csOpts.absoluteX ?? 0,
11183
- absoluteY: csOpts.absoluteY ?? 0,
11184
- extentCx: csOpts.extentCx ?? CHARTSHEET_DEFAULT_CX,
11185
- extentCy: csOpts.extentCy ?? CHARTSHEET_DEFAULT_CY
11186
- }, `${frame}<xdr:clientData/>`);
11187
- const csDrawingXml = `<xdr:wsDr xmlns:xdr="${XDR_NS}" xmlns:a="${A_NS}" xmlns:r="${R_NS$1}">${anchor}</xdr:wsDr>`;
11188
- mapping[`ChartsheetDrawing${i}`] = {
11189
- data: csDrawingXml,
11190
- path: `xl/drawings/drawing${csDrawingIdx}.xml`
11191
- };
11192
- mapping[`ChartsheetDrawingRels${i}`] = {
11193
- data: XML_DECL + csDrawingRels.serialize(),
11194
- path: `xl/drawings/_rels/drawing${csDrawingIdx}.xml.rels`
11195
- };
11196
- mapping[`ChartsheetRels${i}`] = {
11197
- data: XML_DECL + csRels.serialize(),
11198
- path: `xl/chartsheets/_rels/sheet${i + 1}.xml.rels`
11199
- };
11200
- let csPageSetup = csOpts.pageSetup;
11201
- if (csPageSetup?.printerSettingsRId) {
11202
- const srcRid = csPageSetup.printerSettingsRId;
11203
- const rel = (passthroughRelationships ?? []).find((r) => r.source === `xl/chartsheets/sheet${i + 1}.xml` && r.rId === srcRid && r.relationshipType.endsWith("/printerSettings"));
11204
- const rid = rel ? csRels.idOf(rel.relationshipType, rel.target) ?? srcRid : srcRid;
11205
- if (rid !== srcRid) csPageSetup = {
11206
- ...csPageSetup,
11207
- printerSettingsRId: rid
11208
- };
11209
- }
11210
- mapping[`Chartsheet${i}`] = {
11211
- data: XML_DECL + chartsheetDesc.stringify({
11212
- ...csOpts,
11213
- drawingRId: "rId1",
11214
- pageSetup: csPageSetup
11215
- }, ctx),
11216
- path: `xl/chartsheets/sheet${i + 1}.xml`
11217
- };
11218
- }
11219
- }
11220
- /** Compile all dialog sheets (legacy Excel 5.0 dialog sheets). */
11221
- function compileDialogsheets(dialogsheetConfigs, ctx, mapping) {
11222
- for (const [i, dsOpts] of dialogsheetConfigs.entries()) mapping[`Dialogsheet${i}`] = {
11223
- data: XML_DECL + dialogsheetDesc.stringify(dsOpts, ctx),
11224
- path: `xl/dialogSheets/sheet${i + 1}.xml`
11225
- };
11226
- }
11227
- /**
11228
- * Compile shared-workbook revisions (xl/revisionHeaders.xml +
11229
- * xl/revisions/revisionN.xml + xl/users.xml). CT_Workbook has no revision
11230
- * element — parts are discovered via workbook.xml.rels + [Content_Types].
11231
- */
11232
- function compileRevisionLogs(rl, ctx, mapping) {
11233
- const REV_HEADERS_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/revisionHeaders";
11234
- const REV_LOG_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/revisionLog";
11235
- const USERS_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/users";
11236
- mapping["RevisionHeaders"] = {
11237
- data: XML_DECL + (revisionHeadersDesc.stringify(rl.headers, ctx) ?? ""),
11238
- path: "xl/revisionHeaders.xml"
11239
- };
11240
- ctx.workbookRels.addRelationship(ctx.workbookRels.nextRelationshipId, REV_HEADERS_REL, "revisionHeaders.xml");
11241
- const revHeadersRels = new Relationships();
11242
- for (const [i, log] of rl.logs.entries()) {
11243
- mapping[`RevisionLog${i}`] = {
11244
- data: XML_DECL + (revisionLogDesc.stringify(log, ctx) ?? ""),
11245
- path: `xl/revisions/revision${i + 1}.xml`
11246
- };
11247
- revHeadersRels.addRelationship(i + 1, REV_LOG_REL, `revisions/revision${i + 1}.xml`);
11248
- }
11249
- mapping["RevisionHeadersRels"] = {
11250
- data: XML_DECL + revHeadersRels.serialize(),
11251
- path: "xl/_rels/revisionHeaders.xml.rels"
11252
- };
11253
- if (rl.users) {
11254
- const usersXml = usersDesc.stringify(rl.users, ctx);
11255
- if (usersXml) {
11256
- mapping["Users"] = {
11257
- data: XML_DECL + usersXml,
11258
- path: "xl/users.xml"
11259
- };
11260
- ctx.workbookRels.addRelationship(ctx.workbookRels.nextRelationshipId, USERS_REL, "users.xml");
11261
- }
11262
- }
11263
- }
11264
- function buildWorkbookRelationships(rels, wsCount, csCount, dsCount = 0) {
11265
- let rid = 1;
11266
- for (let i = 0; i < wsCount; i++) rels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet", `worksheets/sheet${i + 1}.xml`);
11267
- for (let i = 0; i < csCount; i++) rels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet", `chartsheets/sheet${i + 1}.xml`);
11268
- for (let i = 0; i < dsCount; i++) rels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet", `dialogSheets/sheet${i + 1}.xml`);
11269
- rels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", "styles.xml");
11270
- rels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", "theme/theme1.xml");
11271
- }
11272
- function hasMetadataContent(metadata) {
11273
- return (metadata.types?.length ?? 0) > 0 || (metadata.strings?.length ?? 0) > 0 || (metadata.mdx?.length ?? 0) > 0 || (metadata.futureMetadata?.length ?? 0) > 0 || (metadata.cellMetadata?.length ?? 0) > 0 || (metadata.valueMetadata?.length ?? 0) > 0;
11274
- }
11275
- function extractPivotSourceData(rows, sourceRef) {
11276
- const parts = sourceRef.split(":");
11277
- const start = parseA1Cell(parts[0] ?? "");
11278
- if (!start) return {
11279
- fieldNames: [],
11280
- records: []
11281
- };
11282
- const end = parts[1] !== void 0 ? parseA1Cell(parts[1]) : void 0;
11283
- const startRow = start.row - 1;
11284
- const endRow = (end?.row ?? start.row) - 1;
11285
- const startCol = start.col - 1;
11286
- const endCol = (end?.col ?? start.col) - 1;
11287
- const colCount = endCol - startCol + 1;
11288
- const headerRow = rows[startRow];
11289
- const fieldNames = [];
11290
- if (headerRow?.cells) for (let c = startCol; c <= endCol && c < headerRow.cells.length; c++) {
11291
- const hv = headerRow.cells[c]?.value;
11292
- fieldNames.push(typeof hv === "string" ? hv : typeof hv === "number" || typeof hv === "boolean" ? String(hv) : `Col${c}`);
11293
- }
11294
- const records = [];
11295
- for (let r = startRow + 1; r <= endRow; r++) {
11296
- const row = rows[r];
11297
- if (!row?.cells) continue;
11298
- const record = [];
11299
- for (let c = startCol; c <= endCol; c++) {
11300
- const val = row.cells[c]?.value;
11301
- if (typeof val === "number") record.push(val);
11302
- else if (val instanceof Date) record.push(val.getTime());
11303
- else record.push(typeof val === "string" ? val : typeof val === "boolean" ? String(val) : "");
10691
+ const records = [];
10692
+ for (let r = startRow + 1; r <= endRow; r++) {
10693
+ const row = rows[r];
10694
+ if (!row?.cells) continue;
10695
+ const record = [];
10696
+ for (let c = startCol; c <= endCol; c++) {
10697
+ const val = row.cells[c]?.value;
10698
+ if (typeof val === "number") record.push(val);
10699
+ else if (val instanceof Date) record.push(val.getTime());
10700
+ else record.push(typeof val === "string" ? val : typeof val === "boolean" ? String(val) : "");
11304
10701
  }
11305
10702
  if (record.length === colCount) records.push(record);
11306
10703
  }
@@ -11540,6 +10937,629 @@ function colIndexToLetter(col) {
11540
10937
  return columnToLetter(col + 1);
11541
10938
  }
11542
10939
  //#endregion
10940
+ //#region src/compiler.ts
10941
+ /**
10942
+ * XLSX Compiler — compiles WorkbookOptions into a Zippable structure.
10943
+ *
10944
+ * Accepts pure JSON WorkbookOptions — no intermediate File class needed.
10945
+ * Uses XlsxWriteContext for shared state (strings, styles, media, charts).
10946
+ *
10947
+ * @module
10948
+ */
10949
+ const XML_DECL = OOXML_XML_DECLARATION;
10950
+ const IMAGE_REL = RELATIONSHIP_TYPES.image;
10951
+ /** XLSX part path → content type, derived from the part registry. Matches
10952
+ * actual file paths, so the dense/sequential xlsx part naming is handled. */
10953
+ const XLSX_CONTENT_TYPE_RESOLVER$1 = resolverFromRegistry(XLSX_PARTS);
10954
+ /** Chart part → user-shapes part relationship (c:userShapes bridge). */
10955
+ const CHART_USER_SHAPES_REL = RELATIONSHIP_TYPES.chartUserShapes;
10956
+ const PKG_REL_NS = "http://schemas.openxmlformats.org/package/2006/relationships";
10957
+ /** Extension → MIME for image and VML Default entries. Declared only for
10958
+ * extensions actually present in the package. VML backs legacy comment
10959
+ * anchors (xl/drawings/vmlDrawing${i}.vml). */
10960
+ const XLSX_MEDIA_CONTENT_TYPES = {
10961
+ ...IMAGE_MEDIA_CONTENT_TYPES,
10962
+ vml: "application/vnd.openxmlformats-officedocument.vmlDrawing"
10963
+ };
10964
+ /** UTF-8 encoder for serializing the derived [Content_Types].xml into the package. */
10965
+ const encoder = new TextEncoder();
10966
+ /**
10967
+ * Compile workbook options into a Zippable structure.
10968
+ */
10969
+ function compileWorkbook(options, overrides = [], mediaLevel = 0) {
10970
+ const ctx = new XlsxWriteContext();
10971
+ const mapping = {};
10972
+ if (options.sharedStrings) ctx.sharedStrings.loadEntries(options.sharedStrings);
10973
+ const worksheetConfigs = options.worksheets ?? [];
10974
+ const chartsheetConfigs = options.chartsheets ?? [];
10975
+ const dialogsheetConfigs = options.dialogsheets ?? [];
10976
+ const hasCustomProperties = !!options.customProperties && options.customProperties.length > 0;
10977
+ mapping["Properties"] = {
10978
+ data: XML_DECL + buildCorePropertiesXmlString(options),
10979
+ path: "docProps/core.xml"
10980
+ };
10981
+ mapping["AppProperties"] = {
10982
+ data: XML_DECL + (appPropertiesDesc.stringify(options.appProperties ?? {}, ctx) ?? ""),
10983
+ path: "docProps/app.xml"
10984
+ };
10985
+ if (hasCustomProperties) mapping["CustomProperties"] = {
10986
+ data: XML_DECL + (customPropertiesDesc.stringify({ properties: options.customProperties ?? [] }, ctx) ?? ""),
10987
+ path: "docProps/custom.xml"
10988
+ };
10989
+ const fileRels = buildRootRelationships("xl/workbook.xml", hasCustomProperties, options.passthroughRelationships);
10990
+ mapping["FileRelationships"] = {
10991
+ data: XML_DECL + fileRels.serialize(),
10992
+ path: "_rels/.rels"
10993
+ };
10994
+ if (options.dxfs !== void 0) ctx.styles.setDxfs(options.dxfs);
10995
+ if (options.fonts !== void 0) ctx.styles.adopt({
10996
+ fonts: options.fonts,
10997
+ fills: options.fills ?? [],
10998
+ borders: options.borders ?? [],
10999
+ cellXfs: options.cellXfs ?? [],
11000
+ numFmts: options.numFmts
11001
+ });
11002
+ if (options.colors) ctx.styles.setColors(options.colors);
11003
+ if (options.tableStyles) ctx.styles.setTableStyles(options.tableStyles);
11004
+ if (options.cellStyles !== void 0) ctx.styles.setCustomCellStyles(options.cellStyles);
11005
+ if (options.cellStyleXfs !== void 0) ctx.styles.setCellStyleXfs(options.cellStyleXfs);
11006
+ if (options.styleExtensions) ctx.styles.setExtensions(options.styleExtensions);
11007
+ buildWorkbookRelationships(ctx.workbookRels, worksheetConfigs.length, chartsheetConfigs.length, dialogsheetConfigs.length);
11008
+ const sheets = [];
11009
+ let sheetId = 1;
11010
+ const nextSheetId = (explicit) => {
11011
+ const id = explicit ?? sheetId;
11012
+ if (id >= sheetId) sheetId = id + 1;
11013
+ return id;
11014
+ };
11015
+ let rId = 1;
11016
+ for (const ws of worksheetConfigs) sheets.push({
11017
+ name: ws.name ?? `Sheet${sheetId}`,
11018
+ sheetId: nextSheetId(ws.sheetId),
11019
+ state: ws.state,
11020
+ rId: `rId${rId++}`
11021
+ });
11022
+ for (const cs of chartsheetConfigs) sheets.push({
11023
+ name: cs.name ?? `Chart${sheetId}`,
11024
+ sheetId: nextSheetId(cs.sheetId),
11025
+ state: cs.state,
11026
+ rId: `rId${rId++}`
11027
+ });
11028
+ for (const ds of dialogsheetConfigs) sheets.push({
11029
+ name: ds.name ?? `Dialog${sheetId}`,
11030
+ sheetId: nextSheetId(ds.sheetId),
11031
+ state: ds.state,
11032
+ rId: `rId${rId++}`
11033
+ });
11034
+ const wsContext = {
11035
+ sharedStrings: ctx.sharedStrings,
11036
+ styles: ctx.styles
11037
+ };
11038
+ const state = {
11039
+ globalMediaIdx: 0,
11040
+ globalChartIdx: 0,
11041
+ globalPivotIdx: 0,
11042
+ globalPivotCacheIdx: 0,
11043
+ globalTableIdx: 0,
11044
+ globalQueryTableIdx: 0,
11045
+ globalSingleXmlCellsIdx: 0,
11046
+ pivotCacheDataMap: /* @__PURE__ */ new Map(),
11047
+ calcCells: [],
11048
+ allTableParts: []
11049
+ };
11050
+ for (const [i, wsOpts] of worksheetConfigs.entries()) compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsContext, state, options.passthroughRelationships);
11051
+ compileChartsheets(chartsheetConfigs, ctx, mapping, options.passthroughRelationships);
11052
+ compileDialogsheets(dialogsheetConfigs, ctx, mapping);
11053
+ let rtPivotRefs;
11054
+ if (options.pivotCacheRefs && options.pivotCacheRefs.length > 0) {
11055
+ rtPivotRefs = [];
11056
+ for (const ref of options.pivotCacheRefs) {
11057
+ const rel = (options.passthroughRelationships ?? []).find((r) => r.source === "xl/workbook.xml" && r.rId === ref.rId);
11058
+ if (!rel) continue;
11059
+ let rid = ctx.workbookRels.idOf(rel.relationshipType, rel.target);
11060
+ if (rid === void 0) {
11061
+ ctx.workbookRels.add(rel.relationshipType, rel.target);
11062
+ rid = ctx.workbookRels.idOf(rel.relationshipType, rel.target);
11063
+ }
11064
+ if (rid) rtPivotRefs.push({
11065
+ cacheId: ref.cacheId,
11066
+ rId: rid
11067
+ });
11068
+ }
11069
+ }
11070
+ let wbXml = workbookDesc.stringify({
11071
+ sheets,
11072
+ pivotCaches: ctx.pivotCacheRefs.length > 0 ? ctx.pivotCacheRefs : rtPivotRefs ?? [],
11073
+ protection: options.workbookProtection,
11074
+ customViews: options.customWorkbookViews,
11075
+ fileRecovery: options.fileRecovery,
11076
+ functionGroups: options.functionGroups,
11077
+ webPublishing: options.webPublishing,
11078
+ fileSharing: options.fileSharing,
11079
+ webPublishObjects: options.webPublishObjects,
11080
+ definedNames: options.definedNames,
11081
+ properties: options.properties,
11082
+ calculation: options.calculation,
11083
+ oleSize: options.oleSize,
11084
+ bookView: options.bookView,
11085
+ ...options.absPath !== void 0 ? { absPath: options.absPath } : {},
11086
+ ...options.revisionPtr ? { revisionPtr: options.revisionPtr } : {},
11087
+ ...options.extensions ? { extensions: options.extensions } : {}
11088
+ }, ctx) ?? "";
11089
+ if (options.connections && options.connections.length > 0) {
11090
+ const cRid = ctx.workbookRels.nextRelationshipId;
11091
+ ctx.workbookRels.addRelationship(cRid, RELATIONSHIP_TYPES.connections, "connections.xml");
11092
+ mapping["Connections"] = {
11093
+ data: XML_DECL + connectionsDesc.stringify({ connections: options.connections }, ctx),
11094
+ path: "xl/connections.xml"
11095
+ };
11096
+ }
11097
+ if (options.metadata && hasMetadataContent(options.metadata)) {
11098
+ const mRid = ctx.workbookRels.nextRelationshipId;
11099
+ ctx.workbookRels.addRelationship(mRid, RELATIONSHIP_TYPES.sheetMetadata, "metadata.xml");
11100
+ mapping["Metadata"] = {
11101
+ data: XML_DECL + metadataDesc.stringify(options.metadata, ctx),
11102
+ path: "xl/metadata.xml"
11103
+ };
11104
+ }
11105
+ if (options.xmlMaps) {
11106
+ const xRid = ctx.workbookRels.nextRelationshipId;
11107
+ ctx.workbookRels.addRelationship(xRid, RELATIONSHIP_TYPES.xmlMaps, "xmlMaps.xml");
11108
+ mapping["XmlMaps"] = {
11109
+ data: XML_DECL + mapInfoDesc.stringify(options.xmlMaps, ctx),
11110
+ path: "xl/xmlMaps.xml"
11111
+ };
11112
+ }
11113
+ if (options.volTypes && options.volTypes.length > 0) {
11114
+ const vRid = ctx.workbookRels.nextRelationshipId;
11115
+ ctx.workbookRels.addRelationship(vRid, RELATIONSHIP_TYPES.volTypes, "volTypes.xml");
11116
+ mapping["VolTypes"] = {
11117
+ data: XML_DECL + buildVolTypesXml(options.volTypes),
11118
+ path: "xl/volTypes.xml"
11119
+ };
11120
+ }
11121
+ const extLinks = options.externalLinks ?? [];
11122
+ if (extLinks.length > 0) {
11123
+ const extRefs = [];
11124
+ for (let ei = 0; ei < extLinks.length; ei++) {
11125
+ const elIdx = ei + 1;
11126
+ const elRid = ctx.workbookRels.nextRelationshipId;
11127
+ ctx.workbookRels.addRelationship(elRid, RELATIONSHIP_TYPES.externalLink, `externalLinks/externalLink${elIdx}.xml`);
11128
+ const elOpts = extLinks[ei];
11129
+ if (!elOpts) continue;
11130
+ let bookRId;
11131
+ if (elOpts.externalBook?.target) {
11132
+ const elRels = new Relationships();
11133
+ elRels.addRelationship(1, RELATIONSHIP_TYPES.externalLinkPath, elOpts.externalBook.target, TargetModeType.EXTERNAL);
11134
+ bookRId = "rId1";
11135
+ mapping[`ExternalLinkRels${elIdx}`] = {
11136
+ data: XML_DECL + elRels.serialize(),
11137
+ path: `xl/externalLinks/_rels/externalLink${elIdx}.xml.rels`
11138
+ };
11139
+ }
11140
+ mapping[`ExternalLink${elIdx}`] = {
11141
+ data: XML_DECL + externalLinkDesc.stringify({
11142
+ ...elOpts,
11143
+ bookRId
11144
+ }, ctx),
11145
+ path: `xl/externalLinks/externalLink${elIdx}.xml`
11146
+ };
11147
+ extRefs.push({ rId: `rId${elRid}` });
11148
+ }
11149
+ const extRefsXml = buildExternalReferencesXml(extRefs);
11150
+ wbXml = wbXml.replace("<!--EXTERNAL_REFS-->", extRefsXml);
11151
+ } else wbXml = wbXml.replace("<!--EXTERNAL_REFS-->", "");
11152
+ mapping["Workbook"] = {
11153
+ data: XML_DECL + wbXml,
11154
+ path: "xl/workbook.xml"
11155
+ };
11156
+ if (ctx.sharedStrings.count > 0) {
11157
+ ctx.workbookRels.addRelationship(ctx.workbookRels.nextRelationshipId, RELATIONSHIP_TYPES.sharedStrings, "sharedStrings.xml");
11158
+ const ssXml = sharedStringsDesc.stringify(ctx.sharedStrings.toDescriptorOptions(), ctx);
11159
+ mapping["SharedStrings"] = {
11160
+ data: XML_DECL + ssXml,
11161
+ path: "xl/sharedStrings.xml"
11162
+ };
11163
+ }
11164
+ const stylesXml = stylesDesc.stringify({ styles: ctx.styles }, ctx);
11165
+ mapping["Styles"] = {
11166
+ data: XML_DECL + stylesXml,
11167
+ path: "xl/styles.xml"
11168
+ };
11169
+ const themeRels = new Relationships();
11170
+ const themeXml = options.theme ? bindMediaPlaceholders(buildThemeXml(options.theme, ctx), ctx.media, themeRels) : createThemeXml$1();
11171
+ mapping["Theme"] = {
11172
+ data: XML_DECL + themeXml,
11173
+ path: "xl/theme/theme1.xml"
11174
+ };
11175
+ if (themeRels.relationshipCount > 0) mapping["ThemeRels"] = {
11176
+ data: XML_DECL + themeRels.serialize(),
11177
+ path: "xl/theme/_rels/theme1.xml.rels"
11178
+ };
11179
+ for (const [i, chartData] of ctx.charts.array.entries()) {
11180
+ mapping[`Chart${i}`] = {
11181
+ data: XML_DECL + chartData.chartSpaceXml,
11182
+ path: `xl/charts/chart${i + 1}.xml`
11183
+ };
11184
+ if (chartData.userShapes) {
11185
+ const rid = chartData.userShapes.relationshipId;
11186
+ mapping[`ChartUserShapes${i}`] = {
11187
+ data: XML_DECL + chartData.userShapes.xml,
11188
+ path: `xl/charts/userShapes${i + 1}.xml`
11189
+ };
11190
+ mapping[`ChartRels${i}`] = {
11191
+ data: XML_DECL + `<Relationships xmlns="${PKG_REL_NS}"><Relationship Id="${escapeXml(rid)}" Type="${CHART_USER_SHAPES_REL}" Target="userShapes${i + 1}.xml"/></Relationships>`,
11192
+ path: `xl/charts/_rels/chart${i + 1}.xml.rels`
11193
+ };
11194
+ }
11195
+ }
11196
+ const calcChainCells = options.calcChain ?? state.calcCells;
11197
+ const srcReferencesCalcChain = (options.passthroughRelationships ?? []).some((r) => r.source === "xl/workbook.xml" && r.relationshipType.endsWith("/calcChain"));
11198
+ if (calcChainCells.length > 0 && !(srcReferencesCalcChain && options.calcChain === void 0)) {
11199
+ mapping["CalcChain"] = {
11200
+ data: calcChainDesc.stringify({ cells: calcChainCells }, ctx) ?? "",
11201
+ path: "xl/calcChain.xml"
11202
+ };
11203
+ const calcChainRid = ctx.workbookRels.nextRelationshipId;
11204
+ ctx.workbookRels.addRelationship(calcChainRid, RELATIONSHIP_TYPES.calcChain, "calcChain.xml");
11205
+ }
11206
+ if (options.revisionLog) compileRevisionLogs(options.revisionLog, ctx, mapping);
11207
+ for (const rel of options.passthroughRelationships ?? []) {
11208
+ if (rel.source !== "xl/workbook.xml") continue;
11209
+ if (ctx.workbookRels.hasRelationship(rel.relationshipType, rel.target)) continue;
11210
+ ctx.workbookRels.add(rel.relationshipType, rel.target);
11211
+ }
11212
+ mapping["WorkbookRelationships"] = {
11213
+ data: XML_DECL + ctx.workbookRels.serialize(),
11214
+ path: "xl/_rels/workbook.xml.rels"
11215
+ };
11216
+ const mediaFiles = [];
11217
+ for (const img of ctx.media.array) mediaFiles.push({
11218
+ data: img.data,
11219
+ path: `xl/media/${img.fileName}`
11220
+ });
11221
+ const files = compileMapping(mapping, overrides, mediaFiles, mediaLevel);
11222
+ files["[Content_Types].xml"] = encoder.encode(finalizeContentTypes(files, {
11223
+ resolve: XLSX_CONTENT_TYPE_RESOLVER$1,
11224
+ mediaContentTypes: XLSX_MEDIA_CONTENT_TYPES,
11225
+ source: options.contentTypes,
11226
+ rawParts: options.rawParts
11227
+ }, ctx));
11228
+ dropDanglingPassthroughRels(files, options.passthroughRelationships);
11229
+ return files;
11230
+ }
11231
+ /**
11232
+ * Compile one worksheet: sheet XML, calcChain cells, drawing/media,
11233
+ * comments + VML, background, pivots, tables, query tables and
11234
+ * single-cell XML tables, with their worksheet-level relationships.
11235
+ * Rel registration order is significant (rIds are assigned sequentially).
11236
+ */
11237
+ function compileWorksheetPart(wsOpts, i, worksheetConfigs, ctx, mapping, wsContext, state, passthroughRelationships) {
11238
+ const imgOpts = wsOpts.images ?? [];
11239
+ const chartOpts = wsOpts.charts ?? [];
11240
+ const smartArtOpts = wsOpts.smartArts ?? [];
11241
+ const shapeOpts = wsOpts.shapes ?? [];
11242
+ const connectorOpts = wsOpts.connectors ?? [];
11243
+ const groupOpts = wsOpts.groups ?? [];
11244
+ const hlOpts = wsOpts.hyperlinks ?? [];
11245
+ const sheetName = wsOpts.name ?? `Sheet${i + 1}`;
11246
+ const sheetIdx = wsOpts.sheetId ?? i + 1;
11247
+ const wsRows = wsOpts.rows ?? [];
11248
+ for (let ri = 0; ri < wsRows.length; ri++) {
11249
+ const rowOpts = wsRows[ri];
11250
+ const rowNumber = rowOpts.rowNumber ?? ri + 1;
11251
+ const cells = rowOpts.cells;
11252
+ if (!cells) continue;
11253
+ for (let ci = 0; ci < cells.length; ci++) {
11254
+ const cell = cells[ci];
11255
+ if (!cell.formula) continue;
11256
+ const ref = cell.reference ?? columnToLetter(ci + 1) + rowNumber;
11257
+ state.calcCells.push({
11258
+ reference: ref,
11259
+ sheetIndex: sheetIdx,
11260
+ array: typeof cell.formula === "object" && cell.formula.type === "array"
11261
+ });
11262
+ }
11263
+ }
11264
+ const hasMedia = imgOpts.length > 0 || chartOpts.length > 0 || smartArtOpts.length > 0 || shapeOpts.length > 0 || connectorOpts.length > 0 || groupOpts.length > 0;
11265
+ const hasExternalHyperlinks = hlOpts.some((h) => h.url !== void 0);
11266
+ const commentOpts = wsOpts.comments ?? [];
11267
+ const hasComments = commentOpts.length > 0;
11268
+ const pivotOpts = wsOpts.pivotTables ?? [];
11269
+ const hasPivots = pivotOpts.length > 0;
11270
+ const tableOpts = wsOpts.tables ?? [];
11271
+ const hasTables = tableOpts.length > 0;
11272
+ const queryTableOpts = wsOpts.queryTables ?? [];
11273
+ const hasQueryTables = queryTableOpts.length > 0;
11274
+ const singleXmlCellOpts = wsOpts.singleXmlCells ?? [];
11275
+ const bgImg = wsOpts.backgroundImage;
11276
+ const wsPath = `xl/worksheets/sheet${i + 1}.xml`;
11277
+ let wsRels;
11278
+ if (hasMedia || hasExternalHyperlinks || hasComments || hasPivots || hasTables || hasQueryTables || singleXmlCellOpts.length > 0 || bgImg) {
11279
+ wsRels = new Relationships();
11280
+ wsRels.reserveSourceRids(wsPath, passthroughRelationships ?? []);
11281
+ }
11282
+ const resolvePassthroughRid = (typeFragment, originalRid) => {
11283
+ if (!wsRels) return originalRid;
11284
+ const rel = (passthroughRelationships ?? []).find((r) => r.source === wsPath && r.rId === originalRid && r.relationshipType.endsWith(typeFragment));
11285
+ if (!rel) return originalRid;
11286
+ const existing = wsRels.idOf(rel.relationshipType, rel.target);
11287
+ if (existing) return existing;
11288
+ if (wsRels.hasId(originalRid)) return `rId${wsRels.add(rel.relationshipType, rel.target)}`;
11289
+ wsRels.addRelationship(originalRid, rel.relationshipType, rel.target);
11290
+ return originalRid;
11291
+ };
11292
+ const resolveEmbeddingRid = (originalRid) => {
11293
+ const rid = resolvePassthroughRid("/oleObject", originalRid);
11294
+ return rid === originalRid ? resolvePassthroughRid("/package", originalRid) : rid;
11295
+ };
11296
+ let xmlOpts = wsOpts;
11297
+ if (wsRels && (passthroughRelationships?.length ?? 0) > 0) {
11298
+ const oleObjects = wsOpts.oleObjects?.map((ole) => ({
11299
+ ...ole,
11300
+ rId: ole.rId ? resolveEmbeddingRid(ole.rId) : ole.rId,
11301
+ properties: ole.properties?.iconRid !== void 0 ? {
11302
+ ...ole.properties,
11303
+ iconRid: resolvePassthroughRid("/image", ole.properties.iconRid)
11304
+ } : ole.properties
11305
+ }));
11306
+ const controls = wsOpts.controls?.map((c) => ({
11307
+ ...c,
11308
+ rId: resolvePassthroughRid("/controls", c.rId),
11309
+ iconRid: c.iconRid !== void 0 ? resolvePassthroughRid("/image", c.iconRid) : c.iconRid
11310
+ }));
11311
+ const pageSetup = wsOpts.pageSetup?.printerSettingsRId ? {
11312
+ ...wsOpts.pageSetup,
11313
+ printerSettingsRId: resolvePassthroughRid("/printerSettings", wsOpts.pageSetup.printerSettingsRId)
11314
+ } : wsOpts.pageSetup;
11315
+ const pivotSelection = wsOpts.pivotSelection?.rId ? {
11316
+ ...wsOpts.pivotSelection,
11317
+ rId: resolvePassthroughRid("/pivotTable", wsOpts.pivotSelection.rId)
11318
+ } : wsOpts.pivotSelection;
11319
+ const legacyDrawingHF = wsOpts.legacyDrawingHF ? resolvePassthroughRid("/vmlDrawing", wsOpts.legacyDrawingHF) : wsOpts.legacyDrawingHF;
11320
+ const customProperties = wsOpts.customProperties?.map((cp) => ({
11321
+ ...cp,
11322
+ rId: resolvePassthroughRid("/customXml", cp.rId)
11323
+ }));
11324
+ xmlOpts = {
11325
+ ...wsOpts,
11326
+ ...oleObjects ? { oleObjects } : {},
11327
+ ...controls ? { controls } : {},
11328
+ ...pageSetup !== wsOpts.pageSetup ? { pageSetup } : {},
11329
+ ...pivotSelection !== wsOpts.pivotSelection ? { pivotSelection } : {},
11330
+ ...legacyDrawingHF !== wsOpts.legacyDrawingHF ? { legacyDrawingHF } : {},
11331
+ ...customProperties ? { customProperties } : {}
11332
+ };
11333
+ }
11334
+ let sheetXml = stringifyWorksheet(xmlOpts, wsContext);
11335
+ if (hasExternalHyperlinks) for (const hl of hlOpts) {
11336
+ if (hl.url === void 0) continue;
11337
+ wsRels.add(RELATIONSHIP_TYPES.hyperlink, hl.url, "External");
11338
+ }
11339
+ if (hasMedia) sheetXml = compileSheetDrawing(wsOpts, i, sheetXml, ctx, mapping, state, wsRels);
11340
+ if (hasComments) {
11341
+ const commentsIdx = i + 1;
11342
+ const commentsXml = commentsDesc.stringify({ comments: commentOpts }, ctx);
11343
+ mapping[`Comments${i}`] = {
11344
+ data: XML_DECL + commentsXml,
11345
+ path: `xl/comments${commentsIdx}.xml`
11346
+ };
11347
+ const vmlXml = vmlNotesDesc.stringify({ comments: commentOpts }, ctx);
11348
+ mapping[`VmlDrawing${i}`] = {
11349
+ data: XML_DECL + vmlXml,
11350
+ path: `xl/drawings/vmlDrawing${commentsIdx}.vml`
11351
+ };
11352
+ wsRels.add(RELATIONSHIP_TYPES.comments, `../comments${commentsIdx}.xml`);
11353
+ const vmlRid = wsRels.add(RELATIONSHIP_TYPES.vmlDrawing, `../drawings/vmlDrawing${commentsIdx}.vml`);
11354
+ sheetXml = editSheetTailMarker(sheetXml, "<!--LEGACY_DRAWING-->", `<legacyDrawing r:id="rId${vmlRid}"/>`);
11355
+ }
11356
+ if (bgImg) {
11357
+ const ext = bgImg.type === "jpg" ? "jpeg" : bgImg.type;
11358
+ const rawBytes = toUint8Array(bgImg.data, { encoding: "base64" });
11359
+ const entry = ctx.media.addMedia(rawBytes, ext, (fileName) => ({
11360
+ fileName,
11361
+ type: ext,
11362
+ data: rawBytes,
11363
+ width: 0,
11364
+ height: 0
11365
+ }));
11366
+ state.globalMediaIdx++;
11367
+ const bgRid = wsRels.add(IMAGE_REL, `../media/${entry.fileName}`);
11368
+ sheetXml = editSheetTailMarker(sheetXml, "<!--BACKGROUND_PICTURE-->", `<picture r:id="rId${bgRid}"/>`);
11369
+ }
11370
+ if (wsOpts.drawingRid) {
11371
+ const rid = escapeXml(resolvePassthroughRid("/drawing", wsOpts.drawingRid));
11372
+ sheetXml = editSheetTailMarker(sheetXml, "<!--DRAWING-->", `<drawing r:id="${rid}"/>`);
11373
+ }
11374
+ if (wsOpts.legacyDrawingRid) {
11375
+ const rid = escapeXml(resolvePassthroughRid("/vmlDrawing", wsOpts.legacyDrawingRid));
11376
+ sheetXml = editSheetTailMarker(sheetXml, "<!--LEGACY_DRAWING-->", `<legacyDrawing r:id="${rid}"/>`);
11377
+ }
11378
+ if (hasPivots) compileSheetPivots(wsOpts, worksheetConfigs, ctx, mapping, state, wsRels, sheetName);
11379
+ const wsTableParts = [];
11380
+ if (hasTables) for (const tbl of tableOpts) {
11381
+ state.globalTableIdx++;
11382
+ const tableIdx = state.globalTableIdx;
11383
+ if (!tbl.columns?.length) continue;
11384
+ const tableXmlStr = XML_DECL + tableDesc.stringify({
11385
+ ...tbl,
11386
+ id: tbl.id ?? tableIdx
11387
+ }, ctx);
11388
+ mapping[`Table${tableIdx}`] = {
11389
+ data: tableXmlStr,
11390
+ path: `xl/tables/table${tableIdx}.xml`
11391
+ };
11392
+ const tblRid = wsRels.add(RELATIONSHIP_TYPES.table, `../tables/table${tableIdx}.xml`);
11393
+ wsTableParts.push({ rId: `rId${tblRid}` });
11394
+ state.allTableParts.push({ rId: `rId${tblRid}` });
11395
+ }
11396
+ if (hasQueryTables) for (const qt of queryTableOpts) {
11397
+ state.globalQueryTableIdx++;
11398
+ mapping[`QueryTable${state.globalQueryTableIdx}`] = {
11399
+ data: XML_DECL + queryTableDesc.stringify(qt, ctx),
11400
+ path: `xl/queryTables/queryTable${state.globalQueryTableIdx}.xml`
11401
+ };
11402
+ wsRels.add(RELATIONSHIP_TYPES.queryTable, `../queryTables/queryTable${state.globalQueryTableIdx}.xml`);
11403
+ }
11404
+ if (singleXmlCellOpts.length > 0) {
11405
+ state.globalSingleXmlCellsIdx++;
11406
+ mapping[`TableSingleCells${state.globalSingleXmlCellsIdx}`] = {
11407
+ data: XML_DECL + singleXmlCellsDesc.stringify({ cells: singleXmlCellOpts }, ctx),
11408
+ path: `xl/tables/tableSingleCells${state.globalSingleXmlCellsIdx}.xml`
11409
+ };
11410
+ wsRels.add(RELATIONSHIP_TYPES.tableSingleCells, `../tables/tableSingleCells${state.globalSingleXmlCellsIdx}.xml`);
11411
+ }
11412
+ if (hasPivots) {
11413
+ const rendered = renderPivotSheetData(pivotOpts, worksheetConfigs, ctx.sharedStrings, sheetName);
11414
+ if (rendered.sheetData.length > 0) {
11415
+ sheetXml = sheetXml.replace(/<sheetData\/>|<sheetData><\/sheetData>/, rendered.sheetData);
11416
+ if (!sheetXml.includes("<dimension")) sheetXml = sheetXml.replace("<sheetViews", `<dimension ref="${rendered.dimensionRef}"/><sheetViews`);
11417
+ }
11418
+ }
11419
+ if (wsTableParts.length > 0) sheetXml = editSheetTailMarker(sheetXml, "<!--TABLE_PARTS-->", buildTablePartsXml(wsTableParts));
11420
+ sheetXml = stripWorksheetPlaceholders(sheetXml);
11421
+ if (wsRels) for (const rel of passthroughRelationships ?? []) {
11422
+ if (rel.source !== wsPath) continue;
11423
+ wsRels.claimSourceRel(rel);
11424
+ }
11425
+ if (wsRels) mapping[`WorksheetRels${i}`] = {
11426
+ data: XML_DECL + wsRels.serialize(),
11427
+ path: `xl/worksheets/_rels/sheet${i + 1}.xml.rels`
11428
+ };
11429
+ mapping[`Worksheet${i}`] = {
11430
+ data: sheetXml,
11431
+ path: `xl/worksheets/sheet${i + 1}.xml`
11432
+ };
11433
+ }
11434
+ /** Full-page default frame for a fresh chartsheet chart (≈9.70×6.35 in). */
11435
+ const CHARTSHEET_DEFAULT_CX = 9308969;
11436
+ const CHARTSHEET_DEFAULT_CY = 6096e3;
11437
+ /** Compile all chartsheets: chart part, chartsheet/drawing XML and rels. */
11438
+ function compileChartsheets(chartsheetConfigs, ctx, mapping, passthroughRelationships) {
11439
+ for (const [i, csOpts] of chartsheetConfigs.entries()) {
11440
+ const chartDef = csOpts.chart;
11441
+ if (!chartDef) continue;
11442
+ const csChartGlobalIdx = ctx.charts.array.length;
11443
+ const csChartKey = `cs_chart_${csChartGlobalIdx}`;
11444
+ const csUserShapes = chartDef.userShapes ? buildUserShapesData(chartDef.userShapes) : void 0;
11445
+ ctx.charts.addChart(csChartKey, {
11446
+ key: csChartKey,
11447
+ chartSpaceXml: chartSpaceDesc.stringify(chartDef, ctx) ?? "",
11448
+ ...csUserShapes ? { userShapes: csUserShapes } : {}
11449
+ });
11450
+ const csRels = new Relationships();
11451
+ const csDrawingIdx = i + 1;
11452
+ csRels.addRelationship(1, RELATIONSHIP_TYPES.drawing, `../drawings/drawing${csDrawingIdx}.xml`);
11453
+ let csNextRid = 2;
11454
+ for (const rel of passthroughRelationships ?? []) {
11455
+ if (rel.source !== `xl/chartsheets/sheet${i + 1}.xml`) continue;
11456
+ if (csRels.hasRelationship(rel.relationshipType, rel.target)) continue;
11457
+ csRels.addRelationship(csNextRid++, rel.relationshipType, rel.target);
11458
+ }
11459
+ const csDrawingRels = new Relationships();
11460
+ csDrawingRels.addRelationship(1, RELATIONSHIP_TYPES.chart, `../charts/chart${csChartGlobalIdx + 1}.xml`);
11461
+ const frame = graphicFrameXml(csOpts.shapeId ?? 1, void 0, `Chart ${i + 1}`, "rId1", 0, 0, ctx, {
11462
+ frameLocks: csOpts.frameLocks,
11463
+ macro: csOpts.macro
11464
+ });
11465
+ const anchor = wrapAnchor({
11466
+ anchorType: "absolute",
11467
+ col: 1,
11468
+ row: 1,
11469
+ absoluteX: csOpts.absoluteX ?? 0,
11470
+ absoluteY: csOpts.absoluteY ?? 0,
11471
+ extentCx: csOpts.extentCx ?? CHARTSHEET_DEFAULT_CX,
11472
+ extentCy: csOpts.extentCy ?? CHARTSHEET_DEFAULT_CY
11473
+ }, `${frame}<xdr:clientData/>`);
11474
+ const csDrawingXml = `<xdr:wsDr xmlns:xdr="${XDR_NS}" xmlns:a="${A_NS}" xmlns:r="${R_NS$1}">${anchor}</xdr:wsDr>`;
11475
+ mapping[`ChartsheetDrawing${i}`] = {
11476
+ data: csDrawingXml,
11477
+ path: `xl/drawings/drawing${csDrawingIdx}.xml`
11478
+ };
11479
+ mapping[`ChartsheetDrawingRels${i}`] = {
11480
+ data: XML_DECL + csDrawingRels.serialize(),
11481
+ path: `xl/drawings/_rels/drawing${csDrawingIdx}.xml.rels`
11482
+ };
11483
+ mapping[`ChartsheetRels${i}`] = {
11484
+ data: XML_DECL + csRels.serialize(),
11485
+ path: `xl/chartsheets/_rels/sheet${i + 1}.xml.rels`
11486
+ };
11487
+ let csPageSetup = csOpts.pageSetup;
11488
+ if (csPageSetup?.printerSettingsRId) {
11489
+ const srcRid = csPageSetup.printerSettingsRId;
11490
+ const rel = (passthroughRelationships ?? []).find((r) => r.source === `xl/chartsheets/sheet${i + 1}.xml` && r.rId === srcRid && r.relationshipType.endsWith("/printerSettings"));
11491
+ const rid = rel ? csRels.idOf(rel.relationshipType, rel.target) ?? srcRid : srcRid;
11492
+ if (rid !== srcRid) csPageSetup = {
11493
+ ...csPageSetup,
11494
+ printerSettingsRId: rid
11495
+ };
11496
+ }
11497
+ mapping[`Chartsheet${i}`] = {
11498
+ data: XML_DECL + chartsheetDesc.stringify({
11499
+ ...csOpts,
11500
+ drawingRId: "rId1",
11501
+ pageSetup: csPageSetup
11502
+ }, ctx),
11503
+ path: `xl/chartsheets/sheet${i + 1}.xml`
11504
+ };
11505
+ }
11506
+ }
11507
+ /** Compile all dialog sheets (legacy Excel 5.0 dialog sheets). */
11508
+ function compileDialogsheets(dialogsheetConfigs, ctx, mapping) {
11509
+ for (const [i, dsOpts] of dialogsheetConfigs.entries()) mapping[`Dialogsheet${i}`] = {
11510
+ data: XML_DECL + dialogsheetDesc.stringify(dsOpts, ctx),
11511
+ path: `xl/dialogSheets/sheet${i + 1}.xml`
11512
+ };
11513
+ }
11514
+ /**
11515
+ * Compile shared-workbook revisions (xl/revisionHeaders.xml +
11516
+ * xl/revisions/revisionN.xml + xl/users.xml). CT_Workbook has no revision
11517
+ * element — parts are discovered via workbook.xml.rels + [Content_Types].
11518
+ */
11519
+ function compileRevisionLogs(rl, ctx, mapping) {
11520
+ const REV_HEADERS_REL = RELATIONSHIP_TYPES.revisionHeaders;
11521
+ const REV_LOG_REL = RELATIONSHIP_TYPES.revisionLog;
11522
+ const USERS_REL = RELATIONSHIP_TYPES.users;
11523
+ mapping["RevisionHeaders"] = {
11524
+ data: XML_DECL + (revisionHeadersDesc.stringify(rl.headers, ctx) ?? ""),
11525
+ path: "xl/revisionHeaders.xml"
11526
+ };
11527
+ ctx.workbookRels.addRelationship(ctx.workbookRels.nextRelationshipId, REV_HEADERS_REL, "revisionHeaders.xml");
11528
+ const revHeadersRels = new Relationships();
11529
+ for (const [i, log] of rl.logs.entries()) {
11530
+ mapping[`RevisionLog${i}`] = {
11531
+ data: XML_DECL + (revisionLogDesc.stringify(log, ctx) ?? ""),
11532
+ path: `xl/revisions/revision${i + 1}.xml`
11533
+ };
11534
+ revHeadersRels.addRelationship(i + 1, REV_LOG_REL, `revisions/revision${i + 1}.xml`);
11535
+ }
11536
+ mapping["RevisionHeadersRels"] = {
11537
+ data: XML_DECL + revHeadersRels.serialize(),
11538
+ path: "xl/_rels/revisionHeaders.xml.rels"
11539
+ };
11540
+ if (rl.users) {
11541
+ const usersXml = usersDesc.stringify(rl.users, ctx);
11542
+ if (usersXml) {
11543
+ mapping["Users"] = {
11544
+ data: XML_DECL + usersXml,
11545
+ path: "xl/users.xml"
11546
+ };
11547
+ ctx.workbookRels.addRelationship(ctx.workbookRels.nextRelationshipId, USERS_REL, "users.xml");
11548
+ }
11549
+ }
11550
+ }
11551
+ function buildWorkbookRelationships(rels, wsCount, csCount, dsCount = 0) {
11552
+ let rid = 1;
11553
+ for (let i = 0; i < wsCount; i++) rels.addRelationship(rid++, RELATIONSHIP_TYPES.worksheet, `worksheets/sheet${i + 1}.xml`);
11554
+ for (let i = 0; i < csCount; i++) rels.addRelationship(rid++, RELATIONSHIP_TYPES.chartsheet, `chartsheets/sheet${i + 1}.xml`);
11555
+ for (let i = 0; i < dsCount; i++) rels.addRelationship(rid++, RELATIONSHIP_TYPES.dialogsheet, `dialogSheets/sheet${i + 1}.xml`);
11556
+ rels.addRelationship(rid++, RELATIONSHIP_TYPES.styles, "styles.xml");
11557
+ rels.addRelationship(rid++, RELATIONSHIP_TYPES.theme, "theme/theme1.xml");
11558
+ }
11559
+ function hasMetadataContent(metadata) {
11560
+ return (metadata.types?.length ?? 0) > 0 || (metadata.strings?.length ?? 0) > 0 || (metadata.mdx?.length ?? 0) > 0 || (metadata.futureMetadata?.length ?? 0) > 0 || (metadata.cellMetadata?.length ?? 0) > 0 || (metadata.valueMetadata?.length ?? 0) > 0;
11561
+ }
11562
+ //#endregion
11543
11563
  //#region src/stream.ts
11544
11564
  /**
11545
11565
  * Streaming XLSX compilation — writes parts into a {@link ZipStreamWriter} as
@@ -11662,10 +11682,10 @@ function streamWorkbook(options, ondata, compression = {}) {
11662
11682
  if (hasVolTypes) writeString("xl/volTypes.xml", OOXML_XML_DECLARATION + buildVolTypesXml(options.volTypes ?? []));
11663
11683
  const wbRels = new Relationships();
11664
11684
  let rid = 1;
11665
- for (let i = 0; i < sheets.length; i++) wbRels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet", `worksheets/sheet${i + 1}.xml`);
11666
- wbRels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles", "styles.xml");
11667
- wbRels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme", "theme/theme1.xml");
11668
- if (hasVolTypes) wbRels.addRelationship(rid++, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/volTypes", "volTypes.xml");
11685
+ for (let i = 0; i < sheets.length; i++) wbRels.addRelationship(rid++, RELATIONSHIP_TYPES.worksheet, `worksheets/sheet${i + 1}.xml`);
11686
+ wbRels.addRelationship(rid++, RELATIONSHIP_TYPES.styles, "styles.xml");
11687
+ wbRels.addRelationship(rid++, RELATIONSHIP_TYPES.theme, "theme/theme1.xml");
11688
+ if (hasVolTypes) wbRels.addRelationship(rid++, RELATIONSHIP_TYPES.volTypes, "volTypes.xml");
11669
11689
  writeString("xl/_rels/workbook.xml.rels", OOXML_XML_DECLARATION + wbRels.serialize());
11670
11690
  for (const [i, ws] of worksheets.entries()) {
11671
11691
  const rows = ws.rows ?? [];