@office-kit/xlsx 0.12.0 → 0.14.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 (37) hide show
  1. package/dist/io/save.d.ts +15 -3
  2. package/dist/io.mjs +2 -2
  3. package/dist/iterparse-zWV-5vc6.mjs +164 -0
  4. package/dist/iterparse-zWV-5vc6.mjs.map +1 -0
  5. package/dist/{load-CJdGh50R.mjs → load-B16H5A3S.mjs} +3 -3
  6. package/dist/{load-CJdGh50R.mjs.map → load-B16H5A3S.mjs.map} +1 -1
  7. package/dist/node.mjs +8 -4
  8. package/dist/node.mjs.map +1 -1
  9. package/dist/{reader-BNaUTVCy.mjs → reader-DHMxLBQV.mjs} +81 -26
  10. package/dist/reader-DHMxLBQV.mjs.map +1 -0
  11. package/dist/{save-a0InIbtJ.mjs → save-I6GjvO1k.mjs} +85 -45
  12. package/dist/save-I6GjvO1k.mjs.map +1 -0
  13. package/dist/streaming/write-only.d.ts +11 -1
  14. package/dist/streaming.mjs +158 -64
  15. package/dist/streaming.mjs.map +1 -1
  16. package/dist/{stylesheet-writer-D7Uug85X.mjs → stylesheet-writer-BCS6PzWU.mjs} +66 -62
  17. package/dist/stylesheet-writer-BCS6PzWU.mjs.map +1 -0
  18. package/dist/utf8-OAkCDG5g.mjs +21 -0
  19. package/dist/utf8-OAkCDG5g.mjs.map +1 -0
  20. package/dist/worksheet/writer.d.ts +23 -4
  21. package/dist/{writer-IyFccCRJ.mjs → writer-C38RBZCy.mjs} +61 -9
  22. package/dist/writer-C38RBZCy.mjs.map +1 -0
  23. package/dist/xml.mjs +2 -1
  24. package/dist/xml.mjs.map +1 -1
  25. package/dist/zip/decompression-guard.d.ts +22 -6
  26. package/dist/zip/index.d.ts +1 -1
  27. package/dist/zip/inflate-cache.d.ts +22 -0
  28. package/dist/zip/reader.d.ts +11 -6
  29. package/dist/zip/writer.d.ts +26 -3
  30. package/dist/zip.mjs +2 -2
  31. package/package.json +1 -1
  32. package/dist/reader-BNaUTVCy.mjs.map +0 -1
  33. package/dist/save-a0InIbtJ.mjs.map +0 -1
  34. package/dist/stylesheet-writer-D7Uug85X.mjs.map +0 -1
  35. package/dist/utf8-Tn3nzyik.mjs +0 -143
  36. package/dist/utf8-Tn3nzyik.mjs.map +0 -1
  37. package/dist/writer-IyFccCRJ.mjs.map +0 -1
@@ -3,11 +3,12 @@ import { r as normalizeFormulaText } from "./inference-BMvv9cUY.mjs";
3
3
  import { m as IMAGE_FORMAT_MIME, p as IMAGE_FORMAT_EXTENSION } from "./drawing-ZJ3h4VHD.mjs";
4
4
  import { n as escapeXmlAttr, r as escapeXmlText } from "./escape-rnWSPpWY.mjs";
5
5
  import { At as parseQName, M as CPROPS_TYPE, _ as ARC_WORKBOOK_RELS, c as ARC_CONTENT_TYPES, ct as PKG_REL_NS, f as ARC_ROOT_RELS, ft as SHEET_MAIN_NS, g as ARC_WORKBOOK, h as ARC_THEME, l as ARC_CORE, lt as REL_NS, m as ARC_STYLE, mt as THEME_TYPE, p as ARC_SHARED_STRINGS, pt as STYLES_TYPE, s as ARC_APP, u as ARC_CUSTOM, ut as SHARED_STRINGS_TYPE, wt as XLSX_TYPE, x as CHARTEX_TYPE, yt as WORKSHEET_TYPE } from "./tree-BX-sRRVp.mjs";
6
- import { C as chartExToBytes, E as chartToBytes, S as userShapesToBytes, g as chartsheetToBytes, i as commentsToBytes, m as drawingToBytes, o as placeholderVmlDrawing, r as tableToBytes, t as stylesheetToBytes, y as worksheetToBytes } from "./stylesheet-writer-D7Uug85X.mjs";
6
+ import { C as chartExToBytes, E as chartToBytes, S as userShapesToBytes, g as chartsheetToBytes, i as commentsToBytes, m as drawingToBytes, o as placeholderVmlDrawing, r as tableToBytes, t as stylesheetToBytes, y as writeWorksheetXml } from "./stylesheet-writer-BCS6PzWU.mjs";
7
7
  import { t as serializeXml } from "./serializer-C6nm0mRJ.mjs";
8
8
  import { V as corePropsToBytes, a as makeManifest, l as extendedPropsToBytes, n as addOverride, rt as relsToBytes, s as manifestToBytes, t as addDefault, tt as makeRelationships, v as customPropsToBytes } from "./manifest-pLmx7KYh.mjs";
9
9
  import { D as makeSharedStrings, S as validateSheetTitle, j as sharedStringsToBytes } from "./workbook-B15-T4cs.mjs";
10
- import { t as createZipWriter } from "./writer-IyFccCRJ.mjs";
10
+ import { t as utf8ByteLength } from "./utf8-OAkCDG5g.mjs";
11
+ import { t as createZipWriter } from "./writer-C38RBZCy.mjs";
11
12
  //#region src/io/save.ts
12
13
  const CORE_PROPS_TYPE = "application/vnd.openxmlformats-package.core-properties+xml";
13
14
  const EXT_PROPS_TYPE = "application/vnd.openxmlformats-officedocument.extended-properties+xml";
@@ -80,6 +81,45 @@ const toUint8ArraySink = () => {
80
81
  }
81
82
  };
82
83
  };
84
+ /** Flush threshold for a streamed part's pending text, in UTF-8 bytes. */
85
+ const STREAM_FLUSH_THRESHOLD_BYTES = 64 * 1024;
86
+ /**
87
+ * Open a ZIP entry and let `serialise` push XML fragments into it, flushing
88
+ * once the pending text crosses {@link STREAM_FLUSH_THRESHOLD_BYTES}.
89
+ *
90
+ * The threshold bounds what accumulates between fragments, not what a single
91
+ * fragment can be: a fragment is appended whole, so a one-string block such as
92
+ * `<cols>` or `<hyperlinks>` is still held entire however large it grows. The
93
+ * per-cell and per-row fragments that scale with sheet size are the ones this
94
+ * keeps bounded.
95
+ *
96
+ * The ZIP writer allows one streaming entry at a time, so this awaits `end()`
97
+ * before returning and the caller is free to write the next part.
98
+ */
99
+ const writeStreamedEntry = async (writer, archivePath, serialise) => {
100
+ const stream = writer.addStreamingEntry(archivePath);
101
+ try {
102
+ const encoder = new TextEncoder();
103
+ let pending = "";
104
+ let pendingBytes = 0;
105
+ serialise((chunk) => {
106
+ pending += chunk;
107
+ pendingBytes += utf8ByteLength(chunk);
108
+ if (pendingBytes >= STREAM_FLUSH_THRESHOLD_BYTES) {
109
+ stream.write(encoder.encode(pending));
110
+ pending = "";
111
+ pendingBytes = 0;
112
+ }
113
+ });
114
+ if (pending.length > 0) stream.write(encoder.encode(pending));
115
+ } catch (err) {
116
+ try {
117
+ await stream.end();
118
+ } catch {}
119
+ throw err;
120
+ }
121
+ await stream.end();
122
+ };
83
123
  /**
84
124
  * Validate every sheet title against Excel's character + length rules and
85
125
  * confirm titles are unique within the workbook. Catches bad state introduced
@@ -105,19 +145,19 @@ const validateSheetTitles = (wb) => {
105
145
  }
106
146
  };
107
147
  /** Save a workbook through the given sink. Returns once `finalize()` resolves. */
