@cj-tech-master/excelts 5.0.0 → 5.0.1-canary.20260123024428.98c7ee0

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 (55) hide show
  1. package/dist/browser/modules/excel/column.d.ts +5 -0
  2. package/dist/browser/modules/excel/column.js +10 -2
  3. package/dist/browser/modules/excel/row.d.ts +2 -0
  4. package/dist/browser/modules/excel/row.js +3 -1
  5. package/dist/browser/modules/excel/workbook.d.ts +4 -0
  6. package/dist/browser/modules/excel/workbook.js +4 -1
  7. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +1 -0
  8. package/dist/browser/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +17 -10
  9. package/dist/browser/modules/excel/xlsx/xform/sheet/row-xform.d.ts +1 -0
  10. package/dist/browser/modules/excel/xlsx/xform/sheet/row-xform.js +7 -1
  11. package/dist/browser/modules/excel/xlsx/xform/sheet/sheet-format-properties-xform.d.ts +1 -0
  12. package/dist/browser/modules/excel/xlsx/xform/sheet/sheet-format-properties-xform.js +9 -4
  13. package/dist/browser/modules/excel/xlsx/xform/sheet/sheet-view-xform.js +4 -2
  14. package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +2 -1
  15. package/dist/browser/modules/excel/xlsx/xform/style/style-xform.d.ts +7 -0
  16. package/dist/browser/modules/excel/xlsx/xform/style/style-xform.js +26 -6
  17. package/dist/browser/modules/excel/xlsx/xform/style/styles-xform.d.ts +6 -0
  18. package/dist/browser/modules/excel/xlsx/xform/style/styles-xform.js +52 -4
  19. package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +9 -1
  20. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +24 -10
  21. package/dist/cjs/modules/excel/column.js +10 -2
  22. package/dist/cjs/modules/excel/row.js +3 -1
  23. package/dist/cjs/modules/excel/workbook.js +4 -1
  24. package/dist/cjs/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +17 -10
  25. package/dist/cjs/modules/excel/xlsx/xform/sheet/row-xform.js +7 -1
  26. package/dist/cjs/modules/excel/xlsx/xform/sheet/sheet-format-properties-xform.js +9 -4
  27. package/dist/cjs/modules/excel/xlsx/xform/sheet/sheet-view-xform.js +4 -2
  28. package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +2 -1
  29. package/dist/cjs/modules/excel/xlsx/xform/style/style-xform.js +26 -6
  30. package/dist/cjs/modules/excel/xlsx/xform/style/styles-xform.js +52 -4
  31. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +24 -10
  32. package/dist/esm/modules/excel/column.js +10 -2
  33. package/dist/esm/modules/excel/row.js +3 -1
  34. package/dist/esm/modules/excel/workbook.js +4 -1
  35. package/dist/esm/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.js +17 -10
  36. package/dist/esm/modules/excel/xlsx/xform/sheet/row-xform.js +7 -1
  37. package/dist/esm/modules/excel/xlsx/xform/sheet/sheet-format-properties-xform.js +9 -4
  38. package/dist/esm/modules/excel/xlsx/xform/sheet/sheet-view-xform.js +4 -2
  39. package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +2 -1
  40. package/dist/esm/modules/excel/xlsx/xform/style/style-xform.js +26 -6
  41. package/dist/esm/modules/excel/xlsx/xform/style/styles-xform.js +52 -4
  42. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +24 -10
  43. package/dist/iife/excelts.iife.js +463 -400
  44. package/dist/iife/excelts.iife.js.map +1 -1
  45. package/dist/iife/excelts.iife.min.js +7 -7
  46. package/dist/types/modules/excel/column.d.ts +5 -0
  47. package/dist/types/modules/excel/row.d.ts +2 -0
  48. package/dist/types/modules/excel/workbook.d.ts +4 -0
  49. package/dist/types/modules/excel/xlsx/xform/pivot-table/pivot-table-xform.d.ts +1 -0
  50. package/dist/types/modules/excel/xlsx/xform/sheet/row-xform.d.ts +1 -0
  51. package/dist/types/modules/excel/xlsx/xform/sheet/sheet-format-properties-xform.d.ts +1 -0
  52. package/dist/types/modules/excel/xlsx/xform/style/style-xform.d.ts +7 -0
  53. package/dist/types/modules/excel/xlsx/xform/style/styles-xform.d.ts +6 -0
  54. package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +9 -1
  55. package/package.json +14 -14
