@cj-tech-master/excelts 4.2.3-canary.20260115111903.b80904d → 4.2.3-canary.20260122075539.cc11b20

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 (48) hide show
  1. package/dist/browser/modules/csv/csv-core.d.ts +0 -9
  2. package/dist/browser/modules/csv/csv.browser.js +3 -3
  3. package/dist/browser/modules/excel/utils/parse-sax.d.ts +0 -3
  4. package/dist/browser/modules/excel/utils/parse-sax.js +13 -32
  5. package/dist/browser/modules/excel/utils/passthrough-manager.d.ts +77 -0
  6. package/dist/browser/modules/excel/utils/passthrough-manager.js +129 -0
  7. package/dist/browser/modules/excel/workbook.d.ts +8 -0
  8. package/dist/browser/modules/excel/workbook.js +9 -1
  9. package/dist/browser/modules/excel/worksheet.d.ts +4 -0
  10. package/dist/browser/modules/excel/worksheet.js +4 -1
  11. package/dist/browser/modules/excel/xlsx/xform/base-xform.js +68 -1
  12. package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +16 -10
  13. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +34 -11
  14. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +256 -86
  15. package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +38 -11
  16. package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +36 -1
  17. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +213 -131
  18. package/dist/cjs/modules/csv/csv.browser.js +3 -3
  19. package/dist/cjs/modules/excel/utils/parse-sax.js +13 -32
  20. package/dist/cjs/modules/excel/utils/passthrough-manager.js +133 -0
  21. package/dist/cjs/modules/excel/workbook.js +9 -1
  22. package/dist/cjs/modules/excel/worksheet.js +4 -1
  23. package/dist/cjs/modules/excel/xlsx/xform/base-xform.js +68 -1
  24. package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +16 -10
  25. package/dist/cjs/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +256 -86
  26. package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +38 -11
  27. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +213 -131
  28. package/dist/esm/modules/csv/csv.browser.js +3 -3
  29. package/dist/esm/modules/excel/utils/parse-sax.js +13 -32
  30. package/dist/esm/modules/excel/utils/passthrough-manager.js +129 -0
  31. package/dist/esm/modules/excel/workbook.js +9 -1
  32. package/dist/esm/modules/excel/worksheet.js +4 -1
  33. package/dist/esm/modules/excel/xlsx/xform/base-xform.js +68 -1
  34. package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +16 -10
  35. package/dist/esm/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +256 -86
  36. package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +38 -11
  37. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +213 -131
  38. package/dist/iife/excelts.iife.js +571 -267
  39. package/dist/iife/excelts.iife.js.map +1 -1
  40. package/dist/iife/excelts.iife.min.js +25 -52
  41. package/dist/types/modules/csv/csv-core.d.ts +0 -9
  42. package/dist/types/modules/excel/utils/parse-sax.d.ts +0 -3
  43. package/dist/types/modules/excel/utils/passthrough-manager.d.ts +77 -0
  44. package/dist/types/modules/excel/workbook.d.ts +8 -0
  45. package/dist/types/modules/excel/worksheet.d.ts +4 -0
  46. package/dist/types/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +34 -11
  47. package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +36 -1
  48. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @cj-tech-master/excelts v4.2.3-canary.20260115111903.b80904d
2
+ * @cj-tech-master/excelts v4.2.3-canary.20260122075539.cc11b20
3
3
  * TypeScript Excel Workbook Manager - Read and Write xlsx and csv Files.
4
4
  * (c) 2026 cjnoname
5
5
  * Released under the MIT License
