@4399ywkf/editor 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +45 -27
  2. package/dist/SheetView-YFK7BUS5.js +3 -0
  3. package/dist/{SheetView-SDBRSTVS.js.map → SheetView-YFK7BUS5.js.map} +1 -1
  4. package/dist/{chunk-KRP5V7VF.js → chunk-2DI4FJPC.js} +10 -3
  5. package/dist/chunk-2DI4FJPC.js.map +1 -0
  6. package/dist/{chunk-DGUNVCOM.js → chunk-3QTRZBIK.js} +111 -26
  7. package/dist/chunk-3QTRZBIK.js.map +1 -0
  8. package/dist/chunk-JWHQF2CZ.js +257 -0
  9. package/dist/chunk-JWHQF2CZ.js.map +1 -0
  10. package/dist/{chunk-WF7PIIFR.js → chunk-JZ67Q3QI.js} +4 -4
  11. package/dist/chunk-JZ67Q3QI.js.map +1 -0
  12. package/dist/{chunk-SBTKDJAL.js → chunk-SDVGDHC4.js} +45 -3
  13. package/dist/chunk-SDVGDHC4.js.map +1 -0
  14. package/dist/{chunk-HPSPOM2O.js → chunk-XB6FEC4I.js} +3 -3
  15. package/dist/chunk-XB6FEC4I.js.map +1 -0
  16. package/dist/{csv-parse-D0zTBvDB.d.ts → csv-parse-DXlwzoZ6.d.ts} +28 -1
  17. package/dist/csv.d.ts +2 -2
  18. package/dist/csv.js +4 -4
  19. package/dist/import-O7RUERND.js +6 -0
  20. package/dist/{import-GVZDLWA2.js.map → import-O7RUERND.js.map} +1 -1
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +1 -1
  23. package/dist/pdf.d.ts +1 -1
  24. package/dist/pptx.d.ts +1 -1
  25. package/dist/{registry-CYKivRDh.d.ts → registry-BQ5T1Yko.d.ts} +9 -16
  26. package/dist/sheet-runtime.d.ts +10 -8
  27. package/dist/sheet-runtime.js +6 -14
  28. package/dist/sheet-runtime.js.map +1 -1
  29. package/dist/sheet.d.ts +4 -3
  30. package/dist/sheet.js +1 -1
  31. package/dist/xlsx.d.ts +12 -11
  32. package/dist/xlsx.js +121 -32
  33. package/dist/xlsx.js.map +1 -1
  34. package/package.json +46 -2
  35. package/dist/SheetView-SDBRSTVS.js +0 -3
  36. package/dist/chunk-DGUNVCOM.js.map +0 -1
  37. package/dist/chunk-HPSPOM2O.js.map +0 -1
  38. package/dist/chunk-KRP5V7VF.js.map +0 -1
  39. package/dist/chunk-SBTKDJAL.js.map +0 -1
  40. package/dist/chunk-SYCK6Y5F.js +0 -89
  41. package/dist/chunk-SYCK6Y5F.js.map +0 -1
  42. package/dist/chunk-WF7PIIFR.js.map +0 -1
  43. package/dist/import-GVZDLWA2.js +0 -6
package/dist/xlsx.js CHANGED
@@ -1,9 +1,9 @@
1
- export { importCsv, importSheetSource, importXlsx, parseXlsx } from './chunk-DGUNVCOM.js';
2
- import { pxToPoints, cellRef, escapeXml, pxToColumnWidth, columnName, toArgb, XML_DECL, escapeAttr } from './chunk-SBTKDJAL.js';
3
- import { toSnapshot } from './chunk-WF7PIIFR.js';
4
- export { snapshotFromUniver } from './chunk-WF7PIIFR.js';
5
- import { H_ALIGN, V_ALIGN, CELL_TYPE, WRAP } from './chunk-KRP5V7VF.js';
6
- export { csvToSnapshot, parseCsv } from './chunk-KRP5V7VF.js';
1
+ export { importCsv, importSheetSource, importXlsx, parseXlsx } from './chunk-3QTRZBIK.js';
2
+ import { parseRange, cellRef, pxToPoints, escapeXml, pxToColumnWidth, columnName, toArgb, XML_DECL, escapeAttr, imageMimeOf, dataUrlToImage } from './chunk-SDVGDHC4.js';
3
+ import { toSnapshot } from './chunk-JZ67Q3QI.js';
4
+ export { snapshotFromUniver } from './chunk-JZ67Q3QI.js';
5
+ import { H_ALIGN, V_ALIGN, UNDERLINE, FORMULA_TYPE, CELL_TYPE, WRAP } from './chunk-2DI4FJPC.js';
6
+ export { csvToSnapshot, parseCsv } from './chunk-2DI4FJPC.js';
7
7
  import { numericKeys, richTextToPlain } from './chunk-5HMKRNIH.js';