108
- async function saveWorkbook(wb, sink, _opts = {}) {
148
+ async function saveWorkbook(wb, sink, opts = {}) {
109
149
  validateSheetTitles(wb);
110
- const writer = createZipWriter(sink);
150
+ const writer = createZipWriter(sink, opts);
111
151
  try {
112
152
  await saveWorkbookImpl(wb, writer);
113
153
  } catch (err) {
114
- writer.abort(err);
154
+ await writer.abort(err);
115
155
  throw err;
116
156
  }
117
157
  }
118
158
  async function saveWorkbookImpl(wb, writer) {
119
159
  const sst = makeSharedStrings();
120
- const sheetEmits = [];
160
+ const sheetPlans = [];
121
161
  const tableEmits = [];
122
162
  let nextTableId = 1;
123
163
  const commentEmits = [];
@@ -150,12 +190,25 @@ async function saveWorkbookImpl(wb, writer) {
150
190
  nextRIdCursor++;
151
191
  return id;
152
192
  };
153
- wb.sheets.forEach((ref, _i) => {
193
+ for (const ref of wb.sheets) {
154
194
  const isChartsheet = ref.kind === "chartsheet";
155
195
  const target = isChartsheet ? `chartsheets/sheet${nextChartsheetId}.xml` : `worksheets/sheet${nextWorksheetId}.xml`;
156
196
  const archivePath = isChartsheet ? `xl/chartsheets/sheet${nextChartsheetId}.xml` : `xl/worksheets/sheet${nextWorksheetId}.xml`;
157
197
  if (isChartsheet) nextChartsheetId++;
158
198
  else nextWorksheetId++;
199
+ sheetPlans.push({
200
+ ref,
201
+ id: ref.rId ?? allocateRId(),
202
+ target,
203
+ relType: isChartsheet ? CHARTSHEET_REL : `${REL_NS}/worksheet`,
204
+ archivePath,
205
+ contentType: isChartsheet ? CHARTSHEET_TYPE : WORKSHEET_TYPE
206
+ });
207
+ }
208
+ const workbookXml = serializeWorkbookXml(wb, sheetPlans.map((p) => p.id));
209
+ await writer.addEntry(ARC_WORKBOOK, new TextEncoder().encode(workbookXml));
210
+ const writeSheetPart = async (plan) => {
211
+ const { ref, archivePath } = plan;
159
212
  const sheetRels = makeRelationships();
160
213
  const sheetRelsClaimed = /* @__PURE__ */ new Set();
161
214
  const sheetRelsExtras = ref.kind === "worksheet" ? ref.sheet.relsExtras ?? [] : [];
@@ -322,42 +375,40 @@ async function saveWorkbookImpl(wb, writer) {
322
375
  drawingEmits.push(emit);
323
376
  return { rId };
324
377
  };
325
- let bytes;
326
- if (ref.kind === "worksheet") bytes = worksheetToBytes(ref.sheet, {
327
- sharedStrings: sst,
328
- styles: wb.styles,
329
- date1904: wb.date1904,
330
- rels: sheetRels,
331
- registerTable,
332
- registerComments,
333
- registerDrawing
378
+ if (ref.kind === "worksheet") await writeStreamedEntry(writer, archivePath, (emit) => {
379
+ writeWorksheetXml(ref.sheet, {
380
+ sharedStrings: sst,
381
+ styles: wb.styles,
382
+ date1904: wb.date1904,
383
+ rels: sheetRels,
384
+ registerTable,
385
+ registerComments,
386
+ registerDrawing
387
+ }, emit);
334
388
  });
335
389
  else {
336
390
  let drawingRId;
337
391
  if (ref.sheet.drawing) drawingRId = registerDrawing(ref.sheet.drawing).rId;
338
- bytes = chartsheetToBytes(ref.sheet, drawingRId !== void 0 ? { drawingRId } : {});
392
+ await writer.addEntry(archivePath, chartsheetToBytes(ref.sheet, drawingRId !== void 0 ? { drawingRId } : {}));
339
393
  }
340
394
  for (const e of sheetRelsExtras) sheetRels.rels.push({
341
395
  id: e.id,
342
396
  type: e.type,
343
397
  target: e.target
344
398
  });
345
- const emit = {
346
- id: ref.rId ?? allocateRId(),
347
- target,
348
- bytes,
349
- relType: isChartsheet ? CHARTSHEET_REL : `${REL_NS}/worksheet`,
350
- archivePath,
351
- contentType: isChartsheet ? CHARTSHEET_TYPE : WORKSHEET_TYPE
352
- };
353
- if (sheetRels.rels.length > 0) emit.rels = sheetRels;
354
- sheetEmits.push(emit);
355
- });
399
+ if (sheetRels.rels.length > 0) {
400
+ const slash = archivePath.lastIndexOf("/");
401
+ const dir = archivePath.slice(0, slash);
402
+ const file = archivePath.slice(slash + 1);
403
+ await writer.addEntry(`${dir}/_rels/${file}.rels`, relsToBytes(sheetRels));
404
+ }
405
+ };
406
+ for (const plan of sheetPlans) await writeSheetPart(plan);
356
407
  const wbRels = makeRelationships();
357
- wbRels.rels = sheetEmits.map((e) => ({
358
- id: e.id,
359
- type: e.relType,
360
- target: e.target
408
+ wbRels.rels = sheetPlans.map((p) => ({
409
+ id: p.id,
410
+ type: p.relType,
411
+ target: p.target
361
412
  }));
362
413
  const orig = wb.workbookRelOriginalIds;
363
414
  if (sst.entries.length > 0) wbRels.rels.push({
@@ -385,18 +436,7 @@ async function saveWorkbookImpl(wb, writer) {
385
436
  type: e.type,
386
437
  target: e.target
387
438
  });
388
- const workbookXml = serializeWorkbookXml(wb, sheetEmits.map((e) => e.id));
389
- await writer.addEntry(ARC_WORKBOOK, new TextEncoder().encode(workbookXml));
390
439
  await writer.addEntry(ARC_WORKBOOK_RELS, relsToBytes(wbRels));
391
- for (const e of sheetEmits) {
392
- await writer.addEntry(e.archivePath, e.bytes);
393
- if (e.rels) {
394
- const slash = e.archivePath.lastIndexOf("/");
395
- const dir = e.archivePath.slice(0, slash);
396
- const file = e.archivePath.slice(slash + 1);
397
- await writer.addEntry(`${dir}/_rels/${file}.rels`, relsToBytes(e.rels));
398
- }
399
- }
400
440
  for (const t of tableEmits) await writer.addEntry(`xl/tables/table${t.id}.xml`, t.bytes);
401
441
  for (const c of commentEmits) {
402
442
  await writer.addEntry(`xl/comments${c.id}.xml`, c.commentsBytes);
@@ -449,7 +489,7 @@ async function saveWorkbookImpl(wb, writer) {
449
489
  if (wb.passthroughDefaults) for (const [ext, ct] of wb.passthroughDefaults) addDefault(manifest, ext, ct);
450
490
  const workbookContentType = wb.vbaProject ? "application/vnd.ms-excel.sheet.macroEnabled.main+xml" : XLSX_TYPE;
451
491
  addOverride(manifest, `/${ARC_WORKBOOK}`, workbookContentType);
452
- for (const e of sheetEmits) addOverride(manifest, `/${e.archivePath}`, e.contentType);
492
+ for (const p of sheetPlans) addOverride(manifest, `/${p.archivePath}`, p.contentType);
453
493
  addOverride(manifest, `/${ARC_STYLE}`, STYLES_TYPE);
454
494
  if (sst.entries.length > 0) addOverride(manifest, `/${ARC_SHARED_STRINGS}`, SHARED_STRINGS_TYPE);
455
495
  if (wb.themeXml) addOverride(manifest, `/${ARC_THEME}`, THEME_TYPE);
@@ -792,4 +832,4 @@ function serializeChildNode(node, inScopePrefixes) {
792
832
  //#endregion
793
833
  export { workbookToBytes as n, saveWorkbook as t };
794
834
 
795
- //# sourceMappingURL=save-a0InIbtJ.mjs.map
835
+ //# sourceMappingURL=save-I6GjvO1k.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save-I6GjvO1k.mjs","names":["serializeXmlNode"],"sources":["../src/io/save.ts"],"sourcesContent":["// Public `saveWorkbook` entry point.\n//\n// Part names and workbook rIds are settled in one cheap pass over `wb.sheets`\n// before anything is serialised, so `xl/workbook.xml` can go out first. Each\n// sheet is then serialised straight into its ZIP entry and released, so\n// worksheet XML no longer scales the heap: one flush buffer is live at a time\n// instead of the sum of every sheet's part.\n//\n// The side parts a sheet discovers along the way (tables, comments, drawings,\n// charts, images) are still collected whole and written after the sheets, and\n// the shared-strings table still grows with the workbook. Those two are what\n// bound a large save now.\n//\n// `xl/_rels/workbook.xml.rels` trails the sheet parts because its contents\n// depend on whether serialisation produced any shared strings.\n\nimport { escapeXmlAttr, escapeXmlText } from '../utils/escape.js';\nimport { chartToBytes } from '../chart/chart-xml.js';\nimport { chartExToBytes } from '../chart/cx/chartex-xml.js';\nimport { userShapesToBytes } from '../chart/user-shapes-xml.js';\nimport { chartsheetToBytes } from '../chartsheet/chartsheet-xml.js';\nimport type { Drawing, DrawingItem } from '../drawing/drawing.js';\nimport { drawingToBytes } from '../drawing/drawing-xml.js';\nimport { IMAGE_FORMAT_EXTENSION, IMAGE_FORMAT_MIME, type XlsxImageFormat } from '../drawing/image.js';\nimport type { XlsxSink } from '../io/sink.js';\nimport { OpenXmlIoError, OpenXmlSchemaError } from '../utils/exceptions.js';\nimport { normalizeFormulaText } from '../utils/formula-text.js';\nimport { utf8ByteLength } from '../utils/utf8.js';\nimport { corePropsToBytes } from '../packaging/core.js';\nimport { customPropsToBytes } from '../packaging/custom.js';\nimport { extendedPropsToBytes } from '../packaging/extended.js';\nimport { addDefault, addOverride, makeManifest, manifestToBytes } from '../packaging/manifest.js';\nimport { makeRelationships, type Relationships, relsToBytes } from '../packaging/relationships.js';\nimport { stylesheetToBytes } from '../styles/stylesheet-writer.js';\nimport { makeSharedStrings, sharedStringsToBytes } from '../workbook/shared-strings.js';\nimport { type SheetRef, type Workbook, validateSheetTitle } from '../workbook/workbook.js';\nimport type { LegacyComment } from '../worksheet/comments.js';\nimport { commentsToBytes, placeholderVmlDrawing } from '../worksheet/comments-xml.js';\nimport type { TableDefinition } from '../worksheet/table.js';\nimport { tableToBytes } from '../worksheet/table-xml.js';\nimport { type WorksheetXmlSink, writeWorksheetXml } from '../worksheet/writer.js';\nimport { serializeXml as serializeXmlNode } from '../xml/serializer.js';\nimport {\n ARC_APP,\n ARC_CONTENT_TYPES,\n ARC_CORE,\n ARC_CUSTOM,\n ARC_ROOT_RELS,\n ARC_SHARED_STRINGS,\n ARC_STYLE,\n ARC_THEME,\n ARC_WORKBOOK,\n ARC_WORKBOOK_RELS,\n CHARTEX_TYPE,\n CPROPS_TYPE,\n parseQName,\n PKG_REL_NS,\n REL_NS,\n SHARED_STRINGS_TYPE,\n SHEET_MAIN_NS,\n STYLES_TYPE,\n THEME_TYPE,\n WORKSHEET_TYPE,\n XLSX_TYPE,\n} from '../xml/namespaces.js';\nimport { type CompressionLevel, createZipWriter } from '../zip/writer.js';\n\nconst CORE_PROPS_TYPE = 'application/vnd.openxmlformats-package.core-properties+xml';\nconst EXT_PROPS_TYPE = 'application/vnd.openxmlformats-officedocument.extended-properties+xml';\nconst CORE_PROPS_REL = `${PKG_REL_NS}/metadata/core-properties`;\nconst EXT_PROPS_REL = `${REL_NS}/extended-properties`;\nconst CUSTOM_PROPS_REL = `${REL_NS}/custom-properties`;\nconst THEME_REL = `${REL_NS}/theme`;\nconst TABLE_REL = `${REL_NS}/table`;\nconst TABLE_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml';\nconst COMMENTS_REL = `${REL_NS}/comments`;\nconst VML_DRAWING_REL = `${REL_NS}/vmlDrawing`;\nconst COMMENTS_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml';\nconst VML_DRAWING_TYPE = 'application/vnd.openxmlformats-officedocument.vmlDrawing';\nconst DRAWING_REL = `${REL_NS}/drawing`;\nconst DRAWING_TYPE = 'application/vnd.openxmlformats-officedocument.drawing+xml';\nconst CHART_REL = `${REL_NS}/chart`;\nconst CHARTEX_REL = 'http://schemas.microsoft.com/office/2014/relationships/chartEx';\nconst CHART_TYPE = 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml';\nconst IMAGE_REL = `${REL_NS}/image`;\nconst CHARTSHEET_REL = `${REL_NS}/chartsheet`;\nconst CHARTSHEET_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml';\nconst CHART_USER_SHAPES_REL = `${REL_NS}/chartUserShapes`;\n\nexport interface SaveOptions {\n /**\n * Last-modified timestamp for every ZIP entry. Left unset, fflate stamps the\n * wall clock into each local header and central-directory record, so saving\n * the same workbook twice produces different bytes. Pin it and the output is\n * byte-identical for identical input on any machine, which is what\n * golden-file tests and content-addressed caches need.\n *\n * Recorded as the date's UTC wall time, to ZIP's two-second resolution; the\n * year has to fall in 1980-2099, the range supported by the ZIP backend.\n */\n mtime?: Date;\n /** Deflate level, 0 (no compression) to 9 (smallest). Defaults to fflate's own 6. */\n compressionLevel?: CompressionLevel;\n}\n\n/** Convenience: serialise a Workbook to an in-memory `Uint8Array` xlsx.\n *\n * Browser-safe: this path uses an in-memory `Uint8Array` sink and never\n * touches Node's `Buffer` global, so it works unchanged in browser bundles.\n */\nexport async function workbookToBytes(wb: Workbook, opts: SaveOptions = {}): Promise<Uint8Array> {\n const sink = toUint8ArraySink();\n await saveWorkbook(wb, sink, opts);\n return sink.result();\n}\n\nconst toUint8ArraySink = (): XlsxSink & { result(): Uint8Array } => {\n const chunks: Uint8Array[] = [];\n let finalised: Uint8Array | undefined;\n const finalise = (): Uint8Array => {\n if (finalised !== undefined) return finalised;\n let total = 0;\n for (const c of chunks) total += c.byteLength;\n const out = new Uint8Array(total);\n let off = 0;\n for (const c of chunks) {\n out.set(c, off);\n off += c.byteLength;\n }\n finalised = out;\n chunks.length = 0;\n return out;\n };\n return {\n toBytes() {\n return {\n write(chunk: Uint8Array): void {\n if (finalised !== undefined) {\n throw new OpenXmlIoError('workbookToBytes sink: write after finish');\n }\n if (!(chunk instanceof Uint8Array)) {\n throw new OpenXmlIoError('workbookToBytes sink: chunk is not a Uint8Array');\n }\n chunks.push(chunk);\n },\n async finish(): Promise<Uint8Array> {\n return finalise();\n },\n abort(): void {\n if (finalised !== undefined) return;\n finalised = new Uint8Array(0);\n chunks.length = 0;\n },\n };\n },\n result(): Uint8Array {\n return finalise();\n },\n };\n};\n\n/** Flush threshold for a streamed part's pending text, in UTF-8 bytes. */\nconst STREAM_FLUSH_THRESHOLD_BYTES = 64 * 1024;\n\n/**\n * Open a ZIP entry and let `serialise` push XML fragments into it, flushing\n * once the pending text crosses {@link STREAM_FLUSH_THRESHOLD_BYTES}.\n *\n * The threshold bounds what accumulates between fragments, not what a single\n * fragment can be: a fragment is appended whole, so a one-string block such as\n * `<cols>` or `<hyperlinks>` is still held entire however large it grows. The\n * per-cell and per-row fragments that scale with sheet size are the ones this\n * keeps bounded.\n *\n * The ZIP writer allows one streaming entry at a time, so this awaits `end()`\n * before returning and the caller is free to write the next part.\n */\nconst writeStreamedEntry = async (\n writer: ReturnType<typeof createZipWriter>,\n archivePath: string,\n serialise: (emit: WorksheetXmlSink) => void,\n): Promise<void> => {\n const stream = writer.addStreamingEntry(archivePath);\n try {\n const encoder = new TextEncoder();\n let pending = '';\n let pendingBytes = 0;\n serialise((chunk) => {\n pending += chunk;\n // UTF-8 byte length, computed without a full encode. `chunk.length`\n // counts UTF-16 code units, which undercounts CJK by ~3x and would let\n // the buffer balloon past the threshold on Japanese / Chinese workbooks.\n pendingBytes += utf8ByteLength(chunk);\n if (pendingBytes >= STREAM_FLUSH_THRESHOLD_BYTES) {\n stream.write(encoder.encode(pending));\n pending = '';\n pendingBytes = 0;\n }\n });\n if (pending.length > 0) stream.write(encoder.encode(pending));\n } catch (err) {\n // Seal the entry so the writer's one streaming slot is free again;\n // otherwise every later call fails with \"a streaming entry is still open\"\n // and buries the real cause. A failure from end() on top of a failed\n // serialisation is noise, so the original error is the one that escapes.\n try {\n await stream.end();\n } catch {\n // ignore\n }\n throw err;\n }\n await stream.end();\n};\n\n/**\n * Validate every sheet title against Excel's character + length rules and\n * confirm titles are unique within the workbook. Catches bad state introduced\n * via direct mutation (`ws.title = ...`) that bypassed the public mutators.\n *\n * Without this gate, a workbook with an invalid sheet name would round-trip to\n * an xlsx Excel rejects with a generic \"file is corrupt\" dialog on open —\n * making it hard to diagnose. Raising at save time keeps the bad state\n * recoverable: callers can `renameSheet` and retry.\n */\nconst validateSheetTitles = (wb: Workbook): void => {\n const seen = new Map<string, number>();\n for (let i = 0; i < wb.sheets.length; i++) {\n const ref = wb.sheets[i];\n if (!ref) continue;\n const title = ref.sheet.title;\n const reason = validateSheetTitle(title);\n if (reason) {\n throw new OpenXmlSchemaError(`saveWorkbook: sheet[${i}] title \"${title}\": ${reason}`);\n }\n const lower = title.toLowerCase();\n const prior = seen.get(lower);\n if (prior !== undefined) {\n throw new OpenXmlSchemaError(\n `saveWorkbook: sheet[${i}] title \"${title}\" collides with sheet[${prior}]` +\n ` (Excel treats sheet names case-insensitively for uniqueness).`,\n );\n }\n seen.set(lower, i);\n }\n};\n\n/** Save a workbook through the given sink. Returns once `finalize()` resolves. */\nexport async function saveWorkbook(wb: Workbook, sink: XlsxSink, opts: SaveOptions = {}): Promise<void> {\n validateSheetTitles(wb);\n const writer = createZipWriter(sink, opts);\n try {\n await saveWorkbookImpl(wb, writer);\n } catch (err) {\n // Release the sink so streaming destinations (`toFile` / `toWritable`)\n // don't leave a half-written file looking valid. Awaited because `toFile`\n // cleans up asynchronously: unawaited, this rejects while the partial file\n // is still on disk. abort() is idempotent so a successful finalize() above\n // is a no-op here.\n await writer.abort(err);\n throw err;\n }\n}\n\nasync function saveWorkbookImpl(wb: Workbook, writer: ReturnType<typeof createZipWriter>): Promise<void> {\n // ---- 1. name every sheet part and claim its workbook rId ----------------\n const sst = makeSharedStrings();\n interface SheetPlan {\n ref: SheetRef;\n id: string;\n target: string;\n /** OOXML relationship type used in workbook.xml.rels. */\n relType: string;\n /** ZIP archive path the part is written to. */\n archivePath: string;\n /** Override content type for [Content_Types].xml. */\n contentType: string;\n }\n const sheetPlans: SheetPlan[] = [];\n // Workbook-global table counter so xl/tables/tableN.xml ids stay unique.\n const tableEmits: Array<{ id: number; bytes: Uint8Array }> = [];\n let nextTableId = 1;\n // Same counter pattern for comments parts. The comments part and the VML\n // drawing share their N because Excel always emits them paired.\n interface CommentEmit {\n id: number;\n commentsBytes: Uint8Array;\n vmlBytes: Uint8Array;\n }\n const commentEmits: CommentEmit[] = [];\n // Passthrough carries form-control / header-footer VML under the same\n // xl/drawings/vmlDrawingN.vml naming, so start past whatever is already\n // taken — the zip writer rejects duplicate entries.\n let nextCommentsId = nextFreeIndex(wb, /^xl\\/drawings\\/vmlDrawing(\\d+)\\.vml$/);\n // Drawings: workbook-global drawingN counter for xl/drawings/drawingN.xml +\n // matching drawing-rels file (when chart items are present).\n interface DrawingEmit {\n id: number;\n bytes: Uint8Array;\n /** Drawing rels — when non-empty we also emit the rels file. */\n rels?: Relationships;\n }\n const drawingEmits: DrawingEmit[] = [];\n let nextDrawingId = 1;\n // Chart parts share a workbook-global counter so xl/charts/chartN.xml ids\n // stay unique.\n const chartEmits: Array<{\n id: number;\n bytes: Uint8Array;\n isCx: boolean;\n /** Per-chart rels file (only emitted when chart.userShapes is set). */\n rels?: Relationships;\n }> = [];\n let nextChartId = 1;\n // Workbook-global counter for chartDrawing parts. Each chart with userShapes\n // set produces one xl/drawings/chartDrawingN.xml entry.\n const userShapeEmits: Array<{ id: number; bytes: Uint8Array }> = [];\n let nextUserShapesId = 1;\n // Workbook-global counter for image media parts. Excel uses\n // xl/media/imageN.{ext} where N is shared across the package.\n interface ImageEmit {\n id: number;\n /** File extension (without the dot) — also drives the manifest Default. */\n ext: string;\n bytes: Uint8Array;\n }\n const imageEmits: ImageEmit[] = [];\n const imageExts = new Set<string>();\n // Same collision guard as for VML: images referenced by passthrough parts\n // keep their original xl/media/imageN.* names.\n let nextImageId = nextFreeIndex(wb, /^xl\\/media\\/image(\\d+)\\./);\n // Track separate counters so worksheet / chartsheet IDs do not collide (Excel\n // uses xl/worksheets/sheetN.xml and xl/chartsheets/sheetM.xml independently\n // of one another).\n let nextWorksheetId = 1;\n let nextChartsheetId = 1;\n // Pre-claim every original rId so freshly allocated ones (sheets without a\n // captured rId, plus modeled non-sheet rels) avoid collision with captured\n // workbookRelsExtras and the modeled non-sheet original ids.\n const claimedRIds = new Set<string>();\n for (const ref of wb.sheets) {\n if (ref.rId !== undefined) claimedRIds.add(ref.rId);\n }\n if (wb.workbookRelOriginalIds) {\n for (const v of Object.values(wb.workbookRelOriginalIds)) {\n if (typeof v === 'string') claimedRIds.add(v);\n }\n }\n if (wb.workbookRelsExtras) {\n for (const e of wb.workbookRelsExtras) claimedRIds.add(e.id);\n }\n let nextRIdCursor = 1;\n const allocateRId = (): string => {\n let id = `rId${nextRIdCursor}`;\n while (claimedRIds.has(id)) {\n nextRIdCursor++;\n id = `rId${nextRIdCursor}`;\n }\n claimedRIds.add(id);\n nextRIdCursor++;\n return id;\n };\n // Part names and workbook-level rIds are pure counter arithmetic, so they are\n // settled here, before anything is serialised. That is what lets workbook.xml\n // (which needs every sheet's rId) go out ahead of the sheet parts while the\n // sheets themselves stream one at a time below.\n for (const ref of wb.sheets) {\n const isChartsheet = ref.kind === 'chartsheet';\n const target = isChartsheet ? `chartsheets/sheet${nextChartsheetId}.xml` : `worksheets/sheet${nextWorksheetId}.xml`;\n const archivePath = isChartsheet\n ? `xl/chartsheets/sheet${nextChartsheetId}.xml`\n : `xl/worksheets/sheet${nextWorksheetId}.xml`;\n if (isChartsheet) nextChartsheetId++;\n else nextWorksheetId++;\n sheetPlans.push({\n ref,\n id: ref.rId ?? allocateRId(),\n target,\n relType: isChartsheet ? CHARTSHEET_REL : `${REL_NS}/worksheet`,\n archivePath,\n contentType: isChartsheet ? CHARTSHEET_TYPE : WORKSHEET_TYPE,\n });\n }\n\n // ---- 2. workbook.xml ----------------------------------------------------\n const workbookXml = serializeWorkbookXml(\n wb,\n sheetPlans.map((p) => p.id),\n );\n await writer.addEntry(ARC_WORKBOOK, new TextEncoder().encode(workbookXml));\n\n // ---- 3. each worksheet / chartsheet (and its rels file when present) ----\n // A named function rather than the loop body below: the register* callbacks\n // close over the workbook-global part counters, and `no-loop-func` rejects a\n // closure over a reassigned `let` when it is declared inside a loop. The\n // callbacks are rebuilt per sheet either way.\n const writeSheetPart = async (plan: SheetPlan): Promise<void> => {\n const { ref, archivePath } = plan;\n const sheetRels = makeRelationships();\n // Pre-claim every captured relsExtras rId so freshly allocated modeled rels\n // never clash. The extras themselves are appended to sheetRels at the end\n // so any rId already used inside the worksheet body (drawing / hyperlink\n // refs) keeps pointing at our newly emitted rel.\n const sheetRelsClaimed = new Set<string>();\n const sheetRelsExtras = ref.kind === 'worksheet' ? (ref.sheet.relsExtras ?? []) : [];\n for (const e of sheetRelsExtras) sheetRelsClaimed.add(e.id);\n let sheetRIdCursor = 1;\n const allocateSheetRId = (): string => {\n let id = `rId${sheetRIdCursor}`;\n while (sheetRelsClaimed.has(id) || sheetRels.rels.some((r) => r.id === id)) {\n sheetRIdCursor++;\n id = `rId${sheetRIdCursor}`;\n }\n sheetRIdCursor++;\n return id;\n };\n const registerTable = (table: TableDefinition): { rId: string } => {\n const tableId = nextTableId++;\n const rId = allocateSheetRId();\n sheetRels.rels.push({\n id: rId,\n type: TABLE_REL,\n target: `../tables/table${tableId}.xml`,\n });\n // Emit the table part with its workbook-global id baked in.\n const xmlTable: TableDefinition = { ...table, id: tableId };\n tableEmits.push({ id: tableId, bytes: tableToBytes(xmlTable) });\n return { rId };\n };\n const registerComments = (comments: ReadonlyArray<LegacyComment>): { vmlRelId: string } => {\n const id = nextCommentsId++;\n const commentsRelId = allocateSheetRId();\n sheetRels.rels.push({\n id: commentsRelId,\n type: COMMENTS_REL,\n target: `../comments${id}.xml`,\n });\n const vmlRelId = allocateSheetRId();\n sheetRels.rels.push({\n id: vmlRelId,\n type: VML_DRAWING_REL,\n target: `../drawings/vmlDrawing${id}.vml`,\n });\n commentEmits.push({\n id,\n commentsBytes: commentsToBytes(comments),\n vmlBytes: placeholderVmlDrawing(comments),\n });\n return { vmlRelId };\n };\n const registerDrawing = (drawing: Drawing): { rId: string } => {\n const id = nextDrawingId++;\n const rId = allocateSheetRId();\n sheetRels.rels.push({\n id: rId,\n type: DRAWING_REL,\n target: `../drawings/drawing${id}.xml`,\n });\n // Walk drawing items: for each chart with a payload, allocate a\n // workbook-global chartN id and a per-drawing rId. Emit the chart part +\n // collect a drawing-rels entry so drawing.xml's <c:chart r:id> resolves.\n const drawingRels = makeRelationships();\n // Rels the drawing's verbatim nodes reference keep their original ids —\n // those ids are baked into XML we re-emit untouched — so the allocator\n // below has to step over them.\n const usedDrawingRIds = new Set<string>();\n for (const rel of drawing.rawRels?.rels ?? []) {\n drawingRels.rels.push(rel);\n usedDrawingRIds.add(rel.id);\n }\n let nextDrawingRId = 1;\n const allocateDrawingRId = (): string => {\n let candidate = `rId${nextDrawingRId++}`;\n while (usedDrawingRIds.has(candidate)) candidate = `rId${nextDrawingRId++}`;\n usedDrawingRIds.add(candidate);\n return candidate;\n };\n const itemsForXml: DrawingItem[] = [];\n for (const item of drawing.items) {\n if (item.content.kind === 'chart' && (item.content.chart.space || item.content.chart.cxSpace)) {\n const chartId = nextChartId++;\n const chartRId = allocateDrawingRId();\n // chartex parts use a different relationship Type than the legacy\n // ECMA-376 charts. Excel rejects the workbook when the drawing rels\n // claim a `relationships/chart` target that actually contains a\n // `cx:chartSpace` root.\n const isCxChart = item.content.chart.cxSpace !== undefined;\n drawingRels.rels.push({\n id: chartRId,\n type: isCxChart ? CHARTEX_REL : CHART_REL,\n target: `../charts/chart${chartId}.xml`,\n });\n if (item.content.chart.cxSpace) {\n chartEmits.push({\n id: chartId,\n bytes: chartExToBytes(item.content.chart.cxSpace),\n isCx: true,\n });\n } else if (item.content.chart.space) {\n const space = item.content.chart.space;\n // If the chart carries user shapes, allocate the chartDrawingN part\n // + a per-chart rels file referencing it, then bake the resulting\n // r:id into the chart's <c:userShapes> element.\n let userShapesRId: string | undefined;\n let chartRelsFile: Relationships | undefined;\n if (space.userShapes && space.userShapes.shapes.length > 0) {\n const userShapesId = nextUserShapesId++;\n userShapesRId = 'rId1';\n chartRelsFile = makeRelationships();\n chartRelsFile.rels.push({\n id: userShapesRId,\n type: CHART_USER_SHAPES_REL,\n target: `../drawings/chartDrawing${userShapesId}.xml`,\n });\n userShapeEmits.push({\n id: userShapesId,\n bytes: userShapesToBytes(space.userShapes),\n });\n }\n const chartEmit: typeof chartEmits[number] = {\n id: chartId,\n bytes: chartToBytes(space, userShapesRId !== undefined ? { userShapesRId } : {}),\n isCx: false,\n };\n if (chartRelsFile) chartEmit.rels = chartRelsFile;\n chartEmits.push(chartEmit);\n }\n itemsForXml.push({\n anchor: item.anchor,\n content: {\n kind: 'chart',\n chart: {\n rId: chartRId,\n ...(item.content.chart.cxSpace ? { isCx: true } : {}),\n },\n },\n });\n } else if (item.content.kind === 'picture' && item.content.picture.image) {\n const img = item.content.picture.image;\n const ext = IMAGE_FORMAT_EXTENSION[img.format];\n const imageId = nextImageId++;\n const picRId = allocateDrawingRId();\n drawingRels.rels.push({\n id: picRId,\n type: IMAGE_REL,\n target: `../media/image${imageId}.${ext}`,\n });\n imageEmits.push({ id: imageId, ext, bytes: img.bytes });\n imageExts.add(ext);\n itemsForXml.push({\n anchor: item.anchor,\n content: {\n kind: 'picture',\n picture: {\n rId: picRId,\n ...(item.content.picture.name !== undefined ? { name: item.content.picture.name } : {}),\n ...(item.content.picture.descr !== undefined ? { descr: item.content.picture.descr } : {}),\n ...(item.content.picture.hidden !== undefined ? { hidden: item.content.picture.hidden } : {}),\n ...(item.content.picture.spPr ? { spPr: item.content.picture.spPr } : {}),\n },\n },\n });\n } else {\n itemsForXml.push(item);\n }\n }\n const emit: DrawingEmit = {\n id,\n bytes: drawingToBytes({\n items: itemsForXml,\n ...(drawing.rawChildren ? { rawChildren: drawing.rawChildren } : {}),\n }),\n };\n if (drawingRels.rels.length > 0) emit.rels = drawingRels;\n drawingEmits.push(emit);\n return { rId };\n };\n if (ref.kind === 'worksheet') {\n // Streamed rather than materialised: a sheet with a million cells\n // deflates to a few MB but would hold hundreds of MB as fragments plus\n // the joined string plus the encoded bytes if built in one piece.\n await writeStreamedEntry(writer, archivePath, (emit) => {\n writeWorksheetXml(ref.sheet, {\n sharedStrings: sst,\n styles: wb.styles,\n date1904: wb.date1904,\n rels: sheetRels,\n registerTable,\n registerComments,\n registerDrawing,\n }, emit);\n });\n } else {\n // Chartsheet: register the drawing (if any), then emit the chartsheet\n // part with the resulting r:id baked in. Chartsheets carry no cell grid,\n // so they stay small and go out in one piece.\n let drawingRId: string | undefined;\n if (ref.sheet.drawing) drawingRId = registerDrawing(ref.sheet.drawing).rId;\n await writer.addEntry(archivePath, chartsheetToBytes(ref.sheet, drawingRId !== undefined ? { drawingRId } : {}));\n }\n // Append captured per-sheet rels passthrough (pivotTable / queryTable /\n // printerSettings / oleObject / customProperty / threadedComment …)\n // verbatim. Their original rIds were pre-claimed so the modeled allocations\n // above never collide with them.\n for (const e of sheetRelsExtras) {\n sheetRels.rels.push({ id: e.id, type: e.type, target: e.target });\n }\n if (sheetRels.rels.length > 0) {\n // The rels file sits alongside its part: `xl/<dir>/_rels/<file>.rels`.\n const slash = archivePath.lastIndexOf('/');\n const dir = archivePath.slice(0, slash);\n const file = archivePath.slice(slash + 1);\n await writer.addEntry(`${dir}/_rels/${file}.rels`, relsToBytes(sheetRels));\n }\n };\n // One sheet at a time: the ZIP writer permits a single open streaming entry\n // and rejects a second one, so this is what keeps a sheet's bytes from having\n // to be held while another sheet is written.\n for (const plan of sheetPlans) await writeSheetPart(plan);\n\n // ---- 4. workbook rels -- sheets first, then sst (if any), then styles, then\n // theme / vbaProject, then any captured workbookRelsExtras (e.g.\n // pivotCacheDefinition rels referenced by `<pivotCaches>`). Modeled non-sheet\n // rels prefer the rId captured at load time so any captured extras XML using\n // that Id still resolves after the round-trip.\n const wbRels = makeRelationships();\n wbRels.rels = sheetPlans.map((p) => ({\n id: p.id,\n type: p.relType,\n target: p.target,\n }));\n const orig = wb.workbookRelOriginalIds;\n if (sst.entries.length > 0) {\n wbRels.rels.push({\n id: orig?.sharedStrings ?? allocateRId(),\n type: `${REL_NS}/sharedStrings`,\n target: 'sharedStrings.xml',\n });\n }\n wbRels.rels.push({\n id: orig?.styles ?? allocateRId(),\n type: `${REL_NS}/styles`,\n target: 'styles.xml',\n });\n if (wb.themeXml) {\n wbRels.rels.push({\n id: orig?.theme ?? allocateRId(),\n type: THEME_REL,\n target: 'theme/theme1.xml',\n });\n }\n if (wb.vbaProject) {\n wbRels.rels.push({\n id: orig?.vbaProject ?? allocateRId(),\n type: `${REL_NS}/vbaProject`,\n target: 'vbaProject.bin',\n });\n }\n if (wb.workbookRelsExtras) {\n for (const e of wb.workbookRelsExtras) {\n wbRels.rels.push({ id: e.id, type: e.type, target: e.target });\n }\n }\n\n // Written after the sheet parts, not before them: whether a\n // `sharedStrings.xml` rel belongs here is only known once every sheet has\n // been serialised, since that is what fills the shared-strings table. OPC\n // resolves parts by name, so the position of a rels entry in the archive\n // carries no meaning.\n await writer.addEntry(ARC_WORKBOOK_RELS, relsToBytes(wbRels));\n\n // ---- 4b. table parts ----------------------------------------------------\n for (const t of tableEmits) {\n await writer.addEntry(`xl/tables/table${t.id}.xml`, t.bytes);\n }\n\n // ---- 4c. comments parts + matching VML drawings ------------------------\n for (const c of commentEmits) {\n await writer.addEntry(`xl/comments${c.id}.xml`, c.commentsBytes);\n await writer.addEntry(`xl/drawings/vmlDrawing${c.id}.vml`, c.vmlBytes);\n }\n\n // ---- 4d. drawings + their rels (when charts are embedded) -------------\n for (const d of drawingEmits) {\n await writer.addEntry(`xl/drawings/drawing${d.id}.xml`, d.bytes);\n if (d.rels) {\n await writer.addEntry(`xl/drawings/_rels/drawing${d.id}.xml.rels`, relsToBytes(d.rels));\n }\n }\n\n // ---- 4e. chart parts (and per-chart rels when user shapes attach) -----\n for (const c of chartEmits) {\n await writer.addEntry(`xl/charts/chart${c.id}.xml`, c.bytes);\n if (c.rels) {\n await writer.addEntry(`xl/charts/_rels/chart${c.id}.xml.rels`, relsToBytes(c.rels));\n }\n }\n\n // ---- 4f. user-shape drawings (xl/drawings/chartDrawingN.xml) ----------\n for (const us of userShapeEmits) {\n await writer.addEntry(`xl/drawings/chartDrawing${us.id}.xml`, us.bytes);\n }\n\n // ---- 4g. embedded images (xl/media/imageN.{ext}) ----------------------\n for (const img of imageEmits) {\n await writer.addEntry(`xl/media/image${img.id}.${img.ext}`, img.bytes);\n }\n\n // ---- 5. styles.xml + sharedStrings.xml (if any) -------------------------\n await writer.addEntry(ARC_STYLE, stylesheetToBytes(wb.styles));\n if (sst.entries.length > 0) {\n await writer.addEntry(ARC_SHARED_STRINGS, sharedStringsToBytes(sst));\n }\n\n // ---- 5b. theme1.xml (passthrough) — only when wb carries one. The theme rel\n // was already added to wbRels above so workbook.xml.rels references it.\n if (wb.themeXml) await writer.addEntry(ARC_THEME, wb.themeXml);\n\n // ---- 5c. docProps/{core,app,custom}.xml (when present) ------------------\n if (wb.properties) await writer.addEntry(ARC_CORE, corePropsToBytes(wb.properties));\n if (wb.appProperties) await writer.addEntry(ARC_APP, extendedPropsToBytes(wb.appProperties));\n if (wb.customProperties) await writer.addEntry(ARC_CUSTOM, customPropsToBytes(wb.customProperties));\n\n // ---- 5d. VBA project + signature (when present) -------------------------\n if (wb.vbaProject) await writer.addEntry('xl/vbaProject.bin', wb.vbaProject);\n if (wb.vbaSignature) await writer.addEntry('xl/vbaProjectSignature.bin', wb.vbaSignature);\n\n // ---- 5e. Pass-through bytes (pivot / activeX / customXml / etc.) -------\n if (wb.passthrough) {\n for (const [path, bytes] of wb.passthrough) await writer.addEntry(path, bytes);\n }\n\n // ---- 6. root rels -------------------------------------------------------\n const rootRels: Relationships = { rels: [] };\n rootRels.rels.push({\n id: 'rId1',\n type: `${REL_NS}/officeDocument`,\n target: 'xl/workbook.xml',\n });\n if (wb.properties) {\n rootRels.rels.push({\n id: `rId${rootRels.rels.length + 1}`,\n type: CORE_PROPS_REL,\n target: 'docProps/core.xml',\n });\n }\n if (wb.appProperties) {\n rootRels.rels.push({\n id: `rId${rootRels.rels.length + 1}`,\n type: EXT_PROPS_REL,\n target: 'docProps/app.xml',\n });\n }\n if (wb.customProperties) {\n rootRels.rels.push({\n id: `rId${rootRels.rels.length + 1}`,\n type: CUSTOM_PROPS_REL,\n target: 'docProps/custom.xml',\n });\n }\n await writer.addEntry(ARC_ROOT_RELS, relsToBytes(rootRels));\n\n // ---- 7. [Content_Types].xml --------------------------------------------\n const manifest = makeManifest();\n addDefault(manifest, 'rels', 'application/vnd.openxmlformats-package.relationships+xml');\n addDefault(manifest, 'xml', 'application/xml');\n // Defaults carried over for passthrough parts go first: addDefault is\n // last-wins, so the writer's own registrations below (vml for comments, bin\n // for VBA, image formats) still take precedence on a shared extension.\n if (wb.passthroughDefaults) {\n for (const [ext, ct] of wb.passthroughDefaults) addDefault(manifest, ext, ct);\n }\n // VBA-bearing workbooks promote the workbook content type to xlsm.\n const workbookContentType = wb.vbaProject\n ? 'application/vnd.ms-excel.sheet.macroEnabled.main+xml'\n : XLSX_TYPE;\n addOverride(manifest, `/${ARC_WORKBOOK}`, workbookContentType);\n for (const p of sheetPlans) {\n addOverride(manifest, `/${p.archivePath}`, p.contentType);\n }\n addOverride(manifest, `/${ARC_STYLE}`, STYLES_TYPE);\n if (sst.entries.length > 0) {\n addOverride(manifest, `/${ARC_SHARED_STRINGS}`, SHARED_STRINGS_TYPE);\n }\n if (wb.themeXml) addOverride(manifest, `/${ARC_THEME}`, THEME_TYPE);\n for (const t of tableEmits) {\n addOverride(manifest, `/xl/tables/table${t.id}.xml`, TABLE_TYPE);\n }\n if (commentEmits.length > 0) {\n addDefault(manifest, 'vml', VML_DRAWING_TYPE);\n }\n for (const c of commentEmits) {\n addOverride(manifest, `/xl/comments${c.id}.xml`, COMMENTS_TYPE);\n }\n for (const d of drawingEmits) {\n addOverride(manifest, `/xl/drawings/drawing${d.id}.xml`, DRAWING_TYPE);\n }\n for (const c of chartEmits) {\n addOverride(manifest, `/xl/charts/chart${c.id}.xml`, c.isCx ? CHARTEX_TYPE : CHART_TYPE);\n }\n for (const us of userShapeEmits) {\n addOverride(manifest, `/xl/drawings/chartDrawing${us.id}.xml`, DRAWING_TYPE);\n }\n if (wb.vbaProject) {\n addDefault(manifest, 'bin', 'application/vnd.ms-office.vbaProject');\n }\n if (wb.passthrough) {\n for (const path of wb.passthrough.keys()) {\n const ct = wb.passthroughContentTypes?.get(path);\n if (ct !== undefined) addOverride(manifest, `/${path}`, ct);\n }\n }\n // Each unique image extension gets a Default entry (`<Default Extension=\"png\"\n // ContentType=\"image/png\"/>`).\n for (const ext of imageExts) {\n const fmt = (Object.entries(IMAGE_FORMAT_EXTENSION).find(([, e]) => e === ext) ?? [])[0] as\n | XlsxImageFormat\n | undefined;\n if (fmt) addDefault(manifest, ext, IMAGE_FORMAT_MIME[fmt]);\n }\n if (wb.properties) addOverride(manifest, `/${ARC_CORE}`, CORE_PROPS_TYPE);\n if (wb.appProperties) addOverride(manifest, `/${ARC_APP}`, EXT_PROPS_TYPE);\n if (wb.customProperties) addOverride(manifest, `/${ARC_CUSTOM}`, CPROPS_TYPE);\n await writer.addEntry(ARC_CONTENT_TYPES, manifestToBytes(manifest));\n\n // ---- 8. close ----------------------------------------------------------\n await writer.finalize();\n}\n\n/**\n * 1 + the highest N among passthrough paths matching `pattern` (whose first\n * capture group is N), so freshly numbered modeled parts never collide with a\n * carried-over one.\n */\nfunction nextFreeIndex(wb: Workbook, pattern: RegExp): number {\n let max = 0;\n if (wb.passthrough) {\n for (const path of wb.passthrough.keys()) {\n const m = pattern.exec(path);\n if (m?.[1] !== undefined) max = Math.max(max, Number.parseInt(m[1], 10));\n }\n }\n return max + 1;\n}\n\n/** Serialise the minimum `<workbook><sheets/></workbook>` Excel needs to load a sheet list. */\nfunction serializeWorkbookXml(wb: Workbook, sheetRIds: ReadonlyArray<string>): string {\n // Excel's markup-compatibility header: the extra prefixes it declares on the\n // root and the `mc:Ignorable` list naming them. Both are re-emitted exactly\n // as written, and the same prefix map is handed to every captured child so\n // `xr:revisionPtr` doesn't come back as `x16:revisionPtr`.\n const rootNs = wb.workbookXmlRoot?.namespaces ?? [];\n const nsDecls = rootNs.map((d) => ` xmlns:${d.prefix}=\"${escapeAttr(d.ns)}\"`).join('');\n const ignorable = wb.workbookXmlRoot?.ignorable;\n const ignorableAttr = ignorable !== undefined ? ` mc:Ignorable=\"${escapeAttr(ignorable)}\"` : '';\n const inScopePrefixes: Record<string, string> = { [SHEET_MAIN_NS]: '', [REL_NS]: 'r' };\n for (const d of rootNs) inScopePrefixes[d.ns] ??= d.prefix;\n const emitExtra = (node: import('../xml/tree.js').XmlNode): string =>\n serializeChildNode(node, inScopePrefixes);\n\n const parts: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>',\n `<workbook xmlns=\"${SHEET_MAIN_NS}\" xmlns:r=\"${REL_NS}\"${nsDecls}${ignorableAttr}>`,\n ];\n if (wb.fileVersion) {\n const fv = serializeFileVersion(wb.fileVersion);\n if (fv) parts.push(fv);\n }\n if (wb.fileSharing) {\n const fs = serializeFileSharing(wb.fileSharing);\n if (fs) parts.push(fs);\n }\n // Emit <workbookPr> from the typed model; fall back to a minimal {date1904:\n // true} synthesis so a fresh workbook (no load history) still round-trips\n // through Excel with the right epoch.\n const effectiveWp = effectiveWorkbookProperties(wb);\n if (effectiveWp) {\n const wp = serializeWorkbookProperties(effectiveWp);\n if (wp) parts.push(wp);\n }\n if (wb.workbookProtection) {\n const wp = serializeWorkbookProtection(wb.workbookProtection);\n if (wp) parts.push(wp);\n }\n // The unmodeled head — `mc:AlternateContent`, `xr:revisionPtr` — sits after\n // `<workbookPr>` in what Excel writes, and CT_Workbook has no slot for it,\n // so it goes here rather than ahead of the modeled elements.\n if (wb.workbookXmlExtras?.beforeSheets) {\n for (const node of wb.workbookXmlExtras.beforeSheets) parts.push(emitExtra(node));\n }\n if (wb.bookViews && wb.bookViews.length > 0) parts.push(serializeBookViews(wb.bookViews, inScopePrefixes));\n parts.push('<sheets>');\n wb.sheets.forEach((ref, i) => {\n const stateAttr = ref.state === 'visible' ? '' : ` state=\"${ref.state}\"`;\n const rId = sheetRIds[i] ?? `rId${i + 1}`;\n parts.push(`<sheet name=\"${escapeAttr(ref.sheet.title)}\" sheetId=\"${ref.sheetId}\"${stateAttr} r:id=\"${rId}\"/>`);\n });\n parts.push('</sheets>');\n // ECMA-376 §18.2.27 makes CT_Workbook an xsd:sequence, so the order below is\n // normative: functionGroups, externalReferences, definedNames, calcPr,\n // oleSize, customWorkbookViews, pivotCaches, smartTagPr, smartTagTypes,\n // webPublishing, fileRecoveryPr, webPublishObjects, extLst. Excel rejects a\n // workbook whose children are out of sequence. `afterSheets` is the\n // unmodeled tail (webPublishing / webPublishObjects / extLst /\n // mc:AlternateContent), so it goes last.\n if (wb.functionGroups) {\n const fg = serializeFunctionGroups(wb.functionGroups);\n if (fg) parts.push(fg);\n }\n if (wb.externalReferences && wb.externalReferences.length > 0) {\n const inner: string[] = ['<externalReferences>'];\n for (const er of wb.externalReferences) {\n inner.push(`<externalReference r:id=\"${escapeAttr(er.rId)}\"/>`);\n }\n inner.push('</externalReferences>');\n parts.push(inner.join(''));\n }\n if (wb.definedNames.length > 0) {\n parts.push('<definedNames>');\n for (const dn of wb.definedNames) {\n let attrs = ` name=\"${escapeAttr(dn.name)}\"`;\n if (dn.scope !== undefined) attrs += ` localSheetId=\"${dn.scope}\"`;\n if (dn.hidden) attrs += ' hidden=\"1\"';\n if (dn.comment !== undefined) attrs += ` comment=\"${escapeAttr(dn.comment)}\"`;\n parts.push(`<definedName${attrs}>${escapeText(normalizeFormulaText(dn.value))}</definedName>`);\n }\n parts.push('</definedNames>');\n }\n if (wb.calcProperties) {\n const cp = serializeCalcProperties(wb.calcProperties);\n if (cp) parts.push(cp);\n }\n // No default `<calcPr>` — Excel handles its absence by inserting one on save.\n // Hand-rolled `calcId` values (especially the modern 191029) made Excel\n // reject workbooks whose future-function formulas (LET / LAMBDA / FILTER…)\n // couldn't be evaluated against the declared engine.\n if (wb.oleSize !== undefined) {\n parts.push(`<oleSize ref=\"${escapeAttr(wb.oleSize)}\"/>`);\n }\n if (wb.customWorkbookViews && wb.customWorkbookViews.length > 0) {\n parts.push(serializeCustomWorkbookViews(wb.customWorkbookViews));\n }\n if (wb.pivotCaches && wb.pivotCaches.length > 0) {\n const inner: string[] = ['<pivotCaches>'];\n for (const pc of wb.pivotCaches) {\n inner.push(`<pivotCache cacheId=\"${pc.cacheId}\" r:id=\"${escapeAttr(pc.rId)}\"/>`);\n }\n inner.push('</pivotCaches>');\n parts.push(inner.join(''));\n }\n if (wb.smartTagPr) {\n const stp = serializeSmartTagPr(wb.smartTagPr);\n if (stp) parts.push(stp);\n }\n if (wb.smartTagTypes && wb.smartTagTypes.length > 0) {\n parts.push(serializeSmartTagTypes(wb.smartTagTypes));\n }\n if (wb.fileRecoveryPr) {\n const fp = serializeFileRecoveryPr(wb.fileRecoveryPr);\n if (fp) parts.push(fp);\n }\n if (wb.workbookXmlExtras?.afterSheets) {\n for (const node of wb.workbookXmlExtras.afterSheets) parts.push(emitExtra(node));\n }\n parts.push('</workbook>');\n return parts.join('');\n}\n\nfunction serializeCalcProperties(\n cp: import('../workbook/calc-properties.js').CalcProperties,\n): string | undefined {\n let attrs = '';\n if (cp.calcId !== undefined) attrs += ` calcId=\"${cp.calcId}\"`;\n if (cp.calcMode !== undefined) attrs += ` calcMode=\"${cp.calcMode}\"`;\n if (cp.fullCalcOnLoad !== undefined) attrs += ` fullCalcOnLoad=\"${cp.fullCalcOnLoad ? '1' : '0'}\"`;\n if (cp.refMode !== undefined) attrs += ` refMode=\"${cp.refMode}\"`;\n if (cp.iterate !== undefined) attrs += ` iterate=\"${cp.iterate ? '1' : '0'}\"`;\n if (cp.iterateCount !== undefined) attrs += ` iterateCount=\"${cp.iterateCount}\"`;\n if (cp.iterateDelta !== undefined) attrs += ` iterateDelta=\"${cp.iterateDelta}\"`;\n if (cp.fullPrecision !== undefined) attrs += ` fullPrecision=\"${cp.fullPrecision ? '1' : '0'}\"`;\n if (cp.calcCompleted !== undefined) attrs += ` calcCompleted=\"${cp.calcCompleted ? '1' : '0'}\"`;\n if (cp.calcOnSave !== undefined) attrs += ` calcOnSave=\"${cp.calcOnSave ? '1' : '0'}\"`;\n if (cp.concurrentCalc !== undefined) attrs += ` concurrentCalc=\"${cp.concurrentCalc ? '1' : '0'}\"`;\n if (cp.concurrentManualCount !== undefined) attrs += ` concurrentManualCount=\"${cp.concurrentManualCount}\"`;\n if (cp.forceFullCalc !== undefined) attrs += ` forceFullCalc=\"${cp.forceFullCalc ? '1' : '0'}\"`;\n if (attrs.length === 0) return undefined;\n return `<calcPr${attrs}/>`;\n}\n\nfunction serializeFunctionGroups(\n fg: import('../workbook/function-groups.js').FunctionGroups,\n): string | undefined {\n let attrs = '';\n if (fg.builtInGroupCount !== undefined) attrs += ` builtInGroupCount=\"${fg.builtInGroupCount}\"`;\n if (fg.groups.length === 0 && attrs.length === 0) return undefined;\n if (fg.groups.length === 0) return `<functionGroups${attrs}/>`;\n const inner: string[] = [`<functionGroups${attrs}>`];\n for (const g of fg.groups) inner.push(`<functionGroup name=\"${escapeAttr(g.name)}\"/>`);\n inner.push('</functionGroups>');\n return inner.join('');\n}\n\nfunction serializeSmartTagPr(\n stp: import('../workbook/smart-tags.js').SmartTagProperties,\n): string | undefined {\n let attrs = '';\n if (stp.embed !== undefined) attrs += ` embed=\"${stp.embed ? '1' : '0'}\"`;\n if (stp.show !== undefined) attrs += ` show=\"${stp.show}\"`;\n if (attrs.length === 0) return undefined;\n return `<smartTagPr${attrs}/>`;\n}\n\nfunction serializeSmartTagTypes(\n tags: ReadonlyArray<import('../workbook/smart-tags.js').SmartTagType>,\n): string {\n const inner: string[] = ['<smartTagTypes>'];\n for (const t of tags) {\n let attrs = '';\n if (t.namespaceUri !== undefined) attrs += ` namespaceUri=\"${escapeAttr(t.namespaceUri)}\"`;\n if (t.name !== undefined) attrs += ` name=\"${escapeAttr(t.name)}\"`;\n if (t.url !== undefined) attrs += ` url=\"${escapeAttr(t.url)}\"`;\n inner.push(`<smartTagType${attrs}/>`);\n }\n inner.push('</smartTagTypes>');\n return inner.join('');\n}\n\nfunction serializeFileRecoveryPr(\n fp: import('../workbook/file-recovery.js').FileRecoveryProperties,\n): string | undefined {\n let attrs = '';\n if (fp.autoRecover !== undefined) attrs += ` autoRecover=\"${fp.autoRecover ? '1' : '0'}\"`;\n if (fp.crashSave !== undefined) attrs += ` crashSave=\"${fp.crashSave ? '1' : '0'}\"`;\n if (fp.dataExtractLoad !== undefined) attrs += ` dataExtractLoad=\"${fp.dataExtractLoad ? '1' : '0'}\"`;\n if (fp.repairLoad !== undefined) attrs += ` repairLoad=\"${fp.repairLoad ? '1' : '0'}\"`;\n if (attrs.length === 0) return undefined;\n return `<fileRecoveryPr${attrs}/>`;\n}\n\nfunction serializeFileSharing(\n fs: import('../workbook/file-sharing.js').FileSharing,\n): string | undefined {\n let attrs = '';\n if (fs.readOnlyRecommended !== undefined)\n attrs += ` readOnlyRecommended=\"${fs.readOnlyRecommended ? '1' : '0'}\"`;\n if (fs.userName !== undefined) attrs += ` userName=\"${escapeAttr(fs.userName)}\"`;\n if (fs.reservationPassword !== undefined)\n attrs += ` reservationPassword=\"${escapeAttr(fs.reservationPassword)}\"`;\n if (fs.algorithmName !== undefined) attrs += ` algorithmName=\"${escapeAttr(fs.algorithmName)}\"`;\n if (fs.hashValue !== undefined) attrs += ` hashValue=\"${escapeAttr(fs.hashValue)}\"`;\n if (fs.saltValue !== undefined) attrs += ` saltValue=\"${escapeAttr(fs.saltValue)}\"`;\n if (fs.spinCount !== undefined) attrs += ` spinCount=\"${fs.spinCount}\"`;\n if (attrs.length === 0) return undefined;\n return `<fileSharing${attrs}/>`;\n}\n\nfunction serializeFileVersion(\n fv: import('../workbook/file-version.js').FileVersion,\n): string | undefined {\n let attrs = '';\n if (fv.appName !== undefined) attrs += ` appName=\"${escapeAttr(fv.appName)}\"`;\n if (fv.lastEdited !== undefined) attrs += ` lastEdited=\"${escapeAttr(fv.lastEdited)}\"`;\n if (fv.lowestEdited !== undefined) attrs += ` lowestEdited=\"${escapeAttr(fv.lowestEdited)}\"`;\n if (fv.rupBuild !== undefined) attrs += ` rupBuild=\"${escapeAttr(fv.rupBuild)}\"`;\n if (fv.codeName !== undefined) attrs += ` codeName=\"${escapeAttr(fv.codeName)}\"`;\n if (attrs.length === 0) return undefined;\n return `<fileVersion${attrs}/>`;\n}\n\nfunction effectiveWorkbookProperties(\n wb: Workbook,\n): import('../workbook/workbook-properties.js').WorkbookProperties | undefined {\n const explicit = wb.workbookProperties;\n if (explicit) {\n // Mirror the canonical date1904 flag if the typed model omits it.\n if (wb.date1904 && explicit.date1904 === undefined) {\n return { ...explicit, date1904: true };\n }\n return explicit;\n }\n if (wb.date1904) return { date1904: true };\n return undefined;\n}\n\nfunction serializeWorkbookProperties(\n wp: import('../workbook/workbook-properties.js').WorkbookProperties,\n): string | undefined {\n let attrs = '';\n const boolKeys: ReadonlyArray<keyof import('../workbook/workbook-properties.js').WorkbookProperties> = [\n 'date1904',\n 'dateCompatibility',\n 'showBorderUnselectedTables',\n 'filterPrivacy',\n 'promptedSolutions',\n 'showInkAnnotation',\n 'backupFile',\n 'saveExternalLinkValues',\n 'hidePivotFieldList',\n 'showPivotChartFilter',\n 'allowRefreshQuery',\n 'publishItems',\n 'checkCompatibility',\n 'autoCompressPictures',\n 'refreshAllConnections',\n ];\n for (const k of boolKeys) {\n const v = wp[k];\n if (v !== undefined) attrs += ` ${k}=\"${v ? '1' : '0'}\"`;\n }\n if (wp.showObjects !== undefined) attrs += ` showObjects=\"${wp.showObjects}\"`;\n if (wp.updateLinks !== undefined) attrs += ` updateLinks=\"${wp.updateLinks}\"`;\n if (wp.codeName !== undefined) attrs += ` codeName=\"${escapeAttr(wp.codeName)}\"`;\n if (wp.defaultThemeVersion !== undefined) attrs += ` defaultThemeVersion=\"${wp.defaultThemeVersion}\"`;\n if (attrs.length === 0) return undefined;\n return `<workbookPr${attrs}/>`;\n}\n\nfunction serializeCustomWorkbookViews(\n views: ReadonlyArray<import('../workbook/views.js').CustomWorkbookView>,\n): string {\n const parts: string[] = ['<customWorkbookViews>'];\n for (const v of views) {\n let attrs = ` name=\"${escapeAttr(v.name)}\" guid=\"${escapeAttr(v.guid)}\"`;\n if (v.autoUpdate !== undefined) attrs += ` autoUpdate=\"${v.autoUpdate ? '1' : '0'}\"`;\n if (v.mergeInterval !== undefined) attrs += ` mergeInterval=\"${v.mergeInterval}\"`;\n if (v.changesSavedWin !== undefined) attrs += ` changesSavedWin=\"${v.changesSavedWin ? '1' : '0'}\"`;\n if (v.onlySync !== undefined) attrs += ` onlySync=\"${v.onlySync ? '1' : '0'}\"`;\n if (v.personalView !== undefined) attrs += ` personalView=\"${v.personalView ? '1' : '0'}\"`;\n if (v.includePrintSettings !== undefined)\n attrs += ` includePrintSettings=\"${v.includePrintSettings ? '1' : '0'}\"`;\n if (v.includeHiddenRowCol !== undefined)\n attrs += ` includeHiddenRowCol=\"${v.includeHiddenRowCol ? '1' : '0'}\"`;\n if (v.maximized !== undefined) attrs += ` maximized=\"${v.maximized ? '1' : '0'}\"`;\n if (v.minimized !== undefined) attrs += ` minimized=\"${v.minimized ? '1' : '0'}\"`;\n if (v.showHorizontalScroll !== undefined)\n attrs += ` showHorizontalScroll=\"${v.showHorizontalScroll ? '1' : '0'}\"`;\n if (v.showVerticalScroll !== undefined)\n attrs += ` showVerticalScroll=\"${v.showVerticalScroll ? '1' : '0'}\"`;\n if (v.showSheetTabs !== undefined) attrs += ` showSheetTabs=\"${v.showSheetTabs ? '1' : '0'}\"`;\n if (v.xWindow !== undefined) attrs += ` xWindow=\"${v.xWindow}\"`;\n if (v.yWindow !== undefined) attrs += ` yWindow=\"${v.yWindow}\"`;\n attrs += ` windowWidth=\"${v.windowWidth}\" windowHeight=\"${v.windowHeight}\"`;\n if (v.tabRatio !== undefined) attrs += ` tabRatio=\"${v.tabRatio}\"`;\n attrs += ` activeSheetId=\"${v.activeSheetId}\"`;\n if (v.showFormulaBar !== undefined) attrs += ` showFormulaBar=\"${v.showFormulaBar ? '1' : '0'}\"`;\n if (v.showStatusbar !== undefined) attrs += ` showStatusbar=\"${v.showStatusbar ? '1' : '0'}\"`;\n if (v.showComments !== undefined) attrs += ` showComments=\"${v.showComments}\"`;\n if (v.showObjects !== undefined) attrs += ` showObjects=\"${v.showObjects}\"`;\n parts.push(`<customWorkbookView${attrs}/>`);\n }\n parts.push('</customWorkbookViews>');\n return parts.join('');\n}\n\nfunction serializeBookViews(\n views: ReadonlyArray<import('../workbook/views.js').WorkbookView>,\n prefixOf: Readonly<Record<string, string>>,\n): string {\n const parts: string[] = ['<bookViews>'];\n for (const v of views) {\n let attrs = '';\n if (v.visibility !== undefined) attrs += ` visibility=\"${v.visibility}\"`;\n if (v.minimized !== undefined) attrs += ` minimized=\"${v.minimized ? '1' : '0'}\"`;\n if (v.showHorizontalScroll !== undefined)\n attrs += ` showHorizontalScroll=\"${v.showHorizontalScroll ? '1' : '0'}\"`;\n if (v.showVerticalScroll !== undefined)\n attrs += ` showVerticalScroll=\"${v.showVerticalScroll ? '1' : '0'}\"`;\n if (v.showSheetTabs !== undefined) attrs += ` showSheetTabs=\"${v.showSheetTabs ? '1' : '0'}\"`;\n if (v.xWindow !== undefined) attrs += ` xWindow=\"${v.xWindow}\"`;\n if (v.yWindow !== undefined) attrs += ` yWindow=\"${v.yWindow}\"`;\n if (v.windowWidth !== undefined) attrs += ` windowWidth=\"${v.windowWidth}\"`;\n if (v.windowHeight !== undefined) attrs += ` windowHeight=\"${v.windowHeight}\"`;\n if (v.tabRatio !== undefined) attrs += ` tabRatio=\"${v.tabRatio}\"`;\n if (v.firstSheet !== undefined) attrs += ` firstSheet=\"${v.firstSheet}\"`;\n if (v.activeTab !== undefined) attrs += ` activeTab=\"${v.activeTab}\"`;\n if (v.autoFilterDateGrouping !== undefined)\n attrs += ` autoFilterDateGrouping=\"${v.autoFilterDateGrouping ? '1' : '0'}\"`;\n // Namespaced extras (`xr2:uid`) only make sense with a prefix the root\n // declares; without one the attribute would be unreadable, so skip it.\n for (const [clark, value] of Object.entries(v.extAttrs ?? {})) {\n const { ns, local } = parseQName(clark);\n const prefix = prefixOf[ns];\n if (prefix === undefined) continue;\n attrs += ` ${prefix}:${local}=\"${escapeAttr(value)}\"`;\n }\n parts.push(`<workbookView${attrs}/>`);\n }\n parts.push('</bookViews>');\n return parts.join('');\n}\n\nfunction serializeWorkbookProtection(\n wp: import('../workbook/protection.js').WorkbookProtection,\n): string | undefined {\n let attrs = '';\n const strAttrs = [\n 'workbookPassword',\n 'workbookPasswordCharacterSet',\n 'workbookAlgorithmName',\n 'workbookHashValue',\n 'workbookSaltValue',\n 'revisionsPassword',\n 'revisionsPasswordCharacterSet',\n 'revisionsAlgorithmName',\n 'revisionsHashValue',\n 'revisionsSaltValue',\n ] as const;\n for (const k of strAttrs) {\n const v = wp[k];\n if (v !== undefined) attrs += ` ${k}=\"${escapeAttr(v)}\"`;\n }\n if (wp.workbookSpinCount !== undefined) attrs += ` workbookSpinCount=\"${wp.workbookSpinCount}\"`;\n if (wp.revisionsSpinCount !== undefined) attrs += ` revisionsSpinCount=\"${wp.revisionsSpinCount}\"`;\n if (wp.lockStructure !== undefined) attrs += ` lockStructure=\"${wp.lockStructure ? '1' : '0'}\"`;\n if (wp.lockWindows !== undefined) attrs += ` lockWindows=\"${wp.lockWindows ? '1' : '0'}\"`;\n if (wp.lockRevision !== undefined) attrs += ` lockRevision=\"${wp.lockRevision ? '1' : '0'}\"`;\n if (attrs.length === 0) return undefined;\n return `<workbookProtection${attrs}/>`;\n}\n\n// Local aliases keep the dense call sites below readable. Canonical\n// implementations live in utils/escape.ts so all three writers (this file,\n// xml/serializer, xml/stream-writer) agree on how `>` / whitespace are\n// handled.\nconst escapeText = escapeXmlText;\nconst escapeAttr = escapeXmlAttr;\n\n/**\n * Serialise an XmlNode child of `<workbook>` for inline injection back into the\n * workbook XML stream. Reuses serializeXml then strips the declaration.\n * Captured nodes carry Clark-notation names, so `inScopePrefixes` is what keeps\n * a child on the prefix the root declared for it instead of a freshly\n * allocated one — which matters when `mc:Ignorable` names those prefixes.\n */\nfunction serializeChildNode(\n node: import('../xml/tree.js').XmlNode,\n inScopePrefixes?: Readonly<Record<string, string>>,\n): string {\n const bytes = serializeXmlNode(node, {\n xmlDeclaration: false,\n ...(inScopePrefixes ? { inScopePrefixes } : {}),\n });\n return new TextDecoder().decode(bytes);\n}\n"],"mappings":"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"}
@@ -1,9 +1,19 @@
1
1
  import type { CellValue } from '../cell/cell.js';
2
2
  import type { XlsxSink } from '../io/sink.js';
3
3
  import { type CellStyleSpec } from '../styles/stylesheet.js';
4
+ import { type CompressionLevel } from '../zip/writer.js';
4
5
  export interface WriteOnlyOptions {
5
6
  /** Reserved — currently ignored (the buffered backend doesn't honour it). */
6
7
  estimatedMaxRow?: number;
8
+ /**
9
+ * Last-modified timestamp for every ZIP entry. Same reproducibility story as
10
+ * `SaveOptions.mtime`: unset, fflate stamps the wall clock per entry and two
11
+ * runs over identical rows differ in bytes. Recorded as the date's UTC wall
12
+ * time, to a two-second resolution, and the year has to fall in 1980-2099.
13
+ */
14
+ mtime?: Date;
15
+ /** Deflate level, 0 (no compression) to 9 (smallest). Defaults to fflate's own 6. */
16
+ compressionLevel?: CompressionLevel;
7
17
  }
8
18
  /**
9
19
  * A cell's look on the write-only path. Identical to the modelled writer's
@@ -38,4 +48,4 @@ export interface WriteOnlyWorkbook {
38
48
  abort(cause?: unknown): void;
39
49
  }
40
50
  /** Open a workbook for streaming write-only output. */
41
- export declare function createWriteOnlyWorkbook(sink: XlsxSink, _opts?: WriteOnlyOptions): Promise<WriteOnlyWorkbook>;
51
+ export declare function createWriteOnlyWorkbook(sink: XlsxSink, opts?: WriteOnlyOptions): Promise<WriteOnlyWorkbook>;