@@ -24,24 +24,27 @@ class StyleXform extends BaseXform {
24
24
  if (this.xfId) {
25
25
  xmlStream.addAttribute("xfId", model.xfId || 0);
26
26
  }
27
- if (model.numFmtId) {
27
+ if (model.applyNumberFormat || model.numFmtId) {
28
28
  xmlStream.addAttribute("applyNumberFormat", "1");
29
29
  }
30
- if (model.fontId) {
30
+ if (model.applyFont || model.fontId) {
31
31
  xmlStream.addAttribute("applyFont", "1");
32
32
  }
33
- if (model.fillId) {
33
+ if (model.applyFill || model.fillId) {
34
34
  xmlStream.addAttribute("applyFill", "1");
35
35
  }
36
- if (model.borderId) {
36
+ if (model.applyBorder || model.borderId) {
37
37
  xmlStream.addAttribute("applyBorder", "1");
38
38
  }
39
- if (model.alignment) {
39
+ if (model.applyAlignment || model.alignment) {
40
40
  xmlStream.addAttribute("applyAlignment", "1");
41
41
  }
42
- if (model.protection) {
42
+ if (model.applyProtection || model.protection) {
43
43
  xmlStream.addAttribute("applyProtection", "1");
44
44
  }
45
+ if (model.pivotButton) {
46
+ xmlStream.addAttribute("pivotButton", "1");
47
+ }
45
48
  /**
46
49
  * Rendering tags causes close of XML stream.
47
50
  * Therefore adding attributes must be done before rendering tags.
@@ -82,6 +85,23 @@ class StyleXform extends BaseXform {
82
85
  if (this.xfId) {
83
86
  this.model.xfId = parseInt(node.attributes.xfId, 10);
84
87
  }
88
+ if (node.attributes.pivotButton === "1") {
89
+ this.model.pivotButton = true;
90
+ }
91
+ // Preserve apply* flags from original file
92
+ const applyFlags = [
93
+ "applyNumberFormat",
94
+ "applyFont",
95
+ "applyFill",
96
+ "applyBorder",
97
+ "applyAlignment",
98
+ "applyProtection"
99
+ ];
100
+ for (const flag of applyFlags) {
101
+ if (node.attributes[flag] === "1") {
102
+ this.model[flag] = true;
103
+ }
104
+ }
85
105
  return true;
86
106
  case "alignment":
87
107
  this.parser = this.map.alignment;
@@ -84,6 +84,13 @@ class StylesXform extends BaseXform {
84
84
  this.weakMap = new WeakMap();
85
85
  this._hasCheckboxes = false;
86
86
  }
87
+ /**
88
+ * Set the default font to use when no font is explicitly specified.
89
+ * This preserves the original file's default font during round-trip.
90
+ */
91
+ setDefaultFont(font) {
92
+ this.defaultFont = font;
93
+ }
87
94
  render(xmlStream, model) {
88
95
  const renderModel = model || this.model;
89
96
  //
@@ -100,8 +107,8 @@ class StylesXform extends BaseXform {
100
107
  xmlStream.closeNode();
101
108
  }
102
109
  if (!renderModel.fonts.length) {
103
- // default (zero) font
104
- this._addFont({
110
+ // default (zero) font - use preserved font or fallback to Calibri
111
+ this._addFont(this.defaultFont || {
105
112
  size: 11,
106
113
  color: { theme: 1 },
107
114
  name: "Calibri",
@@ -193,6 +200,10 @@ class StylesXform extends BaseXform {
193
200
  add("borders", this.map.borders);
194
201
  add("styles", this.map.cellXfs);
195
202
  add("dxfs", this.map.dxfs);
203
+ // preserve the default (first) font from the original file
204
+ if (this.map.fonts.model && this.map.fonts.model.length > 0) {
205
+ this.defaultFont = this.map.fonts.model[0];
206
+ }
196
207
  // index numFmts
197
208
  this.index = {
198
209
  model: [],
@@ -220,8 +231,14 @@ class StylesXform extends BaseXform {
220
231
  }
221
232
  // if we have no default font, add it here now
222
233
  if (!this.model.fonts.length) {
223
- // default (zero) font
224
- this._addFont({ size: 11, color: { theme: 1 }, name: "Calibri", family: 2, scheme: "minor" });
234
+ // default (zero) font - use preserved font or fallback to Calibri
235
+ this._addFont(this.defaultFont || {
236
+ size: 11,
237
+ color: { theme: 1 },
238
+ name: "Calibri",
239
+ family: 2,
240
+ scheme: "minor"
241
+ });
225
242
  }
226
243
  const type = cellType || Enums.ValueType.Number;
227
244
  // If we have seen this style object before, assume it has the same styleId.
@@ -262,6 +279,21 @@ class StylesXform extends BaseXform {
262
279
  if (model.protection) {
263
280
  style.protection = model.protection;
264
281
  }
282
+ // Preserve xf-level attributes (pivotButton, apply* flags)
283
+ const xfFlags = [
284
+ "pivotButton",
285
+ "applyNumberFormat",
286
+ "applyFont",
287
+ "applyFill",
288
+ "applyBorder",
289
+ "applyAlignment",
290
+ "applyProtection"
291
+ ];
292
+ for (const flag of xfFlags) {
293
+ if (model[flag]) {
294
+ style[flag] = true;
295
+ }
296
+ }
265
297
  if (type === Enums.ValueType.Checkbox) {
266
298
  // Checkbox rendering relies on style extensions (extLst) and workbook-level parts.
267
299
  // Force applyAlignment="1" (without emitting an <alignment/> node) by providing
@@ -322,6 +354,22 @@ class StylesXform extends BaseXform {
322
354
  if (style.protection) {
323
355
  model.protection = style.protection;
324
356
  }
357
+ // -------------------------------------------------------
358
+ // xf-level attributes (pivotButton, apply* flags)
359
+ const xfFlags = [
360
+ "pivotButton",
361
+ "applyNumberFormat",
362
+ "applyFont",
363
+ "applyFill",
364
+ "applyBorder",
365
+ "applyAlignment",
366
+ "applyProtection"
367
+ ];
368
+ for (const flag of xfFlags) {
369
+ if (style[flag]) {
370
+ model[flag] = true;
371
+ }
372
+ }
325
373
  return model;
326
374
  }
327
375
  addDxfStyle(style) {
@@ -600,6 +600,8 @@ class XLSX {
600
600
  delete model.sharedStrings;
601
601
  delete model.workbookRels;
602
602
  delete model.sheetDefs;
603
+ // Preserve default font before deleting styles
604
+ model.defaultFont = model.styles?.defaultFont;
603
605
  delete model.styles;
604
606
  delete model.mediaIndex;
605
607
  delete model.drawings;
@@ -759,16 +761,26 @@ class XLSX {
759
761
  });
760
762
  }
761
763
  }
762
- async _processDrawingEntry(entry, model, name) {
763
- // Collect raw data first so we can preserve drawings that reference charts.
764
- const rawData = await this.collectStreamData(entry);
764
+ /**
765
+ * Process a drawing XML entry.
766
+ *
767
+ * @param stream - Stream to read from (used in loadFromZipEntries path)
768
+ * @param model - Model to populate
769
+ * @param name - Drawing name (e.g., "drawing1")
770
+ * @param rawData - Pre-read raw data (used in loadFromFiles path to avoid re-reading stream)
771
+ */
772
+ async _processDrawingEntry(stream, model, name, rawData) {
773
+ // Use provided rawData if available (loadFromFiles path), otherwise collect from stream.
774
+ // In loadFromFiles, the stream is created from already-decoded text, and collecting from
775
+ // it may not work correctly due to PassThrough stream timing issues.
776
+ const data = rawData ?? (await this.collectStreamData(stream));
765
777
  // Parse the drawing for normal processing (images, etc.)
766
778
  const xform = new DrawingXform();
767
- const xmlString = this.bufferToString(rawData);
779
+ const xmlString = this.bufferToString(data);
768
780
  const drawing = await xform.parseStream(this.createTextStream(xmlString));
769
781
  model.drawings[name] = drawing;
770
782
  // Store raw data; reconcile() may later drop it if charts are not referenced.
771
- model.rawDrawings[name] = rawData;
783
+ model.rawDrawings[name] = data;
772
784
  }
773
785
  async _processDrawingRelsEntry(entry, model, name) {
774
786
  const xform = new RelationshipsXform();
@@ -885,11 +897,8 @@ class XLSX {
885
897
  }
886
898
  const drawingName = getDrawingNameFromPath(entryName);
887
899
  if (drawingName) {
888
- await this._processDrawingEntry(stream, model, drawingName);
889
- // For loadFromFiles path, store raw data for passthrough (drawings with charts)
890
- if (rawData) {
891
- model.rawDrawings[drawingName] = rawData;
892
- }
900
+ await this._processDrawingEntry(stream, model, drawingName, rawData);
901
+ // rawData is now stored inside _processDrawingEntry
893
902
  return true;
894
903
  }
895
904
  const drawingRelsName = getDrawingNameFromRelsPath(entryName);
@@ -1235,7 +1244,12 @@ class XLSX {
1235
1244
  options.useSharedStrings !== undefined ? options.useSharedStrings : true;
1236
1245
  model.useStyles = options.useStyles !== undefined ? options.useStyles : true;
1237
1246
  model.sharedStrings = new SharedStringsXform();
1247
+ // Preserve default font from parsed styles if available
1248
+ const oldDefaultFont = model.defaultFont;
1238
1249
  model.styles = model.useStyles ? new StylesXform(true) : new StylesXform.Mock();
1250
+ if (oldDefaultFont && model.styles.setDefaultFont) {
1251
+ model.styles.setDefaultFont(oldDefaultFont);
1252
+ }
1239
1253
  const workbookXform = new WorkbookXform();
1240
1254
  const worksheetXform = new WorkSheetXform();
1241
1255
  workbookXform.prepare(model);