8
8
  import { zipSync } from 'fflate';
9
9
 
@@ -37,6 +37,18 @@ var V_ALIGN_NAME = {
37
37
  [V_ALIGN.MIDDLE]: "center",
38
38
  [V_ALIGN.BOTTOM]: "bottom"
39
39
  };
40
+ var UNDERLINE_NAME = {
41
+ [UNDERLINE.DOUBLE]: "double",
42
+ [UNDERLINE.SINGLE_ACCOUNTING]: "singleAccounting",
43
+ [UNDERLINE.DOUBLE_ACCOUNTING]: "doubleAccounting"
44
+ };
45
+ function underlineOf(s) {
46
+ if (!s.ul?.s) return void 0;
47
+ return UNDERLINE_NAME[s.ul.t ?? UNDERLINE.SINGLE] ?? "single";
48
+ }
49
+ function fontNameOf(s) {
50
+ return s.ff ?? s.eastAsiaFontFamily ?? "Calibri";
51
+ }
40
52
  var FIRST_CUSTOM_NUMFMT_ID = 164;
41
53
  function createStyleTable(defaultStyle) {
42
54
  const numFmts = /* @__PURE__ */ new Map();
@@ -58,11 +70,11 @@ function createStyleTable(defaultStyle) {
58
70
  xfs.set("0|0|0|0||0", 0);
59
71
  function fontKey(s) {
60
72
  return JSON.stringify([
61
- s.ff ?? null,
73
+ fontNameOf(s),
62
74
  s.fs ?? null,
63
75
  s.bl ?? 0,
64
76
  s.it ?? 0,
65
- s.ul?.s ?? 0,
77
+ underlineOf(s) ?? null,
66
78
  s.st?.s ?? 0,
67
79
  s.va ?? 0,
68
80
  toArgb(s.cl) ?? null
@@ -73,13 +85,14 @@ function createStyleTable(defaultStyle) {
73
85
  if (s.bl) parts.push("<b/>");
74
86
  if (s.it) parts.push("<i/>");
75
87
  if (s.st?.s) parts.push("<strike/>");
76
- if (s.ul?.s) parts.push('<u val="single"/>');
88
+ const underline = underlineOf(s);
89
+ if (underline) parts.push(`<u val="${underline}"/>`);
77
90
  if (s.va === 1) parts.push('<vertAlign val="superscript"/>');
78
91
  else if (s.va === 2) parts.push('<vertAlign val="subscript"/>');
79
92
  parts.push(`<sz val="${s.fs ?? 11}"/>`);
80
93
  const color = toArgb(s.cl);
81
94
  if (color) parts.push(`<color rgb="${color}"/>`);
82
- parts.push(`<name val="${escapeAttr(s.ff ?? "Calibri")}"/>`);
95
+ parts.push(`<name val="${escapeAttr(fontNameOf(s))}"/>`);
83
96
  return `<font>${parts.join("")}</font>`;
84
97
  }
85
98
  function fontId(s) {
@@ -142,6 +155,7 @@ function createStyleTable(defaultStyle) {
142
155
  if (s.ht && H_ALIGN_NAME[s.ht]) a.horizontal = H_ALIGN_NAME[s.ht];
143
156
  if (s.vt && V_ALIGN_NAME[s.vt]) a.vertical = V_ALIGN_NAME[s.vt];
144
157
  if (s.tb === WRAP.WRAP) a.wrapText = true;
158
+ if (s.stf === 1) a.shrinkToFit = true;
145
159
  const angle = s.tr?.a;
146
160
  if (s.tr?.v === 1) {
147
161
  a.textRotation = 255;
@@ -174,7 +188,7 @@ function createStyleTable(defaultStyle) {
174
188
  if (border) attrs.push('applyBorder="1"');
175
189
  if (align) attrs.push('applyAlignment="1"');
176
190
  if (quotePrefix) attrs.push('quotePrefix="1"');
177
- const body = align ? `<alignment${align.horizontal ? ` horizontal="${align.horizontal}"` : ""}${align.vertical ? ` vertical="${align.vertical}"` : ""}${align.wrapText ? ' wrapText="1"' : ""}${align.textRotation !== void 0 ? ` textRotation="${align.textRotation}"` : ""}/>` : "";
191
+ const body = align ? `<alignment${align.horizontal ? ` horizontal="${align.horizontal}"` : ""}${align.vertical ? ` vertical="${align.vertical}"` : ""}${align.wrapText ? ' wrapText="1"' : ""}${align.textRotation !== void 0 ? ` textRotation="${align.textRotation}"` : ""}${align.shrinkToFit ? ' shrinkToFit="1"' : ""}/>` : "";
178
192
  const id = xfXml.length;
179
193
  xfXml.push(body ? `<xf ${attrs.join(" ")}>${body}</xf>` : `<xf ${attrs.join(" ")}/>`);
180
194
  xfs.set(key, id);
@@ -203,9 +217,11 @@ var RESOURCE_LABELS = {
203
217
  SHEET_WORKSHEET_PROTECTION_PLUGIN: "工作表保护"
204
218
  };
205
219
  var BAD_SHEET_NAME = /[\\/?*[\]:]/g;
220
+ var SHEET_STATE = { 1: "hidden", 2: "veryHidden" };
206
221
  var RELS_NS = 'xmlns="http://schemas.openxmlformats.org/package/2006/relationships"';
207
222
  var MAIN_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
208
223
  var DOC_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
224
+ var DYNAMIC_ARRAY_METADATA = `${XML_DECL}<metadata xmlns="${MAIN_NS}" xmlns:xda="http://schemas.microsoft.com/office/spreadsheetml/2017/dynamicarray"><metadataTypes count="1"><metadataType name="XLDAPR" minSupportedVersion="120000" copy="1" pasteAll="1" pasteValues="1" merge="1" splitFirst="1" rowColShift="1" clearFormats="1" clearComments="1" assign="1" coerce="1" cellMeta="1"/></metadataTypes><futureMetadata name="XLDAPR" count="1"><bk><extLst><ext uri="{bdbb8cdc-fa1e-496e-a857-3c3f30c029c3}"><xda:dynamicArrayProperties fDynamic="1" fCollapsed="0"/></ext></extLst></bk></futureMetadata><cellMetadata count="1"><bk><rc t="1" v="0"/></bk></cellMetadata></metadata>`;
209
225
  function serializeXlsx(workbook, options = {}) {
210
226
  const { cachedFormulaValues = true, creator = "@4399ywkf/editor", created = /* @__PURE__ */ new Date() } = options;
211
227
  const warnings = [];
@@ -261,24 +277,50 @@ function serializeXlsx(workbook, options = {}) {
261
277
  }
262
278
  return unique;
263
279
  };
280
+ const imageExts = /* @__PURE__ */ new Set();
281
+ let dynamicArrays = 0;
282
+ let dataTableCells = 0;
264
283
  order.forEach((sheetId, index) => {
265
284
  const sheet = workbook.sheets?.[sheetId];
266
285
  const name = safeName(sheet.name, index);
267
286
  const path = `xl/worksheets/sheet${index + 1}.xml`;
268
- sheets.push({ name, hidden: sheet.hidden === 1, path });
269
- put(path, buildSheetXml(sheet));
287
+ sheets.push({ name, state: SHEET_STATE[sheet.hidden ?? 0], path });
288
+ put(path, buildSheetXml(sheet, index, name));
270
289
  stats.sheets++;
271
290
  });
272
291
  if (!sheets.length) {
273
- sheets.push({ name: "Sheet1", hidden: false, path: "xl/worksheets/sheet1.xml" });
274
- put("xl/worksheets/sheet1.xml", buildSheetXml({}));
292
+ sheets.push({ name: "Sheet1", path: "xl/worksheets/sheet1.xml" });
293
+ put("xl/worksheets/sheet1.xml", buildSheetXml({}, 0, "Sheet1"));
275
294
  stats.sheets++;
276
295
  }
277
- function buildSheetXml(sheet) {
296
+ function backgroundPictureXml(sheet, index, name) {
297
+ const bg = sheet.backgroundImage;
298
+ if (!bg?.source) return "";
299
+ const image = bg.imageSourceType === "BASE64" ? dataUrlToImage(bg.source) : void 0;
300
+ if (!image) {
301
+ warnings.push(
302
+ bg.imageSourceType === "BASE64" ? `工作表「${name}」的背景图格式不支持(只认 png / jpg / gif / bmp),未随 xlsx 导出` : `工作表「${name}」的背景图是${bg.imageSourceType === "URL" ? "外链地址" : "图床里的图片"},导出不联网取图,未随 xlsx 导出`
303
+ );
304
+ return "";
305
+ }
306
+ const file = `background${index + 1}.${image.ext}`;
307
+ files[`xl/media/${file}`] = image.bytes;
308
+ imageExts.add(image.ext);
309
+ put(
310
+ `xl/worksheets/_rels/sheet${index + 1}.xml.rels`,
311
+ `${XML_DECL}<Relationships ${RELS_NS}><Relationship Id="rId1" Type="${DOC_REL}/image" Target="../media/${file}"/></Relationships>`
312
+ );
313
+ stats.backgroundImages = (stats.backgroundImages ?? 0) + 1;
314
+ return '<picture r:id="rId1"/>';
315
+ }
316
+ function buildSheetXml(sheet, index, name) {
278
317
  const cellData = sheet.cellData ?? {};
279
318
  const rowData = sheet.rowData ?? {};
280
319
  const columnData = sheet.columnData ?? {};
281
320
  const sheetDefault = resolveStyle(sheet.defaultStyle);
321
+ const merges = (sheet.mergeData ?? []).filter(
322
+ (m) => m && (m.endRow > m.startRow || m.endColumn > m.startColumn)
323
+ );
282
324
  const rows = [.../* @__PURE__ */ new Set([...numericKeys(cellData), ...numericKeys(rowData)])].sort(
283
325
  (a, b) => a - b
284
326
  );
@@ -317,6 +359,38 @@ function serializeXlsx(workbook, options = {}) {
317
359
  }
318
360
  sharedIndex.set(si, sharedIndex.size);
319
361
  }
362
+ const arrayRefs = /* @__PURE__ */ new Map();
363
+ const arrayConflict = (range, r0, c0) => {
364
+ for (let r = range.startRow; r <= range.endRow; r++) {
365
+ for (const c of numericKeys(cellData[r])) {
366
+ if (c < range.startColumn || c > range.endColumn || r === r0 && c === c0) continue;
367
+ const other = cellData[r]?.[c];
368
+ if (other?.f || other?.si) return `区域里的 ${cellRef(r, c)} 另有公式`;
369
+ }
370
+ }
371
+ const overlapsMerge = merges.some(
372
+ (m) => m.startRow <= range.endRow && m.endRow >= range.startRow && m.startColumn <= range.endColumn && m.endColumn >= range.startColumn
373
+ );
374
+ return overlapsMerge ? "区域和合并单元格相交" : void 0;
375
+ };
376
+ for (const r of numericKeys(cellData)) {
377
+ for (const c of numericKeys(cellData[r])) {
378
+ const cell = cellData[r]?.[c];
379
+ if (!cell?.f || !cell.ref || cell.ft != null && cell.ft !== FORMULA_TYPE.ARRAY) continue;
380
+ const range = parseRange(cell.ref);
381
+ const reason = !range || range.startRow !== r || range.startColumn !== c ? `引用范围 ${cell.ref} 不以它为左上角` : arrayConflict(range, r, c);
382
+ if (reason || !range) {
383
+ warnings.push(
384
+ `${cellRef(r, c)} 是数组公式,${reason},已降级成普通公式(区域内的值按静态值写出)`
385
+ );
386
+ continue;
387
+ }
388
+ arrayRefs.set(
389
+ `${r},${c}`,
390
+ `${cellRef(range.startRow, range.startColumn)}:${cellRef(range.endRow, range.endColumn)}`
391
+ );
392
+ }
393
+ }
320
394
  const rowXml = [];
321
395
  for (const r of rows) {
322
396
  const cols = numericKeys(cellData[r]);
@@ -348,20 +422,28 @@ function serializeXlsx(workbook, options = {}) {
348
422
  const forceString = cell.t === CELL_TYPE.FORCE_STRING;
349
423
  const styleIndex = style || forceString ? styles.xf(style, forceString) : 0;
350
424
  const s = styleIndex ? ` s="${styleIndex}"` : "";
351
- if (cell.ref && cell.f) {
352
- warnings.push(`${ref} 是数组公式,已降级成普通公式(溢出区域的值按静态值写出)`);
353
- }
425
+ if (cell.ft === FORMULA_TYPE.DATA_TABLE) dataTableCells++;
354
426
  const formula = cell.f?.replace(/^=/, "");
355
427
  if (formula || cell.si) {
356
428
  stats.cells++;
357
429
  const si = cell.si ? sharedIndex.get(cell.si) : void 0;
358
430
  const group = cell.si ? groups.get(cell.si) : void 0;
431
+ const arrayRef = arrayRefs.get(`${r},${c}`);
359
432
  let fXml = "";
433
+ let cm = "";
360
434
  if (formula && si !== void 0 && group) {
361
435
  const range = `${cellRef(group.minR, group.minC)}:${cellRef(group.maxR, group.maxC)}`;
362
436
  fXml = `<f t="shared" ref="${range}" si="${si}">${escapeXml(formula)}</f>`;
363
437
  stats.formulas++;
364
438
  stats.sharedFormulas++;
439
+ } else if (formula && arrayRef) {
440
+ fXml = `<f t="array" ref="${arrayRef}">${escapeXml(formula)}</f>`;
441
+ stats.formulas++;
442
+ stats.arrayFormulas = (stats.arrayFormulas ?? 0) + 1;
443
+ if (cell.fd === 1) {
444
+ cm = ' cm="1"';
445
+ dynamicArrays++;
446
+ }
365
447
  } else if (formula) {
366
448
  fXml = `<f>${escapeXml(formula)}</f>`;
367
449
  stats.formulas++;
@@ -371,7 +453,7 @@ function serializeXlsx(workbook, options = {}) {
371
453
  }
372
454
  const cached = cachedFormulaValues ? formulaValue(cell) : "";
373
455
  const t = cachedFormulaValues && typeof cell.v === "string" ? ' t="str"' : "";
374
- return `<c r="${ref}"${s}${t}>${fXml}${cached}</c>`;
456
+ return `<c r="${ref}"${s}${t}${cm}>${fXml}${cached}</c>`;
375
457
  }
376
458
  const rich = richTextToPlain(cell);
377
459
  if (rich !== void 0) {
@@ -397,18 +479,15 @@ function serializeXlsx(workbook, options = {}) {
397
479
  if (typeof v === "number") return Number.isFinite(v) ? `<v>${v}</v>` : "";
398
480
  return `<v>${escapeXml(String(v))}</v>`;
399
481
  }
400
- const merges = (sheet.mergeData ?? []).filter(
401
- (m) => m && (m.endRow > m.startRow || m.endColumn > m.startColumn)
402
- );
403
482
  for (const m of merges) track(m.endRow, m.endColumn);
404
483
  stats.merges += merges.length;
405
484
  const mergeXml = merges.length ? `<mergeCells count="${merges.length}">${merges.map(
406
485
  (m) => `<mergeCell ref="${cellRef(m.startRow, m.startColumn)}:${cellRef(m.endRow, m.endColumn)}"/>`
407
486
  ).join("")}</mergeCells>` : "";
408
- const colsXml = numericKeys(columnData).map((index) => {
409
- const col = columnData[index];
487
+ const colsXml = numericKeys(columnData).map((index2) => {
488
+ const col = columnData[index2];
410
489
  if (!col) return "";
411
- const attrs = [`min="${index + 1}"`, `max="${index + 1}"`];
490
+ const attrs = [`min="${index2 + 1}"`, `max="${index2 + 1}"`];
412
491
  if (col.w) attrs.push(`width="${pxToColumnWidth(col.w)}"`, 'customWidth="1"');
413
492
  if (col.hd === 1) attrs.push('hidden="1"');
414
493
  const colStyle = resolveStyle(col.s);
@@ -430,24 +509,34 @@ function serializeXlsx(workbook, options = {}) {
430
509
  const dimension = maxRow < 0 ? "A1" : `A1:${columnName(Math.max(maxCol, 0))}${maxRow + 1}`;
431
510
  const tabColor = toArgb(sheet.tabColor);
432
511
  const sheetPr = tabColor ? `<sheetPr><tabColor rgb="${tabColor}"/></sheetPr>` : "";
433
- return `${XML_DECL}<worksheet xmlns="${MAIN_NS}" xmlns:r="${DOC_REL}">` + sheetPr + `<dimension ref="${dimension}"/>` + sheetViewXml + `<sheetFormatPr ${formatAttrs.join(" ")}/>` + (colsXml ? `<cols>${colsXml}</cols>` : "") + `<sheetData>${rowXml.join("")}</sheetData>` + mergeXml + "</worksheet>";
512
+ return `${XML_DECL}<worksheet xmlns="${MAIN_NS}" xmlns:r="${DOC_REL}">` + sheetPr + `<dimension ref="${dimension}"/>` + sheetViewXml + `<sheetFormatPr ${formatAttrs.join(" ")}/>` + (colsXml ? `<cols>${colsXml}</cols>` : "") + `<sheetData>${rowXml.join("")}</sheetData>` + mergeXml + backgroundPictureXml(sheet, index, name) + "</worksheet>";
434
513
  }
435
514
  const sheetEntries = sheets.map(
436
- (s, i) => `<sheet name="${escapeAttr(s.name)}" sheetId="${i + 1}"${s.hidden ? ' state="hidden"' : ""} r:id="rId${i + 1}"/>`
515
+ (s, i) => `<sheet name="${escapeAttr(s.name)}" sheetId="${i + 1}"${s.state ? ` state="${s.state}"` : ""} r:id="rId${i + 1}"/>`
437
516
  ).join("");
517
+ if (dataTableCells) {
518
+ warnings.push(
519
+ `${dataTableCells} 个模拟运算表(数据表)单元格按静态值导出:快照里没有模拟运算表的定义`
520
+ );
521
+ }
438
522
  put(
439
523
  "xl/workbook.xml",
440
- `${XML_DECL}<workbook xmlns="${MAIN_NS}" xmlns:r="${DOC_REL}"><workbookPr/><sheets>${sheetEntries}</sheets>` + // 没写缓存值时必须让 Excel 打开就重算,否则整列公式显示成空白。
524
+ `${XML_DECL}<workbook xmlns="${MAIN_NS}" xmlns:r="${DOC_REL}">` + (workbook.dateSystem === "date1904" ? '<workbookPr date1904="1"/>' : "<workbookPr/>") + `<sheets>${sheetEntries}</sheets>` + // 没写缓存值时必须让 Excel 打开就重算,否则整列公式显示成空白。
441
525
  // 写了缓存值就别加:fullCalcOnLoad 会把文件标脏,用户没改动也会被问「是否保存」
442
526
  (cachedFormulaValues ? "" : '<calcPr calcId="0" fullCalcOnLoad="1"/>') + "</workbook>"
443
527
  );
444
528
  const stylesRelId = sheets.length + 1;
445
529
  const sstRelId = sheets.length + 2;
530
+ const metadataRelId = sheets.length + 3;
531
+ if (dynamicArrays) {
532
+ put("xl/metadata.xml", DYNAMIC_ARRAY_METADATA);
533
+ stats.dynamicArrays = dynamicArrays;
534
+ }
446
535
  put(
447
536
  "xl/_rels/workbook.xml.rels",
448
537
  `${XML_DECL}<Relationships ${RELS_NS}>` + sheets.map(
449
538
  (s, i) => `<Relationship Id="rId${i + 1}" Type="${DOC_REL}/worksheet" Target="worksheets/${s.path.split("/").pop()}"/>`
450
- ).join("") + `<Relationship Id="rId${stylesRelId}" Type="${DOC_REL}/styles" Target="styles.xml"/><Relationship Id="rId${sstRelId}" Type="${DOC_REL}/sharedStrings" Target="sharedStrings.xml"/></Relationships>`
539
+ ).join("") + `<Relationship Id="rId${stylesRelId}" Type="${DOC_REL}/styles" Target="styles.xml"/><Relationship Id="rId${sstRelId}" Type="${DOC_REL}/sharedStrings" Target="sharedStrings.xml"/>` + (dynamicArrays ? `<Relationship Id="rId${metadataRelId}" Type="${DOC_REL}/sheetMetadata" Target="metadata.xml"/>` : "") + "</Relationships>"
451
540
  );
452
541
  put(
453
542
  "xl/sharedStrings.xml",
@@ -456,9 +545,9 @@ function serializeXlsx(workbook, options = {}) {
456
545
  put("xl/styles.xml", styles.xml());
457
546
  put(
458
547
  "[Content_Types].xml",
459
- `${XML_DECL}<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>` + sheets.map(
548
+ `${XML_DECL}<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/>` + [...imageExts].map((ext) => `<Default Extension="${ext}" ContentType="${imageMimeOf(`x.${ext}`)}"/>`).join("") + '<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>' + sheets.map(
460
549
  (s) => `<Override PartName="/${s.path}" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>`
461
- ).join("") + '<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/><Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/><Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/><Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/></Types>'
550
+ ).join("") + '<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/><Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>' + (dynamicArrays ? '<Override PartName="/xl/metadata.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml"/>' : "") + '<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/><Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/></Types>'
462
551
  );
463
552
  put(
464
553
  "_rels/.rels",