@@ -6216,7 +6216,8 @@ var ExcelTS = (function(exports) {
6216
6216
  tables: Object.values(this.tables).map((table) => table.model),
6217
6217
  pivotTables: this.pivotTables,
6218
6218
  conditionalFormattings: this.conditionalFormattings,
6219
- formControls: this.formControls.map((fc) => fc.model)
6219
+ formControls: this.formControls.map((fc) => fc.model),
6220
+ drawing: this._drawing
6220
6221
  };
6221
6222
  model.cols = Column.toModel(this.columns || []);
6222
6223
  const rows = model.rows = [];
@@ -6271,6 +6272,7 @@ var ExcelTS = (function(exports) {
6271
6272
  this.pivotTables = value.pivotTables;
6272
6273
  this.conditionalFormattings = value.conditionalFormattings;
6273
6274
  this.formControls = [];
6275
+ this._drawing = value.drawing;
6274
6276
  }
6275
6277
  };
6276
6278
 
@@ -6763,8 +6765,6 @@ var ExcelTS = (function(exports) {
6763
6765
  quot: "\"",
6764
6766
  apos: "'"
6765
6767
  };
6766
- const HAN_CELL_PREFIXES = /^(ep|cp|dc|dcterms|dcmitype|vt):/;
6767
- const SPREADSHEETML_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
6768
6768
  const S_TEXT = 0;
6769
6769
  const S_OPEN_WAKA = 1;
6770
6770
  const S_OPEN_WAKA_BANG = 2;
@@ -6816,7 +6816,6 @@ var ExcelTS = (function(exports) {
6816
6816
  this.positionAtNewLine = 0;
6817
6817
  this.chunkPosition = 0;
6818
6818
  this.ENTITIES = { ...XML_ENTITIES };
6819
- this.nsPrefix = null;
6820
6819
  this.trackPosition = opt?.position !== false;
6821
6820
  this.fileName = opt?.fileName;
6822
6821
  this.fragment = opt?.fragment ?? false;
@@ -6851,11 +6850,6 @@ var ExcelTS = (function(exports) {
6851
6850
  this.chunk = "";
6852
6851
  this.i = 0;
6853
6852
  this.prevI = 0;
6854
- this.nsPrefix = null;
6855
- }
6856
- stripNsPrefix(name) {
6857
- const n = name.replace(HAN_CELL_PREFIXES, "");
6858
- return this.nsPrefix && n.startsWith(this.nsPrefix + ":") ? n.slice(this.nsPrefix.length + 1) : n;
6859
6853
  }
6860
6854
  on(name, handler) {
6861
6855
  switch (name) {
@@ -7195,7 +7189,7 @@ var ExcelTS = (function(exports) {
7195
7189
  return;
7196
7190
  }
7197
7191
  this.tag = {
7198
- name: this.stripNsPrefix(this.name),
7192
+ name: this.name,
7199
7193
  attributes: Object.create(null),
7200
7194
  isSelfClosing: false
7201
7195
  };
@@ -7491,7 +7485,8 @@ var ExcelTS = (function(exports) {
7491
7485
  openTag() {
7492
7486
  const tag = this.tag;
7493
7487
  tag.isSelfClosing = false;
7494
- this.processAttributes(tag);
7488
+ for (const { name, value } of this.attribList) tag.attributes[name] = value;
7489
+ this.attribList = [];
7495
7490
  this.openTagHandler?.(tag);
7496
7491
  this.tags.push(tag);
7497
7492
  this.name = "";
@@ -7500,26 +7495,16 @@ var ExcelTS = (function(exports) {
7500
7495
  openSelfClosingTag() {
7501
7496
  const tag = this.tag;
7502
7497
  tag.isSelfClosing = true;
7503
- this.processAttributes(tag);
7498
+ for (const { name, value } of this.attribList) tag.attributes[name] = value;
7499
+ this.attribList = [];
7504
7500
  this.openTagHandler?.(tag);
7505
7501
  this.closeTagHandler?.(tag);
7506
7502
  if (this.tags.length === 0) this.closedRoot = true;
7507
7503
  this.name = "";
7508
7504
  this.state = S_TEXT;
7509
7505
  }
7510
- processAttributes(tag) {
7511
- for (const { name, value } of this.attribList) {
7512
- tag.attributes[name] = value;
7513
- if (name.startsWith("xmlns:") && value === SPREADSHEETML_NS) {
7514
- this.nsPrefix = name.slice(6);
7515
- tag.name = this.stripNsPrefix(tag.name);
7516
- }
7517
- }
7518
- this.attribList = [];
7519
- }
7520
7506
  closeTag() {
7521
- const { tags } = this;
7522
- const name = this.stripNsPrefix(this.name);
7507
+ const { tags, name } = this;
7523
7508
  this.state = S_TEXT;
7524
7509
  this.name = "";
7525
7510
  if (name === "") {
@@ -7594,6 +7579,30 @@ var ExcelTS = (function(exports) {
7594
7579
 
7595
7580
  //#endregion
7596
7581
  //#region src/modules/excel/xlsx/xform/base-xform.ts
7582
+ const HAN_CELL_PREFIXES = new Set([
7583
+ "ep",
7584
+ "cp",
7585
+ "dc",
7586
+ "dcterms",
7587
+ "dcmitype",
7588
+ "vt"
7589
+ ]);
7590
+ const SPREADSHEETML_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
7591
+ function detectHanCellPrefix(tagName, attrs) {
7592
+ for (const key in attrs) if (key.length > 6 && key.startsWith("xmlns:")) {
7593
+ const prefix = key.slice(6);
7594
+ if (attrs[key] === SPREADSHEETML_NS) return prefix;
7595
+ if (HAN_CELL_PREFIXES.has(prefix)) return null;
7596
+ }
7597
+ const i = tagName.indexOf(":");
7598
+ return i !== -1 && HAN_CELL_PREFIXES.has(tagName.slice(0, i)) ? null : void 0;
7599
+ }
7600
+ function stripPrefix(name, nsPrefix) {
7601
+ const i = name.indexOf(":");
7602
+ if (i === -1) return name;
7603
+ const p = name.slice(0, i);
7604
+ return p === nsPrefix || HAN_CELL_PREFIXES.has(p) ? name.slice(i + 1) : name;
7605
+ }
7597
7606
  var BaseXform = class BaseXform {
7598
7607
  prepare(_model, _options) {}
7599
7608
  render(_xmlStream, _model) {}
@@ -7616,12 +7625,38 @@ var ExcelTS = (function(exports) {
7616
7625
  async parse(saxParser) {
7617
7626
  let done = false;
7618
7627
  let finalModel;
7628
+ let nsMode = 0;
7629
+ let nsPrefix = null;
7619
7630
  for await (const events of saxParser) {
7620
7631
  if (done) continue;
7621
- for (const { eventType, value } of events) if (eventType === "opentag") this.parseOpen(value);
7622
- else if (eventType === "text") this.parseText(value);
7632
+ for (const { eventType, value } of events) if (eventType === "opentag") {
7633
+ if (nsMode === 1) {
7634
+ this.parseOpen(value);
7635
+ continue;
7636
+ }
7637
+ if (nsMode === 0) {
7638
+ const prefix = detectHanCellPrefix(value.name, value.attributes);
7639
+ if (prefix === void 0) {
7640
+ nsMode = 1;
7641
+ this.parseOpen(value);
7642
+ continue;
7643
+ }
7644
+ nsMode = 2;
7645
+ nsPrefix = prefix;
7646
+ }
7647
+ value.name = stripPrefix(value.name, nsPrefix);
7648
+ this.parseOpen(value);
7649
+ } else if (eventType === "text") this.parseText(value);
7623
7650
  else if (eventType === "closetag") {
7624
- if (!this.parseClose(value.name)) {
7651
+ if (nsMode === 1) {
7652
+ if (!this.parseClose(value.name)) {
7653
+ done = true;
7654
+ finalModel = this.model;
7655
+ break;
7656
+ }
7657
+ continue;
7658
+ }
7659
+ if (!this.parseClose(stripPrefix(value.name, nsPrefix))) {
7625
7660
  done = true;
7626
7661
  finalModel = this.model;
7627
7662
  break;
@@ -10406,28 +10441,26 @@ var ExcelTS = (function(exports) {
10406
10441
  ContentType: "application/vnd.openxmlformats-officedocument.drawing+xml"
10407
10442
  });
10408
10443
  });
10409
- if (model.commentRefs) {
10410
- xmlStream.leafNode("Default", {
10411
- Extension: "vml",
10412
- ContentType: "application/vnd.openxmlformats-officedocument.vmlDrawing"
10413
- });
10414
- model.commentRefs.forEach(({ commentName }) => {
10415
- xmlStream.leafNode("Override", {
10416
- PartName: toContentTypesPartName(commentsPathFromName(commentName)),
10417
- ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"
10418
- });
10419
- });
10420
- }
10421
- if (model.formControlRefs) {
10422
- if (!model.commentRefs) xmlStream.leafNode("Default", {
10423
- Extension: "vml",
10424
- ContentType: "application/vnd.openxmlformats-officedocument.vmlDrawing"
10425
- });
10426
- for (const ctrlPropId of model.formControlRefs) xmlStream.leafNode("Override", {
10427
- PartName: toContentTypesPartName(ctrlPropPath(ctrlPropId)),
10428
- ContentType: "application/vnd.ms-excel.controlproperties+xml"
10444
+ const hasComments = model.commentRefs && model.commentRefs.length > 0;
10445
+ const hasFormControls = model.formControlRefs && model.formControlRefs.length > 0;
10446
+ if (hasComments || hasFormControls) xmlStream.leafNode("Default", {
10447
+ Extension: "vml",
10448
+ ContentType: "application/vnd.openxmlformats-officedocument.vmlDrawing"
10449
+ });
10450
+ if (hasComments) model.commentRefs.forEach(({ commentName }) => {
10451
+ xmlStream.leafNode("Override", {
10452
+ PartName: toContentTypesPartName(commentsPathFromName(commentName)),
10453
+ ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"
10429
10454
  });
10430
- }
10455
+ });
10456
+ if (hasFormControls) for (const ctrlPropId of model.formControlRefs) xmlStream.leafNode("Override", {
10457
+ PartName: toContentTypesPartName(ctrlPropPath(ctrlPropId)),
10458
+ ContentType: "application/vnd.ms-excel.controlproperties+xml"
10459
+ });
10460
+ if (model.passthroughContentTypes) for (const { partName, contentType } of model.passthroughContentTypes) xmlStream.leafNode("Override", {
10461
+ PartName: toContentTypesPartName(partName),
10462
+ ContentType: contentType
10463
+ });
10431
10464
  xmlStream.leafNode("Override", {
10432
10465
  PartName: toContentTypesPartName(OOXML_PATHS.docPropsCore),
10433
10466
  ContentType: "application/vnd.openxmlformats-package.core-properties+xml"
@@ -13862,6 +13895,17 @@ var ExcelTS = (function(exports) {
13862
13895
  vmlDrawing: `vmlDrawing${model.id}`
13863
13896
  });
13864
13897
  }
13898
+ if (model.drawing && model.drawing.anchors) {
13899
+ const drawing = model.drawing;
13900
+ drawing.rId = nextRid(rels);
13901
+ if (!drawing.name) drawing.name = `drawing${++options.drawingsCount}`;
13902
+ options.drawings.push(drawing);
13903
+ rels.push({
13904
+ Id: drawing.rId,
13905
+ Type: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing",
13906
+ Target: drawingRelTargetFromWorksheet(drawing.name)
13907
+ });
13908
+ }
13865
13909
  const drawingRelsHash = [];
13866
13910
  let bookImage;
13867
13911
  model.media.forEach((medium) => {
@@ -14199,17 +14243,25 @@ var ExcelTS = (function(exports) {
14199
14243
  const match = rels[model.drawing.rId].Target.match(/\/drawings\/([a-zA-Z0-9]+)[.][a-zA-Z]{3,4}$/);
14200
14244
  if (match) {
14201
14245
  const drawingName = match[1];
14202
- options.drawings[drawingName].anchors.forEach((anchor) => {
14203
- if (anchor.medium) {
14204
- const image = {
14205
- type: "image",
14206
- imageId: anchor.medium.index,
14207
- range: anchor.range,
14208
- hyperlinks: anchor.picture.hyperlinks
14209
- };
14210
- model.media.push(image);
14211
- }
14212
- });
14246
+ const drawing = options.drawings[drawingName];
14247
+ if (drawing) {
14248
+ model.drawing = {
14249
+ ...drawing,
14250
+ name: drawingName,
14251
+ rels: options.drawingRels?.[drawingName] || drawing.rels || []
14252
+ };
14253
+ drawing.anchors.forEach((anchor) => {
14254
+ if (anchor.medium) {
14255
+ const image = {
14256
+ type: "image",
14257
+ imageId: anchor.medium.index,
14258
+ range: anchor.range,
14259
+ hyperlinks: anchor.picture.hyperlinks
14260
+ };
14261
+ model.media.push(image);
14262
+ }
14263
+ });
14264
+ }
14213
14265
  }
14214
14266
  }
14215
14267
  const backgroundRel = model.background && rels[model.background.rId];
@@ -15961,18 +16013,27 @@ var ExcelTS = (function(exports) {
15961
16013
  var PivotTableXform = class PivotTableXform extends BaseXform {
15962
16014
  constructor() {
15963
16015
  super();
16016
+ this.state = {
16017
+ inPivotFields: false,
16018
+ inRowFields: false,
16019
+ inColFields: false,
16020
+ inDataFields: false,
16021
+ inRowItems: false,
16022
+ inColItems: false,
16023
+ inLocation: false,
16024
+ inItems: false,
16025
+ inPivotTableStyleInfo: false,
16026
+ inChartFormats: false,
16027
+ inPivotArea: false
16028
+ };
16029
+ this.currentPivotField = null;
16030
+ this.currentRowItem = null;
16031
+ this.currentColItem = null;
16032
+ this.currentChartFormat = null;
16033
+ this.pivotAreaXmlBuffer = [];
16034
+ this.pivotAreaDepth = 0;
15964
16035
  this.map = {};
15965
16036
  this.model = null;
15966
- this.inPivotFields = false;
15967
- this.inRowFields = false;
15968
- this.inColFields = false;
15969
- this.inDataFields = false;
15970
- this.inRowItems = false;
15971
- this.inColItems = false;
15972
- this.inLocation = false;
15973
- this.currentPivotField = null;
15974
- this.inItems = false;
15975
- this.inPivotTableStyleInfo = false;
15976
16037
  }
15977
16038
  prepare(_model) {}
15978
16039
  get tag() {
@@ -15980,16 +16041,15 @@ var ExcelTS = (function(exports) {
15980
16041
  }
15981
16042
  reset() {
15982
16043
  this.model = null;
15983
- this.inPivotFields = false;
15984
- this.inRowFields = false;
15985
- this.inColFields = false;
15986
- this.inDataFields = false;
15987
- this.inRowItems = false;
15988
- this.inColItems = false;
15989
- this.inLocation = false;
16044
+ Object.keys(this.state).forEach((key) => {
16045
+ this.state[key] = false;
16046
+ });
15990
16047
  this.currentPivotField = null;
15991
- this.inItems = false;
15992
- this.inPivotTableStyleInfo = false;
16048
+ this.currentRowItem = null;
16049
+ this.currentColItem = null;
16050
+ this.currentChartFormat = null;
16051
+ this.pivotAreaXmlBuffer = [];
16052
+ this.pivotAreaDepth = 0;
15993
16053
  }
15994
16054
  /**
15995
16055
  * Render pivot table XML.
@@ -16088,8 +16148,7 @@ var ExcelTS = (function(exports) {
16088
16148
  * Render loaded pivot table (preserving original structure)
16089
16149
  */
16090
16150
  renderLoaded(xmlStream, model) {
16091
- xmlStream.openXml(XmlStream.StdDocAttributes);
16092
- xmlStream.openNode(this.tag, {
16151
+ const attrs = {
16093
16152
  ...PivotTableXform.PIVOT_TABLE_ATTRIBUTES,
16094
16153
  name: model.name || "PivotTable1",
16095
16154
  cacheId: model.cacheId,
@@ -16098,7 +16157,7 @@ var ExcelTS = (function(exports) {
16098
16157
  applyFontFormats: model.applyFontFormats || "0",
16099
16158
  applyPatternFormats: model.applyPatternFormats || "0",
16100
16159
  applyAlignmentFormats: model.applyAlignmentFormats || "0",
16101
- applyWidthHeightFormats: model.applyWidthHeightFormats || "0",
16160
+ applyWidthHeightFormats: model.applyWidthHeightFormats ?? "0",
16102
16161
  dataCaption: model.dataCaption || "Values",
16103
16162
  updatedVersion: model.updatedVersion || "8",
16104
16163
  minRefreshableVersion: model.minRefreshableVersion || "3",
@@ -16106,10 +16165,15 @@ var ExcelTS = (function(exports) {
16106
16165
  itemPrintTitles: model.itemPrintTitles ? "1" : "0",
16107
16166
  createdVersion: model.createdVersion || "8",
16108
16167
  indent: model.indent !== void 0 ? String(model.indent) : "0",
16109
- compact: model.compact ? "1" : "0",
16110
- compactData: model.compactData ? "1" : "0",
16111
16168
  multipleFieldFilters: model.multipleFieldFilters ? "1" : "0"
16112
- });
16169
+ };
16170
+ if (model.outline) attrs.outline = "1";
16171
+ if (model.outlineData) attrs.outlineData = "1";
16172
+ if (model.chartFormat !== void 0) attrs.chartFormat = String(model.chartFormat);
16173
+ if (model.compact) attrs.compact = "1";
16174
+ if (model.compactData) attrs.compactData = "1";
16175
+ xmlStream.openXml(XmlStream.StdDocAttributes);
16176
+ xmlStream.openNode(this.tag, attrs);
16113
16177
  if (model.location) xmlStream.leafNode("location", {
16114
16178
  ref: model.location.ref,
16115
16179
  firstHeaderRow: model.location.firstHeaderRow,
@@ -16126,30 +16190,46 @@ var ExcelTS = (function(exports) {
16126
16190
  for (const fieldIndex of model.rowFields) xmlStream.leafNode("field", { x: fieldIndex });
16127
16191
  xmlStream.closeNode();
16128
16192
  }
16129
- xmlStream.writeXml(`
16130
- <rowItems count="1">
16131
- <i t="grand"><x /></i>
16132
- </rowItems>`);
16193
+ if (model.rowItems && model.rowItems.length > 0) {
16194
+ xmlStream.openNode("rowItems", { count: model.rowItems.length });
16195
+ for (const item of model.rowItems) this.renderRowColItem(xmlStream, item);
16196
+ xmlStream.closeNode();
16197
+ } else xmlStream.writeXml("<rowItems count=\"1\"><i t=\"grand\"><x/></i></rowItems>");
16133
16198
  const colFieldCount = model.colFields.length === 0 ? 1 : model.colFields.length;
16134
16199
  xmlStream.openNode("colFields", { count: colFieldCount });
16135
16200
  if (model.colFields.length === 0) xmlStream.leafNode("field", { x: -2 });
16136
16201
  else for (const fieldIndex of model.colFields) xmlStream.leafNode("field", { x: fieldIndex });
16137
16202
  xmlStream.closeNode();
16138
- xmlStream.writeXml(`
16139
- <colItems count="1">
16140
- <i t="grand"><x /></i>
16141
- </colItems>`);
16203
+ if (model.colItems && model.colItems.length > 0) {
16204
+ xmlStream.openNode("colItems", { count: model.colItems.length });
16205
+ for (const item of model.colItems) this.renderRowColItem(xmlStream, item);
16206
+ xmlStream.closeNode();
16207
+ } else xmlStream.writeXml("<colItems count=\"1\"><i t=\"grand\"><x/></i></colItems>");
16142
16208
  if (model.dataFields.length > 0) {
16143
16209
  xmlStream.openNode("dataFields", { count: model.dataFields.length });
16144
16210
  for (const dataField of model.dataFields) {
16145
- const attrs = {
16211
+ const dfAttrs = {
16146
16212
  name: dataField.name,
16147
16213
  fld: dataField.fld,
16148
16214
  baseField: dataField.baseField ?? 0,
16149
16215
  baseItem: dataField.baseItem ?? 0
16150
16216
  };
16151
- if (dataField.subtotal && dataField.subtotal !== "sum") attrs.subtotal = dataField.subtotal;
16152
- xmlStream.leafNode("dataField", attrs);
16217
+ if (dataField.subtotal && dataField.subtotal !== "sum") dfAttrs.subtotal = dataField.subtotal;
16218
+ xmlStream.leafNode("dataField", dfAttrs);
16219
+ }
16220
+ xmlStream.closeNode();
16221
+ }
16222
+ if (model.chartFormats && model.chartFormats.length > 0) {
16223
+ xmlStream.openNode("chartFormats", { count: model.chartFormats.length });
16224
+ for (const cf of model.chartFormats) {
16225
+ xmlStream.openNode("chartFormat", {
16226
+ chart: cf.chart,
16227
+ format: cf.format,
16228
+ series: cf.series ? "1" : void 0
16229
+ });
16230
+ if (cf.pivotAreaXml) xmlStream.writeXml(cf.pivotAreaXml);
16231
+ else xmlStream.writeXml(`<pivotArea type="data" outline="0" fieldPosition="0"><references count="1"><reference field="4294967294" count="1" selected="0"><x v="0"/></reference></references></pivotArea>`);
16232
+ xmlStream.closeNode();
16153
16233
  }
16154
16234
  xmlStream.closeNode();
16155
16235
  }
@@ -16161,47 +16241,35 @@ var ExcelTS = (function(exports) {
16161
16241
  showColStripes: "0",
16162
16242
  showLastColumn: "1"
16163
16243
  });
16164
- xmlStream.writeXml(`
16165
- <extLst>
16166
- <ext
16167
- uri="{962EF5D1-5CA2-4c93-8EF4-DBF5C05439D2}"
16168
- xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"
16169
- >
16170
- <x14:pivotTableDefinition
16171
- hideValuesRow="1"
16172
- xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main"
16173
- />
16174
- </ext>
16175
- <ext
16176
- uri="{747A6164-185A-40DC-8AA5-F01512510D54}"
16177
- xmlns:xpdl="http://schemas.microsoft.com/office/spreadsheetml/2016/pivotdefaultlayout"
16178
- >
16179
- <xpdl:pivotTableDefinition16
16180
- EnabledSubtotalsDefault="0"
16181
- SubtotalsOnTopDefault="0"
16182
- />
16183
- </ext>
16184
- </extLst>
16185
- `);
16244
+ xmlStream.writeXml(`<extLst><ext uri="{962EF5D1-5CA2-4c93-8EF4-DBF5C05439D2}" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"><x14:pivotTableDefinition hideValuesRow="1" xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main"/></ext><ext uri="{747A6164-185A-40DC-8AA5-F01512510D54}" xmlns:xpdl="http://schemas.microsoft.com/office/spreadsheetml/2016/pivotdefaultlayout"><xpdl:pivotTableDefinition16/></ext></extLst>`);
16186
16245
  xmlStream.closeNode();
16187
16246
  }
16188
16247
  /**
16248
+ * Render a row or column item element
16249
+ */
16250
+ renderRowColItem(xmlStream, item) {
16251
+ const attrs = {};
16252
+ if (item.t) attrs.t = item.t;
16253
+ if (item.x && item.x.length > 0) {
16254
+ xmlStream.openNode("i", attrs);
16255
+ for (const x of item.x) if (x.v && x.v !== 0) xmlStream.leafNode("x", { v: x.v });
16256
+ else xmlStream.leafNode("x");
16257
+ xmlStream.closeNode();
16258
+ } else xmlStream.leafNode("i", attrs);
16259
+ }
16260
+ /**
16189
16261
  * Render a loaded pivot field
16190
16262
  */
16191
16263
  renderPivotFieldLoaded(xmlStream, field) {
16192
- const attrs = {
16193
- compact: field.compact ? "1" : "0",
16194
- outline: field.outline ? "1" : "0",
16195
- showAll: field.showAll ? "1" : "0",
16196
- defaultSubtotal: field.defaultSubtotal ? "1" : "0"
16197
- };
16264
+ const attrs = {};
16198
16265
  if (field.axis) attrs.axis = field.axis;
16199
16266
  if (field.dataField) attrs.dataField = "1";
16267
+ attrs.showAll = field.showAll ? "1" : "0";
16200
16268
  if (field.items && field.items.length > 0) {
16201
16269
  xmlStream.openNode("pivotField", attrs);
16202
16270
  xmlStream.openNode("items", { count: field.items.length + 1 });
16203
16271
  for (const itemIndex of field.items) xmlStream.leafNode("item", { x: itemIndex });
16204
- xmlStream.writeXml("<item t=\"default\" />");
16272
+ xmlStream.writeXml("<item t=\"default\"/>");
16205
16273
  xmlStream.closeNode();
16206
16274
  xmlStream.closeNode();
16207
16275
  } else xmlStream.leafNode("pivotField", attrs);
@@ -16235,6 +16303,12 @@ var ExcelTS = (function(exports) {
16235
16303
  compact: attributes.compact === "1",
16236
16304
  compactData: attributes.compactData === "1",
16237
16305
  multipleFieldFilters: attributes.multipleFieldFilters === "1",
16306
+ outline: attributes.outline === "1",
16307
+ outlineData: attributes.outlineData === "1",
16308
+ chartFormat: attributes.chartFormat ? parseInt(attributes.chartFormat, 10) : void 0,
16309
+ rowItems: [],
16310
+ colItems: [],
16311
+ chartFormats: [],
16238
16312
  isLoaded: true
16239
16313
  };
16240
16314
  break;
@@ -16247,10 +16321,10 @@ var ExcelTS = (function(exports) {
16247
16321
  };
16248
16322
  break;
16249
16323
  case "pivotFields":
16250
- this.inPivotFields = true;
16324
+ this.state.inPivotFields = true;
16251
16325
  break;
16252
16326
  case "pivotField":
16253
- if (this.inPivotFields) this.currentPivotField = {
16327
+ if (this.state.inPivotFields) this.currentPivotField = {
16254
16328
  axis: attributes.axis,
16255
16329
  dataField: attributes.dataField === "1",
16256
16330
  items: [],
@@ -16261,35 +16335,77 @@ var ExcelTS = (function(exports) {
16261
16335
  };
16262
16336
  break;
16263
16337
  case "items":
16264
- if (this.currentPivotField) this.inItems = true;
16338
+ if (this.currentPivotField) this.state.inItems = true;
16265
16339
  break;
16266
16340
  case "item":
16267
- if (this.inItems && this.currentPivotField && attributes.x !== void 0) this.currentPivotField.items.push(parseInt(attributes.x, 10));
16341
+ if (this.state.inItems && this.currentPivotField && attributes.x !== void 0) this.currentPivotField.items.push(parseInt(attributes.x, 10));
16268
16342
  break;
16269
16343
  case "rowFields":
16270
- this.inRowFields = true;
16344
+ this.state.inRowFields = true;
16271
16345
  break;
16272
16346
  case "colFields":
16273
- this.inColFields = true;
16347
+ this.state.inColFields = true;
16274
16348
  break;
16275
16349
  case "dataFields":
16276
- this.inDataFields = true;
16350
+ this.state.inDataFields = true;
16277
16351
  break;
16278
16352
  case "rowItems":
16279
- this.inRowItems = true;
16353
+ this.state.inRowItems = true;
16280
16354
  break;
16281
16355
  case "colItems":
16282
- this.inColItems = true;
16356
+ this.state.inColItems = true;
16357
+ break;
16358
+ case "i":
16359
+ if (this.state.inRowItems && this.model) this.currentRowItem = {
16360
+ t: attributes.t,
16361
+ x: []
16362
+ };
16363
+ else if (this.state.inColItems && this.model) this.currentColItem = {
16364
+ t: attributes.t,
16365
+ x: []
16366
+ };
16367
+ break;
16368
+ case "x":
16369
+ if (this.state.inPivotArea) {
16370
+ const xAttrs = Object.entries(attributes).map(([k, v]) => `${k}="${v}"`).join(" ");
16371
+ this.pivotAreaXmlBuffer.push(xAttrs ? `<x ${xAttrs}/>` : "<x/>");
16372
+ } else if (this.currentRowItem) this.currentRowItem.x.push({ v: attributes.v ? parseInt(attributes.v, 10) : 0 });
16373
+ else if (this.currentColItem) this.currentColItem.x.push({ v: attributes.v ? parseInt(attributes.v, 10) : 0 });
16374
+ break;
16375
+ case "chartFormats":
16376
+ this.state.inChartFormats = true;
16377
+ break;
16378
+ case "chartFormat":
16379
+ if (this.state.inChartFormats && this.model) this.currentChartFormat = {
16380
+ chart: attributes.chart ? parseInt(attributes.chart, 10) : 0,
16381
+ format: attributes.format ? parseInt(attributes.format, 10) : 0,
16382
+ series: attributes.series === "1"
16383
+ };
16384
+ break;
16385
+ case "pivotArea":
16386
+ if (this.currentChartFormat) {
16387
+ this.state.inPivotArea = true;
16388
+ const attrsStr = Object.entries(attributes).map(([k, v]) => `${k}="${v}"`).join(" ");
16389
+ this.pivotAreaXmlBuffer = [attrsStr ? `<pivotArea ${attrsStr}>` : "<pivotArea>"];
16390
+ }
16391
+ break;
16392
+ case "references":
16393
+ case "reference":
16394
+ if (this.state.inPivotArea) {
16395
+ this.pivotAreaDepth++;
16396
+ const attrsStr = Object.entries(attributes).map(([k, v]) => `${k}="${v}"`).join(" ");
16397
+ this.pivotAreaXmlBuffer.push(`<${name}${attrsStr ? " " + attrsStr : ""}>`);
16398
+ }
16283
16399
  break;
16284
16400
  case "field":
16285
16401
  if (this.model) {
16286
16402
  const fieldIndex = parseInt(attributes.x || "0", 10);
16287
- if (this.inRowFields) this.model.rowFields.push(fieldIndex);
16288
- else if (this.inColFields) this.model.colFields.push(fieldIndex);
16403
+ if (this.state.inRowFields) this.model.rowFields.push(fieldIndex);
16404
+ else if (this.state.inColFields) this.model.colFields.push(fieldIndex);
16289
16405
  }
16290
16406
  break;
16291
16407
  case "dataField":
16292
- if (this.inDataFields && this.model) this.model.dataFields.push({
16408
+ if (this.state.inDataFields && this.model) this.model.dataFields.push({
16293
16409
  name: xmlDecode(attributes.name || ""),
16294
16410
  fld: parseInt(attributes.fld || "0", 10),
16295
16411
  baseField: attributes.baseField ? parseInt(attributes.baseField, 10) : 0,
@@ -16305,10 +16421,25 @@ var ExcelTS = (function(exports) {
16305
16421
  }
16306
16422
  parseText(_text) {}
16307
16423
  parseClose(name) {
16424
+ if (this.state.inPivotArea) {
16425
+ if (name === "pivotArea") {
16426
+ this.pivotAreaXmlBuffer.push("</pivotArea>");
16427
+ if (this.currentChartFormat) this.currentChartFormat.pivotAreaXml = this.pivotAreaXmlBuffer.join("");
16428
+ this.state.inPivotArea = false;
16429
+ this.pivotAreaXmlBuffer = [];
16430
+ this.pivotAreaDepth = 0;
16431
+ return true;
16432
+ } else if (name === "references" || name === "reference") {
16433
+ this.pivotAreaXmlBuffer.push(`</${name}>`);
16434
+ this.pivotAreaDepth--;
16435
+ return true;
16436
+ }
16437
+ return true;
16438
+ }
16308
16439
  switch (name) {
16309
16440
  case this.tag: return false;
16310
16441
  case "pivotFields":
16311
- this.inPivotFields = false;
16442
+ this.state.inPivotFields = false;
16312
16443
  break;
16313
16444
  case "pivotField":
16314
16445
  if (this.currentPivotField && this.model) {
@@ -16317,22 +16448,40 @@ var ExcelTS = (function(exports) {
16317
16448
  }
16318
16449
  break;
16319
16450
  case "items":
16320
- this.inItems = false;
16451
+ this.state.inItems = false;
16321
16452
  break;
16322
16453
  case "rowFields":
16323
- this.inRowFields = false;
16454
+ this.state.inRowFields = false;
16324
16455
  break;
16325
16456
  case "colFields":
16326
- this.inColFields = false;
16457
+ this.state.inColFields = false;
16327
16458
  break;
16328
16459
  case "dataFields":
16329
- this.inDataFields = false;
16460
+ this.state.inDataFields = false;
16330
16461
  break;
16331
16462
  case "rowItems":
16332
- this.inRowItems = false;
16463
+ this.state.inRowItems = false;
16333
16464
  break;
16334
16465
  case "colItems":
16335
- this.inColItems = false;
16466
+ this.state.inColItems = false;
16467
+ break;
16468
+ case "i":
16469
+ if (this.currentRowItem && this.model) {
16470
+ this.model.rowItems.push(this.currentRowItem);
16471
+ this.currentRowItem = null;
16472
+ } else if (this.currentColItem && this.model) {
16473
+ this.model.colItems.push(this.currentColItem);
16474
+ this.currentColItem = null;
16475
+ }
16476
+ break;
16477
+ case "chartFormats":
16478
+ this.state.inChartFormats = false;
16479
+ break;
16480
+ case "chartFormat":
16481
+ if (this.currentChartFormat && this.model) {
16482
+ this.model.chartFormats.push(this.currentChartFormat);
16483
+ this.currentChartFormat = null;
16484
+ }
16336
16485
  break;
16337
16486
  }
16338
16487
  return true;
@@ -20205,6 +20354,115 @@ var ExcelTS = (function(exports) {
20205
20354
  }
20206
20355
  };
20207
20356
 
20357
+ //#endregion
20358
+ //#region src/modules/excel/utils/passthrough-manager.ts
20359
+ /**
20360
+ * Content type definitions for passthrough files
20361
+ */
20362
+ const PASSTHROUGH_CONTENT_TYPES = new Map([
20363
+ [/^xl\/charts\/chart\d+\.xml$/, "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"],
20364
+ [/^xl\/charts\/style\d+\.xml$/, "application/vnd.ms-office.chartstyle+xml"],
20365
+ [/^xl\/charts\/colors\d+\.xml$/, "application/vnd.ms-office.chartcolorstyle+xml"]
20366
+ ]);
20367
+ /**
20368
+ * Passthrough path prefixes that should be preserved
20369
+ */
20370
+ const PASSTHROUGH_PREFIXES = ["xl/charts/"];
20371
+ /**
20372
+ * PassthroughManager handles storage and retrieval of passthrough files
20373
+ * that need to be preserved during Excel read/write cycles.
20374
+ */
20375
+ var PassthroughManager = class PassthroughManager {
20376
+ constructor() {
20377
+ this.files = /* @__PURE__ */ new Map();
20378
+ }
20379
+ /**
20380
+ * Check if a path should be treated as passthrough
20381
+ */
20382
+ static isPassthroughPath(path) {
20383
+ return PASSTHROUGH_PREFIXES.some((prefix) => path.startsWith(prefix));
20384
+ }
20385
+ /**
20386
+ * Get the content type for a passthrough file path
20387
+ * @returns Content type string or undefined if unknown
20388
+ */
20389
+ static getContentType(path) {
20390
+ if (path.startsWith("xl/charts/_rels/")) return;
20391
+ for (const [regex, contentType] of PASSTHROUGH_CONTENT_TYPES) if (regex.test(path)) return contentType;
20392
+ }
20393
+ /**
20394
+ * Add a file to passthrough storage
20395
+ */
20396
+ add(path, data) {
20397
+ this.files.set(path, data);
20398
+ }
20399
+ /**
20400
+ * Get a file from passthrough storage
20401
+ */
20402
+ get(path) {
20403
+ return this.files.get(path);
20404
+ }
20405
+ /**
20406
+ * Check if a file exists in passthrough storage
20407
+ */
20408
+ has(path) {
20409
+ return this.files.has(path);
20410
+ }
20411
+ /**
20412
+ * Get all stored paths
20413
+ */
20414
+ getPaths() {
20415
+ return [...this.files.keys()];
20416
+ }
20417
+ /**
20418
+ * Get all files as a record (for serialization)
20419
+ */
20420
+ toRecord() {
20421
+ const record = {};
20422
+ for (const [path, data] of this.files) record[path] = data;
20423
+ return record;
20424
+ }
20425
+ /**
20426
+ * Load files from a record (for deserialization)
20427
+ */
20428
+ fromRecord(record) {
20429
+ this.files.clear();
20430
+ for (const [path, data] of Object.entries(record)) this.files.set(path, data);
20431
+ }
20432
+ /**
20433
+ * Get content types for all stored files that have known types
20434
+ */
20435
+ getContentTypes() {
20436
+ const contentTypes = [];
20437
+ for (const path of this.files.keys()) {
20438
+ const contentType = PassthroughManager.getContentType(path);
20439
+ if (contentType) contentTypes.push({
20440
+ partName: path,
20441
+ contentType
20442
+ });
20443
+ }
20444
+ return contentTypes;
20445
+ }
20446
+ /**
20447
+ * Write all passthrough files to a ZIP writer
20448
+ */
20449
+ writeToZip(zip$1) {
20450
+ for (const [path, data] of this.files) zip$1.append(data, { name: path });
20451
+ }
20452
+ /**
20453
+ * Clear all stored files
20454
+ */
20455
+ clear() {
20456
+ this.files.clear();
20457
+ }
20458
+ /**
20459
+ * Get the number of stored files
20460
+ */
20461
+ get size() {
20462
+ return this.files.size;
20463
+ }
20464
+ };
20465
+
20208
20466
  //#endregion
20209
20467
  //#region src/modules/excel/xlsx/xlsx.browser.ts
20210
20468
  /**
@@ -20355,6 +20613,7 @@ var ExcelTS = (function(exports) {
20355
20613
  this.addDrawings(zip$1, model);
20356
20614
  this.addTables(zip$1, model);
20357
20615
  this.addPivotTables(zip$1, model);
20616
+ this.addPassthrough(zip$1, model);
20358
20617
  await Promise.all([this.addThemes(zip$1, model), this.addStyles(zip$1, model)]);
20359
20618
  await this.addFeaturePropertyBag(zip$1, model);
20360
20619
  await this.addMedia(zip$1, model);
@@ -20428,8 +20687,12 @@ var ExcelTS = (function(exports) {
20428
20687
  * This is the foundation for TRUE streaming reads on platforms that have a
20429
20688
  * streaming ZIP parser (e.g. Node.js `modules/archive` Parse).
20430
20689
  */
20431
- async loadFromZipEntries(entries, options) {
20432
- const model = {
20690
+ /**
20691
+ * Create an empty model for parsing XLSX files.
20692
+ * Shared by loadFromZipEntries and loadFromFiles.
20693
+ */
20694
+ createEmptyModel() {
20695
+ return {
20433
20696
  worksheets: [],
20434
20697
  worksheetHash: {},
20435
20698
  worksheetRels: [],
@@ -20438,6 +20701,7 @@ var ExcelTS = (function(exports) {
20438
20701
  mediaIndex: {},
20439
20702
  drawings: {},
20440
20703
  drawingRels: {},
20704
+ rawDrawings: {},
20441
20705
  comments: {},
20442
20706
  tables: {},
20443
20707
  vmlDrawings: {},
@@ -20445,8 +20709,93 @@ var ExcelTS = (function(exports) {
20445
20709
  pivotTableRels: {},
20446
20710
  pivotCacheDefinitions: {},
20447
20711
  pivotCacheDefinitionRels: {},
20448
- pivotCacheRecords: {}
20712
+ pivotCacheRecords: {},
20713
+ passthrough: {}
20449
20714
  };
20715
+ }
20716
+ /**
20717
+ * Collect all data from a stream into a single Uint8Array.
20718
+ * Reusable helper for passthrough and drawing processing.
20719
+ */
20720
+ async collectStreamData(stream) {
20721
+ const chunks = [];
20722
+ await new Promise((resolve, reject) => {
20723
+ stream.on("data", (chunk) => {
20724
+ if (typeof chunk === "string") chunks.push(new TextEncoder().encode(chunk));
20725
+ else if (chunk instanceof Uint8Array) chunks.push(chunk);
20726
+ else chunks.push(new Uint8Array(chunk));
20727
+ });
20728
+ stream.on("end", () => resolve());
20729
+ stream.on("error", reject);
20730
+ });
20731
+ return concatUint8Arrays$2(chunks);
20732
+ }
20733
+ /**
20734
+ * Check if a drawing has chart references in its relationships
20735
+ */
20736
+ drawingHasChartReference(drawing) {
20737
+ return drawing.rels && drawing.rels.some((rel) => rel.Target && rel.Target.includes("/charts/"));
20738
+ }
20739
+ /**
20740
+ * Check if a drawing rels list references charts.
20741
+ * Used to decide whether we need to keep raw drawing XML for passthrough.
20742
+ */
20743
+ drawingRelsHasChartReference(drawingRels) {
20744
+ return Array.isArray(drawingRels) && drawingRels.some((rel) => typeof rel?.Target === "string" && rel.Target.includes("/charts/"));
20745
+ }
20746
+ /**
20747
+ * Process a known OOXML entry (workbook, styles, shared strings, etc.)
20748
+ * Returns true if handled, false if should be passed to _processDefaultEntry
20749
+ */
20750
+ async _processKnownEntry(stream, model, entryName, options) {
20751
+ const sheetNo = getWorksheetNoFromWorksheetPath(entryName);
20752
+ if (sheetNo !== void 0) {
20753
+ await this._processWorksheetEntry(stream, model, sheetNo, options, entryName);
20754
+ return true;
20755
+ }
20756
+ switch (entryName) {
20757
+ case OOXML_PATHS.rootRels:
20758
+ model.globalRels = await this.parseRels(stream);
20759
+ return true;
20760
+ case OOXML_PATHS.xlWorkbook: {
20761
+ const workbook = await this.parseWorkbook(stream);
20762
+ model.sheets = workbook.sheets;
20763
+ model.definedNames = workbook.definedNames;
20764
+ model.views = workbook.views;
20765
+ model.properties = workbook.properties;
20766
+ model.calcProperties = workbook.calcProperties;
20767
+ model.pivotCaches = workbook.pivotCaches;
20768
+ return true;
20769
+ }
20770
+ case OOXML_PATHS.xlSharedStrings:
20771
+ model.sharedStrings = new SharedStringsXform();
20772
+ await model.sharedStrings.parseStream(stream);
20773
+ return true;
20774
+ case OOXML_PATHS.xlWorkbookRels:
20775
+ model.workbookRels = await this.parseRels(stream);
20776
+ return true;
20777
+ case OOXML_PATHS.docPropsApp: {
20778
+ const appProperties = await new AppXform().parseStream(stream);
20779
+ if (appProperties) {
20780
+ model.company = appProperties.company;
20781
+ model.manager = appProperties.manager;
20782
+ }
20783
+ return true;
20784
+ }
20785
+ case OOXML_PATHS.docPropsCore: {
20786
+ const coreProperties = await new CoreXform().parseStream(stream);
20787
+ Object.assign(model, coreProperties);
20788
+ return true;
20789
+ }
20790
+ case OOXML_PATHS.xlStyles:
20791
+ model.styles = new StylesXform();
20792
+ await model.styles.parseStream(stream);
20793
+ return true;
20794
+ default: return false;
20795
+ }
20796
+ }
20797
+ async loadFromZipEntries(entries, options) {
20798
+ const model = this.createEmptyModel();
20450
20799
  for await (const entry of entries) {
20451
20800
  let drained = false;
20452
20801
  const drainEntry = async () => {
@@ -20461,52 +20810,8 @@ var ExcelTS = (function(exports) {
20461
20810
  const entryName = normalizeZipPath(entry.name);
20462
20811
  const stream = entry.stream;
20463
20812
  try {
20464
- const sheetNo = getWorksheetNoFromWorksheetPath(entryName);
20465
- if (sheetNo !== void 0) {
20466
- await this._processWorksheetEntry(stream, model, sheetNo, options, entryName);
20467
- continue;
20468
- }
20469
- switch (entryName) {
20470
- case OOXML_PATHS.rootRels:
20471
- model.globalRels = await this.parseRels(stream);
20472
- break;
20473
- case OOXML_PATHS.xlWorkbook: {
20474
- const workbook = await this.parseWorkbook(stream);
20475
- model.sheets = workbook.sheets;
20476
- model.definedNames = workbook.definedNames;
20477
- model.views = workbook.views;
20478
- model.properties = workbook.properties;
20479
- model.calcProperties = workbook.calcProperties;
20480
- model.pivotCaches = workbook.pivotCaches;
20481
- break;
20482
- }
20483
- case OOXML_PATHS.xlSharedStrings:
20484
- model.sharedStrings = new SharedStringsXform();
20485
- await model.sharedStrings.parseStream(stream);
20486
- break;
20487
- case OOXML_PATHS.xlWorkbookRels:
20488
- model.workbookRels = await this.parseRels(stream);
20489
- break;
20490
- case OOXML_PATHS.docPropsApp: {
20491
- const appProperties = await new AppXform().parseStream(stream);
20492
- if (appProperties) {
20493
- model.company = appProperties.company;
20494
- model.manager = appProperties.manager;
20495
- }
20496
- break;
20497
- }
20498
- case OOXML_PATHS.docPropsCore: {
20499
- const coreProperties = await new CoreXform().parseStream(stream);
20500
- Object.assign(model, coreProperties);
20501
- break;
20502
- }
20503
- case OOXML_PATHS.xlStyles:
20504
- model.styles = new StylesXform();
20505
- await model.styles.parseStream(stream);
20506
- break;
20507
- default:
20508
- if (!await this._processDefaultEntry(stream, model, entryName)) await drainEntry();
20509
- break;
20813
+ if (!await this._processKnownEntry(stream, model, entryName, options)) {
20814
+ if (!await this._processDefaultEntry(stream, model, entryName)) await drainEntry();
20510
20815
  }
20511
20816
  } finally {
20512
20817
  try {
@@ -20595,6 +20900,10 @@ var ExcelTS = (function(exports) {
20595
20900
  drawingXform.reconcile(drawing, drawingOptions);
20596
20901
  }
20597
20902
  });
20903
+ if (model.rawDrawings && model.drawingRels) for (const name of Object.keys(model.rawDrawings)) {
20904
+ const drawingRel = model.drawingRels[name];
20905
+ if (drawingRel && !this.drawingRelsHasChartReference(drawingRel)) delete model.rawDrawings[name];
20906
+ }
20598
20907
  const tableOptions = { styles: model.styles };
20599
20908
  Object.values(model.tables).forEach((table) => {
20600
20909
  tableXform.reconcile(table, tableOptions);
@@ -20607,6 +20916,7 @@ var ExcelTS = (function(exports) {
20607
20916
  mediaIndex: model.mediaIndex,
20608
20917
  date1904: model.properties && model.properties.date1904,
20609
20918
  drawings: model.drawings,
20919
+ drawingRels: model.drawingRels,
20610
20920
  comments: model.comments,
20611
20921
  tables: model.tables,
20612
20922
  vmlDrawings: model.vmlDrawings,
@@ -20763,8 +21073,12 @@ var ExcelTS = (function(exports) {
20763
21073
  }
20764
21074
  }
20765
21075
  async _processDrawingEntry(entry, model, name) {
20766
- const drawing = await new DrawingXform().parseStream(entry);
21076
+ const rawData = await this.collectStreamData(entry);
21077
+ const xform$1 = new DrawingXform();
21078
+ const xmlString = this.bufferToString(rawData);
21079
+ const drawing = await xform$1.parseStream(this.createTextStream(xmlString));
20767
21080
  model.drawings[name] = drawing;
21081
+ model.rawDrawings[name] = rawData;
20768
21082
  }
20769
21083
  async _processDrawingRelsEntry(entry, model, name) {
20770
21084
  const relationships = await new RelationshipsXform().parseStream(entry);
@@ -20819,24 +21133,7 @@ var ExcelTS = (function(exports) {
20819
21133
  if (cacheRecords) model.pivotCacheRecords[name] = cacheRecords;
20820
21134
  }
20821
21135
  async loadFromFiles(zipData, options) {
20822
- const model = {
20823
- worksheets: [],
20824
- worksheetHash: {},
20825
- worksheetRels: [],
20826
- themes: {},
20827
- media: [],
20828
- mediaIndex: {},
20829
- drawings: {},
20830
- drawingRels: {},
20831
- comments: {},
20832
- tables: {},
20833
- vmlDrawings: {},
20834
- pivotTables: {},
20835
- pivotTableRels: {},
20836
- pivotCacheDefinitions: {},
20837
- pivotCacheDefinitionRels: {},
20838
- pivotCacheRecords: {}
20839
- };
21136
+ const model = this.createEmptyModel();
20840
21137
  const entries = Object.keys(zipData).map((name) => ({
20841
21138
  name,
20842
21139
  dir: name.endsWith("/"),
@@ -20845,48 +21142,7 @@ var ExcelTS = (function(exports) {
20845
21142
  for (const entry of entries) if (!entry.dir) {
20846
21143
  const entryName = normalizeZipPath(entry.name);
20847
21144
  const stream = isBinaryEntryPath(entryName) ? this.createBinaryStream(entry.data) : this.createTextStream(this.bufferToString(entry.data));
20848
- const sheetNo = getWorksheetNoFromWorksheetPath(entryName);
20849
- if (sheetNo !== void 0) await this._processWorksheetEntry(stream, model, sheetNo, options, entryName);
20850
- else switch (entryName) {
20851
- case OOXML_PATHS.rootRels:
20852
- model.globalRels = await this.parseRels(stream);
20853
- break;
20854
- case OOXML_PATHS.xlWorkbook: {
20855
- const workbook = await this.parseWorkbook(stream);
20856
- model.sheets = workbook.sheets;
20857
- model.definedNames = workbook.definedNames;
20858
- model.views = workbook.views;
20859
- model.properties = workbook.properties;
20860
- model.calcProperties = workbook.calcProperties;
20861
- model.pivotCaches = workbook.pivotCaches;
20862
- break;
20863
- }
20864
- case OOXML_PATHS.xlSharedStrings:
20865
- model.sharedStrings = new SharedStringsXform();
20866
- await model.sharedStrings.parseStream(stream);
20867
- break;
20868
- case OOXML_PATHS.xlWorkbookRels:
20869
- model.workbookRels = await this.parseRels(stream);
20870
- break;
20871
- case OOXML_PATHS.docPropsApp: {
20872
- const appProperties = await new AppXform().parseStream(stream);
20873
- if (appProperties) {
20874
- model.company = appProperties.company;
20875
- model.manager = appProperties.manager;
20876
- }
20877
- break;
20878
- }
20879
- case OOXML_PATHS.docPropsCore: {
20880
- const coreProperties = await new CoreXform().parseStream(stream);
20881
- Object.assign(model, coreProperties);
20882
- break;
20883
- }
20884
- case OOXML_PATHS.xlStyles:
20885
- model.styles = new StylesXform();
20886
- await model.styles.parseStream(stream);
20887
- break;
20888
- default: await this._processDefaultEntry(stream, model, entryName);
20889
- }
21145
+ if (!await this._processKnownEntry(stream, model, entryName, options)) await this._processDefaultEntry(stream, model, entryName, entry.data);
20890
21146
  }
20891
21147
  this.reconcile(model, options);
20892
21148
  this.workbook.model = model;
@@ -20894,11 +21150,11 @@ var ExcelTS = (function(exports) {
20894
21150
  }
20895
21151
  /**
20896
21152
  * Process default entries (drawings, comments, tables, etc.)
21153
+ * @param rawData Optional raw entry data for passthrough preservation (used by loadFromFiles)
20897
21154
  */
20898
- async _processDefaultEntry(stream, model, entryName) {
20899
- const worksheetRelsSheetNo = getWorksheetNoFromWorksheetRelsPath(entryName);
20900
- if (worksheetRelsSheetNo !== void 0) {
20901
- const sheetNo = worksheetRelsSheetNo;
21155
+ async _processDefaultEntry(stream, model, entryName, rawData) {
21156
+ const sheetNo = getWorksheetNoFromWorksheetRelsPath(entryName);
21157
+ if (sheetNo !== void 0) {
20902
21158
  await this._processWorksheetRelsEntry(stream, model, sheetNo);
20903
21159
  return true;
20904
21160
  }
@@ -20910,6 +21166,7 @@ var ExcelTS = (function(exports) {
20910
21166
  const drawingName = getDrawingNameFromPath(entryName);
20911
21167
  if (drawingName) {
20912
21168
  await this._processDrawingEntry(stream, model, drawingName);
21169
+ if (rawData) model.rawDrawings[drawingName] = rawData;
20913
21170
  return true;
20914
21171
  }
20915
21172
  const drawingRelsName = getDrawingNameFromRelsPath(entryName);
@@ -20962,8 +21219,21 @@ var ExcelTS = (function(exports) {
20962
21219
  await this._processPivotCacheRecordsEntry(stream, model, pivotCacheRecordsName);
20963
21220
  return true;
20964
21221
  }
21222
+ if (PassthroughManager.isPassthroughPath(entryName)) {
21223
+ if (rawData) model.passthrough[entryName] = rawData;
21224
+ else await this._processPassthroughEntry(stream, model, entryName);
21225
+ return true;
21226
+ }
20965
21227
  return false;
20966
21228
  }
21229
+ /**
21230
+ * Store a passthrough file for preservation during read/write cycles.
21231
+ * These files are not parsed but stored as raw bytes to be written back unchanged.
21232
+ */
21233
+ async _processPassthroughEntry(stream, model, entryName) {
21234
+ const data = await this.collectStreamData(stream);
21235
+ model.passthrough[entryName] = data;
21236
+ }
20967
21237
  async addContentTypes(zip$1, model) {
20968
21238
  const xml = new ContentTypesXform().toXml(model);
20969
21239
  zip$1.append(xml, { name: OOXML_PATHS.contentTypes });
@@ -21100,14 +21370,29 @@ var ExcelTS = (function(exports) {
21100
21370
  addDrawings(zip$1, model) {
21101
21371
  const drawingXform = new DrawingXform();
21102
21372
  const relsXform = new RelationshipsXform();
21373
+ const rawDrawings = model.rawDrawings || {};
21103
21374
  model.worksheets.forEach((worksheet) => {
21104
21375
  const { drawing } = worksheet;
21105
21376
  if (drawing) {
21106
- drawingXform.prepare(drawing);
21107
- let xml = drawingXform.toXml(drawing);
21108
- zip$1.append(xml, { name: drawingPath(drawing.name) });
21109
- xml = relsXform.toXml(drawing.rels);
21110
- zip$1.append(xml, { name: drawingRelsPath(drawing.name) });
21377
+ if (this.drawingHasChartReference(drawing) && rawDrawings[drawing.name]) zip$1.append(rawDrawings[drawing.name], { name: drawingPath(drawing.name) });
21378
+ else {
21379
+ const filteredAnchors = (drawing.anchors || []).filter((a) => {
21380
+ if (a == null) return false;
21381
+ if (a.range?.br && a.shape) return true;
21382
+ if (!a.br && !a.picture) return false;
21383
+ if (a.br && !a.picture && !a.shape) return false;
21384
+ return true;
21385
+ });
21386
+ const drawingForWrite = drawing.anchors ? {
21387
+ ...drawing,
21388
+ anchors: filteredAnchors
21389
+ } : drawing;
21390
+ drawingXform.prepare(drawingForWrite);
21391
+ const xml = drawingXform.toXml(drawingForWrite);
21392
+ zip$1.append(xml, { name: drawingPath(drawing.name) });
21393
+ }
21394
+ const relsXml = relsXform.toXml(drawing.rels);
21395
+ zip$1.append(relsXml, { name: drawingRelsPath(drawing.name) });
21111
21396
  }
21112
21397
  });
21113
21398
  }
@@ -21122,6 +21407,15 @@ var ExcelTS = (function(exports) {
21122
21407
  });
21123
21408
  });
21124
21409
  }
21410
+ /**
21411
+ * Write passthrough files (charts, etc.) that were preserved during read.
21412
+ * These files are written back unchanged to preserve unsupported features.
21413
+ */
21414
+ addPassthrough(zip$1, model) {
21415
+ const passthroughManager = new PassthroughManager();
21416
+ passthroughManager.fromRecord(model.passthrough || {});
21417
+ passthroughManager.writeToZip(zip$1);
21418
+ }
21125
21419
  addPivotTables(zip$1, model) {
21126
21420
  if (!model.pivotTables.length) return;
21127
21421
  const pivotCacheRecordsXform = new PivotCacheRecordsXform();
@@ -21204,6 +21498,10 @@ var ExcelTS = (function(exports) {
21204
21498
  worksheetXform.prepare(worksheet, worksheetOptions);
21205
21499
  });
21206
21500
  model.hasCheckboxes = model.styles.hasCheckboxes;
21501
+ const passthrough = model.passthrough || {};
21502
+ const passthroughManager = new PassthroughManager();
21503
+ passthroughManager.fromRecord(passthrough);
21504
+ model.passthroughContentTypes = passthroughManager.getContentTypes();
21207
21505
  }
21208
21506
  };
21209
21507
 
@@ -22405,7 +22703,7 @@ var ExcelTS = (function(exports) {
22405
22703
  else str = String(content);
22406
22704
  const worksheet = this.workbook.addWorksheet(options?.sheetName);
22407
22705
  const dateFormats = options?.dateFormats ?? DEFAULT_DATE_FORMATS;
22408
- const map = options?.map || createDefaultValueMapper(dateFormats, { decimalSeparator: options?.valueMapperOptions?.decimalSeparator ?? options?.parserOptions?.decimalSeparator });
22706
+ const map = options?.map || createDefaultValueMapper(dateFormats, { decimalSeparator: options?.valueMapperOptions?.decimalSeparator });
22409
22707
  const rows = parseCsv(str, options?.parserOptions);
22410
22708
  for (const row of rows) worksheet.addRow(row.map(map));
22411
22709
  return worksheet;
@@ -22433,7 +22731,7 @@ var ExcelTS = (function(exports) {
22433
22731
  async read(stream, options) {
22434
22732
  const worksheet = this.workbook.addWorksheet(options?.sheetName);
22435
22733
  const dateFormats = options?.dateFormats ?? DEFAULT_DATE_FORMATS;
22436
- const map = options?.map || createDefaultValueMapper(dateFormats, { decimalSeparator: options?.valueMapperOptions?.decimalSeparator ?? options?.parserOptions?.decimalSeparator });
22734
+ const map = options?.map || createDefaultValueMapper(dateFormats, { decimalSeparator: options?.valueMapperOptions?.decimalSeparator });
22437
22735
  const parser = new CsvParserStream(options?.parserOptions);
22438
22736
  return new Promise((resolve, reject) => {
22439
22737
  parser.on("data", (row) => worksheet.addRow(row.map(map)));
@@ -22485,7 +22783,7 @@ var ExcelTS = (function(exports) {
22485
22783
  createWriteStream(options) {
22486
22784
  const worksheet = this.workbook.addWorksheet(options?.sheetName);
22487
22785
  const dateFormats = options?.dateFormats ?? DEFAULT_DATE_FORMATS;
22488
- const map = options?.map || createDefaultValueMapper(dateFormats, { decimalSeparator: options?.valueMapperOptions?.decimalSeparator ?? options?.parserOptions?.decimalSeparator });
22786
+ const map = options?.map || createDefaultValueMapper(dateFormats, { decimalSeparator: options?.valueMapperOptions?.decimalSeparator });
22489
22787
  const parser = new CsvParserStream(options?.parserOptions);
22490
22788
  parser.on("data", (row) => worksheet.addRow(row.map(map)));
22491
22789
  return parser;
@@ -25486,6 +25784,8 @@ onmessage = async (ev) => {
25486
25784
  this.views = [];
25487
25785
  this.media = [];
25488
25786
  this.pivotTables = [];
25787
+ this._passthrough = {};
25788
+ this._rawDrawings = {};
25489
25789
  this._definedNames = new DefinedNames();
25490
25790
  }
25491
25791
  /**
@@ -25658,7 +25958,9 @@ onmessage = async (ev) => {
25658
25958
  themes: this._themes,
25659
25959
  media: this.media,
25660
25960
  pivotTables: this.pivotTables,
25661
- calcProperties: this.calcProperties
25961
+ calcProperties: this.calcProperties,
25962
+ passthrough: this._passthrough,
25963
+ rawDrawings: this._rawDrawings
25662
25964
  };
25663
25965
  }
25664
25966
  set model(value) {
@@ -25697,6 +25999,8 @@ onmessage = async (ev) => {
25697
25999
  this._themes = value.themes;
25698
26000
  this.media = value.media || [];
25699
26001
  this.pivotTables = value.pivotTables || value.loadedPivotTables || [];
26002
+ this._passthrough = value.passthrough || {};
26003
+ this._rawDrawings = value.rawDrawings || {};
25700
26004
  }
25701
26005
  };
25702
26006