ooxml-core 0.14.0 → 0.15.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 (180) hide show
  1. package/dist/automation/node.d.ts.map +1 -1
  2. package/dist/collab/broadcast-transport.d.ts.map +1 -1
  3. package/dist/collab/emitter.d.ts.map +1 -1
  4. package/dist/collab/index.cjs +3 -2
  5. package/dist/collab/index.mjs +3 -2
  6. package/dist/collab/ordering.d.ts.map +1 -1
  7. package/dist/crypto/detect.d.ts.map +1 -1
  8. package/dist/crypto/errors.d.ts +3 -3
  9. package/dist/crypto/errors.d.ts.map +1 -1
  10. package/dist/crypto/index.cjs +6 -6
  11. package/dist/crypto/index.mjs +6 -6
  12. package/dist/crypto/key-derivation.d.ts.map +1 -1
  13. package/dist/diagram/drawing.d.ts.map +1 -1
  14. package/dist/diagram/relationships.d.ts.map +1 -1
  15. package/dist/digest/sha512.d.ts.map +1 -1
  16. package/dist/docx/diagram.d.ts.map +1 -1
  17. package/dist/docx/docpr-ids.d.ts.map +1 -1
  18. package/dist/docx/field-runs.d.ts.map +1 -1
  19. package/dist/docx/generated/wml-simple-types.d.ts +99 -99
  20. package/dist/docx/generated/wml-simple-types.d.ts.map +1 -1
  21. package/dist/docx/heading-list-kinds.d.ts.map +1 -1
  22. package/dist/docx/highlight.d.ts +1 -1
  23. package/dist/docx/highlight.d.ts.map +1 -1
  24. package/dist/docx/layout/page-cursor.d.ts.map +1 -1
  25. package/dist/docx/ligatures.d.ts +1 -1
  26. package/dist/docx/ligatures.d.ts.map +1 -1
  27. package/dist/docx/load/index.cjs +18 -18
  28. package/dist/docx/load/index.mjs +18 -18
  29. package/dist/docx/load/legacy-doc.d.ts.map +1 -1
  30. package/dist/docx/paragraph-styles.d.ts +1 -1
  31. package/dist/docx/paragraph-styles.d.ts.map +1 -1
  32. package/dist/docx/relationship-allocator.d.ts.map +1 -1
  33. package/dist/docx/revision-commands.d.ts.map +1 -1
  34. package/dist/docx/simple-types.d.ts.map +1 -1
  35. package/dist/docx/table-of-contents.d.ts.map +1 -1
  36. package/dist/docx/table-of-figures.d.ts.map +1 -1
  37. package/dist/docx/test-support/restart-fixture.d.ts +3 -3
  38. package/dist/docx/test-support/restart-fixture.d.ts.map +1 -1
  39. package/dist/docx/validate-issues.d.ts.map +1 -1
  40. package/dist/docx/write-revisions.d.ts.map +1 -1
  41. package/dist/docx/xml.d.ts.map +1 -1
  42. package/dist/docx/zip-parts.d.ts.map +1 -1
  43. package/dist/opc/properties/types.d.ts +6 -6
  44. package/dist/opc/properties/types.d.ts.map +1 -1
  45. package/dist/opc/relationship-types.d.ts +6 -6
  46. package/dist/opc/relationship-types.d.ts.map +1 -1
  47. package/dist/opc/relationships.d.ts.map +1 -1
  48. package/dist/pptx/automation/index.cjs +138 -138
  49. package/dist/pptx/automation/index.d.ts +3 -3
  50. package/dist/pptx/automation/index.mjs +138 -138
  51. package/dist/pptx/chunks/{index-BWRd8p4y.d.ts → index-BtBj3VG1.d.ts} +3 -3
  52. package/dist/pptx/chunks/index-BtBj3VG1.d.ts.map +1 -0
  53. package/dist/pptx/chunks/{index-CT9y69AZ.d.ts → index-D0yGoLyw.d.ts} +136 -136
  54. package/dist/pptx/chunks/index-D0yGoLyw.d.ts.map +1 -0
  55. package/dist/pptx/chunks/{text-operations-2tKzrY5o.d.ts → text-operations-GuisjlbR.d.ts} +2 -2
  56. package/dist/pptx/chunks/{text-operations-2tKzrY5o.d.ts.map → text-operations-GuisjlbR.d.ts.map} +1 -1
  57. package/dist/pptx/cli/index.cjs +104 -104
  58. package/dist/pptx/cli/index.d.ts +1 -1
  59. package/dist/pptx/cli/index.mjs +104 -104
  60. package/dist/pptx/converter/index.d.ts +1 -1
  61. package/dist/pptx/index.cjs +138 -138
  62. package/dist/pptx/index.d.ts +3 -3
  63. package/dist/pptx/index.mjs +138 -138
  64. package/dist/teams/call.d.ts +61 -0
  65. package/dist/teams/call.d.ts.map +1 -0
  66. package/dist/teams/chat.d.ts +34 -0
  67. package/dist/teams/chat.d.ts.map +1 -0
  68. package/dist/teams/index.cjs +2207 -0
  69. package/dist/teams/index.d.ts +10 -0
  70. package/dist/teams/index.d.ts.map +1 -0
  71. package/dist/teams/index.mjs +2153 -0
  72. package/dist/teams/model.d.ts +49 -0
  73. package/dist/teams/model.d.ts.map +1 -0
  74. package/dist/teams/peer.d.ts +76 -0
  75. package/dist/teams/peer.d.ts.map +1 -0
  76. package/dist/teams/server-config.d.ts +27 -0
  77. package/dist/teams/server-config.d.ts.map +1 -0
  78. package/dist/teams/signaling.d.ts +81 -0
  79. package/dist/teams/signaling.d.ts.map +1 -0
  80. package/dist/teams/store.d.ts +113 -0
  81. package/dist/teams/store.d.ts.map +1 -0
  82. package/dist/teams/view.d.ts +77 -0
  83. package/dist/teams/view.d.ts.map +1 -0
  84. package/dist/teams/workspace.d.ts +51 -0
  85. package/dist/teams/workspace.d.ts.map +1 -0
  86. package/dist/units/units.d.ts.map +1 -1
  87. package/dist/visio/edit-geometry-admission.d.ts.map +1 -1
  88. package/dist/visio/edit-recalculate-index.d.ts.map +1 -1
  89. package/dist/visio/emf-admission-context.d.ts +1 -1
  90. package/dist/visio/emf-admission-context.d.ts.map +1 -1
  91. package/dist/visio/foreign-vector-types.d.ts.map +1 -1
  92. package/dist/visio/formula-master.d.ts +2 -2
  93. package/dist/visio/formula.d.ts.map +1 -1
  94. package/dist/visio/index.cjs +2048 -290
  95. package/dist/visio/index.mjs +2048 -290
  96. package/dist/visio/media.d.ts.map +1 -1
  97. package/dist/visio/package-common.d.ts.map +1 -1
  98. package/dist/visio/package.d.ts.map +1 -1
  99. package/dist/visio/sheet.d.ts.map +1 -1
  100. package/dist/visio/theme-color.d.ts.map +1 -1
  101. package/dist/xlsx/address.d.ts.map +1 -1
  102. package/dist/xlsx/cell-styles.d.ts.map +1 -1
  103. package/dist/xlsx/cells.d.ts.map +1 -1
  104. package/dist/xlsx/edit/calc-mode.d.ts.map +1 -1
  105. package/dist/xlsx/edit/clipboard-html.d.ts.map +1 -1
  106. package/dist/xlsx/edit/columns.d.ts.map +1 -1
  107. package/dist/xlsx/edit/context.d.ts.map +1 -1
  108. package/dist/xlsx/edit/fill-series.d.ts.map +1 -1
  109. package/dist/xlsx/edit/history.d.ts.map +1 -1
  110. package/dist/xlsx/edit/outline.d.ts.map +1 -1
  111. package/dist/xlsx/edit/range-math.d.ts.map +1 -1
  112. package/dist/xlsx/edit/session-calc.d.ts.map +1 -1
  113. package/dist/xlsx/edit/structure.d.ts.map +1 -1
  114. package/dist/xlsx/formula/area-index.d.ts.map +1 -1
  115. package/dist/xlsx/formula/ast.d.ts.map +1 -1
  116. package/dist/xlsx/formula/date-serial.d.ts.map +1 -1
  117. package/dist/xlsx/formula/engine-core.d.ts.map +1 -1
  118. package/dist/xlsx/formula/engine-host.d.ts.map +1 -1
  119. package/dist/xlsx/formula/engine-util.d.ts.map +1 -1
  120. package/dist/xlsx/formula/functions/criteria.d.ts.map +1 -1
  121. package/dist/xlsx/formula/functions/dist-core.d.ts.map +1 -1
  122. package/dist/xlsx/formula/functions/helpers.d.ts.map +1 -1
  123. package/dist/xlsx/formula/functions/math-combin.d.ts.map +1 -1
  124. package/dist/xlsx/formula/functions/registry.d.ts.map +1 -1
  125. package/dist/xlsx/formula/functions/stats-core.d.ts.map +1 -1
  126. package/dist/xlsx/formula/functions/text-case.d.ts.map +1 -1
  127. package/dist/xlsx/formula/functions/types.d.ts.map +1 -1
  128. package/dist/xlsx/formula/graph-index.d.ts.map +1 -1
  129. package/dist/xlsx/formula/lexemes.d.ts +1 -1
  130. package/dist/xlsx/formula/lexemes.d.ts.map +1 -1
  131. package/dist/xlsx/formula/references.d.ts.map +1 -1
  132. package/dist/xlsx/formula/spill.d.ts.map +1 -1
  133. package/dist/xlsx/formula/test-helpers.d.ts.map +1 -1
  134. package/dist/xlsx/formula/tokenizer.d.ts.map +1 -1
  135. package/dist/xlsx/formula/values.d.ts +2 -1
  136. package/dist/xlsx/formula/values.d.ts.map +1 -1
  137. package/dist/xlsx/layout/axis-metrics.d.ts.map +1 -1
  138. package/dist/xlsx/layout/chart-svg-util.d.ts.map +1 -1
  139. package/dist/xlsx/layout/colors.d.ts +1 -1
  140. package/dist/xlsx/layout/colors.d.ts.map +1 -1
  141. package/dist/xlsx/layout/tint.d.ts.map +1 -1
  142. package/dist/xlsx/layout/units.d.ts.map +1 -1
  143. package/dist/xlsx/load/errors.d.ts.map +1 -1
  144. package/dist/xlsx/load/index.cjs +24 -24
  145. package/dist/xlsx/load/index.mjs +24 -24
  146. package/dist/xlsx/load/legacy-xls-sheet.d.ts.map +1 -1
  147. package/dist/xlsx/load/legacy-xls.d.ts.map +1 -1
  148. package/dist/xlsx/model.d.ts +1 -1
  149. package/dist/xlsx/model.d.ts.map +1 -1
  150. package/dist/xlsx/numfmt/decimal.d.ts.map +1 -1
  151. package/dist/xlsx/read/package.d.ts +22 -22
  152. package/dist/xlsx/read/package.d.ts.map +1 -1
  153. package/dist/xlsx/read/password-hash.d.ts.map +1 -1
  154. package/dist/xlsx/read/sheet-props.d.ts +7 -7
  155. package/dist/xlsx/read/sheet-props.d.ts.map +1 -1
  156. package/dist/xlsx/read/theme.d.ts +2 -2
  157. package/dist/xlsx/read/theme.d.ts.map +1 -1
  158. package/dist/xlsx/read/worksheet.d.ts +1 -1
  159. package/dist/xlsx/read/worksheet.d.ts.map +1 -1
  160. package/dist/xlsx/read/xml-util.d.ts.map +1 -1
  161. package/dist/xlsx/workbook.d.ts.map +1 -1
  162. package/dist/xlsx/write/carried-refs.d.ts.map +1 -1
  163. package/dist/xlsx/write/comments.d.ts.map +1 -1
  164. package/dist/xlsx/write/doc-props.d.ts.map +1 -1
  165. package/dist/xlsx/write/drawing.d.ts.map +1 -1
  166. package/dist/xlsx/write/dynamic-array.d.ts.map +1 -1
  167. package/dist/xlsx/write/metadata.d.ts.map +1 -1
  168. package/dist/xlsx/write/package-writer.d.ts.map +1 -1
  169. package/dist/xlsx/write/shared-strings.d.ts.map +1 -1
  170. package/dist/xlsx/write/snapshot.d.ts.map +1 -1
  171. package/dist/xlsx/write/style-xml.d.ts.map +1 -1
  172. package/dist/xlsx/write/styles.d.ts.map +1 -1
  173. package/dist/xlsx/write/vml-ids.d.ts.map +1 -1
  174. package/dist/xlsx/write/xml-out.d.ts.map +1 -1
  175. package/dist/xml/namespaces.d.ts +31 -31
  176. package/dist/xml/namespaces.d.ts.map +1 -1
  177. package/dist/xml/xml.d.ts.map +1 -1
  178. package/package.json +19 -14
  179. package/dist/pptx/chunks/index-BWRd8p4y.d.ts.map +0 -1
  180. package/dist/pptx/chunks/index-CT9y69AZ.d.ts.map +0 -1
@@ -2246,7 +2246,7 @@ function sanitize(root, limits) {
2246
2246
  }
2247
2247
  return { tag: data2.tag, attrs, children: data2.children };
2248
2248
  }
2249
- function children3(value, optional = false) {
2249
+ function children4(value, optional = false) {
2250
2250
  if (value === void 0 && optional) return [];
2251
2251
  if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype)
2252
2252
  unsafe("Expected plain child array.");
@@ -2277,7 +2277,7 @@ function sanitize(root, limits) {
2277
2277
  return target;
2278
2278
  }
2279
2279
  function leaf(data2) {
2280
- if (children3(data2.children, true).length !== 0) unsafe("Path cannot contain child elements.");
2280
+ if (children4(data2.children, true).length !== 0) unsafe("Path cannot contain child elements.");
2281
2281
  return pathCommands(data2.attrs.d, limits, pathBudget);
2282
2282
  }
2283
2283
  function item(value, depth) {
@@ -2290,7 +2290,7 @@ function sanitize(root, limits) {
2290
2290
  paint: paint(data2.attrs)
2291
2291
  }) : Object.assign(target, {
2292
2292
  kind: "group",
2293
- items: Object.freeze(children3(data2.children).map((child2) => item(child2, depth + 1)))
2293
+ items: Object.freeze(children4(data2.children).map((child2) => item(child2, depth + 1)))
2294
2294
  });
2295
2295
  freezeLater.push(result);
2296
2296
  return result;
@@ -2307,7 +2307,7 @@ function sanitize(root, limits) {
2307
2307
  ids.set(id, clips.length);
2308
2308
  const target = base(data2.attrs);
2309
2309
  const paths = [];
2310
- for (const child2 of children3(data2.children)) {
2310
+ for (const child2 of children4(data2.children)) {
2311
2311
  const part = node(child2, depth + 1, true);
2312
2312
  if (part.tag !== "path") unsafe("Clip content must be a path.");
2313
2313
  const path = Object.assign(base(part.attrs), {
@@ -2332,11 +2332,11 @@ function sanitize(root, limits) {
2332
2332
  if (viewBox[0] !== 0 || viewBox[1] !== 0 || viewBox[2] !== width || viewBox[3] !== height)
2333
2333
  unsafe("Viewport differs from dimensions.");
2334
2334
  const items = [];
2335
- for (const child2 of children3(data.children)) {
2335
+ for (const child2 of children4(data.children)) {
2336
2336
  const peek = record(child2, ["tag", "attrs", "children"]);
2337
2337
  if (peek.tag === "defs") {
2338
2338
  const defs = node(child2, 1);
2339
- for (const value of children3(defs.children)) definition(value, 2);
2339
+ for (const value of children4(defs.children)) definition(value, 2);
2340
2340
  } else items.push(item(child2, 1));
2341
2341
  }
2342
2342
  for (const { target, id } of pending) {
@@ -5128,7 +5128,7 @@ function getVisioPageLayers(document, pageId) {
5128
5128
  return result.reverse();
5129
5129
  }
5130
5130
 
5131
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-types.js
5131
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-types.js
5132
5132
  var OLE_MAGIC = new Uint8Array([208, 207, 17, 224, 161, 177, 26, 225]);
5133
5133
  var ENDOFCHAIN = 4294967294;
5134
5134
  var FREESECT = 4294967295;
@@ -5146,7 +5146,7 @@ var Ole2ParseError = class extends Error {
5146
5146
  }
5147
5147
  };
5148
5148
 
5149
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-read.js
5149
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-read.js
5150
5150
  function parseOle2(buffer) {
5151
5151
  const data = new Uint8Array(buffer);
5152
5152
  const view2 = new DataView(buffer);
@@ -5376,7 +5376,7 @@ function parseOle2(buffer) {
5376
5376
  return { entries, getStream };
5377
5377
  }
5378
5378
 
5379
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-document-base.js
5379
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-document-base.js
5380
5380
  var Ole2DocumentError = class extends Error {
5381
5381
  code;
5382
5382
  constructor(code, message) {
@@ -5441,7 +5441,7 @@ var Ole2DocumentBase = class {
5441
5441
  }
5442
5442
  };
5443
5443
 
5444
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-stream-edit.js
5444
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-edit.js
5445
5445
  var END = 4294967294;
5446
5446
  var MAX = 4294967290;
5447
5447
  var NIL = 4294967295;
@@ -5601,11 +5601,11 @@ function processCompoundFileStream(input, path, replacement) {
5601
5601
  if (!workbook)
5602
5602
  continue;
5603
5603
  for (let p = 0; p + 4 <= workbook.length; ) {
5604
- const record4 = workbook[p] | workbook[p + 1] << 8;
5604
+ const record5 = workbook[p] | workbook[p + 1] << 8;
5605
5605
  const length = workbook[p + 2] | workbook[p + 3] << 8;
5606
- if (record4 === 47)
5606
+ if (record5 === 47)
5607
5607
  return reject2();
5608
- if (p + 4 + length > workbook.length || record4 === 10)
5608
+ if (p + 4 + length > workbook.length || record5 === 10)
5609
5609
  break;
5610
5610
  p += 4 + length;
5611
5611
  }
@@ -5714,7 +5714,7 @@ function replaceCompoundFileStream(input, path, replacement) {
5714
5714
  return processCompoundFileStream(input, path, replacement) ?? input;
5715
5715
  }
5716
5716
 
5717
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-v4.js
5717
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-v4.js
5718
5718
  var END2 = 4294967294;
5719
5719
  var FREE = 4294967295;
5720
5720
  var FAT = 4294967293;
@@ -5786,49 +5786,49 @@ function validateHierarchy(slots) {
5786
5786
  throw new Error("Unreachable directory entries");
5787
5787
  }
5788
5788
  function resizeCompoundFileStreamV4(input, path, replacement) {
5789
- const fail2 = (reason) => ({ ok: false, bytes: input, reason });
5789
+ const fail3 = (reason) => ({ ok: false, bytes: input, reason });
5790
5790
  try {
5791
5791
  if (input.length < 512 || !path.length || path.some((part) => !part))
5792
- return fail2("invalid-or-missing-stream");
5792
+ return fail3("invalid-or-missing-stream");
5793
5793
  const view2 = new DataView(input.buffer, input.byteOffset, input.byteLength);
5794
5794
  const read = (offset) => view2.getUint32(offset, true);
5795
5795
  const version = view2.getUint16(26, true);
5796
5796
  if (version !== 4)
5797
- return fail2("unsupported-version");
5797
+ return fail3("unsupported-version");
5798
5798
  const SECTOR3 = 4096, FAT_ENTRIES2 = SECTOR3 / 4, DIRECTORY_ENTRIES = SECTOR3 / 128;
5799
5799
  if (read(72) !== 0 || read(44) > 109)
5800
- return fail2("unsupported-difat");
5800
+ return fail3("unsupported-difat");
5801
5801
  const cutoff = read(56);
5802
5802
  if (cutoff !== 0 && cutoff !== 4096)
5803
- return fail2("unsupported-layout");
5803
+ return fail3("unsupported-layout");
5804
5804
  const original = readCompoundFileStream(input, path);
5805
5805
  if (!original)
5806
- return fail2("invalid-or-missing-stream");
5806
+ return fail3("invalid-or-missing-stream");
5807
5807
  const name = path[path.length - 1].toLocaleLowerCase();
5808
5808
  if (name === "worddocument" && original.length >= 12 && (original[10] | original[11] << 8) & 33024)
5809
- return fail2("unsafe-edit");
5809
+ return fail3("unsafe-edit");
5810
5810
  if (name === "book" || name === "workbook") {
5811
5811
  for (let offset = 0; offset + 4 <= original.length; ) {
5812
- const record4 = original[offset] | original[offset + 1] << 8;
5812
+ const record5 = original[offset] | original[offset + 1] << 8;
5813
5813
  const length = original[offset + 2] | original[offset + 3] << 8;
5814
- if (record4 === 47)
5815
- return fail2("unsafe-edit");
5816
- if (record4 === 10 || offset + 4 + length > original.length)
5814
+ if (record5 === 47)
5815
+ return fail3("unsafe-edit");
5816
+ if (record5 === 10 || offset + 4 + length > original.length)
5817
5817
  break;
5818
5818
  offset += 4 + length;
5819
5819
  }
5820
5820
  }
5821
5821
  const validated = replaceCompoundFileStream(input, path, original);
5822
5822
  if (validated === input)
5823
- return fail2("unsafe-edit");
5823
+ return fail3("unsafe-edit");
5824
5824
  const sameLength = replacement.length === original.length;
5825
5825
  if (!sameLength && original.length < cutoff)
5826
- return fail2("unsupported-mini-stream");
5826
+ return fail3("unsupported-mini-stream");
5827
5827
  if (!sameLength && replacement.length < cutoff)
5828
- return fail2("unsupported-mini-transition");
5828
+ return fail3("unsupported-mini-transition");
5829
5829
  const sectorCount = input.length / SECTOR3 - 1, fatCount = read(44);
5830
5830
  if (sectorCount > fatCount * FAT_ENTRIES2)
5831
- return fail2("unsafe-edit");
5831
+ return fail3("unsafe-edit");
5832
5832
  const fatIds = Array.from({ length: fatCount }, (_, i) => read(76 + 4 * i));
5833
5833
  const fat = [];
5834
5834
  for (const id of fatIds) {
@@ -5836,11 +5836,11 @@ function resizeCompoundFileStreamV4(input, path, replacement) {
5836
5836
  fat.push(read((id + 1) * SECTOR3 + i * 4));
5837
5837
  }
5838
5838
  if (fatIds.some((id) => fat[id] !== FAT))
5839
- return fail2("unsafe-edit");
5839
+ return fail3("unsafe-edit");
5840
5840
  const slots = /* @__PURE__ */ new Map();
5841
5841
  const directoryChain = follow(fat, read(48));
5842
5842
  if (read(40) !== directoryChain.length)
5843
- return fail2("unsafe-edit");
5843
+ return fail3("unsafe-edit");
5844
5844
  for (const [block, sector] of directoryChain.entries()) {
5845
5845
  for (let entry = 0; entry < DIRECTORY_ENTRIES; entry++) {
5846
5846
  const offset = (sector + 1) * SECTOR3 + entry * 128, type = view2.getUint8(offset + 66);
@@ -5848,33 +5848,33 @@ function resizeCompoundFileStreamV4(input, path, replacement) {
5848
5848
  continue;
5849
5849
  const nameLength = view2.getUint16(offset + 64, true);
5850
5850
  if (![1, 2, 5].includes(type) || nameLength < 2 || nameLength > 64 || nameLength % 2 || view2.getUint16(offset + nameLength - 2, true))
5851
- return fail2("unsafe-edit");
5851
+ return fail3("unsafe-edit");
5852
5852
  let name2 = "";
5853
5853
  for (let i = 0; i < nameLength - 2; i += 2)
5854
5854
  name2 += String.fromCharCode(view2.getUint16(offset + i, true));
5855
5855
  if (read(offset + 124) !== 0)
5856
- return fail2("unsafe-edit");
5856
+ return fail3("unsafe-edit");
5857
5857
  const id = block * DIRECTORY_ENTRIES + entry;
5858
5858
  slots.set(id, { id, name: name2, type, left: read(offset + 68), right: read(offset + 72), child: read(offset + 76), start: read(offset + 116), size: read(offset + 120), offset });
5859
5859
  }
5860
5860
  }
5861
5861
  if ([...slots.values()].filter((slot) => slot.type === 5).length !== 1)
5862
- return fail2("unsafe-edit");
5862
+ return fail3("unsafe-edit");
5863
5863
  const target = findSlot(slots, path);
5864
5864
  validateHierarchy(slots);
5865
5865
  if (sameLength) {
5866
5866
  const bytes = replaceCompoundFileStream(input, path, replacement);
5867
- return bytes === input ? fail2("unsafe-edit") : { ok: true, bytes };
5867
+ return bytes === input ? fail3("unsafe-edit") : { ok: true, bytes };
5868
5868
  }
5869
5869
  const oldChain = follow(fat, target.start);
5870
5870
  if (target.size !== original.length || oldChain.length !== Math.ceil(target.size / SECTOR3))
5871
- return fail2("unsafe-edit");
5871
+ return fail3("unsafe-edit");
5872
5872
  const payloadSectors = Math.ceil(replacement.length / SECTOR3);
5873
5873
  let newFatCount = fatCount;
5874
5874
  while (sectorCount + payloadSectors + newFatCount - fatCount > newFatCount * FAT_ENTRIES2)
5875
5875
  newFatCount++;
5876
5876
  if (newFatCount > 109)
5877
- return fail2("allocation-limit");
5877
+ return fail3("allocation-limit");
5878
5878
  const totalSectors = sectorCount + payloadSectors + newFatCount - fatCount;
5879
5879
  const output = new Uint8Array((totalSectors + 1) * SECTOR3);
5880
5880
  output.set(input);
@@ -5898,11 +5898,11 @@ function resizeCompoundFileStreamV4(input, path, replacement) {
5898
5898
  outView.setUint32(target.offset + 120, replacement.length, true);
5899
5899
  return { ok: true, bytes: output };
5900
5900
  } catch {
5901
- return fail2("unsafe-edit");
5901
+ return fail3("unsafe-edit");
5902
5902
  }
5903
5903
  }
5904
5904
 
5905
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-allocation.js
5905
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-allocation.js
5906
5906
  function appendCompoundAllocations(input, existingFatIds, payloads, sectorSize = 512) {
5907
5907
  const sectorCount = input.length / sectorSize - 1;
5908
5908
  const entriesPerFat = sectorSize / 4;
@@ -5949,7 +5949,7 @@ function followCompoundAllocation(table, start) {
5949
5949
  return ids;
5950
5950
  }
5951
5951
 
5952
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-mini.js
5952
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize-mini.js
5953
5953
  var END3 = 4294967294;
5954
5954
  var FREE2 = 4294967295;
5955
5955
  var SECTOR = 512;
@@ -6021,7 +6021,7 @@ function resizeMiniCompoundStream(input, fat, fatIds, root, target, replacement,
6021
6021
  return output.bytes;
6022
6022
  }
6023
6023
 
6024
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize.js
6024
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-stream-resize.js
6025
6025
  var END4 = 4294967294;
6026
6026
  var FREE3 = 4294967295;
6027
6027
  var FAT2 = 4294967293;
@@ -6097,43 +6097,43 @@ function validateHierarchy2(slots) {
6097
6097
  function resizeCompoundFileStream(input, path, replacement) {
6098
6098
  if (input.length >= 512 && new DataView(input.buffer, input.byteOffset, input.byteLength).getUint16(26, true) === 4)
6099
6099
  return resizeCompoundFileStreamV4(input, path, replacement);
6100
- const fail2 = (reason) => ({ ok: false, bytes: input, reason });
6100
+ const fail3 = (reason) => ({ ok: false, bytes: input, reason });
6101
6101
  try {
6102
6102
  if (input.length < SECTOR2 || !path.length || path.some((part) => !part))
6103
- return fail2("invalid-or-missing-stream");
6103
+ return fail3("invalid-or-missing-stream");
6104
6104
  const view2 = new DataView(input.buffer, input.byteOffset, input.byteLength);
6105
6105
  const read = (offset) => view2.getUint32(offset, true);
6106
6106
  if (view2.getUint16(26, true) !== 3)
6107
- return fail2("unsupported-version");
6107
+ return fail3("unsupported-version");
6108
6108
  if (read(72) !== 0 || read(44) > 109)
6109
- return fail2("unsupported-difat");
6109
+ return fail3("unsupported-difat");
6110
6110
  const cutoff = read(56);
6111
6111
  if (cutoff !== 0 && cutoff !== 4096)
6112
- return fail2("unsupported-layout");
6112
+ return fail3("unsupported-layout");
6113
6113
  const original = readCompoundFileStream(input, path);
6114
6114
  if (!original)
6115
- return fail2("invalid-or-missing-stream");
6115
+ return fail3("invalid-or-missing-stream");
6116
6116
  const name = path[path.length - 1].toLocaleLowerCase();
6117
6117
  if (name === "worddocument" && original.length >= 12 && (original[10] | original[11] << 8) & 33024)
6118
- return fail2("unsafe-edit");
6118
+ return fail3("unsafe-edit");
6119
6119
  if (name === "book" || name === "workbook") {
6120
6120
  for (let offset = 0; offset + 4 <= original.length; ) {
6121
- const record4 = original[offset] | original[offset + 1] << 8;
6121
+ const record5 = original[offset] | original[offset + 1] << 8;
6122
6122
  const length = original[offset + 2] | original[offset + 3] << 8;
6123
- if (record4 === 47)
6124
- return fail2("unsafe-edit");
6125
- if (record4 === 10 || offset + 4 + length > original.length)
6123
+ if (record5 === 47)
6124
+ return fail3("unsafe-edit");
6125
+ if (record5 === 10 || offset + 4 + length > original.length)
6126
6126
  break;
6127
6127
  offset += 4 + length;
6128
6128
  }
6129
6129
  }
6130
6130
  const validated = replaceCompoundFileStream(input, path, original);
6131
6131
  if (validated === input)
6132
- return fail2("unsafe-edit");
6132
+ return fail3("unsafe-edit");
6133
6133
  const sameLength = replacement.length === original.length;
6134
6134
  const sectorCount = input.length / SECTOR2 - 1, fatCount = read(44);
6135
6135
  if (sectorCount > fatCount * FAT_ENTRIES)
6136
- return fail2("unsafe-edit");
6136
+ return fail3("unsafe-edit");
6137
6137
  const fatIds = Array.from({ length: fatCount }, (_, i) => read(76 + 4 * i));
6138
6138
  const fat = [];
6139
6139
  for (const id of fatIds) {
@@ -6141,7 +6141,7 @@ function resizeCompoundFileStream(input, path, replacement) {
6141
6141
  fat.push(read((id + 1) * SECTOR2 + i * 4));
6142
6142
  }
6143
6143
  if (fatIds.some((id) => fat[id] !== FAT2))
6144
- return fail2("unsafe-edit");
6144
+ return fail3("unsafe-edit");
6145
6145
  const slots = /* @__PURE__ */ new Map();
6146
6146
  for (const [block, sector] of follow2(fat, read(48)).entries()) {
6147
6147
  for (let entry = 0; entry < 4; entry++) {
@@ -6150,7 +6150,7 @@ function resizeCompoundFileStream(input, path, replacement) {
6150
6150
  continue;
6151
6151
  const nameLength = view2.getUint16(offset + 64, true);
6152
6152
  if (![1, 2, 5].includes(type) || nameLength < 2 || nameLength > 64 || nameLength % 2 || view2.getUint16(offset + nameLength - 2, true))
6153
- return fail2("unsafe-edit");
6153
+ return fail3("unsafe-edit");
6154
6154
  let name2 = "";
6155
6155
  for (let i = 0; i < nameLength - 2; i += 2)
6156
6156
  name2 += String.fromCharCode(view2.getUint16(offset + i, true));
@@ -6159,34 +6159,34 @@ function resizeCompoundFileStream(input, path, replacement) {
6159
6159
  }
6160
6160
  }
6161
6161
  if ([...slots.values()].filter((slot) => slot.type === 5).length !== 1)
6162
- return fail2("unsafe-edit");
6162
+ return fail3("unsafe-edit");
6163
6163
  const target = findSlot2(slots, path);
6164
6164
  validateHierarchy2(slots);
6165
6165
  if (sameLength) {
6166
6166
  const bytes = replaceCompoundFileStream(input, path, replacement);
6167
- return bytes === input ? fail2("unsafe-edit") : { ok: true, bytes };
6167
+ return bytes === input ? fail3("unsafe-edit") : { ok: true, bytes };
6168
6168
  }
6169
6169
  if (original.length < cutoff || replacement.length < cutoff) {
6170
6170
  const bytes = resizeMiniCompoundStream(input, fat, fatIds, slots.get(0), target, replacement, cutoff);
6171
- return bytes ? { ok: true, bytes } : fail2("allocation-limit");
6171
+ return bytes ? { ok: true, bytes } : fail3("allocation-limit");
6172
6172
  }
6173
6173
  const oldChain = follow2(fat, target.start);
6174
6174
  if (target.size !== original.length || oldChain.length !== Math.ceil(target.size / SECTOR2))
6175
- return fail2("unsafe-edit");
6175
+ return fail3("unsafe-edit");
6176
6176
  const output = appendCompoundAllocations(input, fatIds, [replacement]);
6177
6177
  if (!output)
6178
- return fail2("allocation-limit");
6178
+ return fail3("allocation-limit");
6179
6179
  for (const id of oldChain)
6180
6180
  output.writeFat(id, FREE3);
6181
6181
  output.view.setUint32(target.offset + 116, output.chains[0][0] ?? END4, true);
6182
6182
  output.view.setUint32(target.offset + 120, replacement.length, true);
6183
6183
  return { ok: true, bytes: output.bytes };
6184
6184
  } catch {
6185
- return fail2("unsafe-edit");
6185
+ return fail3("unsafe-edit");
6186
6186
  }
6187
6187
  }
6188
6188
 
6189
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fib.js
6189
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fib.js
6190
6190
  var FC_LCB_INDEX = {
6191
6191
  plcfbteChpx: 12,
6192
6192
  plcfbtePapx: 13,
@@ -6282,7 +6282,7 @@ function patchDocFib(wordDoc, fib, patch) {
6282
6282
  view2.setUint32(papxOff + 4, patch.plcfbtePapx.lcb, true);
6283
6283
  }
6284
6284
 
6285
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole-document-doc-cfb.js
6285
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-cfb.js
6286
6286
  var DocCfbRewriteError = class extends Error {
6287
6287
  constructor(message) {
6288
6288
  super(message);
@@ -6337,7 +6337,7 @@ function unwrapDocBytes(bytes) {
6337
6337
  }
6338
6338
  }
6339
6339
 
6340
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fkp.js
6340
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fkp.js
6341
6341
  var PAGE_SIZE = 512;
6342
6342
  function parseBteTable(tableStream, at) {
6343
6343
  const view2 = new DataView(tableStream.buffer, tableStream.byteOffset, tableStream.byteLength);
@@ -6478,7 +6478,7 @@ function buildSingleRunChpxPage(fcStart, fcEnd, blob) {
6478
6478
  return page;
6479
6479
  }
6480
6480
 
6481
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole-document-doc-cp1252.js
6481
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-cp1252.js
6482
6482
  var CP1252_HIGH_BLOCK = [
6483
6483
  8364,
6484
6484
  129,
@@ -6546,7 +6546,7 @@ function encodeCp1252(text) {
6546
6546
  return Uint8Array.from(bytes);
6547
6547
  }
6548
6548
 
6549
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole-document-doc-pieces.js
6549
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-pieces.js
6550
6550
  var CLXT_PRC = 1;
6551
6551
  var CLXT_PCDT = 2;
6552
6552
  var DocResourceLimitError = class extends Error {
@@ -6758,7 +6758,7 @@ function buildClxBytes(pieces, prcBytes = new Uint8Array()) {
6758
6758
  return result;
6759
6759
  }
6760
6760
 
6761
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fields.js
6761
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-fields.js
6762
6762
  var UnsupportedDocFieldEditError = class extends Error {
6763
6763
  constructor(message) {
6764
6764
  super(message);
@@ -6842,7 +6842,7 @@ function shiftDocMainFieldCps(table, at, body, editStart, editEnd, delta, maxFie
6842
6842
  return result;
6843
6843
  }
6844
6844
 
6845
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole-document-doc-editor.js
6845
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-editor.js
6846
6846
  var RISKY_PLCF_INDICES = [2, 3, 4, 5, 17, 18, 19, 20, 40, 41, 42, 43, 46, 47, 48, 54, 55, 56, 57, 58, 59, 75, 76, 89, 90];
6847
6847
  var RISKY_STTB_INDICES = [21, 22, 23];
6848
6848
  var SAFE_EXTENDED_FC_LCB_INDICES = /* @__PURE__ */ new Set([93, 94, 113, 181, 182]);
@@ -7111,7 +7111,7 @@ function tryWriteOleDocParagraphEdit(docBytes, paragraphIndex, text, limits) {
7111
7111
  }
7112
7112
  }
7113
7113
 
7114
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole-document-doc-runs.js
7114
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-runs.js
7115
7115
  var LIMIT = 65536;
7116
7116
  var SAFE_OPERANDS = /* @__PURE__ */ new Set([
7117
7117
  2101,
@@ -7139,9 +7139,12 @@ var SAFE_OPERANDS = /* @__PURE__ */ new Set([
7139
7139
  26646,
7140
7140
  26647
7141
7141
  ]);
7142
- function parsePrls(word, start, end) {
7142
+ function parsePrls(word, start, end, budget) {
7143
7143
  const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [];
7144
7144
  for (let at = start; at < end; ) {
7145
+ if (budget.remaining <= 0)
7146
+ throw new Error("Formatting SPRM limit");
7147
+ budget.remaining--;
7145
7148
  if (at + 2 > end)
7146
7149
  throw new Error("Truncated SPRM");
7147
7150
  const opcode = view2.getUint16(at, true), spra = opcode >>> 13;
@@ -7161,9 +7164,9 @@ function parsePrls(word, start, end) {
7161
7164
  function parsePhysicalRuns(word, table) {
7162
7165
  if (table.pns.length > LIMIT)
7163
7166
  throw new Error("Formatting page limit");
7164
- const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [];
7167
+ const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [], budget = { remaining: 262144 };
7165
7168
  for (let bte = 0; bte < table.pns.length; bte++) {
7166
- const page = table.pns[bte] * 512;
7169
+ const page = (table.pns[bte] & 4194303) * 512;
7167
7170
  if (page > word.length - 512)
7168
7171
  throw new Error("Truncated CHPX page");
7169
7172
  const count = word[page + 511], header = (count + 1) * 4 + count;
@@ -7177,7 +7180,7 @@ function parsePhysicalRuns(word, table) {
7177
7180
  if (offset && (offset < header || offset + 1 + word[page + offset] > 511))
7178
7181
  throw new Error("Invalid CHPX blob");
7179
7182
  const blob = offset ? page + offset : 0, blobEnd = blob ? blob + 1 + word[blob] : 0;
7180
- out.push({ start, end, blob, blobEnd, prls: blob ? parsePrls(word, blob + 1, blobEnd) : [] });
7183
+ out.push({ start, end, blob, blobEnd, prls: blob ? parsePrls(word, blob + 1, blobEnd, budget) : [] });
7181
7184
  }
7182
7185
  }
7183
7186
  out.sort((a, b) => a.start - b.start);
@@ -7201,7 +7204,9 @@ function inspect2(input) {
7201
7204
  if (fib.plcfbteChpx.lcb > LIMIT * 8 + 4 || fib.plcfbtePapx.lcb > LIMIT * 8 + 4)
7202
7205
  throw new Error("Formatting table limit");
7203
7206
  const chpx = parseBteTable(doc.tableBytes, fib.plcfbteChpx), papx = parseBteTable(doc.tableBytes, fib.plcfbtePapx);
7207
+ papx.pns = papx.pns.map((pn) => pn & 4194303);
7204
7208
  const physical = parsePhysicalRuns(word, chpx), runs = [];
7209
+ const snapshots = /* @__PURE__ */ new Map();
7205
7210
  for (const piece of pieces) {
7206
7211
  if (piece.cpStart >= fib.ccpText)
7207
7212
  break;
@@ -7228,16 +7233,24 @@ function inspect2(input) {
7228
7233
  const values = row.prls.filter((p) => p.opcode === opcode);
7229
7234
  return values.length === 1 && values[0].operand[0] <= 1 ? values[0].operand[0] === 1 : void 0;
7230
7235
  };
7236
+ const underline = row.prls.filter((p) => p.opcode === 10814);
7237
+ const kul = underline.length === 1 ? underline[0].operand[0] : void 0;
7231
7238
  const size = row.prls.filter((p) => p.opcode === 19011);
7232
7239
  const halfPoints = size.length === 1 ? size[0].operand[0] + size[0].operand[1] * 256 : void 0;
7240
+ let sprms = snapshots.get(row);
7241
+ if (!sprms) {
7242
+ sprms = Object.freeze(row.prls.map((p) => Object.freeze({ opcode: p.opcode, operand: Object.freeze(p.operand.slice()) })));
7243
+ snapshots.set(row, sprms);
7244
+ }
7233
7245
  runs.push({
7234
7246
  cpStart: cp,
7235
7247
  cpEnd: end,
7236
7248
  text: text.slice(cp, end),
7237
7249
  directBold: direct(2101),
7238
7250
  directItalic: direct(2102),
7251
+ directUnderline: piece.prm === 0 && row.prls.every((p) => SAFE_OPERANDS.has(p.opcode)) ? kul === 0 ? "none" : kul === 1 ? "single" : kul === 3 ? "double" : void 0 : void 0,
7239
7252
  directFontSizePoints: piece.prm === 0 && halfPoints !== void 0 && halfPoints >= 2 && halfPoints <= 3276 && row.prls.every((p) => SAFE_OPERANDS.has(p.opcode)) ? halfPoints / 2 : void 0,
7240
- sprms: Object.freeze(row.prls.map((p) => Object.freeze({ opcode: p.opcode, operand: Object.freeze(p.operand.slice()) }))),
7253
+ sprms,
7241
7254
  physical: row,
7242
7255
  prm: piece.prm
7243
7256
  });
@@ -7270,10 +7283,23 @@ function readDocParagraphStyleIndices(input) {
7270
7283
  function writeDocCharacterRunFlag(input, cpStart, cpEnd, flag, value) {
7271
7284
  if (typeof value !== "boolean" || !Number.isSafeInteger(cpStart) || !Number.isSafeInteger(cpEnd) || flag !== "bold" && flag !== "italic")
7272
7285
  throw new Error("invalid-formatting");
7286
+ return writeExclusiveOperand(input, cpStart, cpEnd, flag === "bold" ? 2101 : 2102, Number(value));
7287
+ }
7288
+ function writeDocCharacterRunFontSize(input, cpStart, cpEnd, points) {
7289
+ if (typeof points !== "number" || !Number.isFinite(points) || !Number.isInteger(points * 2) || points < 1 || points > 1638 || !Number.isSafeInteger(cpStart) || !Number.isSafeInteger(cpEnd))
7290
+ throw new Error("invalid-formatting");
7291
+ return writeExclusiveOperand(input, cpStart, cpEnd, 19011, points * 2);
7292
+ }
7293
+ function writeDocCharacterRunUnderline(input, cpStart, cpEnd, value) {
7294
+ if (typeof value !== "string" || !["none", "single", "double"].includes(value) || !Number.isSafeInteger(cpStart) || !Number.isSafeInteger(cpEnd))
7295
+ throw new Error("invalid-formatting");
7296
+ return writeExclusiveOperand(input, cpStart, cpEnd, 10814, value === "none" ? 0 : value === "single" ? 1 : 3);
7297
+ }
7298
+ function writeExclusiveOperand(input, cpStart, cpEnd, opcode, value) {
7273
7299
  const parsed = inspect2(input), target = parsed.runs.find((run) => run.cpStart === cpStart && run.cpEnd === cpEnd);
7274
7300
  if (!target || target.prm !== 0 || /[\x00-\x1f]/u.test(target.text))
7275
7301
  throw new Error("unsupported-formatting");
7276
- const row = target.physical, opcode = flag === "bold" ? 2101 : 2102;
7302
+ const row = target.physical;
7277
7303
  const extension2 = parsed.fib.fibRgFcLcbOffset + parsed.fib.fibRgFcLcbCount * 8;
7278
7304
  const fibEnd = extension2 + 2 + new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength).getUint16(extension2, true) * 2;
7279
7305
  if (row.blob < fibEnd)
@@ -7281,7 +7307,11 @@ function writeDocCharacterRunFlag(input, cpStart, cpEnd, flag, value) {
7281
7307
  if (row.prls.some((p) => !SAFE_OPERANDS.has(p.opcode)))
7282
7308
  throw new Error("opaque-formatting");
7283
7309
  const operands = row.prls.filter((p) => p.opcode === opcode);
7284
- if (operands.length !== 1 || ![0, 1, 128, 129].includes(operands[0].operand[0]))
7310
+ if (operands.length !== 1)
7311
+ throw new Error("inherited-formatting");
7312
+ const operand = operands[0], size = opcode === 19011;
7313
+ const previous = operand.operand[0] + (size ? operand.operand[1] * 256 : 0);
7314
+ if (size ? operand.operand.length !== 2 || previous < 2 || previous > 3276 : opcode === 10814 ? ![0, 1, 3].includes(previous) : ![0, 1, 128, 129].includes(previous))
7285
7315
  throw new Error("inherited-formatting");
7286
7316
  const piece = parsed.pieces.find((p) => p.cpStart <= cpStart && p.cpEnd >= cpEnd);
7287
7317
  const unit = piece.compressed ? 1 : 2, start = piece.fc + (cpStart - piece.cpStart) * unit;
@@ -7289,25 +7319,241 @@ function writeDocCharacterRunFlag(input, cpStart, cpEnd, flag, value) {
7289
7319
  throw new Error("shared-formatting");
7290
7320
  if (parsed.physical.some((r) => r !== row && r.blob && r.blob < row.blobEnd && row.blob < r.blobEnd) || parsed.papx.pns.includes(Math.floor(row.blob / 512)) || parsed.pieces.some((p) => p.fc < row.blobEnd && row.blob < p.fc + (p.cpEnd - p.cpStart) * (p.compressed ? 1 : 2)))
7291
7321
  throw new Error("aliased-formatting");
7292
- if (operands[0].operand[0] === Number(value))
7322
+ const sed = parsed.fib.sed;
7323
+ if (sed.lcb > LIMIT * 16 + 4)
7324
+ throw new Error("resource-limit");
7325
+ if (sed.lcb) {
7326
+ if (sed.lcb < 4 || (sed.lcb - 4) % 16 || sed.fc > parsed.doc.tableBytes.length - sed.lcb)
7327
+ throw new Error("invalid-formatting");
7328
+ const n = (sed.lcb - 4) / 16, tableView = new DataView(parsed.doc.tableBytes.buffer, parsed.doc.tableBytes.byteOffset, parsed.doc.tableBytes.byteLength);
7329
+ const wordView = new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength);
7330
+ for (let i = 0; i < n; i++) {
7331
+ const at = tableView.getInt32(sed.fc + (n + 1) * 4 + i * 12 + 2, true);
7332
+ if (at === -1)
7333
+ continue;
7334
+ if (at < 0 || at > parsed.word.length - 2)
7335
+ throw new Error("invalid-formatting");
7336
+ const end = at + 2 + wordView.getUint16(at, true);
7337
+ if (end > parsed.word.length)
7338
+ throw new Error("invalid-formatting");
7339
+ if (at < row.blobEnd && row.blob < end)
7340
+ throw new Error("aliased-formatting");
7341
+ }
7342
+ }
7343
+ if (previous === value)
7344
+ return input;
7345
+ const word = parsed.word.slice();
7346
+ word[operand.at] = value & 255;
7347
+ if (size)
7348
+ word[operand.at + 1] = value >>> 8;
7349
+ return parsed.doc.rewrap(word, parsed.doc.tableBytes);
7350
+ }
7351
+
7352
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole-document-doc-paragraph-format.js
7353
+ var LIMIT2 = 65536;
7354
+ var SPRM_LIMIT = 262144;
7355
+ var PAGE_NUMBER_MASK = 4194303;
7356
+ var ALIGNMENTS = ["start", "center", "end", "justify"];
7357
+ var SAFE = /* @__PURE__ */ new Set([
7358
+ 9219,
7359
+ 9313,
7360
+ 25703,
7361
+ 9221,
7362
+ 9222,
7363
+ 9223,
7364
+ 9228,
7365
+ 25618,
7366
+ 42003,
7367
+ 42004,
7368
+ 9307,
7369
+ 9308,
7370
+ 33885,
7371
+ 33886,
7372
+ 33888,
7373
+ 9281,
7374
+ 9325
7375
+ ]);
7376
+ function alignmentOperands(row) {
7377
+ const values = row.prls.filter((p) => p.opcode === 9313), mirrors = row.prls.filter((p) => p.opcode === 9219);
7378
+ if (values.length !== 1 || values[0].operand[0] > 3 || mirrors.length > 1)
7379
+ return void 0;
7380
+ const value = values[0], mirror = mirrors[0];
7381
+ if (mirror && (mirror.at > value.at || mirror.operand[0] !== value.operand[0]))
7382
+ return void 0;
7383
+ return { value, mirror };
7384
+ }
7385
+ function parsePrls2(word, start, end, budget) {
7386
+ const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), out = [];
7387
+ for (let at = start; at < end; ) {
7388
+ if (at + 2 > end)
7389
+ throw new Error("invalid-formatting");
7390
+ const opcode = view2.getUint16(at, true), spra = opcode >>> 13;
7391
+ let length = [1, 1, 2, 4, 2, 2, 0, 3][spra];
7392
+ if (spra === 6) {
7393
+ if (opcode === 54792 || opcode === 50709 || at + 3 > end)
7394
+ throw new Error("unsupported-formatting");
7395
+ length = 1 + word[at + 2];
7396
+ }
7397
+ if (at + 2 + length > end)
7398
+ throw new Error("invalid-formatting");
7399
+ if (budget.remaining === 0)
7400
+ throw new Error("resource-limit");
7401
+ budget.remaining--;
7402
+ out.push({ opcode, at: at + 2, operand: word.subarray(at + 2, at + 2 + length) });
7403
+ at += 2 + length;
7404
+ }
7405
+ return out;
7406
+ }
7407
+ function inspect3(input) {
7408
+ const doc = unwrapDocBytes(input);
7409
+ if (!doc)
7410
+ throw new Error("unsupported-formatting");
7411
+ const word = doc.wordDocBytes, fib = readDocFib(word), limits = DEFAULT_OLE_DOC_PROCESSING_LIMITS;
7412
+ if (fib.ccpText > limits.maxCharacters)
7413
+ throw new Error("resource-limit");
7414
+ const pieces = parseDocClx(doc.tableBytes, fib.clx, limits.maxPieces).pieces;
7415
+ const total = pieces.at(-1)?.cpEnd ?? 0;
7416
+ if (total < fib.ccpText || total > fib.ccpText + fib.ccpOtherStories + 1)
7417
+ throw new Error("invalid-formatting");
7418
+ const text = decodePiecesText(word, pieces, fib.ccpText);
7419
+ if (fib.plcfbtePapx.lcb > LIMIT2 * 8 + 4 || fib.plcfbteChpx.lcb > LIMIT2 * 8 + 4)
7420
+ throw new Error("resource-limit");
7421
+ const papx = parseBteTable(doc.tableBytes, fib.plcfbtePapx), chpx = parseBteTable(doc.tableBytes, fib.plcfbteChpx);
7422
+ const view2 = new DataView(word.buffer, word.byteOffset, word.byteLength), rows = [];
7423
+ const sprmBudget = { remaining: SPRM_LIMIT };
7424
+ for (let pageIndex = 0; pageIndex < papx.pns.length; pageIndex++) {
7425
+ const page = (papx.pns[pageIndex] & PAGE_NUMBER_MASK) * 512;
7426
+ if (page > word.length - 512)
7427
+ throw new Error("invalid-formatting");
7428
+ const count = word[page + 511], header = (count + 1) * 4 + count * 13;
7429
+ if (!count || header > 511 || rows.length + count > LIMIT2)
7430
+ throw new Error("resource-limit");
7431
+ for (let i = 0; i < count; i++) {
7432
+ const start = view2.getInt32(page + i * 4, true), end = view2.getInt32(page + (i + 1) * 4, true);
7433
+ if (start < papx.fcs[pageIndex] || end > papx.fcs[pageIndex + 1] || end <= start)
7434
+ throw new Error("invalid-formatting");
7435
+ const offset = word[page + (count + 1) * 4 + i * 13] * 2;
7436
+ if (!offset) {
7437
+ rows.push({ start, end, blob: 0, blobEnd: 0, prls: [] });
7438
+ continue;
7439
+ }
7440
+ if (offset < header || offset + 2 > 511)
7441
+ throw new Error("invalid-formatting");
7442
+ const blob = page + offset, cb = word[blob], prefix = cb === 0 ? 2 : 1;
7443
+ const length = cb === 0 ? 2 + word[blob + 1] * 2 : cb * 2;
7444
+ if (cb === 0 && !word[blob + 1] || length < prefix + 2 || offset + length > 511)
7445
+ throw new Error("invalid-formatting");
7446
+ const blobEnd = blob + length;
7447
+ rows.push({ start, end, blob, blobEnd, prls: parsePrls2(word, blob + prefix + 2, blobEnd, sprmBudget) });
7448
+ }
7449
+ }
7450
+ rows.sort((a, b) => a.start - b.start);
7451
+ for (let i = 1; i < rows.length; i++)
7452
+ if (rows[i].start < rows[i - 1].end)
7453
+ throw new Error("invalid-formatting");
7454
+ const paragraphs = [];
7455
+ let cpStart = 0, pieceIndex = 0;
7456
+ for (let cp = 0; cp < text.length; cp++) {
7457
+ if (text[cp] !== "\r" && cp !== text.length - 1)
7458
+ continue;
7459
+ if (paragraphs.length >= LIMIT2)
7460
+ throw new Error("resource-limit");
7461
+ while (pieces[pieceIndex].cpEnd <= cp)
7462
+ pieceIndex++;
7463
+ const piece = pieces[pieceIndex], fc = piece.fc + (cp - piece.cpStart) * (piece.compressed ? 1 : 2);
7464
+ let lo = 0, hi = rows.length;
7465
+ while (lo < hi) {
7466
+ const middle = lo + hi >>> 1;
7467
+ if (rows[middle].end <= fc)
7468
+ lo = middle + 1;
7469
+ else
7470
+ hi = middle;
7471
+ }
7472
+ const row = rows[lo];
7473
+ if (!row || fc < row.start || fc >= row.end)
7474
+ throw new Error("invalid-formatting");
7475
+ const operands = alignmentOperands(row);
7476
+ const directAlignment = piece.prm === 0 && row.prls.every((p) => SAFE.has(p.opcode)) && operands ? ALIGNMENTS[operands.value.operand[0]] : void 0;
7477
+ paragraphs.push({ cpStart, cpEnd: cp + 1, mark: text[cp] === "\r", row, prm: piece.prm, directAlignment });
7478
+ cpStart = cp + 1;
7479
+ }
7480
+ return { doc, word, fib, pieces, rows, chpx, paragraphs, text };
7481
+ }
7482
+ function readDocParagraphAlignments(input) {
7483
+ return Object.freeze(inspect3(input).paragraphs.map((p) => p.directAlignment));
7484
+ }
7485
+ function writeDocParagraphAlignment(input, index, alignment) {
7486
+ if (!Number.isSafeInteger(index) || index < 0 || typeof alignment !== "string" || !ALIGNMENTS.includes(alignment))
7487
+ throw new Error("invalid-formatting");
7488
+ const parsed = inspect3(input), target = parsed.paragraphs[index];
7489
+ if (!target?.mark || target.prm !== 0 || /[\x00-\x1f]/u.test(parsed.text.slice(target.cpStart, target.cpEnd - 1)))
7490
+ throw new Error("unsupported-formatting");
7491
+ const row = target.row;
7492
+ if (row.prls.some((p) => !SAFE.has(p.opcode)))
7493
+ throw new Error("opaque-formatting");
7494
+ const operands = alignmentOperands(row);
7495
+ if (!operands)
7496
+ throw new Error("inherited-formatting");
7497
+ if (operands.mirror && alignment !== "center" && alignment !== "justify")
7498
+ throw new Error("direction-dependent-alignment");
7499
+ const piece = parsed.pieces.find((p) => p.cpStart <= target.cpStart && p.cpEnd >= target.cpEnd);
7500
+ if (!piece || piece.prm !== 0)
7501
+ throw new Error("unsupported-formatting");
7502
+ const unit = piece.compressed ? 1 : 2, start = piece.fc + (target.cpStart - piece.cpStart) * unit;
7503
+ if (start !== row.start || start + (target.cpEnd - target.cpStart) * unit !== row.end || parsed.paragraphs.some((p) => p !== target && p.row === row) || parsed.pieces.some((p) => p !== piece && p.fc < row.end && row.start < p.fc + (p.cpEnd - p.cpStart) * (p.compressed ? 1 : 2)))
7504
+ throw new Error("shared-formatting");
7505
+ const extension2 = parsed.fib.fibRgFcLcbOffset + parsed.fib.fibRgFcLcbCount * 8;
7506
+ const fibEnd = extension2 + 2 + new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength).getUint16(extension2, true) * 2;
7507
+ if (row.blob < fibEnd || parsed.rows.some((r) => r !== row && r.blob && r.blob < row.blobEnd && row.blob < r.blobEnd) || parsed.chpx.pns.some((pn) => (pn & PAGE_NUMBER_MASK) === Math.floor(row.blob / 512)) || parsed.pieces.some((p) => p.fc < row.blobEnd && row.blob < p.fc + (p.cpEnd - p.cpStart) * (p.compressed ? 1 : 2)))
7508
+ throw new Error("aliased-formatting");
7509
+ const sed = parsed.fib.sed;
7510
+ if (sed.lcb > LIMIT2 * 16 + 4)
7511
+ throw new Error("resource-limit");
7512
+ if (sed.lcb) {
7513
+ if (sed.lcb < 4 || (sed.lcb - 4) % 16 || sed.fc > parsed.doc.tableBytes.length - sed.lcb)
7514
+ throw new Error("invalid-formatting");
7515
+ const n = (sed.lcb - 4) / 16, tableView = new DataView(parsed.doc.tableBytes.buffer, parsed.doc.tableBytes.byteOffset, parsed.doc.tableBytes.byteLength);
7516
+ const wordView = new DataView(parsed.word.buffer, parsed.word.byteOffset, parsed.word.byteLength);
7517
+ for (let i = 0; i < n; i++) {
7518
+ const at = tableView.getInt32(sed.fc + (n + 1) * 4 + i * 12 + 2, true);
7519
+ if (at === -1)
7520
+ continue;
7521
+ if (at < 0 || at > parsed.word.length - 2)
7522
+ throw new Error("invalid-formatting");
7523
+ const end = at + 2 + wordView.getUint16(at, true);
7524
+ if (end > parsed.word.length)
7525
+ throw new Error("invalid-formatting");
7526
+ if (at < row.blobEnd && row.blob < end)
7527
+ throw new Error("aliased-formatting");
7528
+ }
7529
+ }
7530
+ const value = ALIGNMENTS.indexOf(alignment);
7531
+ if (operands.value.operand[0] === value)
7293
7532
  return input;
7294
7533
  const word = parsed.word.slice();
7295
- word[operands[0].at] = Number(value);
7534
+ word[operands.value.at] = value;
7535
+ if (operands.mirror)
7536
+ word[operands.mirror.at] = value;
7296
7537
  return parsed.doc.rewrap(word, parsed.doc.tableBytes);
7297
7538
  }
7298
7539
 
7299
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/doc-document.js
7540
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/doc-document.js
7300
7541
  var DOC_CAPABILITIES = Object.freeze({
7301
- read: Object.freeze(["paragraph-text", "character-runs", "direct-character-formatting", "paragraph-style-index", "compound-streams"]),
7302
- write: Object.freeze(["paragraph-text", "existing-direct-bold-italic"]),
7542
+ read: Object.freeze(["paragraph-text", "character-runs", "direct-character-formatting", "paragraph-style-index", "direct-paragraph-alignment", "compound-streams"]),
7543
+ write: Object.freeze(["paragraph-text", "existing-direct-bold-italic", "existing-direct-font-size", "existing-direct-underline", "existing-direct-paragraph-alignment"]),
7303
7544
  limitations: Object.freeze([
7304
7545
  "Paragraph insertion, removal and embedded paragraph breaks are unsupported.",
7305
7546
  "Character formatting reports direct CHPX exceptions, without resolving styles or piece PRMs.",
7306
7547
  "Bold/italic setters force an absolute value in an existing exclusive understood CHPX run. Run handles expire after edits.",
7548
+ "Underline setters replace an existing exclusive sprmCKul byte with none, single or double; inherited and other styles refuse.",
7549
+ "Font-size setters replace an existing exclusive sprmCHps slot with 1..1638 points in exact half-point increments.",
7307
7550
  "Fields, tables, objects and inherited styles are preserved where supported; their models are not editable.",
7308
7551
  "Unsupported edits and processing limits throw without changing the document.",
7309
7552
  "Text uses the bounded DOC codec defaults: 16,777,216 main-story characters and 65,536 pieces or field records.",
7310
- "Rich formatting is bounded to 65,536 physical/mapped runs and paragraph style records."
7553
+ "Character run inspection is bounded to 262,144 SPRM records before allocation, including shared or stale formatting runs.",
7554
+ "Rich formatting is bounded to 65,536 physical/mapped runs and paragraph style records.",
7555
+ "Logical paragraph alignment replaces a sole existing exclusive sprmPJc slot. Matching legacy mirrors support center/justify only, with both slots updated. Styles, legacy-only alignment, tables and opaque formatting refuse.",
7556
+ "Paragraph alignment inspection is bounded to 262,144 SPRM records before allocation, including shared or stale formatting runs."
7311
7557
  ])
7312
7558
  });
7313
7559
  var DocDocument = class extends Ole2DocumentBase {
@@ -7321,6 +7567,7 @@ var DocDocument = class extends Ole2DocumentBase {
7321
7567
  #text;
7322
7568
  #runsCache;
7323
7569
  #stylesCache;
7570
+ #alignmentsCache;
7324
7571
  constructor(input) {
7325
7572
  super(input);
7326
7573
  const text = readOleDocParagraphs(this.getBytes());
@@ -7337,6 +7584,16 @@ var DocDocument = class extends Ole2DocumentBase {
7337
7584
  set text(value) {
7338
7585
  owner.#setParagraphText(index, value);
7339
7586
  },
7587
+ get directAlignment() {
7588
+ try {
7589
+ return owner.#paragraphAlignments()[index];
7590
+ } catch {
7591
+ throw new UnsupportedOle2EditError("unsupported-formatting");
7592
+ }
7593
+ },
7594
+ set directAlignment(value) {
7595
+ owner.#setParagraphAlignment(index, value);
7596
+ },
7340
7597
  get runs() {
7341
7598
  return owner.#paragraphRuns(index);
7342
7599
  },
@@ -7353,6 +7610,25 @@ var DocDocument = class extends Ole2DocumentBase {
7353
7610
  get paragraphs() {
7354
7611
  return this.#paragraphs;
7355
7612
  }
7613
+ #paragraphAlignments() {
7614
+ if (this.#alignmentsCache?.revision !== this.revision)
7615
+ this.#alignmentsCache = { revision: this.revision, alignments: readDocParagraphAlignments(this.getBytes()) };
7616
+ return this.#alignmentsCache.alignments;
7617
+ }
7618
+ #setParagraphAlignment(index, value) {
7619
+ if (typeof value !== "string")
7620
+ throw new UnsupportedOle2EditError("invalid-formatting");
7621
+ let bytes;
7622
+ try {
7623
+ bytes = writeDocParagraphAlignment(this.getBytes(), index, value);
7624
+ } catch (error) {
7625
+ throw new UnsupportedOle2EditError(error instanceof Error ? error.message : "unsupported-formatting");
7626
+ }
7627
+ const text = readOleDocParagraphs(bytes), alignments = readDocParagraphAlignments(bytes);
7628
+ if (!text || text.length !== this.#text.length || text.some((t, i) => t !== this.#text[i]) || alignments[index] !== value)
7629
+ throw new UnsupportedOle2EditError("invalid-document");
7630
+ this.commitBytes(bytes);
7631
+ }
7356
7632
  #currentRuns() {
7357
7633
  if (this.#runsCache?.revision !== this.revision)
7358
7634
  this.#runsCache = { revision: this.revision, runs: readDocCharacterRuns(this.getBytes()) };
@@ -7371,15 +7647,15 @@ var DocDocument = class extends Ole2DocumentBase {
7371
7647
  try {
7372
7648
  return Object.freeze(this.#currentRuns().filter((r) => r.cpStart < end && r.cpEnd > start).map((run) => {
7373
7649
  const cpStart = Math.max(start, run.cpStart), cpEnd = Math.min(end, run.cpEnd);
7374
- let bold = run.directBold, italic = run.directItalic, sprms = run.sprms;
7650
+ let bold = run.directBold, italic = run.directItalic, size = run.directFontSizePoints, underline = run.directUnderline, sprms = run.sprms;
7375
7651
  const set = (flag, value) => {
7376
7652
  if (owner.revision !== revision)
7377
7653
  throw new UnsupportedOle2EditError("stale-run");
7378
- if (typeof value !== "boolean")
7654
+ if (flag === "underline" ? typeof value !== "string" : flag === "size" ? typeof value !== "number" : typeof value !== "boolean")
7379
7655
  throw new UnsupportedOle2EditError("invalid-formatting");
7380
7656
  let bytes;
7381
7657
  try {
7382
- bytes = writeDocCharacterRunFlag(owner.getBytes(), cpStart, cpEnd, flag, value);
7658
+ bytes = flag === "underline" ? writeDocCharacterRunUnderline(owner.getBytes(), cpStart, cpEnd, value) : flag === "size" ? writeDocCharacterRunFontSize(owner.getBytes(), cpStart, cpEnd, value) : writeDocCharacterRunFlag(owner.getBytes(), cpStart, cpEnd, flag, value);
7383
7659
  } catch (error) {
7384
7660
  throw new UnsupportedOle2EditError(error instanceof Error ? error.message : "unsupported-formatting");
7385
7661
  }
@@ -7390,15 +7666,26 @@ var DocDocument = class extends Ole2DocumentBase {
7390
7666
  owner.commitBytes(bytes);
7391
7667
  if (flag === "bold")
7392
7668
  bold = value;
7393
- else
7669
+ else if (flag === "italic")
7394
7670
  italic = value;
7395
- sprms = Object.freeze(sprms.map((p) => p.opcode === (flag === "bold" ? 2101 : 2102) ? Object.freeze({ opcode: p.opcode, operand: Object.freeze([Number(value)]) }) : p));
7671
+ else if (flag === "underline")
7672
+ underline = value;
7673
+ else
7674
+ size = value;
7675
+ const opcode = flag === "bold" ? 2101 : flag === "italic" ? 2102 : flag === "underline" ? 10814 : 19011;
7676
+ const operand = flag === "size" ? [value * 2 & 255, value * 2 >>> 8] : flag === "underline" ? [value === "none" ? 0 : value === "single" ? 1 : 3] : [Number(value)];
7677
+ sprms = Object.freeze(sprms.map((p) => p.opcode === opcode ? Object.freeze({ opcode: p.opcode, operand: Object.freeze(operand) }) : p));
7396
7678
  };
7397
7679
  return Object.freeze({
7398
7680
  cpStart,
7399
7681
  cpEnd,
7400
7682
  text: run.text.slice(cpStart - run.cpStart, cpEnd - run.cpStart),
7401
- directFontSizePoints: run.directFontSizePoints,
7683
+ get directFontSizePoints() {
7684
+ return size;
7685
+ },
7686
+ set directFontSizePoints(value) {
7687
+ set("size", value);
7688
+ },
7402
7689
  get sprms() {
7403
7690
  return sprms;
7404
7691
  },
@@ -7408,6 +7695,12 @@ var DocDocument = class extends Ole2DocumentBase {
7408
7695
  set directBold(value) {
7409
7696
  set("bold", value);
7410
7697
  },
7698
+ get directUnderline() {
7699
+ return underline;
7700
+ },
7701
+ set directUnderline(value) {
7702
+ set("underline", value);
7703
+ },
7411
7704
  get directItalic() {
7412
7705
  return italic;
7413
7706
  },
@@ -7440,7 +7733,7 @@ var DocDocument = class extends Ole2DocumentBase {
7440
7733
  }
7441
7734
  };
7442
7735
 
7443
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-helpers.js
7736
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-helpers.js
7444
7737
  function compareDirEntryNames(a, b) {
7445
7738
  const ua = a.toUpperCase();
7446
7739
  const ub = b.toUpperCase();
@@ -7507,7 +7800,7 @@ function writeInt32Sectors(outBytes, int32Data, firstSector, numSectors, sectorS
7507
7800
  }
7508
7801
  }
7509
7802
 
7510
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-serialize.js
7803
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write-serialize.js
7511
7804
  function writeHeader(outView, outBytes, params) {
7512
7805
  outBytes.set(OLE_MAGIC, 0);
7513
7806
  outView.setUint16(24, 62, true);
@@ -7600,7 +7893,7 @@ function writeStreamSectors(outBytes, streamData, chain2, sectorSize) {
7600
7893
  }
7601
7894
  }
7602
7895
 
7603
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-parser-write.js
7896
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-parser-write.js
7604
7897
  function buildOle2(streams, rootClsid, miniStreamCutoff = 4096) {
7605
7898
  const sectorSize = 512;
7606
7899
  const miniSectorSize = 64;
@@ -7781,7 +8074,7 @@ function buildOle2(streams, rootClsid, miniStreamCutoff = 4096) {
7781
8074
  return output;
7782
8075
  }
7783
8076
 
7784
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-cfb.js
8077
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-cfb.js
7785
8078
  var WORKBOOK_STREAM_NAMES = ["workbook", "book"];
7786
8079
  function unwrapXlsBytes(bytes) {
7787
8080
  if (!isCfb(bytes)) {
@@ -7848,7 +8141,7 @@ function isCfb(bytes) {
7848
8141
  return OLE_MAGIC.every((value, index) => bytes[index] === value);
7849
8142
  }
7850
8143
 
7851
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-functions.js
8144
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-functions.js
7852
8145
  var TABLE = `0 COUNT -1|1 IF -1|2 ISNA 1|3 ISERROR 1|4 SUM -1|5 AVERAGE -1|6 MIN -1|7 MAX -1|8 ROW -1|9 COLUMN -1|10 NA 0|11 NPV -1|12 STDEV -1|13 DOLLAR -1|14 FIXED -1|15 SIN 1|16 COS 1|17 TAN 1|18 ATAN 1|19 PI 0|20 SQRT 1|21 EXP 1|22 LN 1|23 LOG10 1|24 ABS 1|25 INT 1|26 SIGN 1|27 ROUND 2|28 LOOKUP -1|29 INDEX -1|30 REPT 2|31 MID 3|32 LEN 1|33 VALUE 1|34 TRUE 0|35 FALSE 0|36 AND -1|37 OR -1|38 NOT 1|39 MOD 2|40 DCOUNT 3|41 DSUM 3|42 DAVERAGE 3|43 DMIN 3|44 DMAX 3|45 DSTDEV 3|46 VAR -1|47 DVAR 3|48 TEXT 2|49 LINEST -1|50 TREND -1|51 LOGEST -1|52 GROWTH -1|56 PV -1|57 FV -1|58 NPER -1|59 PMT -1|60 RATE -1|61 MIRR 3|62 IRR -1|63 RAND 0|64 MATCH -1|65 DATE 3|66 TIME 3|67 DAY 1|68 MONTH 1|69 YEAR 1|70 WEEKDAY -1|71 HOUR 1|72 MINUTE 1|73 SECOND 1|74 NOW 0|75 AREAS 1|76 ROWS 1|77 COLUMNS 1|78 OFFSET -1|82 SEARCH -1|83 TRANSPOSE 1|86 TYPE 1|97 ATAN2 2|98 ASIN 1|99 ACOS 1|100 CHOOSE -1|101 HLOOKUP -1|102 VLOOKUP -1|105 ISREF 1|109 LOG -1|111 CHAR 1|112 LOWER 1|113 UPPER 1|114 PROPER 1|115 LEFT -1|116 RIGHT -1|117 EXACT 2|118 TRIM 1|119 REPLACE 4|120 SUBSTITUTE -1|121 CODE 1|124 FIND -1|125 CELL -1|126 ISERR 1|127 ISTEXT 1|128 ISNUMBER 1|129 ISBLANK 1|130 T 1|131 N 1|140 DATEVALUE 1|141 TIMEVALUE 1|142 SLN 3|143 SYD 4|144 DDB -1|148 INDIRECT -1|150 CALL -1|162 CLEAN 1|163 MDETERM 1|164 MINVERSE 1|165 MMULT 2|167 IPMT -1|168 PPMT -1|169 COUNTA -1|183 PRODUCT -1|184 FACT 1|189 DPRODUCT 3|190 ISNONTEXT 1|193 STDEVP -1|194 VARP -1|195 DSTDEVP 3|196 DVARP 3|197 TRUNC -1|198 ISLOGICAL 1|199 DCOUNTA 3|204 USDOLLAR -1|205 FINDB -1|206 SEARCHB -1|207 REPLACEB 4|208 LEFTB -1|209 RIGHTB -1|210 MIDB 3|211 LENB 1|212 ROUNDUP 2|213 ROUNDDOWN 2|214 ASC 1|215 DBCS 1|216 RANK -1|219 ADDRESS -1|220 DAYS360 -1|221 TODAY 0|222 VDB -1|227 MEDIAN -1|228 SUMPRODUCT -1|229 SINH 1|230 COSH 1|231 TANH 1|232 ASINH 1|233 ACOSH 1|234 ATANH 1|235 DGET 3|244 INFO 1|247 DB -1|252 FREQUENCY 2|261 ERROR.TYPE 1|269 AVEDEV -1|270 BETADIST -1|271 GAMMALN 1|272 BETAINV -1|273 BINOMDIST 4|274 CHIDIST 2|275 CHIINV 2|276 COMBIN 2|277 CONFIDENCE 3|278 CRITBINOM 3|279 EVEN 1|280 EXPONDIST 3|281 FDIST 3|282 FINV 3|283 FISHER 1|284 FISHERINV 1|285 FLOOR 2|286 GAMMADIST 4|287 GAMMAINV 3|288 CEILING 2|289 HYPGEOMDIST 4|290 LOGNORMDIST 3|291 LOGINV 3|292 NEGBINOMDIST 3|293 NORMDIST 4|294 NORMSDIST 1|295 NORMINV 3|296 NORMSINV 1|297 STANDARDIZE 3|298 ODD 1|299 PERMUT 2|300 POISSON 3|301 TDIST 3|302 WEIBULL 4|303 SUMXMY2 2|304 SUMX2MY2 2|305 SUMX2PY2 2|306 CHITEST 2|307 CORREL 2|308 COVAR 2|309 FORECAST 3|310 FTEST 2|311 INTERCEPT 2|312 PEARSON 2|313 RSQ 2|314 STEYX 2|315 SLOPE 2|316 TTEST 4|317 PROB -1|318 DEVSQ -1|319 GEOMEAN -1|320 HARMEAN -1|321 SUMSQ -1|322 KURT -1|323 SKEW -1|324 ZTEST -1|325 LARGE 2|326 SMALL 2|327 QUARTILE 2|328 PERCENTILE 2|329 PERCENTRANK -1|330 MODE -1|331 TRIMMEAN 2|332 TINV 2|336 CONCATENATE -1|337 POWER 2|342 RADIANS 1|343 DEGREES 1|344 SUBTOTAL -1|345 SUMIF -1|346 COUNTIF 2|347 COUNTBLANK 1|350 ISPMT 4|351 DATEDIF 3|352 DATESTRING 1|353 NUMBERSTRING 2|354 ROMAN -1|358 GETPIVOTDATA -1|359 HYPERLINK -1|360 PHONETIC 1|361 AVERAGEA -1|362 MAXA -1|363 MINA -1|364 STDEVPA -1|365 VARPA -1|366 STDEVA -1|367 VARA -1|368 BAHTTEXT 1`;
7853
8146
  var XLS_FUNCTIONS = new Map(TABLE.split("|").map((entry) => {
7854
8147
  const [id, name, argc] = entry.split(" ");
@@ -7856,7 +8149,7 @@ var XLS_FUNCTIONS = new Map(TABLE.split("|").map((entry) => {
7856
8149
  }));
7857
8150
  var XLS_USER_FUNCTION_ID = 255;
7858
8151
 
7859
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-ptg-text.js
8152
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-ptg-text.js
7860
8153
  var BIFF_ERRORS = {
7861
8154
  0: "#NULL!",
7862
8155
  7: "#DIV/0!",
@@ -7951,7 +8244,7 @@ function readArrayConstant(extra) {
7951
8244
  return `{${lines.join(";")}}`;
7952
8245
  }
7953
8246
 
7954
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-records.js
8247
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-records.js
7955
8248
  var RT_CONTINUE = 60;
7956
8249
  function readXlsRecords(bytes, start = 0, end = bytes.length) {
7957
8250
  const records = [];
@@ -8043,8 +8336,8 @@ var SegmentReader = class _SegmentReader {
8043
8336
  constructor(segments) {
8044
8337
  this.segments = segments;
8045
8338
  }
8046
- static of(record4) {
8047
- return new _SegmentReader([record4.data, ...record4.continues]);
8339
+ static of(record5) {
8340
+ return new _SegmentReader([record5.data, ...record5.continues]);
8048
8341
  }
8049
8342
  get done() {
8050
8343
  this.normalize();
@@ -8103,21 +8396,21 @@ var SegmentReader = class _SegmentReader {
8103
8396
  return this.continuedChars(count, (flags & 1) !== 0);
8104
8397
  }
8105
8398
  };
8106
- function joinedData(record4) {
8107
- if (record4.continues.length === 0)
8108
- return record4.data;
8109
- const total = record4.continues.reduce((sum, part) => sum + part.length, record4.data.length);
8399
+ function joinedData(record5) {
8400
+ if (record5.continues.length === 0)
8401
+ return record5.data;
8402
+ const total = record5.continues.reduce((sum, part) => sum + part.length, record5.data.length);
8110
8403
  const out = new Uint8Array(total);
8111
- out.set(record4.data, 0);
8112
- let at = record4.data.length;
8113
- for (const part of record4.continues) {
8404
+ out.set(record5.data, 0);
8405
+ let at = record5.data.length;
8406
+ for (const part of record5.continues) {
8114
8407
  out.set(part, at);
8115
8408
  at += part.length;
8116
8409
  }
8117
8410
  return out;
8118
8411
  }
8119
8412
 
8120
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-ptg.js
8413
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-ptg.js
8121
8414
  function decodeFormula(rgce, extra, context, options) {
8122
8415
  try {
8123
8416
  return decode(rgce, new ByteReader(extra), context, options);
@@ -8348,9 +8641,9 @@ function readAttr(reader, stack, whitespace) {
8348
8641
  }
8349
8642
  }
8350
8643
 
8351
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sst.js
8352
- function parseSharedStrings(record4) {
8353
- const reader = SegmentReader.of(record4);
8644
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sst.js
8645
+ function parseSharedStrings(record5) {
8646
+ const reader = SegmentReader.of(record5);
8354
8647
  reader.u32();
8355
8648
  const unique = reader.u32();
8356
8649
  const strings = [];
@@ -8365,7 +8658,7 @@ function parseSharedStrings(record4) {
8365
8658
  return strings;
8366
8659
  }
8367
8660
 
8368
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-styles.js
8661
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-styles.js
8369
8662
  var DEFAULT_XLS_PALETTE = "000000 FFFFFF FF0000 00FF00 0000FF FFFF00 FF00FF 00FFFF 000000 FFFFFF FF0000 00FF00 0000FF FFFF00 FF00FF 00FFFF 800000 008000 000080 808000 800080 008080 C0C0C0 808080 9999FF 993366 FFFFCC CCFFFF 660066 FF8080 0066CC CCCCFF 000080 FF00FF FFFF00 00FFFF 800080 800000 008080 0000FF 00CCFF CCFFFF CCFFCC FFFF99 99CCFF FF99CC CC99FF FFCC99 3366FF 33CCCC 99CC00 FFCC00 FF9900 FF6600 666699 969696 003366 339966 003300 333300 993300 993366 333399 333333".split(" ");
8370
8663
  var XLS_BUILTIN_FORMATS = {
8371
8664
  0: "General",
@@ -8622,7 +8915,7 @@ function applyXfExt(data, xfs, palette) {
8622
8915
  }
8623
8916
  }
8624
8917
 
8625
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-types.js
8918
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-types.js
8626
8919
  var XlsReadError = class extends Error {
8627
8920
  code;
8628
8921
  constructor(code, message) {
@@ -8632,7 +8925,7 @@ var XlsReadError = class extends Error {
8632
8925
  }
8633
8926
  };
8634
8927
 
8635
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-globals.js
8928
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-globals.js
8636
8929
  var RT = {
8637
8930
  BOF: 2057,
8638
8931
  EOF: 10,
@@ -8731,17 +9024,17 @@ function parseGlobals(records) {
8731
9024
  const version = first.data[0] | first.data[1] << 8;
8732
9025
  if (version !== 1536)
8733
9026
  throw new XlsReadError("unsupported-version", "Only Excel 97-2003 (BIFF8) workbooks are supported; this file uses an older Excel format.");
8734
- const end = records.findIndex((record4) => record4.opcode === RT.EOF);
9027
+ const end = records.findIndex((record5) => record5.opcode === RT.EOF);
8735
9028
  const globals = end >= 0 ? records.slice(0, end) : records;
8736
- if (globals.some((record4) => record4.opcode === RT.FILEPASS))
9029
+ if (globals.some((record5) => record5.opcode === RT.FILEPASS))
8737
9030
  throw new XlsReadError("encrypted", "The workbook is password protected (encrypted).");
8738
- const paletteRecord = globals.find((record4) => record4.opcode === RT.PALETTE);
9031
+ const paletteRecord = globals.find((record5) => record5.opcode === RT.PALETTE);
8739
9032
  const palette = paletteRecord ? parsePalette(paletteRecord.data) : [...DEFAULT_XLS_PALETTE];
8740
9033
  const numberFormats = /* @__PURE__ */ new Map();
8741
- for (const record4 of globals) {
8742
- if (record4.opcode !== RT.FORMAT)
9034
+ for (const record5 of globals) {
9035
+ if (record5.opcode !== RT.FORMAT)
8743
9036
  continue;
8744
- const format = parseFormat(joinedData(record4));
9037
+ const format = parseFormat(joinedData(record5));
8745
9038
  numberFormats.set(format.id, format.code);
8746
9039
  }
8747
9040
  const formatCode = (id) => numberFormats.get(id) ?? XLS_BUILTIN_FORMATS[id] ?? "General";
@@ -8762,17 +9055,17 @@ function parseGlobals(records) {
8762
9055
  const supbooks = [];
8763
9056
  const xtis = [];
8764
9057
  const rawNames = [];
8765
- for (const record4 of globals) {
8766
- const r = new ByteReader(record4.data);
8767
- switch (record4.opcode) {
9058
+ for (const record5 of globals) {
9059
+ const r = new ByteReader(record5.data);
9060
+ switch (record5.opcode) {
8768
9061
  case RT.FONT:
8769
- out.fonts.push(parseFont(record4.data, palette));
9062
+ out.fonts.push(parseFont(record5.data, palette));
8770
9063
  break;
8771
9064
  case RT.XF:
8772
- out.xfs.push(parseXf(record4.data, palette, formatCode));
9065
+ out.xfs.push(parseXf(record5.data, palette, formatCode));
8773
9066
  break;
8774
9067
  case RT.XFEXT:
8775
- applyXfExt(record4.data, out.xfs, palette);
9068
+ applyXfExt(record5.data, out.xfs, palette);
8776
9069
  break;
8777
9070
  case RT.DATEMODE:
8778
9071
  out.date1904 = r.u16() === 1;
@@ -8795,26 +9088,26 @@ function parseGlobals(records) {
8795
9088
  break;
8796
9089
  }
8797
9090
  case RT.SST:
8798
- out.sst = parseSharedStrings(record4);
9091
+ out.sst = parseSharedStrings(record5);
8799
9092
  break;
8800
9093
  case RT.SUPBOOK:
8801
- supbooks.push(parseSupBook(joinedData(record4)));
9094
+ supbooks.push(parseSupBook(joinedData(record5)));
8802
9095
  break;
8803
9096
  case RT.EXTERNNAME: {
8804
9097
  const book = supbooks[supbooks.length - 1];
8805
- const nr = new ByteReader(joinedData(record4), 6);
9098
+ const nr = new ByteReader(joinedData(record5), 6);
8806
9099
  book?.externNames.push(nr.shortXlString());
8807
9100
  break;
8808
9101
  }
8809
9102
  case RT.EXTERNSHEET: {
8810
- const xr = new ByteReader(joinedData(record4));
9103
+ const xr = new ByteReader(joinedData(record5));
8811
9104
  const count = xr.u16();
8812
9105
  for (let i = 0; i < count; i++)
8813
9106
  xtis.push({ book: xr.u16(), first: xr.i16(), last: xr.i16() });
8814
9107
  break;
8815
9108
  }
8816
9109
  case RT.NAME:
8817
- rawNames.push(parseName(joinedData(record4)));
9110
+ rawNames.push(parseName(joinedData(record5)));
8818
9111
  break;
8819
9112
  case RT.OBPROJ:
8820
9113
  out.unsupported.push("VBA macros");
@@ -8870,7 +9163,7 @@ function parseGlobals(records) {
8870
9163
  return out;
8871
9164
  }
8872
9165
 
8873
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-biff8-edit.js
9166
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-biff8-edit.js
8874
9167
  function encodeRkExact(value) {
8875
9168
  if (!Number.isFinite(value))
8876
9169
  return void 0;
@@ -8898,19 +9191,19 @@ function worksheetRanges(bytes) {
8898
9191
  const ranges = [];
8899
9192
  let depth = 0;
8900
9193
  let start;
8901
- for (const record4 of records) {
8902
- if (record4.opcode === 2057) {
8903
- if (record4.length < 4 || view2.getUint16(record4.dataOffset, true) !== 1536 || depth >= 64)
9194
+ for (const record5 of records) {
9195
+ if (record5.opcode === 2057) {
9196
+ if (record5.length < 4 || view2.getUint16(record5.dataOffset, true) !== 1536 || depth >= 64)
8904
9197
  return void 0;
8905
- if (depth === 0 && view2.getUint16(record4.dataOffset + 2, true) === 16)
8906
- start = record4.headerOffset;
9198
+ if (depth === 0 && view2.getUint16(record5.dataOffset + 2, true) === 16)
9199
+ start = record5.headerOffset;
8907
9200
  depth++;
8908
- } else if (record4.opcode === 10) {
8909
- if (depth === 0 || record4.length !== 0)
9201
+ } else if (record5.opcode === 10) {
9202
+ if (depth === 0 || record5.length !== 0)
8910
9203
  return void 0;
8911
9204
  depth--;
8912
9205
  if (depth === 0 && start !== void 0) {
8913
- ranges.push({ start, end: record4.dataOffset });
9206
+ ranges.push({ start, end: record5.dataOffset });
8914
9207
  start = void 0;
8915
9208
  }
8916
9209
  }
@@ -8965,24 +9258,24 @@ function editXlsNumericCell(input, edit) {
8965
9258
  let packed = false;
8966
9259
  let depth = 0;
8967
9260
  let matches = 0;
8968
- for (const record4 of readRecords(bytes, range.start, range.end)) {
8969
- if (record4.opcode === 2057) {
9261
+ for (const record5 of readRecords(bytes, range.start, range.end)) {
9262
+ if (record5.opcode === 2057) {
8970
9263
  depth++;
8971
9264
  continue;
8972
9265
  }
8973
- if (record4.opcode === 10) {
9266
+ if (record5.opcode === 10) {
8974
9267
  depth--;
8975
9268
  continue;
8976
9269
  }
8977
9270
  if (depth !== 1)
8978
9271
  continue;
8979
- const p = record4.dataOffset;
8980
- if (record4.opcode === 189) {
8981
- if (record4.length < 12 || (record4.length - 6) % 6 !== 0)
9272
+ const p = record5.dataOffset;
9273
+ if (record5.opcode === 189) {
9274
+ if (record5.length < 12 || (record5.length - 6) % 6 !== 0)
8982
9275
  return unchanged("malformed-records");
8983
9276
  const first = view2.getUint16(p + 2, true);
8984
- const lastCol = view2.getUint16(p + record4.length - 2, true);
8985
- if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (record4.length - 6) / 6)
9277
+ const lastCol = view2.getUint16(p + record5.length - 2, true);
9278
+ if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (record5.length - 6) / 6)
8986
9279
  return unchanged("malformed-records");
8987
9280
  if (view2.getUint16(p, true) === edit.row && edit.col >= first && edit.col <= lastCol) {
8988
9281
  if (++matches > 1)
@@ -8990,26 +9283,26 @@ function editXlsNumericCell(input, edit) {
8990
9283
  payload = p + 6 + (edit.col - first) * 6;
8991
9284
  packed = true;
8992
9285
  }
8993
- } else if (record4.opcode === 515 || record4.opcode === 638) {
8994
- if (record4.length !== (record4.opcode === 515 ? 14 : 10))
9286
+ } else if (record5.opcode === 515 || record5.opcode === 638) {
9287
+ if (record5.length !== (record5.opcode === 515 ? 14 : 10))
8995
9288
  return unchanged("malformed-records");
8996
9289
  if (view2.getUint16(p, true) === edit.row && view2.getUint16(p + 2, true) === edit.col) {
8997
9290
  if (++matches > 1)
8998
9291
  return unchanged("ambiguous-cell");
8999
9292
  payload = p + 6;
9000
- packed = record4.opcode === 638;
9293
+ packed = record5.opcode === 638;
9001
9294
  }
9002
- } else if ([6, 513, 516, 517, 253, 214].includes(record4.opcode)) {
9003
- if (record4.length < 6)
9295
+ } else if ([6, 513, 516, 517, 253, 214].includes(record5.opcode)) {
9296
+ if (record5.length < 6)
9004
9297
  return unchanged("malformed-records");
9005
9298
  if (view2.getUint16(p, true) === edit.row && view2.getUint16(p + 2, true) === edit.col && ++matches > 1)
9006
9299
  return unchanged("ambiguous-cell");
9007
- } else if (record4.opcode === 190) {
9008
- if (record4.length < 8 || (record4.length - 6) % 2 !== 0)
9300
+ } else if (record5.opcode === 190) {
9301
+ if (record5.length < 8 || (record5.length - 6) % 2 !== 0)
9009
9302
  return unchanged("malformed-records");
9010
9303
  const first = view2.getUint16(p + 2, true);
9011
- const lastCol = view2.getUint16(p + record4.length - 2, true);
9012
- if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (record4.length - 6) / 2)
9304
+ const lastCol = view2.getUint16(p + record5.length - 2, true);
9305
+ if (lastCol > 255 || lastCol < first || lastCol - first + 1 !== (record5.length - 6) / 2)
9013
9306
  return unchanged("malformed-records");
9014
9307
  if (view2.getUint16(p, true) === edit.row && edit.col >= first && edit.col <= lastCol && ++matches > 1)
9015
9308
  return unchanged("ambiguous-cell");
@@ -9035,7 +9328,7 @@ function editXlsNumericCell(input, edit) {
9035
9328
  }
9036
9329
  }
9037
9330
 
9038
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-biff8.js
9331
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-biff8.js
9039
9332
  var OPCODE_BOF = 2057;
9040
9333
  var OPCODE_EOF = 10;
9041
9334
  var OPCODE_FILEPASS = 47;
@@ -9063,8 +9356,8 @@ function isSupportedBiff8Workbook(bytes) {
9063
9356
  const view2 = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
9064
9357
  if (view2.getUint16(bof.dataOffset, true) !== 1536 || view2.getUint16(bof.dataOffset + 2, true) !== 5)
9065
9358
  return false;
9066
- const globalsEnd = records.find((record4) => record4.opcode === OPCODE_EOF)?.headerOffset ?? bytes.length;
9067
- return !records.some((record4) => record4.opcode === OPCODE_FILEPASS && record4.headerOffset < globalsEnd);
9359
+ const globalsEnd = records.find((record5) => record5.opcode === OPCODE_EOF)?.headerOffset ?? bytes.length;
9360
+ return !records.some((record5) => record5.opcode === OPCODE_FILEPASS && record5.headerOffset < globalsEnd);
9068
9361
  }
9069
9362
  function decodeRk(rk) {
9070
9363
  const isInt = (rk & 2) !== 0;
@@ -9082,7 +9375,7 @@ function decodeRk(rk) {
9082
9375
  return isDiv100 ? value / 100 : value;
9083
9376
  }
9084
9377
 
9085
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-formulas.js
9378
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-formulas.js
9086
9379
  function readRefU(r) {
9087
9380
  return { firstRow: r.u16(), lastRow: r.u16(), firstCol: r.u8(), lastCol: r.u8() };
9088
9381
  }
@@ -9140,7 +9433,7 @@ function resolveFormulas(formulas, shared, arrays, globals) {
9140
9433
  }
9141
9434
  }
9142
9435
 
9143
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sheet-extras.js
9436
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sheet-extras.js
9144
9437
  function parseMergedCells(data) {
9145
9438
  const r = new ByteReader(data);
9146
9439
  const count = r.u16();
@@ -9318,11 +9611,11 @@ function parseObj(data) {
9318
9611
  r.skip(2);
9319
9612
  return { type: r.u16(), id: r.u16() };
9320
9613
  }
9321
- function parseTxoText(record4) {
9322
- const count = new ByteReader(record4.data, 10).u16();
9323
- if (count === 0 || record4.continues.length === 0)
9614
+ function parseTxoText(record5) {
9615
+ const count = new ByteReader(record5.data, 10).u16();
9616
+ if (count === 0 || record5.continues.length === 0)
9324
9617
  return "";
9325
- const reader = new SegmentReader(record4.continues);
9618
+ const reader = new SegmentReader(record5.continues);
9326
9619
  const wide = (reader.u8() & 1) !== 0;
9327
9620
  return reader.continuedChars(count, wide).replace(/\r\n?/g, "\n");
9328
9621
  }
@@ -9335,7 +9628,7 @@ function parseNote(data) {
9335
9628
  return { row, col, visible: (flags & 2) !== 0, id, author: r.xlString() };
9336
9629
  }
9337
9630
 
9338
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sheet.js
9631
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook-sheet.js
9339
9632
  var UNSUPPORTED = {
9340
9633
  432: "conditional formatting",
9341
9634
  2169: "conditional formatting",
@@ -9385,8 +9678,8 @@ function parseSheet(bound2, records, start, globals) {
9385
9678
  return result;
9386
9679
  };
9387
9680
  for (let index = start; index < records.length; index++) {
9388
- const record4 = records[index];
9389
- const { opcode, data } = record4;
9681
+ const record5 = records[index];
9682
+ const { opcode, data } = record5;
9390
9683
  if (opcode === 2057) {
9391
9684
  depth++;
9392
9685
  if (depth > 1)
@@ -9438,7 +9731,7 @@ function parseSheet(bound2, records, start, globals) {
9438
9731
  case 516:
9439
9732
  case 214: {
9440
9733
  const target = cell(r, "");
9441
- const reader = SegmentReader.of({ ...record4, data: data.subarray(6) });
9734
+ const reader = SegmentReader.of({ ...record5, data: data.subarray(6) });
9442
9735
  target.value = reader.xlString();
9443
9736
  break;
9444
9737
  }
@@ -9462,7 +9755,7 @@ function parseSheet(bound2, records, start, globals) {
9462
9755
  }
9463
9756
  case 519:
9464
9757
  if (stringTarget)
9465
- stringTarget.value = SegmentReader.of(record4).xlString();
9758
+ stringTarget.value = SegmentReader.of(record5).xlString();
9466
9759
  stringTarget = void 0;
9467
9760
  break;
9468
9761
  case 1212: {
@@ -9542,7 +9835,7 @@ function parseSheet(bound2, records, start, globals) {
9542
9835
  }
9543
9836
  case 438:
9544
9837
  if (lastObject?.type === 25)
9545
- texts.set(lastObject.id, parseTxoText(record4));
9838
+ texts.set(lastObject.id, parseTxoText(record5));
9546
9839
  break;
9547
9840
  case 28:
9548
9841
  notes.push(parseNote(data));
@@ -9591,7 +9884,7 @@ function parseSheet(bound2, records, start, globals) {
9591
9884
  return sheet;
9592
9885
  }
9593
9886
 
9594
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook.js
9887
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-workbook.js
9595
9888
  function compoundStreamNames(bytes) {
9596
9889
  if (!OLE_MAGIC.every((value, index) => bytes[index] === value))
9597
9890
  return [];
@@ -9605,12 +9898,12 @@ function compoundStreamNames(bytes) {
9605
9898
  function topLevelSubstreams(records) {
9606
9899
  const starts = [];
9607
9900
  let depth = 0;
9608
- records.forEach((record4, index) => {
9609
- if (record4.opcode === 2057) {
9901
+ records.forEach((record5, index) => {
9902
+ if (record5.opcode === 2057) {
9610
9903
  if (depth === 0 && index > 0)
9611
9904
  starts.push(index);
9612
9905
  depth++;
9613
- } else if (record4.opcode === 10)
9906
+ } else if (record5.opcode === 10)
9614
9907
  depth = Math.max(0, depth - 1);
9615
9908
  });
9616
9909
  return starts;
@@ -9633,7 +9926,7 @@ function readXlsWorkbook(bytes) {
9633
9926
  unsupported2.push("VBA macros");
9634
9927
  if (streams.some((name) => name === "_SX_DB_CUR") && !unsupported2.includes("pivot caches"))
9635
9928
  unsupported2.push("pivot caches");
9636
- const byOffset = new Map(records.map((record4, index) => [record4.offset, index]));
9929
+ const byOffset = new Map(records.map((record5, index) => [record5.offset, index]));
9637
9930
  const substreams = topLevelSubstreams(records);
9638
9931
  const sheets = globals.sheets.map((bound2, position) => {
9639
9932
  const start = byOffset.get(bound2.offset) ?? substreams[position];
@@ -9661,7 +9954,7 @@ function readXlsWorkbook(bytes) {
9661
9954
  };
9662
9955
  }
9663
9956
 
9664
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-sst.js
9957
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-sst.js
9665
9958
  var SstCursor = class {
9666
9959
  segments;
9667
9960
  segment = 0;
@@ -9784,7 +10077,7 @@ function appendXlsSstString(value) {
9784
10077
  return Uint8Array.from(records);
9785
10078
  }
9786
10079
 
9787
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-cell-record-splices.js
10080
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-cell-record-splices.js
9788
10081
  var CELL_OPS = /* @__PURE__ */ new Set([6, 513, 515, 516, 517, 638, 253, 189, 190, 214]);
9789
10082
  function record2(opcode, data) {
9790
10083
  const out = new Uint8Array(data.length + 4), view2 = new DataView(out.buffer);
@@ -9876,7 +10169,7 @@ function relocateXlsDbCells(input, out, records, replacement, map) {
9876
10169
  }
9877
10170
  }
9878
10171
 
9879
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-known-records.js
10172
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-known-records.js
9880
10173
  var KNOWN_XLS_RECORDS = /* @__PURE__ */ new Set([
9881
10174
  6,
9882
10175
  10,
@@ -10234,7 +10527,7 @@ var KNOWN_XLS_RECORDS = /* @__PURE__ */ new Set([
10234
10527
  ]);
10235
10528
  var XLS_FRT_WRAPPER = 2129;
10236
10529
 
10237
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-record-edit-model.js
10530
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-record-edit-model.js
10238
10531
  var EditError = class extends Error {
10239
10532
  reason;
10240
10533
  constructor(reason) {
@@ -10335,6 +10628,8 @@ function findTarget(bytes, m, edit, allowed = [253, 638, 515, 189]) {
10335
10628
  const first = view2.getUint16(p + 2, true), last = view2.getUint16(p + r.length - 2, true);
10336
10629
  if (last > 255 || last < first || last - first + 1 !== (r.length - 6) / stride)
10337
10630
  reject("malformed-records");
10631
+ if (r.opcode === 190 && (first > 254 || last <= first))
10632
+ reject("malformed-records");
10338
10633
  if (view2.getUint16(p, true) === edit.row && edit.col >= first && edit.col <= last)
10339
10634
  targets.push(r);
10340
10635
  }
@@ -10344,19 +10639,19 @@ function findTarget(bytes, m, edit, allowed = [253, 638, 515, 189]) {
10344
10639
  const target = targets[0];
10345
10640
  if (!target || !allowed.includes(target.opcode))
10346
10641
  reject("cell-not-supported");
10347
- if (target.opcode !== 189 && target.length !== (target.opcode === 515 ? 14 : target.opcode === 517 ? 8 : 10))
10642
+ if (target.opcode !== 189 && target.opcode !== 190 && target.length !== (target.opcode === 515 ? 14 : target.opcode === 517 ? 8 : target.opcode === 513 ? 6 : 10))
10348
10643
  reject("malformed-records");
10349
- for (const record4 of m.records.filter((r) => r.headerOffset >= range.start && r.headerOffset < range.end && r.depth === 1 && [545, 1212, 566].includes(r.opcode))) {
10350
- if (record4.length < 6)
10644
+ for (const record5 of m.records.filter((r) => r.headerOffset >= range.start && r.headerOffset < range.end && r.depth === 1 && [545, 1212, 566].includes(r.opcode))) {
10645
+ if (record5.length < 6)
10351
10646
  reject("malformed-records");
10352
- const p = record4.dataOffset;
10647
+ const p = record5.dataOffset;
10353
10648
  if (edit.row >= view2.getUint16(p, true) && edit.row <= view2.getUint16(p + 2, true) && edit.col >= view2.getUint8(p + 4) && edit.col <= view2.getUint8(p + 5))
10354
10649
  reject("cell-not-supported");
10355
10650
  }
10356
10651
  return target;
10357
10652
  }
10358
10653
 
10359
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-string-edit.js
10654
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-string-edit.js
10360
10655
  function extSst(entries, map) {
10361
10656
  const interval = Math.max(Math.floor(entries.length / 128) + 1, 8);
10362
10657
  const count = Math.ceil(entries.length / interval);
@@ -10468,18 +10763,18 @@ function editXlsStringWorkbookStream(input, edit) {
10468
10763
  view2.setUint32(map(sst.start) + 8, sst.entries.length + (index === sst.entries.length ? 1 : 0), true);
10469
10764
  if (splices.length) {
10470
10765
  const byOffset = new Map(m.records.map((r) => [r.headerOffset, r]));
10471
- for (const record4 of m.records) {
10472
- if (record4.opcode === 133 && (record4.headerOffset >= m.globalsEnd || record4.depth !== 1))
10766
+ for (const record5 of m.records) {
10767
+ if (record5.opcode === 133 && (record5.headerOffset >= m.globalsEnd || record5.depth !== 1))
10473
10768
  reject("malformed-records");
10474
- if (record4.opcode === 133)
10475
- view2.setUint32(map(record4.dataOffset), map(sourceView.getUint32(record4.dataOffset, true)), true);
10476
- if (record4.opcode === 523) {
10477
- if (record4.length < 16 || (record4.length - 16) % 4 !== 0)
10769
+ if (record5.opcode === 133)
10770
+ view2.setUint32(map(record5.dataOffset), map(sourceView.getUint32(record5.dataOffset, true)), true);
10771
+ if (record5.opcode === 523) {
10772
+ if (record5.length < 16 || (record5.length - 16) % 4 !== 0)
10478
10773
  reject("malformed-records");
10479
- for (let p = record4.dataOffset + 12; p < record4.dataOffset + record4.length; p += 4) {
10774
+ for (let p = record5.dataOffset + 12; p < record5.dataOffset + record5.length; p += 4) {
10480
10775
  const address = sourceView.getUint32(p, true);
10481
10776
  const pointed = byOffset.get(address);
10482
- if (!pointed || pointed.opcode !== (p === record4.dataOffset + 12 ? 85 : 215))
10777
+ if (!pointed || pointed.opcode !== (p === record5.dataOffset + 12 ? 85 : 215))
10483
10778
  reject("malformed-records");
10484
10779
  view2.setUint32(map(p), map(address), true);
10485
10780
  }
@@ -10492,7 +10787,7 @@ function editXlsStringWorkbookStream(input, edit) {
10492
10787
  }
10493
10788
  }
10494
10789
 
10495
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-string-cell.js
10790
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-preserved-string-cell.js
10496
10791
  function editXlsPreservedStringCell(input, edit) {
10497
10792
  if (!OLE_MAGIC.every((value, index) => input[index] === value))
10498
10793
  return editXlsStringWorkbookStream(input, edit);
@@ -10511,7 +10806,7 @@ function editXlsPreservedStringCell(input, edit) {
10511
10806
  return resized.ok ? { ...result, bytes: resized.bytes } : { status: "unchanged", bytes: input, reason: "container-not-writable" };
10512
10807
  }
10513
10808
 
10514
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-excel-bool-error-edit.js
10809
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-bool-error-edit.js
10515
10810
  var ERRORS = Object.freeze({
10516
10811
  "#NULL!": 0,
10517
10812
  "#DIV/0!": 7,
@@ -10522,6 +10817,9 @@ var ERRORS = Object.freeze({
10522
10817
  "#N/A": 42,
10523
10818
  "#GETTING_DATA": 43
10524
10819
  });
10820
+ function isValidXlsBoolErrorRecordValue(flag, value) {
10821
+ return flag === 0 && (value === 0 || value === 1) || flag === 1 && Object.values(ERRORS).includes(value);
10822
+ }
10525
10823
  function normalizeXlsErrorValue(value) {
10526
10824
  try {
10527
10825
  if (!value || typeof value !== "object" || Array.isArray(value))
@@ -10549,7 +10847,7 @@ function editXlsBoolErrorWorkbookStream(input, edit) {
10549
10847
  const source = new DataView(input.buffer, input.byteOffset, input.byteLength);
10550
10848
  if (target.opcode === 517) {
10551
10849
  const flag = source.getUint8(target.dataOffset + 7), value2 = source.getUint8(target.dataOffset + 6);
10552
- if (flag > 1 || (flag === 0 ? value2 > 1 : !Object.values(ERRORS).includes(value2)))
10850
+ if (!isValidXlsBoolErrorRecordValue(flag, value2))
10553
10851
  reject("malformed-records");
10554
10852
  }
10555
10853
  const data = new Uint8Array(12), view2 = new DataView(data.buffer);
@@ -10626,7 +10924,175 @@ function editXlsBoolErrorCell(input, edit) {
10626
10924
  return resized.ok ? { ...result, bytes: resized.bytes } : { status: "unchanged", bytes: input, reason: "container-not-writable" };
10627
10925
  }
10628
10926
 
10629
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/xls-document.js
10927
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-blank-record.js
10928
+ function record3(opcode, data) {
10929
+ const out = new Uint8Array(4 + data.length), view2 = new DataView(out.buffer);
10930
+ view2.setUint16(0, opcode, true);
10931
+ view2.setUint16(2, data.length, true);
10932
+ out.set(data, 4);
10933
+ return out;
10934
+ }
10935
+ function replaceXlsBlankRecord(input, target, col, value) {
10936
+ if (!Number.isInteger(col) || col < 0 || col > 255 || !Number.isFinite(value) || !Number.isSafeInteger(target.headerOffset) || target.headerOffset < 0 || target.dataOffset !== target.headerOffset + 4 || !Number.isInteger(target.length) || target.length < 6 || target.dataOffset + target.length > input.length || ![513, 190].includes(target.opcode))
10937
+ throw new Error("Invalid blank record replacement");
10938
+ const view2 = new DataView(input.buffer, input.byteOffset, input.byteLength), p = target.dataOffset;
10939
+ if (view2.getUint16(target.headerOffset, true) !== target.opcode || view2.getUint16(target.headerOffset + 2, true) !== target.length)
10940
+ throw new Error("Blank record framing mismatch");
10941
+ const packed = target.opcode === 190;
10942
+ if (packed ? target.length < 10 || (target.length - 6) % 2 !== 0 : target.length !== 6)
10943
+ throw new Error("Invalid blank record length");
10944
+ const row = view2.getUint16(p, true), first = view2.getUint16(p + 2, true), count = packed ? (target.length - 6) / 2 : 1;
10945
+ const selected = col - first;
10946
+ if (first > 255 || first + count - 1 > 255 || selected < 0 || selected >= count || packed && view2.getUint16(p + target.length - 2, true) !== first + count - 1)
10947
+ throw new Error("Invalid blank column range");
10948
+ const data = new Uint8Array(14), cell = new DataView(data.buffer);
10949
+ cell.setUint16(0, row, true);
10950
+ cell.setUint16(2, col, true);
10951
+ cell.setUint16(4, view2.getUint16(p + 4 + (packed ? selected * 2 : 0), true), true);
10952
+ cell.setFloat64(6, value, true);
10953
+ const number2 = record3(515, data);
10954
+ const group = (start, size) => {
10955
+ if (!size)
10956
+ return new Uint8Array();
10957
+ const data2 = new Uint8Array(size === 1 ? 6 : 6 + size * 2), groupView = new DataView(data2.buffer);
10958
+ groupView.setUint16(0, row, true);
10959
+ groupView.setUint16(2, first + start, true);
10960
+ data2.set(input.subarray(p + 4 + start * 2, p + 4 + (start + size) * 2), 4);
10961
+ if (size > 1)
10962
+ groupView.setUint16(data2.length - 2, first + start + size - 1, true);
10963
+ return record3(size === 1 ? 513 : 190, data2);
10964
+ };
10965
+ const prefix = packed ? group(0, selected) : new Uint8Array(), suffix = packed ? group(selected + 1, count - selected - 1) : new Uint8Array();
10966
+ const bytes = new Uint8Array(prefix.length + number2.length + suffix.length);
10967
+ bytes.set(prefix);
10968
+ bytes.set(number2, prefix.length);
10969
+ bytes.set(suffix, prefix.length + number2.length);
10970
+ return { start: target.headerOffset, end: p + target.length, bytes };
10971
+ }
10972
+
10973
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-stored-cell-edit.js
10974
+ function applyXlsCellRecordReplacement(input, m, replacement) {
10975
+ if (!Number.isSafeInteger(replacement.start) || !Number.isSafeInteger(replacement.end) || replacement.start < 0 || replacement.end <= replacement.start || replacement.end > input.length || !(replacement.bytes instanceof Uint8Array))
10976
+ reject("malformed-records");
10977
+ const target = m.records.find((r) => r.headerOffset === replacement.start);
10978
+ if (!target || target.dataOffset + target.length !== replacement.end || ![513, 190, 517].includes(target.opcode))
10979
+ reject("malformed-records");
10980
+ const delta = replacement.bytes.length - (replacement.end - replacement.start);
10981
+ if (delta !== 0 && m.records.some((r) => !KNOWN_XLS_RECORDS.has(r.opcode) || r.opcode === XLS_FRT_WRAPPER))
10982
+ reject("unsupported-pointer-record");
10983
+ const map = (address) => {
10984
+ if (!Number.isSafeInteger(address) || address < 0 || address > input.length || address > replacement.start && address < replacement.end)
10985
+ reject("malformed-records");
10986
+ return address >= replacement.end ? address + delta : address;
10987
+ };
10988
+ const out = new Uint8Array(input.length + delta);
10989
+ out.set(input.subarray(0, replacement.start));
10990
+ out.set(replacement.bytes, replacement.start);
10991
+ out.set(input.subarray(replacement.end), replacement.start + replacement.bytes.length);
10992
+ if (delta !== 0) {
10993
+ relocateXlsDbCells(input, out, m.records, replacement, map);
10994
+ const source = new DataView(input.buffer, input.byteOffset, input.byteLength), dest = new DataView(out.buffer), byOffset = new Map(m.records.map((r) => [r.headerOffset, r]));
10995
+ for (const r of m.records) {
10996
+ if (r.opcode === 133) {
10997
+ if (r.headerOffset >= m.globalsEnd || r.depth !== 1)
10998
+ reject("malformed-records");
10999
+ dest.setUint32(map(r.dataOffset), map(source.getUint32(r.dataOffset, true)), true);
11000
+ }
11001
+ if (r.opcode === 523) {
11002
+ if (r.length < 16 || (r.length - 16) % 4 !== 0)
11003
+ reject("malformed-records");
11004
+ const owner = m.worksheets.find((sheet) => r.depth === 1 && r.headerOffset >= sheet.start && r.headerOffset < sheet.end);
11005
+ if (!owner)
11006
+ reject("malformed-records");
11007
+ const pointers = /* @__PURE__ */ new Set();
11008
+ for (let p = r.dataOffset + 12; p < r.dataOffset + r.length; p += 4) {
11009
+ const address = source.getUint32(p, true);
11010
+ const pointed = byOffset.get(address);
11011
+ if (pointed?.opcode !== (p === r.dataOffset + 12 ? 85 : 215) || pointed.depth !== 1 || address < owner.start || address >= owner.end)
11012
+ reject("malformed-records");
11013
+ if (pointers.has(address))
11014
+ reject("malformed-records");
11015
+ pointers.add(address);
11016
+ dest.setUint32(map(p), map(address), true);
11017
+ }
11018
+ }
11019
+ }
11020
+ }
11021
+ return out;
11022
+ }
11023
+ function editXlsStoredCellWorkbookStream(input, edit, sourceKind) {
11024
+ const unchanged = (reason) => ({ status: "unchanged", bytes: input, reason });
11025
+ const row = edit.row, col = edit.col, worksheetIndex = edit.worksheetIndex ?? 0, supplied = edit.value;
11026
+ const value = supplied !== null && typeof supplied === "object" ? normalizeXlsErrorValue(supplied) : supplied;
11027
+ if (!["blank", "bool-error"].includes(sourceKind) || !Number.isInteger(row) || row < 0 || row > 65535 || !Number.isInteger(col) || col < 0 || col > 255 || !Number.isInteger(worksheetIndex) || worksheetIndex < 0 || sourceKind === "bool-error" && typeof value !== "number" && typeof value !== "string" || (typeof value === "number" ? !Number.isFinite(value) : typeof value !== "string" && typeof value !== "boolean" && (value === void 0 || value === null || typeof value !== "object")))
11028
+ return unchanged("invalid-edit");
11029
+ try {
11030
+ const m = model(input), target = findTarget(input, m, { row, col, worksheetIndex }, sourceKind === "blank" ? [513, 190] : [517]);
11031
+ const range = m.worksheets[worksheetIndex], source = new DataView(input.buffer, input.byteOffset, input.byteLength);
11032
+ for (const record5 of m.records.filter((r) => r.opcode === 229 && r.depth === 1 && r.headerOffset >= range.start && r.headerOffset < range.end)) {
11033
+ if (record5.length < 2)
11034
+ reject("malformed-records");
11035
+ const count = source.getUint16(record5.dataOffset, true);
11036
+ if (record5.length !== 2 + count * 8)
11037
+ reject("malformed-records");
11038
+ for (let p = record5.dataOffset + 2; p < record5.dataOffset + record5.length; p += 8) {
11039
+ const firstRow = source.getUint16(p, true), lastRow = source.getUint16(p + 2, true), firstCol = source.getUint16(p + 4, true), lastCol = source.getUint16(p + 6, true);
11040
+ if (firstRow > lastRow || firstCol > lastCol || lastCol > 255)
11041
+ reject("malformed-records");
11042
+ if (row >= firstRow && row <= lastRow && col >= firstCol && col <= lastCol && (row !== firstRow || col !== firstCol))
11043
+ reject("cell-not-supported");
11044
+ }
11045
+ }
11046
+ let replacement;
11047
+ if (sourceKind === "blank")
11048
+ replacement = replaceXlsBlankRecord(input, target, col, typeof value === "number" ? value : 0);
11049
+ else {
11050
+ if (!isValidXlsBoolErrorRecordValue(source.getUint8(target.dataOffset + 7), source.getUint8(target.dataOffset + 6)))
11051
+ reject("malformed-records");
11052
+ const bytes = new Uint8Array(18), number2 = new DataView(bytes.buffer);
11053
+ number2.setUint16(0, 515, true);
11054
+ number2.setUint16(2, 14, true);
11055
+ bytes.set(input.subarray(target.dataOffset, target.dataOffset + 6), 4);
11056
+ number2.setFloat64(10, typeof value === "number" ? value : 0, true);
11057
+ replacement = { start: target.headerOffset, end: target.dataOffset + target.length, bytes };
11058
+ }
11059
+ const staged = applyXlsCellRecordReplacement(input, m, replacement);
11060
+ if (typeof value === "number")
11061
+ return { status: "edited", bytes: staged, recalculationRequired: true };
11062
+ const result = typeof value === "string" ? editXlsStringWorkbookStream(staged, { row, col, worksheetIndex, value }) : editXlsBoolErrorWorkbookStream(staged, { row, col, worksheetIndex, value });
11063
+ return result.status === "edited" ? result : { ...result, bytes: input };
11064
+ } catch (error) {
11065
+ return unchanged(error instanceof EditError ? error.reason : "malformed-records");
11066
+ }
11067
+ }
11068
+ function editXlsStoredCell(input, edit, sourceKind) {
11069
+ if (!OLE_MAGIC.every((value, index) => input[index] === value))
11070
+ return editXlsStoredCellWorkbookStream(input, edit, sourceKind);
11071
+ const streams = ["Workbook", "Book"].map((name) => ({ name, bytes: readCompoundFileStream(input, [name]) })).filter((s) => s.bytes !== void 0);
11072
+ if (streams.length !== 1)
11073
+ return { status: "unchanged", bytes: input, reason: "unsupported-workbook" };
11074
+ const stream = streams[0], result = editXlsStoredCellWorkbookStream(stream.bytes, edit, sourceKind);
11075
+ if (result.status !== "edited")
11076
+ return { ...result, bytes: input };
11077
+ if (result.bytes.length === stream.bytes.length) {
11078
+ const bytes = replaceCompoundFileStream(input, [stream.name], result.bytes);
11079
+ return bytes === input ? { status: "unchanged", bytes: input, reason: "container-not-writable" } : { ...result, bytes };
11080
+ }
11081
+ const resized = resizeCompoundFileStream(input, [stream.name], result.bytes);
11082
+ return resized.ok ? { ...result, bytes: resized.bytes } : { status: "unchanged", bytes: input, reason: "container-not-writable" };
11083
+ }
11084
+
11085
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-blank-edit.js
11086
+ function editXlsBlankCell(input, edit) {
11087
+ return editXlsStoredCell(input, edit, "blank");
11088
+ }
11089
+
11090
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-excel-bool-error-conversion.js
11091
+ function editXlsBoolErrorScalarCell(input, edit) {
11092
+ return editXlsStoredCell(input, edit, "bool-error");
11093
+ }
11094
+
11095
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/xls-document.js
10630
11096
  function cellType(cell) {
10631
11097
  if (cell.formula !== void 0 || cell.formulaUndecoded || cell.arrayRange || cell.sharedFormula)
10632
11098
  return "formula";
@@ -10726,8 +11192,8 @@ var XlsSheetNode = class {
10726
11192
  };
10727
11193
  var XLS_CAPABILITIES = Object.freeze({
10728
11194
  read: Object.freeze(["BIFF8 worksheets", "cell values and cached formulas", "styles and merges", "opaque compound streams"]),
10729
- write: Object.freeze(["existing NUMBER/RK/MULRK numeric values", "existing LABELSST/NUMBER/RK/MULRK plain string values", "existing NUMBER/RK/MULRK/BOOLERR boolean and error values"]),
10730
- limitations: Object.freeze(["No cell creation, formula editing or recalculation", "Numeric writes require exact original encoding", "Resizing writes reject unsupported relocation records and container layouts", "Plain string replacement removes selected rich text runs", "String-to-boolean/error and boolean/error-to-number/string conversions unsupported"])
11195
+ write: Object.freeze(["existing NUMBER/RK/MULRK numeric values", "existing LABELSST/NUMBER/RK/MULRK plain string values", "existing NUMBER/RK/MULRK/BOOLERR boolean and error values", "existing BLANK/MULBLANK cells to number, plain string, boolean or error values", "existing BOOLERR cells to finite number or plain string values"]),
11196
+ limitations: Object.freeze(["No implicit cell creation, formula editing or recalculation", "Numeric replacement of existing numeric cells requires exact original encoding", "Resizing writes reject unsupported relocation records and container layouts", "Plain string replacement removes selected rich text runs", "String-to-boolean/error conversions unsupported"])
10731
11197
  });
10732
11198
  var XlsDocument = class extends Ole2DocumentBase {
10733
11199
  get kind() {
@@ -10742,6 +11208,7 @@ var XlsDocument = class extends Ole2DocumentBase {
10742
11208
  }
10743
11209
  #model;
10744
11210
  #needsRecalculation = false;
11211
+ #settingCellValue = false;
10745
11212
  constructor(input) {
10746
11213
  super(input);
10747
11214
  const bytes = this.getBytes();
@@ -10772,6 +11239,16 @@ var XlsDocument = class extends Ole2DocumentBase {
10772
11239
  }
10773
11240
  /** @internal All changes are validated and parsed before committing bytes. */
10774
11241
  setCellValue(sheetIndex, row, col, value) {
11242
+ if (this.#settingCellValue)
11243
+ throw new UnsupportedOle2EditError("reentrant-cell-edit");
11244
+ this.#settingCellValue = true;
11245
+ try {
11246
+ this.#applyCellValue(sheetIndex, row, col, value);
11247
+ } finally {
11248
+ this.#settingCellValue = false;
11249
+ }
11250
+ }
11251
+ #applyCellValue(sheetIndex, row, col, value) {
10775
11252
  if (value !== null && typeof value === "object") {
10776
11253
  const normalized = normalizeXlsErrorValue(value);
10777
11254
  if (!normalized)
@@ -10784,13 +11261,14 @@ var XlsDocument = class extends Ole2DocumentBase {
10784
11261
  const sheet = this.#model.sheets[sheetIndex];
10785
11262
  if (sheet?.kind !== "worksheet")
10786
11263
  throw new UnsupportedOle2EditError("sheet-not-supported");
10787
- if (cell.value === null)
10788
- throw new UnsupportedOle2EditError("cell-type-not-supported");
11264
+ if (cell.value === null && value === null)
11265
+ return;
10789
11266
  if (typeof value !== "number" && typeof value !== "string" && typeof value !== "boolean" && !isXlsErrorValue(value))
10790
11267
  throw new UnsupportedOle2EditError("value-type-not-supported");
10791
- if (typeof value === "number" && (typeof cell.value !== "number" || !Number.isFinite(value)))
11268
+ const boolError = typeof cell.value === "boolean" || isXlsErrorValue(cell.value);
11269
+ if (typeof value === "number" && (cell.value !== null && typeof cell.value !== "number" && !boolError || !Number.isFinite(value)))
10792
11270
  throw new UnsupportedOle2EditError("numeric-type-change-not-supported");
10793
- if (typeof value === "string" && typeof cell.value !== "number" && typeof cell.value !== "string")
11271
+ if (typeof value === "string" && cell.value !== null && typeof cell.value !== "number" && typeof cell.value !== "string" && !boolError)
10794
11272
  throw new UnsupportedOle2EditError("string-type-change-not-supported");
10795
11273
  if ((typeof value === "boolean" || isXlsErrorValue(value)) && typeof cell.value === "string")
10796
11274
  throw new UnsupportedOle2EditError("bool-error-type-change-not-supported");
@@ -10798,7 +11276,7 @@ var XlsDocument = class extends Ole2DocumentBase {
10798
11276
  return;
10799
11277
  const worksheetIndex = this.#model.sheets.slice(0, sheetIndex).filter((s) => s.kind === "worksheet").length;
10800
11278
  const edit = { row, col, value, worksheetIndex };
10801
- const result = typeof value === "number" ? editXlsNumericCell(this.getBytes(), { ...edit, value }) : typeof value === "string" ? editXlsPreservedStringCell(this.getBytes(), { ...edit, value }) : editXlsBoolErrorCell(this.getBytes(), { ...edit, value });
11279
+ const result = cell.value === null ? editXlsBlankCell(this.getBytes(), { ...edit, value }) : boolError && (typeof value === "number" || typeof value === "string") ? editXlsBoolErrorScalarCell(this.getBytes(), { ...edit, value }) : typeof value === "number" ? editXlsNumericCell(this.getBytes(), { ...edit, value }) : typeof value === "string" ? editXlsPreservedStringCell(this.getBytes(), { ...edit, value }) : editXlsBoolErrorCell(this.getBytes(), { ...edit, value });
10802
11280
  if (result.status !== "edited")
10803
11281
  throw new UnsupportedOle2EditError(result.reason);
10804
11282
  const next = readXlsWorkbook(result.bytes);
@@ -10811,7 +11289,7 @@ var XlsDocument = class extends Ole2DocumentBase {
10811
11289
  }
10812
11290
  };
10813
11291
 
10814
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-ppt-record-stream.js
11292
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-record-stream.js
10815
11293
  var PptParseError = class extends Error {
10816
11294
  constructor(message) {
10817
11295
  super(message);
@@ -10845,18 +11323,88 @@ function readRecordOrThrow(view2, offset) {
10845
11323
  return rec;
10846
11324
  }
10847
11325
 
10848
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-ppt-record-types.js
11326
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-record-types.js
10849
11327
  var RT2 = {
10850
11328
  Document: 1e3,
11329
+ DocumentAtom: 1001,
11330
+ EndDocumentAtom: 1002,
10851
11331
  Slide: 1006,
11332
+ SlideAtom: 1007,
11333
+ Notes: 1008,
11334
+ NotesAtom: 1009,
11335
+ Environment: 1010,
10852
11336
  SlidePersistAtom: 1011,
11337
+ MainMaster: 1016,
11338
+ SlideShowSlideInfoAtom: 1017,
11339
+ SlideViewInfo: 1018,
11340
+ ExternalObjectList: 1033,
11341
+ ExternalObjectListAtom: 1034,
11342
+ DrawingGroup: 1035,
11343
+ Drawing: 1036,
11344
+ List: 2e3,
11345
+ FontCollection: 2005,
11346
+ SoundCollection: 2020,
11347
+ SoundCollectionAtom: 2021,
11348
+ Sound: 2022,
11349
+ SoundDataBlob: 2023,
11350
+ ColorSchemeAtom: 2032,
11351
+ ExternalObjectRefAtom: 3009,
11352
+ OEPlaceholderAtom: 3011,
11353
+ RoundTripSlideSyncInfo12: 3012,
10853
11354
  OutlineTextRefAtom: 3998,
11355
+ TextHeaderAtom: 3999,
10854
11356
  TextCharsAtom: 4e3,
11357
+ StyleTextPropAtom: 4001,
11358
+ MasterTextPropAtom: 4002,
11359
+ TextMasterStyleAtom: 4003,
10855
11360
  TextBytesAtom: 4008,
11361
+ TextSpecInfoAtom: 4010,
11362
+ CString: 4026,
11363
+ ExternalOleObjectAtom: 4035,
11364
+ ExternalOleEmbed: 4044,
11365
+ ExternalOleEmbedAtom: 4045,
11366
+ ExternalHyperlinkAtom: 4051,
11367
+ ExternalHyperlink: 4055,
11368
+ ExternalOleObjectStg: 4113,
11369
+ /** [MS-PPT] 2.10.6: information about external audio/video data (exObjId + loop/rewind/narration flags). */
11370
+ ExternalMediaAtom: 4100,
11371
+ /** [MS-PPT] 2.10.5: wraps an ExMediaAtom + optional UncOrLocalPathAtom for a linked video file. */
11372
+ ExternalVideo: 4101,
11373
+ /** [MS-PPT] 2.10.4: wraps an ExVideoContainer for a linked AVI movie. */
11374
+ ExternalAviMovie: 4102,
11375
+ /** [MS-PPT] 2.10.3: wraps an ExVideoContainer for a linked (generic/MCI-played) movie; what real
11376
+ * PowerPoint 16.0 writes for a linked non-AVI video file (COM-verified). */
11377
+ ExternalMciMovie: 4103,
11378
+ /** [MS-PPT] 2.10.8: wraps an ExMediaAtom + ExWAVAudioEmbeddedAtom referencing a SoundCollection entry. */
11379
+ ExternalWavAudioEmbedded: 4111,
11380
+ /** [MS-PPT] 2.10.9: soundIdRef (into SoundCollectionContainer) + soundLength (ms). recVer/recInstance = 0x1/0x001. */
11381
+ ExternalWavAudioEmbeddedAtom: 4115,
11382
+ TextInteractiveInfoAtom: 4063,
10856
11383
  SlideListWithText: 4080,
11384
+ InteractiveInfo: 4082,
11385
+ InteractiveInfoAtom: 4083,
10857
11386
  UserEditAtom: 4085,
10858
11387
  CurrentUserAtom: 4086,
10859
- PersistDirectoryAtom: 6002};
11388
+ FontEntityAtom: 4023,
11389
+ CryptSession10Container: 12052,
11390
+ PersistDirectoryAtom: 6002,
11391
+ HeadersFooters: 4057,
11392
+ HeadersFootersAtom: 4058,
11393
+ ProgTags: 5e3,
11394
+ ProgBinaryTag: 5002,
11395
+ BinaryTagDataBlob: 5003,
11396
+ RoundTripCustomTableStyles12Atom: 17036,
11397
+ /** [MS-PPT] 2.11.21: a master's theme as a zipped OOXML package. */
11398
+ RoundTripTheme12Atom: 1038,
11399
+ /** [MS-PPT] 2.11.19: a master's `a:clrMap` as an XML string. */
11400
+ RoundTripColorMapping12Atom: 1039,
11401
+ /** [MS-PPT] 2.11.22: a master's `p:txStyles` as a zipped OOXML package. */
11402
+ RoundTripOArtTextStyles12Atom: 1059,
11403
+ /** [MS-PPT] 2.9.28: a date field (`*`) in a master date placeholder. */
11404
+ GenericDateMCAtom: 4088,
11405
+ /** [MS-PPT] 2.9.25: a slide-number field (`*`) in a placeholder. */
11406
+ SlideNumberMCAtom: 4056
11407
+ };
10860
11408
  var OA = {
10861
11409
  SpgrContainer: 61443,
10862
11410
  SpContainer: 61444,
@@ -10870,7 +11418,7 @@ var OA = {
10870
11418
  var HEADER_TOKEN_PLAIN = 3817979999;
10871
11419
  var HEADER_TOKEN_ENCRYPTED = 4090610911;
10872
11420
 
10873
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ppt/persist-directory.js
11421
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ppt/persist-directory.js
10874
11422
  var DEFAULT_MAX_EDITS = 1e4;
10875
11423
  var DEFAULT_MAX_ENTRIES = 1e6;
10876
11424
  function checkedLimit(value) {
@@ -10987,7 +11535,7 @@ function buildPersistDirectory(view2, offsetToCurrentEdit, limits = {}) {
10987
11535
  return { currentEdit: edits[0], directory };
10988
11536
  }
10989
11537
 
10990
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-ppt-text.js
11538
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-text.js
10991
11539
  var PptTextError = class extends PptParseError {
10992
11540
  code;
10993
11541
  constructor(code, message) {
@@ -11062,7 +11610,7 @@ function inlineText(view2, parent) {
11062
11610
  }
11063
11611
  return { texts: result.sort((a, b) => a.headerOffset - b.headerOffset), mirrors };
11064
11612
  }
11065
- function inspect3(input) {
11613
+ function inspect4(input) {
11066
11614
  const current = readCompoundFileStream(input, ["Current User"]);
11067
11615
  const stream = readCompoundFileStream(input, ["PowerPoint Document"]);
11068
11616
  if (!current || !stream)
@@ -11140,19 +11688,69 @@ function inspect3(input) {
11140
11688
  }
11141
11689
  function readPptSlideTexts(input) {
11142
11690
  try {
11143
- return inspect3(input).model;
11691
+ return inspect4(input).model;
11144
11692
  } catch (error) {
11145
11693
  if (error instanceof PptTextError)
11146
11694
  throw error;
11147
11695
  throw new PptTextError("corrupt", error instanceof Error ? error.message : "Malformed PPT");
11148
11696
  }
11149
11697
  }
11698
+ function textOwnershipRefusal(input, stream, persistId, atom) {
11699
+ const user = readCompoundFileStream(input, ["Current User"]);
11700
+ if (!user)
11701
+ throw new PptParseError("Missing Current User stream");
11702
+ const view2 = viewOf(stream), uv = viewOf(user), cu = readRecordOrThrow(uv, 0);
11703
+ const editOffset = uv.getUint32(cu.dataOffset + 8, true);
11704
+ const { directory, currentEdit } = buildPersistDirectory(view2, editOffset);
11705
+ const slideOffset = directory.get(persistId);
11706
+ if (slideOffset === void 0)
11707
+ return "Missing active slide persist object";
11708
+ const slide = readRecordOrThrow(view2, slideOffset), text = readRecordOrThrow(view2, atom.headerOffset);
11709
+ const textEnd = text.dataOffset + text.recLen;
11710
+ const owners = [persistId];
11711
+ if (atom.headerOffset < slide.dataOffset || textEnd > slide.dataOffset + slide.recLen) {
11712
+ const docOffset = directory.get(currentEdit.docPersistIdRef);
11713
+ if (docOffset === void 0)
11714
+ return "Missing outline text owner";
11715
+ const doc = readRecordOrThrow(view2, docOffset);
11716
+ if (atom.headerOffset < doc.dataOffset || textEnd > doc.dataOffset + doc.recLen)
11717
+ return "Text is outside its active owning containers";
11718
+ owners.push(currentEdit.docPersistIdRef);
11719
+ }
11720
+ for (const ownerId of owners) {
11721
+ const owned = readRecordOrThrow(view2, directory.get(ownerId));
11722
+ const start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
11723
+ if (end > view2.byteLength)
11724
+ return "Unbounded text owning persist object";
11725
+ const overlaps = (offset) => {
11726
+ const other = readRecordOrThrow(view2, offset), otherEnd = other.dataOffset + other.recLen;
11727
+ if (otherEnd > view2.byteLength)
11728
+ throw new PptParseError("Unbounded live persist object prevents safe text edit");
11729
+ return start < otherEnd && other.headerOffset < end;
11730
+ };
11731
+ for (const [id, offset] of directory)
11732
+ if (id !== ownerId && overlaps(offset))
11733
+ return "Text owning container overlaps another live persist object";
11734
+ const visited = /* @__PURE__ */ new Set();
11735
+ for (let offset = editOffset; offset; ) {
11736
+ if (visited.has(offset) || visited.size >= 1e4)
11737
+ return "Invalid text save-history ownership";
11738
+ visited.add(offset);
11739
+ const edit = parseUserEditAtom(view2, offset);
11740
+ if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
11741
+ return "Text owning container overlaps save-history metadata";
11742
+ offset = edit.offsetLastEdit;
11743
+ }
11744
+ }
11745
+ return void 0;
11746
+ }
11150
11747
  function editPptSlideText(input, edit) {
11151
11748
  const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
11152
11749
  try {
11750
+ edit = { slideIndex: edit.slideIndex, textIndex: edit.textIndex, expectedText: edit.expectedText, text: edit.text };
11153
11751
  if (!Number.isSafeInteger(edit.slideIndex) || !Number.isSafeInteger(edit.textIndex) || edit.slideIndex < 0 || edit.textIndex < 0)
11154
11752
  return reject2("Invalid text location");
11155
- const { stream, model: model2, mirroredAtoms } = inspect3(input);
11753
+ const { stream, model: model2, mirroredAtoms } = inspect4(input);
11156
11754
  const atom = model2.slides[edit.slideIndex]?.texts[edit.textIndex];
11157
11755
  if (!atom || atom.text !== edit.expectedText)
11158
11756
  return reject2("Text location or expected text does not match");
@@ -11175,6 +11773,9 @@ function editPptSlideText(input, edit) {
11175
11773
  if (value >= 56320 && value <= 57343 && !(edit.text.charCodeAt(i - 1) >= 55296 && edit.text.charCodeAt(i - 1) <= 56319))
11176
11774
  return reject2("Unpaired UTF-16 surrogate");
11177
11775
  }
11776
+ const ownership = textOwnershipRefusal(input, stream, model2.slides[edit.slideIndex].persistId, atom);
11777
+ if (ownership)
11778
+ return reject2(ownership);
11178
11779
  const output = stream.slice(), view2 = viewOf(output), start = atom.headerOffset + 8;
11179
11780
  for (let i = 0; i < edit.text.length; i++) {
11180
11781
  if (atom.encoding === "utf16")
@@ -11189,7 +11790,7 @@ function editPptSlideText(input, edit) {
11189
11790
  }
11190
11791
  }
11191
11792
 
11192
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-ppt-shape-reader.js
11793
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-shape-reader.js
11193
11794
  var DEFAULT_LIMITS = { maxRecords: 1e5, maxShapes: 1e4, maxProperties: 1e5, maxNameChars: 1e6, maxTextBytes: 16 * 1024 * 1024 };
11194
11795
  var GEOMETRY_PROPERTY_IDS = /* @__PURE__ */ new Set([4, 127, 128, 191, 385, 447, 448, 459, 511, 896, 959]);
11195
11796
  function pptShapeChildren(view2, parent) {
@@ -11229,13 +11830,13 @@ function readPptSlideShapes(input, limits = {}) {
11229
11830
  if (documentOffset === void 0)
11230
11831
  throw new PptTextError("corrupt", "Missing active document");
11231
11832
  const documentRecord = readRecordOrThrow(view2, documentOffset);
11232
- const slideOffsets = [], activeLists = pptShapeChildren(view2, documentRecord).filter((record4) => record4.recType === RT2.SlideListWithText && record4.recInstance === 0);
11833
+ const slideOffsets = [], activeLists = pptShapeChildren(view2, documentRecord).filter((record5) => record5.recType === RT2.SlideListWithText && record5.recInstance === 0);
11233
11834
  for (const list of activeLists)
11234
- for (const record4 of pptShapeChildren(view2, list))
11235
- if (record4.recType === RT2.SlidePersistAtom) {
11236
- if (record4.recLen !== 20)
11835
+ for (const record5 of pptShapeChildren(view2, list))
11836
+ if (record5.recType === RT2.SlidePersistAtom) {
11837
+ if (record5.recLen !== 20)
11237
11838
  throw new PptTextError("corrupt", "Invalid slide persist atom");
11238
- const offset = chain2.directory.get(view2.getUint32(record4.dataOffset, true));
11839
+ const offset = chain2.directory.get(view2.getUint32(record5.dataOffset, true));
11239
11840
  if (offset === void 0)
11240
11841
  throw new PptTextError("corrupt", "Missing active slide");
11241
11842
  slideOffsets.push(offset);
@@ -11280,9 +11881,9 @@ function readPptSlideShapes(input, limits = {}) {
11280
11881
  const item = stack.pop();
11281
11882
  if (item.depth > 128)
11282
11883
  throw new PptTextError("corrupt", "Shape nesting exceeds limit");
11283
- const children3 = pptShapeChildren(view2, item.rec);
11884
+ const children4 = pptShapeChildren(view2, item.rec);
11284
11885
  if (item.rec.recType === OA.SpContainer) {
11285
- const fsps = children3.filter((rec) => rec.recType === OA.FSP);
11886
+ const fsps = children4.filter((rec) => rec.recType === OA.FSP);
11286
11887
  if (fsps.length !== 1 || fsps[0].recVer !== 2 || fsps[0].recLen !== 8)
11287
11888
  throw new PptTextError("corrupt", "Missing or ambiguous OfficeArtFSP");
11288
11889
  const fsp = fsps[0], shapeId = view2.getUint32(fsp.dataOffset, true), flags = view2.getUint32(fsp.dataOffset + 4, true);
@@ -11307,7 +11908,7 @@ function readPptSlideShapes(input, limits = {}) {
11307
11908
  };
11308
11909
  let propertyAmbiguity = false, unknownProperties = false, protectedGeometry = false, unknownTextFit = false;
11309
11910
  const seenProperties = /* @__PURE__ */ new Set();
11310
- const anchors = children3.filter((rec) => rec.recType === OA.ClientAnchor || rec.recType === OA.ChildAnchor);
11911
+ const anchors = children4.filter((rec) => rec.recType === OA.ClientAnchor || rec.recType === OA.ChildAnchor);
11311
11912
  if (anchors.length === 1) {
11312
11913
  const rec = anchors[0];
11313
11914
  if (rec.recVer !== 0 || rec.recInstance !== 0 || (rec.recType === OA.ClientAnchor ? rec.recLen !== 8 && rec.recLen !== 16 : rec.recLen !== 16))
@@ -11321,13 +11922,13 @@ function readPptSlideShapes(input, limits = {}) {
11321
11922
  };
11322
11923
  shape.coordinateSpace = largeClient ? "unknown" : rec.recType === OA.ChildAnchor ? "group-child-master-units" : item.group !== void 0 || flags & 2 ? "unknown" : "slide-master-units";
11323
11924
  }
11324
- const group = children3.find((rec) => rec.recType === OA.FSPGR);
11925
+ const group = children4.find((rec) => rec.recType === OA.FSPGR);
11325
11926
  if (group) {
11326
11927
  if (group.recVer !== 1 || group.recLen !== 16)
11327
11928
  throw new PptTextError("corrupt", "Invalid group coordinate space");
11328
11929
  shape.groupBounds = bounds(view2, group);
11329
11930
  }
11330
- for (const rec of children3.filter((rec2) => rec2.recType === OA.FOPT || rec2.recType === OA.TertiaryFOPT || rec2.recType === 61729)) {
11931
+ for (const rec of children4.filter((rec2) => rec2.recType === OA.FOPT || rec2.recType === OA.TertiaryFOPT || rec2.recType === 61729)) {
11331
11932
  if (rec.recVer !== 3 || rec.recInstance * 6 > rec.recLen)
11332
11933
  throw new PptTextError("corrupt", "Invalid shape property table");
11333
11934
  let complexOffset = rec.dataOffset + rec.recInstance * 6;
@@ -11365,7 +11966,7 @@ function readPptSlideShapes(input, limits = {}) {
11365
11966
  shape.textIndexes = slide.texts.flatMap((atom, index) => atom.headerOffset >= item.rec.dataOffset && atom.headerOffset < shape.recordEnd ? [index] : []);
11366
11967
  if (shape.textIndexes.length)
11367
11968
  shape.textReference = "inline";
11368
- for (const textbox of children3.filter((rec) => rec.recType === OA.ClientTextbox))
11969
+ for (const textbox of children4.filter((rec) => rec.recType === OA.ClientTextbox))
11369
11970
  if (pptShapeChildren(view2, textbox).some((rec) => rec.recType === RT2.OutlineTextRefAtom))
11370
11971
  shape.textReference = "unresolved";
11371
11972
  if (shape.mirrored)
@@ -11389,7 +11990,7 @@ function readPptSlideShapes(input, limits = {}) {
11389
11990
  }
11390
11991
  let parentGroup = item.group;
11391
11992
  if (item.rec.recType === OA.SpgrContainer) {
11392
- const head = children3[0];
11993
+ const head = children4[0];
11393
11994
  if (!head || head.recType !== OA.SpContainer)
11394
11995
  throw new PptTextError("corrupt", "Group has no shape container");
11395
11996
  const fsp = pptShapeChildren(view2, head).find((rec) => rec.recType === OA.FSP);
@@ -11398,8 +11999,8 @@ function readPptSlideShapes(input, limits = {}) {
11398
11999
  if (!(view2.getUint32(fsp.dataOffset + 4, true) & 4))
11399
12000
  parentGroup = view2.getUint32(fsp.dataOffset, true);
11400
12001
  }
11401
- for (let i = children3.length - 1; i >= 0; i--) {
11402
- const rec = children3[i];
12002
+ for (let i = children4.length - 1; i >= 0; i--) {
12003
+ const rec = children4[i];
11403
12004
  if (rec.recVer === 15 || rec.recType === OA.ClientTextbox)
11404
12005
  stack.push({ rec, depth: item.depth + 1, group: item.rec.recType === OA.SpgrContainer && i === 0 ? item.group : parentGroup });
11405
12006
  }
@@ -11408,10 +12009,44 @@ function readPptSlideShapes(input, limits = {}) {
11408
12009
  });
11409
12010
  }
11410
12011
 
11411
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/legacy-ppt-shape-edit.js
12012
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-shape-edit.js
11412
12013
  function equalPptShapeBounds(a, b) {
11413
12014
  return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
11414
12015
  }
12016
+ function slideOwnershipRefusal(input, stream, persistId) {
12017
+ const user = readCompoundFileStream(input, ["Current User"]);
12018
+ if (!user)
12019
+ throw new PptParseError("Missing Current User stream");
12020
+ const view2 = new DataView(stream.buffer, stream.byteOffset, stream.byteLength), uv = new DataView(user.buffer, user.byteOffset, user.byteLength);
12021
+ const cu = readRecordOrThrow(uv, 0), editOffset = uv.getUint32(cu.dataOffset + 8, true);
12022
+ const { directory } = buildPersistDirectory(view2, editOffset), ownedOffset = directory.get(persistId);
12023
+ if (ownedOffset === void 0)
12024
+ return "Missing active slide persist object";
12025
+ const owned = readRecordOrThrow(view2, ownedOffset), start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
12026
+ if (end > view2.byteLength)
12027
+ return "Unbounded slide persist object";
12028
+ const overlaps = (offset) => {
12029
+ const other = readRecordOrThrow(view2, offset), otherEnd = other.dataOffset + other.recLen;
12030
+ if (otherEnd > view2.byteLength)
12031
+ throw new PptParseError("Unbounded live persist object prevents safe geometry edit");
12032
+ return start < otherEnd && other.headerOffset < end;
12033
+ };
12034
+ for (const [id, offset] of directory) {
12035
+ if (id !== persistId && overlaps(offset))
12036
+ return "Slide container overlaps another live persist object";
12037
+ }
12038
+ const visited = /* @__PURE__ */ new Set();
12039
+ for (let offset = editOffset; offset; ) {
12040
+ if (visited.has(offset) || visited.size >= 1e4)
12041
+ return "Invalid geometry save-history ownership";
12042
+ visited.add(offset);
12043
+ const edit = parseUserEditAtom(view2, offset);
12044
+ if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
12045
+ return "Slide container overlaps save-history metadata";
12046
+ offset = edit.offsetLastEdit;
12047
+ }
12048
+ return void 0;
12049
+ }
11415
12050
  function editPptShapeBounds(input, edit) {
11416
12051
  const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
11417
12052
  try {
@@ -11444,7 +12079,11 @@ function editPptShapeBounds(input, edit) {
11444
12079
  const edges = [next.y, next.x, next.x + next.width, next.y + next.height];
11445
12080
  if (!edges.every((value) => Number.isSafeInteger(value) && value >= -32768 && value <= 32767))
11446
12081
  return reject2("Geometry exceeds the existing small anchor encoding");
11447
- const stream = readCompoundFileStream(input, ["PowerPoint Document"]), out = stream.slice(), view2 = new DataView(out.buffer);
12082
+ const stream = readCompoundFileStream(input, ["PowerPoint Document"]);
12083
+ const ownership = slideOwnershipRefusal(input, stream, persistId);
12084
+ if (ownership)
12085
+ return reject2(ownership);
12086
+ const out = stream.slice(), view2 = new DataView(out.buffer);
11448
12087
  for (let i = 0; i < edges.length; i++)
11449
12088
  view2.setInt16(anchor + 8 + i * 2, edges[i], true);
11450
12089
  const bytes = replaceCompoundFileStream(input, ["PowerPoint Document"], out);
@@ -11459,12 +12098,604 @@ function editPptShapeBounds(input, edit) {
11459
12098
  }
11460
12099
  }
11461
12100
 
11462
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ppt-document.js
12101
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-notes.js
12102
+ var viewOf2 = (bytes) => new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
12103
+ function fail2(message) {
12104
+ throw new PptTextError("corrupt", message);
12105
+ }
12106
+ function inspect5(input, limits = {}) {
12107
+ const maxRecords = limits.maxRecords ?? 1e5, maxNotes = limits.maxNotes ?? 1e4, maxTextBytes = limits.maxTextBytes ?? 16 * 1024 * 1024;
12108
+ for (const value of [maxRecords, maxNotes, maxTextBytes])
12109
+ if (!Number.isSafeInteger(value) || value < 1)
12110
+ fail2("Invalid notes resource limit");
12111
+ const stream = readCompoundFileStream(input, ["PowerPoint Document"]), user = readCompoundFileStream(input, ["Current User"]);
12112
+ if (!stream || !user)
12113
+ fail2("Missing PowerPoint streams");
12114
+ const view2 = viewOf2(stream), uv = viewOf2(user);
12115
+ const record5 = (offset, type) => {
12116
+ const r = readRecordOrThrow(view2, offset);
12117
+ if (r.dataOffset + r.recLen > view2.byteLength || type !== void 0 && r.recType !== type)
12118
+ fail2("Invalid notes record bounds/type");
12119
+ return r;
12120
+ };
12121
+ const cu = readRecordOrThrow(uv, 0);
12122
+ if (cu.recType !== RT2.CurrentUserAtom || cu.recVer !== 0 || cu.recInstance !== 0 || cu.recLen < 24 || cu.dataOffset + cu.recLen > uv.byteLength)
12123
+ fail2("Invalid CurrentUserAtom");
12124
+ const token = uv.getUint32(cu.dataOffset + 4, true);
12125
+ if (token === HEADER_TOKEN_ENCRYPTED)
12126
+ throw new PptTextError("encrypted", "Encrypted PPT notes are unsupported");
12127
+ if (token !== HEADER_TOKEN_PLAIN)
12128
+ fail2("Unknown encryption token");
12129
+ const { currentEdit, directory } = buildPersistDirectory(view2, uv.getUint32(cu.dataOffset + 8, true), { maxEntries: maxRecords });
12130
+ if (currentEdit.encryptSessionPersistIdRef !== void 0)
12131
+ throw new PptTextError("encrypted", "Encrypted notes persist objects are unsupported");
12132
+ let recordCount = 0, textBytes = 0;
12133
+ const children4 = (r) => {
12134
+ const result = [], end = r.dataOffset + r.recLen;
12135
+ for (let pos = r.dataOffset; pos < end; ) {
12136
+ if (++recordCount > maxRecords)
12137
+ fail2("Notes record budget exceeded");
12138
+ if (end - pos < 8)
12139
+ fail2("Truncated notes child header");
12140
+ const child2 = record5(pos);
12141
+ if (child2.dataOffset + child2.recLen > end)
12142
+ fail2("Notes child exceeds parent");
12143
+ result.push(child2);
12144
+ pos = child2.dataOffset + child2.recLen;
12145
+ }
12146
+ return result;
12147
+ };
12148
+ const docOffset = directory.get(currentEdit.docPersistIdRef);
12149
+ if (docOffset === void 0)
12150
+ fail2("Missing active document");
12151
+ const doc = record5(docOffset, RT2.Document);
12152
+ if (doc.recVer !== 15)
12153
+ fail2("Invalid document container");
12154
+ const docChildren = children4(doc), refs = /* @__PURE__ */ new Map(), persistIds = /* @__PURE__ */ new Set();
12155
+ const notesLists = docChildren.filter((r) => r.recType === RT2.SlideListWithText && r.recInstance === 2);
12156
+ if (notesLists.length > 1)
12157
+ fail2("Ambiguous notes list");
12158
+ for (const list of notesLists) {
12159
+ if (list.recVer !== 15)
12160
+ fail2("Invalid notes list");
12161
+ for (const r of children4(list)) {
12162
+ if (r.recType !== RT2.SlidePersistAtom || r.recVer !== 0 || r.recInstance !== 0 || r.recLen !== 20)
12163
+ fail2("Invalid NotesPersistAtom");
12164
+ const persistId = view2.getUint32(r.dataOffset, true), notesId = view2.getUint32(r.dataOffset + 12, true);
12165
+ if (!notesId || !persistId || refs.has(notesId) || persistIds.has(persistId))
12166
+ fail2("Duplicate or null notes identity");
12167
+ if (refs.size >= maxNotes)
12168
+ fail2("Notes count budget exceeded");
12169
+ refs.set(notesId, persistId);
12170
+ persistIds.add(persistId);
12171
+ }
12172
+ }
12173
+ const slides = readPptSlideShapes(input, { maxRecords, maxTextBytes, maxShapes: maxRecords });
12174
+ if (slides.length > maxNotes)
12175
+ fail2("Active slide budget exceeded");
12176
+ const links = /* @__PURE__ */ new Map(), linkedNotes = /* @__PURE__ */ new Set();
12177
+ for (const slide of slides) {
12178
+ const offset = directory.get(slide.persistId);
12179
+ if (offset === void 0)
12180
+ fail2("Missing active slide");
12181
+ const sr = record5(offset, RT2.Slide), slideAtoms = children4(sr).filter((r) => r.recType === RT2.SlideAtom);
12182
+ if (slideAtoms.length !== 1 || slideAtoms[0].recVer !== 2 || slideAtoms[0].recInstance !== 0 || slideAtoms[0].recLen !== 24)
12183
+ fail2("Invalid SlideAtom notes linkage");
12184
+ const notesId = view2.getUint32(slideAtoms[0].dataOffset + 16, true);
12185
+ if (notesId && linkedNotes.has(notesId))
12186
+ fail2("Notes linked by multiple active slides");
12187
+ if (notesId)
12188
+ linkedNotes.add(notesId);
12189
+ links.set(slide.slideId, notesId);
12190
+ }
12191
+ const activeNotes = new Set(links.values());
12192
+ const raw = /* @__PURE__ */ new Map();
12193
+ for (const [notesId, persistId] of refs) {
12194
+ if (!activeNotes.has(notesId))
12195
+ continue;
12196
+ const offset = directory.get(persistId);
12197
+ if (offset === void 0)
12198
+ fail2("Missing notes persist object");
12199
+ const header = record5(offset, RT2.Notes);
12200
+ if (header.recVer !== 15 || header.recInstance !== 0)
12201
+ fail2("Invalid NotesContainer");
12202
+ const direct = children4(header), atoms = direct.filter((r) => r.recType === RT2.NotesAtom);
12203
+ if (atoms.length !== 1 || atoms[0].recVer !== 1 || atoms[0].recInstance !== 0 || atoms[0].recLen !== 8)
12204
+ fail2("Invalid NotesAtom");
12205
+ const records = [...direct], stack = direct.filter((r) => r.recVer === 15 || r.recType === OA.ClientTextbox).map((r) => ({ r, depth: 1 }));
12206
+ while (stack.length) {
12207
+ const item = stack.pop();
12208
+ if (item.depth > 128)
12209
+ fail2("Notes nesting budget exceeded");
12210
+ for (const r of children4(item.r)) {
12211
+ records.push(r);
12212
+ if (r.recType === RT2.TextCharsAtom || r.recType === RT2.TextBytesAtom) {
12213
+ textBytes += r.recLen;
12214
+ if (textBytes > maxTextBytes)
12215
+ fail2("Notes text byte budget exceeded");
12216
+ if (r.recVer !== 0 || r.recInstance !== 0 || r.recType === RT2.TextCharsAtom && r.recLen % 2)
12217
+ fail2("Invalid notes text atom");
12218
+ }
12219
+ if (r.recVer === 15 || r.recType === OA.ClientTextbox)
12220
+ stack.push({ r, depth: item.depth + 1 });
12221
+ }
12222
+ }
12223
+ raw.set(notesId, { header, backref: view2.getUint32(atoms[0].dataOffset, true), records });
12224
+ }
12225
+ const notes = [];
12226
+ for (const slide of slides) {
12227
+ const notesId = links.get(slide.slideId);
12228
+ if (!notesId)
12229
+ continue;
12230
+ const info = raw.get(notesId), persistId = refs.get(notesId);
12231
+ if (!info || persistId === void 0 || info.backref !== slide.slideId)
12232
+ fail2("Notes ID or slide back-reference mismatch");
12233
+ const all = info.records;
12234
+ let notesMirror = false;
12235
+ for (const r of all.filter((r2) => [OA.FOPT, OA.TertiaryFOPT, 61729].includes(r2.recType))) {
12236
+ if (r.recVer !== 3 || r.recInstance * 6 > r.recLen)
12237
+ fail2("Invalid notes property table");
12238
+ for (let i = 0; i < r.recInstance; i++)
12239
+ if ((view2.getUint16(r.dataOffset + i * 6, true) & 16383) === 937)
12240
+ notesMirror = true;
12241
+ }
12242
+ const texts = [], shapeIds = /* @__PURE__ */ new Set();
12243
+ const shapeRecords = [];
12244
+ let activeShape;
12245
+ for (const r of all.sort((a, b) => a.headerOffset - b.headerOffset)) {
12246
+ if (activeShape && r.headerOffset >= activeShape.shape.dataOffset + activeShape.shape.recLen)
12247
+ activeShape = void 0;
12248
+ if (r.recType === OA.SpContainer) {
12249
+ if (activeShape)
12250
+ fail2("Nested notes shape containers");
12251
+ activeShape = { shape: r, within: [] };
12252
+ shapeRecords.push(activeShape);
12253
+ } else if (activeShape)
12254
+ activeShape.within.push(r);
12255
+ }
12256
+ for (const { shape, within } of shapeRecords) {
12257
+ const fsps = within.filter((r) => r.recType === OA.FSP);
12258
+ if (fsps.length !== 1 || fsps[0].recVer !== 2 || fsps[0].recLen !== 8)
12259
+ fail2("Invalid notes shape identity");
12260
+ const shapeId = view2.getUint32(fsps[0].dataOffset, true);
12261
+ if (!shapeId || shapeIds.has(shapeId))
12262
+ fail2("Duplicate notes shape identity");
12263
+ shapeIds.add(shapeId);
12264
+ const placeholders = within.filter((r) => r.recType === RT2.OEPlaceholderAtom);
12265
+ if (placeholders.some((r) => r.recVer !== 0 || r.recInstance !== 0 || r.recLen !== 8))
12266
+ fail2("Invalid notes PlaceholderAtom");
12267
+ const placeholderId = placeholders.length === 1 ? view2.getUint8(placeholders[0].dataOffset + 4) : void 0;
12268
+ const atoms = within.filter((r) => r.recType === RT2.TextCharsAtom || r.recType === RT2.TextBytesAtom);
12269
+ const headers = within.filter((r) => r.recType === RT2.TextHeaderAtom);
12270
+ const textboxes = within.filter((r) => r.recType === OA.ClientTextbox);
12271
+ const body = placeholderId === 12 && headers.length === 1 && headers[0].recVer === 0 && headers[0].recInstance === 0 && headers[0].recLen === 4 && view2.getUint32(headers[0].dataOffset, true) === 2;
12272
+ for (const atom of atoms) {
12273
+ const wide = atom.recType === RT2.TextCharsAtom;
12274
+ let text = "";
12275
+ for (let p = atom.dataOffset; p < atom.dataOffset + atom.recLen; p += wide ? 2 : 1) {
12276
+ const value = wide ? view2.getUint16(p, true) : view2.getUint8(p);
12277
+ if (!value)
12278
+ fail2("NUL in notes text atom");
12279
+ text += String.fromCharCode(value);
12280
+ }
12281
+ texts.push({
12282
+ shapeId,
12283
+ shapeHeaderOffset: shape.headerOffset,
12284
+ placeholderId,
12285
+ role: body ? "body" : "other",
12286
+ text,
12287
+ headerOffset: atom.headerOffset,
12288
+ encoding: wide ? "utf16" : "compressed-unicode",
12289
+ editRefusal: notesMirror ? "Notes have an OOXML mirror" : !body ? "Not a validated notes body placeholder" : atoms.length !== 1 || placeholders.length !== 1 || textboxes.length !== 1 || headers[0].headerOffset < textboxes[0].dataOffset || headers[0].headerOffset > atom.headerOffset || atom.dataOffset + atom.recLen > textboxes[0].dataOffset + textboxes[0].recLen ? "Ambiguous notes text slot" : void 0
12290
+ });
12291
+ }
12292
+ }
12293
+ notes.push({ slideId: slide.slideId, slidePersistId: slide.persistId, notesId, persistId, headerOffset: info.header.headerOffset, texts });
12294
+ }
12295
+ return { stream, notes };
12296
+ }
12297
+ function readPptSlideNotes(input, limits = {}) {
12298
+ return inspect5(input, limits).notes;
12299
+ }
12300
+ function ownershipRefusal(input, stream, note) {
12301
+ const view2 = viewOf2(stream), user = readCompoundFileStream(input, ["Current User"]);
12302
+ const uv = viewOf2(user), cu = readRecordOrThrow(uv, 0), editOffset = uv.getUint32(cu.dataOffset + 8, true);
12303
+ const { directory } = buildPersistDirectory(view2, editOffset);
12304
+ const owned = readRecordOrThrow(view2, note.headerOffset), start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
12305
+ const overlaps = (offset2) => {
12306
+ const other = readRecordOrThrow(view2, offset2), otherEnd = other.dataOffset + other.recLen;
12307
+ if (otherEnd > view2.byteLength)
12308
+ fail2("Unbounded live persist object prevents safe notes edit");
12309
+ return start < otherEnd && other.headerOffset < end;
12310
+ };
12311
+ for (const [persistId, offset2] of directory) {
12312
+ if (persistId !== note.persistId && overlaps(offset2))
12313
+ return "Notes container overlaps another live persist object";
12314
+ }
12315
+ let offset = editOffset;
12316
+ const visited = /* @__PURE__ */ new Set();
12317
+ while (offset) {
12318
+ if (visited.has(offset) || visited.size >= 1e4)
12319
+ return "Invalid notes save-history ownership";
12320
+ visited.add(offset);
12321
+ const edit = parseUserEditAtom(view2, offset);
12322
+ if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
12323
+ return "Notes container overlaps save-history metadata";
12324
+ offset = edit.offsetLastEdit;
12325
+ }
12326
+ return void 0;
12327
+ }
12328
+ function editPptNotesText(input, edit) {
12329
+ const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
12330
+ try {
12331
+ const { slideId, slidePersistId, notesId, persistId, shapeId, expectedHeaderOffset, expectedText, text } = edit;
12332
+ if (typeof text !== "string" || typeof expectedText !== "string")
12333
+ return reject2("Notes replacement must be a string");
12334
+ const { stream, notes } = inspect5(input);
12335
+ const selected = notes.filter((n) => n.slideId === slideId && n.slidePersistId === slidePersistId && n.notesId === notesId && n.persistId === persistId);
12336
+ const matches = selected.length === 1 ? selected[0].texts.filter((t) => t.shapeId === shapeId && t.headerOffset === expectedHeaderOffset) : [];
12337
+ const atom = matches[0];
12338
+ if (matches.length !== 1 || !atom || atom.text !== expectedText)
12339
+ return reject2("Notes identity or expected text no longer matches");
12340
+ if (text === atom.text)
12341
+ return { status: "unchanged", bytes: input };
12342
+ if (atom.editRefusal)
12343
+ return reject2(atom.editRefusal);
12344
+ const ownership = ownershipRefusal(input, stream, selected[0]);
12345
+ if (ownership)
12346
+ return reject2(ownership);
12347
+ if (notes.reduce((n, note) => n + note.texts.filter((t) => t.headerOffset === atom.headerOffset).length, 0) !== 1)
12348
+ return reject2("Notes text atom is shared by active locations");
12349
+ const start = atom.headerOffset, end = start + 8 + atom.text.length * (atom.encoding === "utf16" ? 2 : 1);
12350
+ for (const slide of readPptSlideTexts(input).slides)
12351
+ for (const text2 of slide.texts) {
12352
+ const textEnd = text2.headerOffset + 8 + text2.text.length * (text2.encoding === "utf16" ? 2 : 1);
12353
+ if (start < textEnd && text2.headerOffset < end)
12354
+ return reject2("Notes slot overlaps active slide text");
12355
+ }
12356
+ if (text.length !== atom.text.length)
12357
+ return reject2("Notes replacement must keep the UTF-16 character count");
12358
+ for (let i = 0; i < text.length; i++) {
12359
+ const old = atom.text.charCodeAt(i), value = text.charCodeAt(i);
12360
+ if (!value || (old < 32 || value < 32 || old === 42 || value === 42) && old !== value)
12361
+ return reject2("Notes controls and field markers must remain at the same offsets");
12362
+ if (atom.encoding === "compressed-unicode" && value > 255)
12363
+ return reject2("Notes character does not fit existing encoding");
12364
+ if (value >= 55296 && value <= 56319 && !(text.charCodeAt(i + 1) >= 56320 && text.charCodeAt(i + 1) <= 57343) || value >= 56320 && value <= 57343 && !(text.charCodeAt(i - 1) >= 55296 && text.charCodeAt(i - 1) <= 56319))
12365
+ return reject2("Unpaired notes UTF-16 surrogate");
12366
+ }
12367
+ const next = stream.slice(), view2 = viewOf2(next);
12368
+ for (let i = 0; i < text.length; i++) {
12369
+ if (atom.encoding === "utf16")
12370
+ view2.setUint16(atom.headerOffset + 8 + i * 2, text.charCodeAt(i), true);
12371
+ else
12372
+ next[atom.headerOffset + 8 + i] = text.charCodeAt(i);
12373
+ }
12374
+ const bytes = replaceCompoundFileStream(input, ["PowerPoint Document"], next);
12375
+ if (bytes === input)
12376
+ return reject2("Notes compound stream cannot be safely replaced");
12377
+ const candidate = inspect5(bytes).notes.find((n) => n.slideId === slideId && n.notesId === notesId && n.persistId === persistId);
12378
+ const confirmed = candidate?.texts.filter((t) => t.shapeId === shapeId && t.headerOffset === expectedHeaderOffset);
12379
+ if (confirmed?.length !== 1 || confirmed[0].text !== text)
12380
+ return reject2("Candidate notes revalidation failed");
12381
+ return { status: "edited", bytes };
12382
+ } catch (error) {
12383
+ return reject2(error instanceof Error ? error.message : "Malformed PPT notes");
12384
+ }
12385
+ }
12386
+
12387
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/legacy-ppt-text-style.js
12388
+ var viewOf3 = (bytes) => new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
12389
+ var MAX_RECORDS = 1e5;
12390
+ var MAX_RUNS = 2e4;
12391
+ var MAX_STYLE_BYTES = 16 * 1024 * 1024;
12392
+ function children3(view2, parent) {
12393
+ const result = [], end = parent.dataOffset + parent.recLen;
12394
+ if (end > view2.byteLength)
12395
+ throw new Error("Unbounded formatting parent");
12396
+ for (let offset = parent.dataOffset; offset < end; ) {
12397
+ if (result.length >= MAX_RECORDS || end - offset < 8)
12398
+ throw new Error("Formatting record bounds exceeded");
12399
+ const record5 = readRecordOrThrow(view2, offset);
12400
+ if (record5.dataOffset + record5.recLen > end)
12401
+ throw new Error("Formatting child exceeds its parent");
12402
+ result.push(record5);
12403
+ offset = record5.dataOffset + record5.recLen;
12404
+ }
12405
+ return result;
12406
+ }
12407
+ function decodeStyle(view2, style, textLength, budget) {
12408
+ if (style.recVer !== 0 || style.recInstance !== 0)
12409
+ throw new Error("Invalid StyleTextPropAtom header");
12410
+ let pos = style.dataOffset;
12411
+ const end = pos + style.recLen, total = textLength + 1;
12412
+ const take = (bytes) => {
12413
+ if (bytes > end - pos)
12414
+ throw new Error("Truncated formatting exception");
12415
+ const offset = pos;
12416
+ pos += bytes;
12417
+ return offset;
12418
+ };
12419
+ const u16 = () => view2.getUint16(take(2), true), u32 = () => view2.getUint32(take(4), true);
12420
+ const count = (sum) => {
12421
+ if (++budget.runs > budget.maxRuns)
12422
+ throw new Error("Character/paragraph run budget exceeded");
12423
+ const value = u32();
12424
+ if (value === 0 || value > total - sum)
12425
+ throw new Error("Invalid formatting run count");
12426
+ return value;
12427
+ };
12428
+ for (let sum = 0; sum < total; ) {
12429
+ sum += count(sum);
12430
+ if (u16() > 4)
12431
+ throw new Error("Invalid paragraph indentation");
12432
+ const mask = u32();
12433
+ if (mask & -3111680)
12434
+ throw new Error("Unsupported paragraph formatting mask");
12435
+ if (mask & 15)
12436
+ take(2);
12437
+ for (const bit of [128, 16, 64])
12438
+ if (mask & bit)
12439
+ take(2);
12440
+ if (mask & 32)
12441
+ take(4);
12442
+ for (const bit of [2048, 4096, 8192, 16384, 65536])
12443
+ if (mask & bit)
12444
+ take(2);
12445
+ if (mask & 917504)
12446
+ take(2);
12447
+ if (mask & 2097152)
12448
+ take(2);
12449
+ }
12450
+ const result = [];
12451
+ for (let sum = 0; sum < total; ) {
12452
+ const runOffset = pos, rawCount = count(sum), start = sum;
12453
+ sum += rawCount;
12454
+ const mask = u32();
12455
+ if (mask & -15728640)
12456
+ throw new Error("Unsupported character formatting mask");
12457
+ if (mask & 16055)
12458
+ take(2);
12459
+ for (const bit of [65536, 2097152, 4194304, 8388608])
12460
+ if (mask & bit)
12461
+ take(2);
12462
+ let fontSizeOffset, directFontSizePoints;
12463
+ if (mask & 131072) {
12464
+ fontSizeOffset = take(2);
12465
+ directFontSizePoints = view2.getInt16(fontSizeOffset, true);
12466
+ if (directFontSizePoints < 1 || directFontSizePoints > 4e3)
12467
+ throw new Error("Invalid literal font size");
12468
+ }
12469
+ if (mask & 262144)
12470
+ take(4);
12471
+ if (mask & 524288) {
12472
+ const position = view2.getInt16(take(2), true);
12473
+ if (position < -100 || position > 100)
12474
+ throw new Error("Invalid baseline position");
12475
+ }
12476
+ result.push({
12477
+ start: Math.min(start, textLength),
12478
+ end: Math.min(sum, textLength),
12479
+ rawCount,
12480
+ mask,
12481
+ styleHeaderOffset: style.headerOffset,
12482
+ runOffset,
12483
+ fontSizeOffset,
12484
+ directFontSizePoints
12485
+ });
12486
+ }
12487
+ if (pos !== end)
12488
+ throw new Error("Unconsumed StyleTextPropAtom bytes");
12489
+ return result;
12490
+ }
12491
+ function textOwnershipRefusal2(input, stream, persistId, atom) {
12492
+ const user = readCompoundFileStream(input, ["Current User"]);
12493
+ if (!user)
12494
+ throw new PptParseError("Missing Current User stream");
12495
+ const view2 = viewOf3(stream), uv = viewOf3(user), cu = readRecordOrThrow(uv, 0);
12496
+ const editOffset = uv.getUint32(cu.dataOffset + 8, true);
12497
+ const { directory, currentEdit } = buildPersistDirectory(view2, editOffset);
12498
+ const slideOffset = directory.get(persistId);
12499
+ if (slideOffset === void 0)
12500
+ return "Missing active slide persist object";
12501
+ const slide = readRecordOrThrow(view2, slideOffset), text = readRecordOrThrow(view2, atom.headerOffset);
12502
+ const textEnd = text.dataOffset + text.recLen;
12503
+ const owners = [persistId];
12504
+ if (atom.headerOffset < slide.dataOffset || textEnd > slide.dataOffset + slide.recLen) {
12505
+ const docOffset = directory.get(currentEdit.docPersistIdRef);
12506
+ if (docOffset === void 0)
12507
+ return "Missing outline text owner";
12508
+ const doc = readRecordOrThrow(view2, docOffset);
12509
+ if (atom.headerOffset < doc.dataOffset || textEnd > doc.dataOffset + doc.recLen)
12510
+ return "Text is outside its active owning containers";
12511
+ owners.push(currentEdit.docPersistIdRef);
12512
+ }
12513
+ for (const ownerId of owners) {
12514
+ const owned = readRecordOrThrow(view2, directory.get(ownerId));
12515
+ const start = owned.headerOffset, end = owned.dataOffset + owned.recLen;
12516
+ if (end > view2.byteLength)
12517
+ return "Unbounded text owning persist object";
12518
+ const overlaps = (offset) => {
12519
+ const other = readRecordOrThrow(view2, offset), otherEnd = other.dataOffset + other.recLen;
12520
+ if (otherEnd > view2.byteLength)
12521
+ throw new PptParseError("Unbounded live persist object prevents safe text edit");
12522
+ return start < otherEnd && other.headerOffset < end;
12523
+ };
12524
+ for (const [id, offset] of directory)
12525
+ if (id !== ownerId && overlaps(offset))
12526
+ return "Text owning container overlaps another live persist object";
12527
+ const visited = /* @__PURE__ */ new Set();
12528
+ for (let offset = editOffset; offset; ) {
12529
+ if (visited.has(offset) || visited.size >= 1e4)
12530
+ return "Invalid text save-history ownership";
12531
+ visited.add(offset);
12532
+ const edit = parseUserEditAtom(view2, offset);
12533
+ if (overlaps(offset) || overlaps(edit.offsetPersistDirectory))
12534
+ return "Text owning container overlaps save-history metadata";
12535
+ offset = edit.offsetLastEdit;
12536
+ }
12537
+ }
12538
+ return void 0;
12539
+ }
12540
+ function readPptCharacterRuns(input, limits = {}) {
12541
+ const maxRecords = limits.maxRecords ?? MAX_RECORDS, maxRuns = limits.maxRuns ?? MAX_RUNS, maxStyleBytes = limits.maxStyleBytes ?? MAX_STYLE_BYTES;
12542
+ if (![maxRecords, maxRuns, maxStyleBytes].every((value) => Number.isSafeInteger(value) && value > 0))
12543
+ throw new Error("Invalid character-format resource limit");
12544
+ readPptSlideShapes(input, { maxRecords });
12545
+ const texts = readPptSlideTexts(input), stream = readCompoundFileStream(input, ["PowerPoint Document"]), user = readCompoundFileStream(input, ["Current User"]);
12546
+ const view2 = viewOf3(stream), uv = viewOf3(user), cu = readRecordOrThrow(uv, 0);
12547
+ const { directory, currentEdit } = buildPersistDirectory(view2, uv.getUint32(cu.dataOffset + 8, true));
12548
+ const associations = /* @__PURE__ */ new Map();
12549
+ let records = 0, styleBytes = 0;
12550
+ const scan = (root) => {
12551
+ const stack = [{ record: root, depth: 0 }];
12552
+ while (stack.length) {
12553
+ const { record: record5, depth } = stack.pop();
12554
+ if (depth > 128)
12555
+ throw new Error("Formatting nesting exceeds limit");
12556
+ const list = children3(view2, record5);
12557
+ records += list.length;
12558
+ if (records > maxRecords)
12559
+ throw new Error("Formatting record budget exceeded");
12560
+ let group;
12561
+ const textParent = record5.recType === OA.ClientTextbox || record5.recType === RT2.SlideListWithText && record5.recInstance === 0;
12562
+ const finish = () => {
12563
+ if (group)
12564
+ for (const atom of group.atoms) {
12565
+ if (associations.has(atom))
12566
+ throw new Error("Ambiguous formatting parent");
12567
+ associations.set(atom, { styles: group.styles, textCount: group.atoms.length });
12568
+ }
12569
+ };
12570
+ for (const child2 of list) {
12571
+ if (textParent && (child2.recType === RT2.TextHeaderAtom || child2.recType === RT2.SlidePersistAtom)) {
12572
+ finish();
12573
+ group = child2.recType === RT2.TextHeaderAtom ? { atoms: [], styles: [] } : void 0;
12574
+ if (group && (child2.recVer !== 0 || child2.recInstance > (record5.recType === OA.ClientTextbox ? 0 : 5) || child2.recLen !== 4))
12575
+ throw new Error("Invalid formatting TextHeaderAtom");
12576
+ } else if (group && (child2.recType === RT2.TextCharsAtom || child2.recType === RT2.TextBytesAtom))
12577
+ group.atoms.push(child2.headerOffset);
12578
+ else if (group && child2.recType === RT2.StyleTextPropAtom) {
12579
+ styleBytes += child2.recLen;
12580
+ if (styleBytes > maxStyleBytes)
12581
+ throw new Error("Formatting payload budget exceeded");
12582
+ group.styles.push(child2);
12583
+ }
12584
+ if (child2.recVer === 15 || child2.recType === OA.ClientTextbox)
12585
+ stack.push({ record: child2, depth: depth + 1 });
12586
+ }
12587
+ finish();
12588
+ }
12589
+ };
12590
+ let scanDiagnostic;
12591
+ try {
12592
+ const doc = readRecordOrThrow(view2, directory.get(currentEdit.docPersistIdRef));
12593
+ for (const list of children3(view2, doc))
12594
+ if (list.recType === RT2.SlideListWithText && list.recInstance === 0)
12595
+ scan(list);
12596
+ const visited = /* @__PURE__ */ new Set();
12597
+ for (const slide of texts.slides) {
12598
+ const offset = directory.get(slide.persistId);
12599
+ if (!visited.has(offset)) {
12600
+ visited.add(offset);
12601
+ scan(readRecordOrThrow(view2, offset));
12602
+ }
12603
+ }
12604
+ } catch (error) {
12605
+ scanDiagnostic = error instanceof Error ? error.message : "Unsupported formatting graph";
12606
+ }
12607
+ const budget = { runs: 0, maxRuns };
12608
+ return texts.slides.flatMap((slide) => slide.texts.map((atom) => {
12609
+ const base = { slideId: slide.slideId, persistId: slide.persistId, headerOffset: atom.headerOffset, text: atom.text };
12610
+ if (scanDiagnostic)
12611
+ return { ...base, status: "unsupported", diagnostic: scanDiagnostic, runs: [] };
12612
+ const group = associations.get(atom.headerOffset);
12613
+ if (!group)
12614
+ return { ...base, status: "unsupported", diagnostic: "Text has no unambiguous TextHeader formatting parent", runs: [] };
12615
+ if (!group.styles.length)
12616
+ return { ...base, status: "absent", runs: [] };
12617
+ if (group.textCount !== 1 || group.styles.length !== 1)
12618
+ return { ...base, status: "unsupported", diagnostic: "Text or style atom association is ambiguous", runs: [] };
12619
+ try {
12620
+ return { ...base, status: "decoded", runs: decodeStyle(view2, group.styles[0], atom.text.length, budget) };
12621
+ } catch (error) {
12622
+ return { ...base, status: "unsupported", diagnostic: error instanceof Error ? error.message : "Unsupported formatting", runs: [] };
12623
+ }
12624
+ }));
12625
+ }
12626
+ function editPptCharacterFontSize(input, edit) {
12627
+ const reject2 = (reason) => ({ status: "unsupported", bytes: input, reason });
12628
+ try {
12629
+ const { slideId, persistId, headerOffset, runOffset, styleHeaderOffset, start, end, expectedFontSizePoints, fontSizePoints } = edit;
12630
+ const matches = readPptCharacterRuns(input).filter((text) => text.slideId === slideId && text.persistId === persistId && text.headerOffset === headerOffset);
12631
+ const record5 = matches.length === 1 ? matches[0] : void 0;
12632
+ const runs = record5?.status === "decoded" ? record5.runs.filter((run2) => run2.runOffset === runOffset && run2.styleHeaderOffset === styleHeaderOffset && run2.start === start && run2.end === end) : [];
12633
+ const run = runs.length === 1 ? runs[0] : void 0;
12634
+ if (!run || run.directFontSizePoints !== expectedFontSizePoints)
12635
+ return reject2(record5?.diagnostic ?? "Character run identity or expected font size does not match");
12636
+ if (fontSizePoints === run.directFontSizePoints)
12637
+ return { status: "unchanged", bytes: input };
12638
+ if (run.start === run.end)
12639
+ return reject2("Run covers only the implicit paragraph mark");
12640
+ if (run.fontSizeOffset === void 0)
12641
+ return reject2("Font size is inherited; no existing literal slot");
12642
+ if (!Number.isSafeInteger(fontSizePoints) || fontSizePoints < 1 || fontSizePoints > 4e3)
12643
+ return reject2("Literal font size must be an integer from 1 to 4000 points");
12644
+ const textModel = readPptSlideTexts(input), slides = textModel.slides.filter((slide) => slide.slideId === slideId && slide.persistId === persistId);
12645
+ const indexes = slides.length === 1 ? slides[0].texts.flatMap((atom, index) => atom.headerOffset === headerOffset ? [index] : []) : [];
12646
+ if (indexes.length !== 1 || textModel.slides.reduce((count, slide) => count + slide.texts.filter((atom) => atom.headerOffset === headerOffset).length, 0) !== 1)
12647
+ return reject2("Text atom is shared by multiple active slide positions");
12648
+ const shapeSlides = readPptSlideShapes(input).filter((slide) => slide.slideId === slideId && slide.persistId === persistId);
12649
+ const shapes = shapeSlides.length === 1 ? shapeSlides[0].shapes.filter((shape) => shape.textReference === "inline" && shape.textIndexes.includes(indexes[0])) : [];
12650
+ if (shapes.length !== 1 || shapes[0].kind !== "text-box")
12651
+ return reject2("Font-size edits require uniquely linked inline text-box text");
12652
+ if (shapes[0].geometryRefusal)
12653
+ return reject2(`Unsupported text-box formatting context: ${shapes[0].geometryRefusal}`);
12654
+ const originalStream = readCompoundFileStream(input, ["PowerPoint Document"]);
12655
+ const refusal = textOwnershipRefusal2(input, originalStream, persistId, slides[0].texts[indexes[0]]);
12656
+ if (refusal)
12657
+ return reject2(refusal);
12658
+ const stream = readCompoundFileStream(input, ["PowerPoint Document"]).slice();
12659
+ viewOf3(stream).setInt16(run.fontSizeOffset, fontSizePoints, true);
12660
+ const bytes = replaceCompoundFileStream(input, ["PowerPoint Document"], stream);
12661
+ if (bytes === input)
12662
+ return reject2("Compound stream cannot be safely replaced");
12663
+ const candidate = readPptCharacterRuns(bytes).filter((text) => text.slideId === slideId && text.persistId === persistId && text.headerOffset === headerOffset);
12664
+ const next = candidate.length === 1 && candidate[0].status === "decoded" ? candidate[0].runs.find((item) => item.runOffset === runOffset && item.styleHeaderOffset === styleHeaderOffset && item.start === start && item.end === end) : void 0;
12665
+ if (!next || next.directFontSizePoints !== fontSizePoints || candidate[0].text !== record5.text)
12666
+ return reject2("Edited character run failed candidate validation");
12667
+ return { status: "edited", bytes };
12668
+ } catch (error) {
12669
+ return reject2(error instanceof Error ? error.message : "Malformed PPT formatting");
12670
+ }
12671
+ }
12672
+
12673
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ppt-document.js
11463
12674
  var PPT_CAPABILITIES = Object.freeze({
11464
- read: Object.freeze(["active-slide-ids", "active-outline-and-inline-text", "text-encoding", "active-shape-ids-and-flags", "primitive-shape-kind", "explicit-anchor-geometry", "validated-inline-shape-text", "opaque-streams"]),
11465
- write: Object.freeze(["existing-text-fixed-utf16-length", "unmirrored-top-level-small-anchor-bounds"]),
11466
- limitations: Object.freeze(["unresolved-outline-shape-text", "rich-text-runs", "notes", "variable-length-text", "OOXML-mirrored-text-and-shapes", "group-transforms-and-geometry", "large-anchor-writes", "inherited-rotated-or-flipped-geometry", "animations", "masters", "embedded-objects"])
12675
+ read: Object.freeze(["active-slide-ids", "active-outline-and-inline-text", "text-encoding", "direct-character-run-spans-and-font-size", "active-shape-ids-and-flags", "primitive-shape-kind", "explicit-anchor-geometry", "validated-inline-shape-text", "active-notes-identities-and-inline-text", "opaque-streams"]),
12676
+ write: Object.freeze(["existing-text-fixed-utf16-length", "existing-literal-inline-text-box-font-size", "unmirrored-top-level-small-anchor-bounds", "existing-notes-body-fixed-utf16-length"]),
12677
+ limitations: Object.freeze(["unresolved-outline-shape-text", "inherited-character-formatting", "run-splitting-and-style-insertion", "character-properties-except-existing-font-size", "outline-and-unsupported-shape-font-size-edits", "notes-creation-and-inherited-fields", "variable-length-text", "OOXML-mirrored-text-and-shapes", "group-transforms-and-geometry", "large-anchor-writes", "inherited-rotated-or-flipped-geometry", "animations", "masters", "embedded-objects"])
11467
12678
  });
12679
+ var RUN_LOOKUPS = /* @__PURE__ */ new WeakMap();
12680
+ function resolveCharacterRun(record5, original) {
12681
+ let lookup = RUN_LOOKUPS.get(record5);
12682
+ if (!lookup) {
12683
+ lookup = /* @__PURE__ */ new Map();
12684
+ for (const run2 of record5.runs) {
12685
+ const bucket = lookup.get(run2.runOffset);
12686
+ if (bucket)
12687
+ bucket.push(run2);
12688
+ else
12689
+ lookup.set(run2.runOffset, [run2]);
12690
+ }
12691
+ RUN_LOOKUPS.set(record5, lookup);
12692
+ }
12693
+ const matches = record5.status === "decoded" ? lookup.get(original.runOffset) : void 0, run = matches?.[0];
12694
+ if (matches?.length !== 1 || !run || run.styleHeaderOffset !== original.styleHeaderOffset || run.start !== original.start || run.end !== original.end || run.rawCount !== original.rawCount || run.mask !== original.mask || run.fontSizeOffset !== original.fontSizeOffset)
12695
+ throw new UnsupportedOle2EditError("PPT character run identity no longer matches or is ambiguous");
12696
+ return run;
12697
+ }
12698
+ var textRunKey = (node) => `${node.slideId}:${node.persistId}:${node.headerOffset}`;
11468
12699
  var PptText = class {
11469
12700
  slideId;
11470
12701
  persistId;
@@ -11474,7 +12705,10 @@ var PptText = class {
11474
12705
  headerOffset;
11475
12706
  #text;
11476
12707
  #write;
11477
- constructor(identity, atom, write) {
12708
+ #readRuns;
12709
+ #writeRun;
12710
+ #runs;
12711
+ constructor(identity, atom, write, readRuns, writeRun) {
11478
12712
  this.slideId = identity.slideId;
11479
12713
  this.persistId = identity.persistId;
11480
12714
  this.textIndex = identity.textIndex;
@@ -11482,6 +12716,10 @@ var PptText = class {
11482
12716
  this.headerOffset = atom.headerOffset;
11483
12717
  this.#text = atom.text;
11484
12718
  this.#write = write;
12719
+ this.#readRuns = readRuns ?? (() => ({ ...identity, headerOffset: atom.headerOffset, text: this.#text, status: "unsupported", diagnostic: "Text has no document formatting owner", runs: [] }));
12720
+ this.#writeRun = writeRun ?? (() => {
12721
+ throw new UnsupportedOle2EditError("Text has no document formatting owner");
12722
+ });
11485
12723
  Object.freeze(this);
11486
12724
  }
11487
12725
  get text() {
@@ -11493,8 +12731,50 @@ var PptText = class {
11493
12731
  this.#write(this, value);
11494
12732
  this.#text = value;
11495
12733
  }
12734
+ get runsStatus() {
12735
+ return this.#readRuns(this).status;
12736
+ }
12737
+ get runsDiagnostic() {
12738
+ return this.#readRuns(this).diagnostic;
12739
+ }
12740
+ /** Direct character exceptions only; inherited/effective formatting is unresolved. */
11496
12741
  get runs() {
11497
- throw new UnsupportedOle2EditError("PPT rich-text runs are not decoded by this adapter");
12742
+ if (!this.#runs) {
12743
+ const model2 = this.#readRuns(this);
12744
+ this.#runs = Object.freeze(model2.runs.map((run) => new PptCharacterRun(run, () => {
12745
+ const current = this.#readRuns(this);
12746
+ return { text: current.text, run: resolveCharacterRun(current, run) };
12747
+ }, (value) => this.#writeRun(this, run, value))));
12748
+ }
12749
+ return this.#runs;
12750
+ }
12751
+ };
12752
+ var PptCharacterRun = class {
12753
+ start;
12754
+ end;
12755
+ styleHeaderOffset;
12756
+ runOffset;
12757
+ #read;
12758
+ #write;
12759
+ constructor(record5, read, write) {
12760
+ this.start = record5.start;
12761
+ this.end = record5.end;
12762
+ this.styleHeaderOffset = record5.styleHeaderOffset;
12763
+ this.runOffset = record5.runOffset;
12764
+ this.#read = read;
12765
+ this.#write = write;
12766
+ Object.freeze(this);
12767
+ }
12768
+ get text() {
12769
+ return this.#read().text.slice(this.start, this.end);
12770
+ }
12771
+ get directFontSizePoints() {
12772
+ return this.#read().run.directFontSizePoints;
12773
+ }
12774
+ set directFontSizePoints(value) {
12775
+ if (value !== void 0 && typeof value !== "number")
12776
+ throw new UnsupportedOle2EditError("PPT direct font size must be numeric");
12777
+ this.#write(value);
11498
12778
  }
11499
12779
  };
11500
12780
  var PptSlide = class {
@@ -11505,15 +12785,71 @@ var PptSlide = class {
11505
12785
  /** Flat OfficeArt preorder, including group descendants with parentGroupId.
11506
12786
  * Canvas patriarchs/background structures remain preserved outside this list. */
11507
12787
  shapes;
11508
- constructor(slideId, persistId, texts, shapes = []) {
12788
+ /** Existing active notes; undefined when the slide has a null notes reference. */
12789
+ notes;
12790
+ notesStatus;
12791
+ /** A decode refusal is distinct from a null notes reference. Bytes remain opaque. */
12792
+ notesDiagnostic;
12793
+ constructor(slideId, persistId, texts, shapes = [], notes, notesDiagnostic) {
11509
12794
  this.slideId = slideId;
11510
12795
  this.persistId = persistId;
11511
12796
  this.texts = Object.freeze([...texts]);
11512
12797
  this.shapes = Object.freeze([...shapes]);
12798
+ this.notes = notes;
12799
+ this.notesDiagnostic = notesDiagnostic;
12800
+ this.notesStatus = notesDiagnostic ? "unsupported" : notes ? "present" : "absent";
12801
+ Object.freeze(this);
12802
+ }
12803
+ };
12804
+ var PptNoteText = class {
12805
+ shapeId;
12806
+ headerOffset;
12807
+ #read;
12808
+ #write;
12809
+ constructor(atom, read, write) {
12810
+ this.shapeId = atom.shapeId;
12811
+ this.headerOffset = atom.headerOffset;
12812
+ this.#read = read;
12813
+ this.#write = write;
11513
12814
  Object.freeze(this);
11514
12815
  }
11515
- get notes() {
11516
- throw new UnsupportedOle2EditError("PPT notes are preserved but are not decoded by this adapter");
12816
+ get text() {
12817
+ return this.#read().text;
12818
+ }
12819
+ set text(value) {
12820
+ if (typeof value !== "string")
12821
+ throw new UnsupportedOle2EditError("Notes replacement must be a string");
12822
+ this.#write(value);
12823
+ }
12824
+ get role() {
12825
+ return this.#read().role;
12826
+ }
12827
+ get placeholderId() {
12828
+ return this.#read().placeholderId;
12829
+ }
12830
+ get encoding() {
12831
+ return this.#read().encoding;
12832
+ }
12833
+ get editRefusal() {
12834
+ return this.#read().editRefusal;
12835
+ }
12836
+ get runs() {
12837
+ throw new UnsupportedOle2EditError("PPT notes rich-text runs are preserved but not decoded");
12838
+ }
12839
+ };
12840
+ var PptNotes = class {
12841
+ slideId;
12842
+ slidePersistId;
12843
+ notesId;
12844
+ persistId;
12845
+ texts;
12846
+ constructor(record5, texts) {
12847
+ this.slideId = record5.slideId;
12848
+ this.slidePersistId = record5.slidePersistId;
12849
+ this.notesId = record5.notesId;
12850
+ this.persistId = record5.persistId;
12851
+ this.texts = Object.freeze([...texts]);
12852
+ Object.freeze(this);
11517
12853
  }
11518
12854
  };
11519
12855
  var PptShape = class {
@@ -11526,13 +12862,13 @@ var PptShape = class {
11526
12862
  texts;
11527
12863
  #read;
11528
12864
  #write;
11529
- constructor(identity, record4, texts, read, write) {
12865
+ constructor(identity, record5, texts, read, write) {
11530
12866
  this.slideId = identity.slideId;
11531
12867
  this.persistId = identity.persistId;
11532
- this.shapeId = record4.shapeId;
11533
- this.headerOffset = record4.headerOffset;
11534
- this.flags = record4.flags;
11535
- this.shapeType = record4.shapeType;
12868
+ this.shapeId = record5.shapeId;
12869
+ this.headerOffset = record5.headerOffset;
12870
+ this.flags = record5.flags;
12871
+ this.shapeType = record5.shapeType;
11536
12872
  this.texts = Object.freeze([...texts]);
11537
12873
  this.#read = read;
11538
12874
  this.#write = write;
@@ -11622,6 +12958,9 @@ var PptDocument = class extends Ole2DocumentBase {
11622
12958
  #slides;
11623
12959
  #unsupported;
11624
12960
  #shapeCache;
12961
+ #notesCache;
12962
+ #runsCache;
12963
+ #validatedTextRuns = /* @__PURE__ */ new WeakMap();
11625
12964
  get slides() {
11626
12965
  return this.#slides;
11627
12966
  }
@@ -11632,14 +12971,102 @@ var PptDocument = class extends Ole2DocumentBase {
11632
12971
  super(input);
11633
12972
  const shapeModel = readPptSlideShapes(this.getBytes());
11634
12973
  const model2 = readPptSlideTexts(this.getBytes());
12974
+ let notesModel = [], notesDiagnostic;
12975
+ try {
12976
+ notesModel = readPptSlideNotes(this.getBytes());
12977
+ } catch (error) {
12978
+ notesDiagnostic = error instanceof Error ? error.message : "Notes decoding unsupported";
12979
+ }
11635
12980
  this.#shapeCache = { revision: this.revision, slides: shapeModel };
11636
- this.#unsupported = Object.freeze(["formatting", "group-transforms", "pictures-content", "masters", "notes", "animations", "embedded-objects", "unresolved-outline-shape-text", "variable-length-text"]);
12981
+ this.#notesCache = { revision: this.revision, notes: notesModel };
12982
+ this.#unsupported = Object.freeze(["formatting", "group-transforms", "pictures-content", "masters", "notes-creation-and-inherited-fields", "animations", "embedded-objects", "unresolved-outline-shape-text", "variable-length-text", ...notesDiagnostic ? ["notes-decoding"] : []]);
11637
12983
  this.#slides = Object.freeze(model2.slides.map((slide, index) => {
11638
- const texts = slide.texts.map((atom, textIndex) => new PptText({ slideId: slide.slideId, persistId: slide.persistId, textIndex }, atom, (node, value) => this.#edit(node, value)));
11639
- const shapes = shapeModel[index].shapes.map((record4) => new PptShape(slide, record4, record4.textIndexes.map((textIndex) => texts[textIndex]), () => this.#readShape(slide.slideId, slide.persistId, record4), (value) => this.#editShape(slide.slideId, slide.persistId, record4, value)));
11640
- return new PptSlide(slide.slideId, slide.persistId, texts, shapes);
12984
+ const texts = slide.texts.map((atom, textIndex) => new PptText({ slideId: slide.slideId, persistId: slide.persistId, textIndex }, atom, (node, value) => this.#edit(node, value), (node) => this.#readTextRuns(node), (node, run, value) => this.#editRun(node, run, value)));
12985
+ const shapes = shapeModel[index].shapes.map((record6) => new PptShape(slide, record6, record6.textIndexes.map((textIndex) => texts[textIndex]), () => this.#readShape(slide.slideId, slide.persistId, record6), (value) => this.#editShape(slide.slideId, slide.persistId, record6, value)));
12986
+ const record5 = notesModel.find((note) => note.slideId === slide.slideId && note.slidePersistId === slide.persistId);
12987
+ const notes = record5 && new PptNotes(record5, record5.texts.map((atom) => new PptNoteText(atom, () => this.#readNote(record5, atom), (value) => this.#editNote(record5, atom, value))));
12988
+ return new PptSlide(slide.slideId, slide.persistId, texts, shapes, notes, notesDiagnostic);
11641
12989
  }));
11642
12990
  }
12991
+ #readTextRuns(node) {
12992
+ if (!this.#runsCache || this.#runsCache.revision !== this.revision) {
12993
+ const revision = this.revision;
12994
+ const byIdentity = /* @__PURE__ */ new Map();
12995
+ for (const record6 of readPptCharacterRuns(this.getBytes())) {
12996
+ const key2 = textRunKey(record6), bucket = byIdentity.get(key2);
12997
+ if (bucket)
12998
+ bucket.push(record6);
12999
+ else
13000
+ byIdentity.set(key2, [record6]);
13001
+ }
13002
+ if (this.revision !== revision)
13003
+ throw new UnsupportedOle2EditError("Document changed during character formatting read");
13004
+ this.#runsCache = { revision, byIdentity };
13005
+ }
13006
+ const matches = this.#runsCache.byIdentity.get(textRunKey(node)), record5 = matches?.[0];
13007
+ if (matches?.length !== 1 || !record5)
13008
+ throw new UnsupportedOle2EditError("PPT text formatting identity no longer matches or is ambiguous");
13009
+ if (this.#validatedTextRuns.get(node) !== record5) {
13010
+ if (record5.text !== node.text)
13011
+ throw new UnsupportedOle2EditError("PPT text formatting identity no longer matches or is ambiguous");
13012
+ this.#validatedTextRuns.set(node, record5);
13013
+ }
13014
+ return record5;
13015
+ }
13016
+ #editRun(node, original, fontSizePoints) {
13017
+ const revision = this.revision, current = this.#readTextRuns(node);
13018
+ const run = resolveCharacterRun(current, original);
13019
+ const result = editPptCharacterFontSize(this.getBytes(), {
13020
+ slideId: node.slideId,
13021
+ persistId: node.persistId,
13022
+ headerOffset: node.headerOffset,
13023
+ runOffset: run.runOffset,
13024
+ styleHeaderOffset: run.styleHeaderOffset,
13025
+ start: run.start,
13026
+ end: run.end,
13027
+ expectedFontSizePoints: run.directFontSizePoints,
13028
+ fontSizePoints
13029
+ });
13030
+ if (this.revision !== revision)
13031
+ throw new UnsupportedOle2EditError("Document changed during character formatting edit");
13032
+ if (result.status === "unsupported")
13033
+ throw new UnsupportedOle2EditError(result.reason);
13034
+ if (result.status === "edited")
13035
+ this.commitBytes(result.bytes);
13036
+ }
13037
+ #readNote(original, atom) {
13038
+ if (this.#notesCache.revision !== this.revision) {
13039
+ try {
13040
+ this.#notesCache = { revision: this.revision, notes: readPptSlideNotes(this.getBytes()) };
13041
+ } catch (error) {
13042
+ throw new UnsupportedOle2EditError(error instanceof Error ? error.message : "Notes decoding unsupported");
13043
+ }
13044
+ }
13045
+ const notes = this.#notesCache.notes.filter((note) => note.slideId === original.slideId && note.slidePersistId === original.slidePersistId && note.notesId === original.notesId && note.persistId === original.persistId && note.headerOffset === original.headerOffset);
13046
+ const matches = notes.length === 1 ? notes[0].texts.filter((text) => text.shapeId === atom.shapeId && text.headerOffset === atom.headerOffset && text.shapeHeaderOffset === atom.shapeHeaderOffset && text.encoding === atom.encoding && text.placeholderId === atom.placeholderId) : [];
13047
+ if (matches.length !== 1)
13048
+ throw new UnsupportedOle2EditError("PPT notes identity no longer matches or is ambiguous");
13049
+ return matches[0];
13050
+ }
13051
+ #editNote(note, atom, text) {
13052
+ const revision = this.revision, current = this.#readNote(note, atom);
13053
+ const result = editPptNotesText(this.getBytes(), {
13054
+ slideId: note.slideId,
13055
+ slidePersistId: note.slidePersistId,
13056
+ notesId: note.notesId,
13057
+ persistId: note.persistId,
13058
+ shapeId: atom.shapeId,
13059
+ expectedHeaderOffset: atom.headerOffset,
13060
+ expectedText: current.text,
13061
+ text
13062
+ });
13063
+ if (this.revision !== revision)
13064
+ throw new UnsupportedOle2EditError("Document changed during notes edit");
13065
+ if (result.status === "unsupported")
13066
+ throw new UnsupportedOle2EditError(result.reason);
13067
+ if (result.status === "edited")
13068
+ this.commitBytes(result.bytes);
13069
+ }
11643
13070
  #readShape(slideId, persistId, original) {
11644
13071
  if (this.#shapeCache.revision !== this.revision)
11645
13072
  this.#shapeCache = { revision: this.revision, slides: readPptSlideShapes(this.getBytes()) };
@@ -11679,7 +13106,7 @@ var PptDocument = class extends Ole2DocumentBase {
11679
13106
  }
11680
13107
  };
11681
13108
 
11682
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/vsd-compression.js
13109
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-compression.js
11683
13110
  function decodeVsdBlock(input, limit3 = 32 * 1024 * 1024) {
11684
13111
  if (!Number.isSafeInteger(limit3) || limit3 < 0 || limit3 > 64 * 1024 * 1024)
11685
13112
  throw new Error("Invalid VSD decompression limit");
@@ -11726,7 +13153,7 @@ function encodeVsdBlock(input) {
11726
13153
  return output;
11727
13154
  }
11728
13155
 
11729
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/vsd-reader.js
13156
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-reader.js
11730
13157
  var VsdError = class extends Error {
11731
13158
  reason;
11732
13159
  constructor(reason) {
@@ -11774,6 +13201,8 @@ function readVsdDrawing(input) {
11774
13201
  if (size < 54 || size > stream.length)
11775
13202
  throw new VsdError("document-size");
11776
13203
  const data = { stream, streamPath, version: 11, pages: [], blocks: [], writable: true };
13204
+ const shapeOrders = /* @__PURE__ */ new Map(), sheetIds = /* @__PURE__ */ new Map();
13205
+ let orderElements = 0;
11777
13206
  const active = /* @__PURE__ */ new Set(), seen = /* @__PURE__ */ new Set();
11778
13207
  let decodedBudget = MAX_BYTES, records = 0;
11779
13208
  function visit(ownerBytes, pointerOffset, parent, page, shape, depth = 0, id = 0) {
@@ -11847,7 +13276,7 @@ function readVsdDrawing(input) {
11847
13276
  for (const idx of indexes)
11848
13277
  visit(bytes, table + 12 + idx * 18, block, page, shape, depth + 1, idx);
11849
13278
  } else if (page && [8, 12, 13].includes(mode)) {
11850
- const stack = [];
13279
+ const stack = [], orderStack = [];
11851
13280
  let cursor = 0;
11852
13281
  while (cursor < bytes.length) {
11853
13282
  while (cursor < bytes.length && bytes[cursor] === 0)
@@ -11875,6 +13304,57 @@ function readVsdDrawing(input) {
11875
13304
  let current = stack[stack.length - 1]?.shape ?? shape;
11876
13305
  if (current && [70, 74].includes(chunk))
11877
13306
  throw new VsdError("unsupported-sheet-owner");
13307
+ while (orderStack.length && level <= orderStack[orderStack.length - 1].level)
13308
+ orderStack.pop();
13309
+ if (page && chunk === 70) {
13310
+ if (sheetIds.has(page))
13311
+ page.shapeOrderIssue = "ambiguous-page-owner";
13312
+ sheetIds.set(page, length2 >= 54 && level === 1 && [10, 18, 26].every((o) => cv.getUint32(start + o, true) === 4294967295) ? chunkId : void 0);
13313
+ }
13314
+ if (page && chunk === 101) {
13315
+ const orders = shapeOrders.get(page) ?? /* @__PURE__ */ new Map();
13316
+ shapeOrders.set(page, orders);
13317
+ const order = { owner: current, elements: [], ids: /* @__PURE__ */ new Map(), level };
13318
+ if (orders.has(current))
13319
+ order.issue = "duplicate-shape-order";
13320
+ orders.set(current, order);
13321
+ orderStack.push(order);
13322
+ const end = start + length2 + trailer - 4;
13323
+ if (end - start < 8)
13324
+ order.issue = "shape-order-bounds";
13325
+ else {
13326
+ const subHeader = cv.getUint32(start, true), childrenBytes = cv.getUint32(start + 4, true), children4 = start + 8 + subHeader;
13327
+ if (children4 > end || childrenBytes > end - children4 || childrenBytes % 4)
13328
+ order.issue = "shape-order-bounds";
13329
+ else {
13330
+ const count = childrenBytes / 4;
13331
+ orderElements += count;
13332
+ if (orderElements > 1e5)
13333
+ throw new VsdError("shape-order-budget");
13334
+ const seen2 = /* @__PURE__ */ new Set();
13335
+ for (let i = 0; i < count; i++) {
13336
+ const id2 = cv.getUint32(children4 + i * 4, true);
13337
+ if (seen2.has(id2))
13338
+ order.issue = "duplicate-order-element";
13339
+ seen2.add(id2);
13340
+ order.elements.push(id2);
13341
+ }
13342
+ }
13343
+ }
13344
+ }
13345
+ if (page && chunk === 131) {
13346
+ const order = orderStack[orderStack.length - 1];
13347
+ if (!order)
13348
+ page.shapeOrderIssue = "orphan-shape-id";
13349
+ else if (level !== order.level + 1)
13350
+ order.issue = "shape-id-owner-level";
13351
+ else if (length2 < 4)
13352
+ order.issue = "shape-id-bounds";
13353
+ else if (order.ids.has(chunkId))
13354
+ order.issue = "duplicate-shape-id-map";
13355
+ else
13356
+ order.ids.set(chunkId, cv.getUint32(start, true));
13357
+ }
11878
13358
  if (page && [71, 72, 78].includes(chunk)) {
11879
13359
  current = { id: chunkId, kind: chunk === 71 ? "group" : chunk === 78 ? "foreign" : "shape", coordinateSpace: "shape-local", unsupportedGeometry: false, unsafeTransform: false, geometry: [], unsafeText: false };
11880
13360
  if (length2 < 54)
@@ -11949,42 +13429,304 @@ function readVsdDrawing(input) {
11949
13429
  ids.add(shape.id);
11950
13430
  }
11951
13431
  }
13432
+ for (const page of data.pages) {
13433
+ const shapes = new Map(page.shapes.map((s) => [s.id, s])), orders = shapeOrders.get(page), sheet = sheetIds.get(page);
13434
+ if (sheet !== void 0 && shapes.has(sheet))
13435
+ page.shapeOrderIssue = "ambiguous-page-owner";
13436
+ const rootParent = (s) => s.parentId === 4294967295 || sheet !== void 0 && s.parentId === sheet;
13437
+ const rootIds = /* @__PURE__ */ new Set(), childrenByParent = /* @__PURE__ */ new Map(), emptyIds = /* @__PURE__ */ new Set();
13438
+ for (const shape of page.shapes) {
13439
+ if (rootParent(shape))
13440
+ rootIds.add(shape.id);
13441
+ if (shape.parentId !== void 0) {
13442
+ const children4 = childrenByParent.get(shape.parentId) ?? /* @__PURE__ */ new Set();
13443
+ children4.add(shape.id);
13444
+ childrenByParent.set(shape.parentId, children4);
13445
+ }
13446
+ }
13447
+ const resolve = (owner) => {
13448
+ const order = orders?.get(owner);
13449
+ let issue2 = order?.issue;
13450
+ if (!order)
13451
+ issue2 = "missing-shape-order";
13452
+ if (owner && owner.kind !== "group" && order?.elements.length)
13453
+ issue2 = "unsupported-child-owner";
13454
+ const result = [], seen2 = /* @__PURE__ */ new Set();
13455
+ if (order && !issue2) {
13456
+ for (const element of order.elements) {
13457
+ const id = order.ids.get(element), shape = id === void 0 ? void 0 : shapes.get(id);
13458
+ if (!shape) {
13459
+ issue2 = "unresolved-shape-id";
13460
+ break;
13461
+ }
13462
+ if (seen2.has(id)) {
13463
+ issue2 = "duplicate-shape-reference";
13464
+ break;
13465
+ }
13466
+ seen2.add(id);
13467
+ if (owner ? shape.parentId !== owner.id : !rootParent(shape)) {
13468
+ issue2 = "contradictory-shape-owner";
13469
+ break;
13470
+ }
13471
+ result.push(id);
13472
+ }
13473
+ if (!issue2) {
13474
+ const expected = owner ? childrenByParent.get(owner.id) ?? emptyIds : rootIds;
13475
+ if (expected.size !== result.length || [...expected].some((id) => !seen2.has(id)))
13476
+ issue2 = "incomplete-shape-order";
13477
+ }
13478
+ }
13479
+ if (issue2) {
13480
+ if (owner)
13481
+ owner.shapeOrderIssue = issue2;
13482
+ else
13483
+ page.shapeOrderIssue ??= issue2;
13484
+ return void 0;
13485
+ }
13486
+ return result;
13487
+ };
13488
+ const root = resolve(void 0);
13489
+ for (const shape of page.shapes)
13490
+ if (shape.kind === "group" || orders?.has(shape))
13491
+ shape.childShapeIds = resolve(shape);
13492
+ let issue = page.shapeOrderIssue;
13493
+ const queue = (root ?? []).map((id) => ({ id, depth: 0 })), visited = /* @__PURE__ */ new Set();
13494
+ if (root && !issue) {
13495
+ for (let i = 0; i < queue.length; i++) {
13496
+ const item = queue[i];
13497
+ if (item.depth > 64) {
13498
+ issue = "shape-order-depth";
13499
+ break;
13500
+ }
13501
+ if (visited.has(item.id)) {
13502
+ issue = "cyclic-shape-order";
13503
+ break;
13504
+ }
13505
+ visited.add(item.id);
13506
+ const shape = shapes.get(item.id);
13507
+ if (shape.shapeOrderIssue) {
13508
+ issue = "unresolved-child-order";
13509
+ break;
13510
+ }
13511
+ for (const id of shape.childShapeIds ?? [])
13512
+ queue.push({ id, depth: item.depth + 1 });
13513
+ }
13514
+ if (!issue && visited.size !== page.shapes.length)
13515
+ issue = "unreachable-shape-order";
13516
+ }
13517
+ if (issue) {
13518
+ page.shapeOrderIssue = issue;
13519
+ for (const shape of page.shapes)
13520
+ if (shape.childShapeIds) {
13521
+ shape.childShapeIds = void 0;
13522
+ shape.shapeOrderIssue ??= "unresolved-page-order";
13523
+ }
13524
+ } else
13525
+ page.topLevelShapeIds = root;
13526
+ }
11952
13527
  return data;
11953
13528
  }
11954
13529
 
11955
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/vsd-writer.js
11956
- function replaceRecord(input, drawing, record4, replacement) {
13530
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-compression-fit.js
13531
+ var VSD_COMPRESSION_FIT_MAX_BYTES = 8 * 1024 * 1024;
13532
+ var MAX_INPUT = VSD_COMPRESSION_FIT_MAX_BYTES;
13533
+ var MAX_GAP = 4096;
13534
+ var MAX_PROBES = 16 * 1024 * 1024;
13535
+ var VsdCompressionFitError = class extends Error {
13536
+ reason;
13537
+ constructor(reason) {
13538
+ super(`VSD compression ${reason}`);
13539
+ this.reason = reason;
13540
+ this.name = "VsdCompressionFitError";
13541
+ }
13542
+ };
13543
+ function encodeVsdBlockToSize(input, capacity) {
13544
+ if (!(input instanceof Uint8Array) || input.length > MAX_INPUT || !Number.isSafeInteger(capacity) || capacity < 0 || capacity > MAX_INPUT)
13545
+ throw new VsdCompressionFitError("input-budget");
13546
+ const output = new Uint8Array(capacity), heads = new Int32Array(65536).fill(-1), previous = new Int32Array(input.length).fill(-1);
13547
+ let cursor = 0, flagOffset = -1, bit = 8, tokens = 0, probes = 0;
13548
+ const tailSize = 4096, positions = new Int32Array(tailSize), lengths = new Uint8Array(tailSize), sources = new Int32Array(tailSize), starts = new Int32Array(tailSize);
13549
+ function emit(literal2, a, b) {
13550
+ const size = (bit === 8 ? 1 : 0) + (literal2 ? 1 : 2);
13551
+ if (size > capacity - cursor)
13552
+ return false;
13553
+ if (bit === 8) {
13554
+ flagOffset = cursor++;
13555
+ output[flagOffset] = 0;
13556
+ bit = 0;
13557
+ }
13558
+ if (literal2)
13559
+ output[flagOffset] |= 1 << bit;
13560
+ output[cursor++] = a;
13561
+ if (!literal2)
13562
+ output[cursor++] = b;
13563
+ bit++;
13564
+ tokens++;
13565
+ return true;
13566
+ }
13567
+ const hash2 = (p) => (input[p] * 251 + input[p + 1]) * 251 + input[p + 2] & 65535;
13568
+ function remember(p) {
13569
+ if (p + 2 < input.length) {
13570
+ const h = hash2(p);
13571
+ previous[p] = heads[h];
13572
+ heads[h] = p;
13573
+ }
13574
+ }
13575
+ function match(position) {
13576
+ let length = 0, source = -1;
13577
+ if (position < 4060) {
13578
+ while (length < 18 && position + length < input.length && input[position + length] === 0)
13579
+ length++;
13580
+ if (length >= 3)
13581
+ source = -18;
13582
+ else
13583
+ length = 0;
13584
+ }
13585
+ if (position + 2 < input.length) {
13586
+ let candidate = heads[hash2(position)], attempts = 0;
13587
+ while (candidate >= Math.max(0, position - 4096) && candidate < position && attempts++ < 512) {
13588
+ let n = 0;
13589
+ while (n < 18 && position + n < input.length) {
13590
+ if (++probes > MAX_PROBES)
13591
+ throw new VsdCompressionFitError("work-limit");
13592
+ if (input[candidate + n] !== input[position + n])
13593
+ break;
13594
+ n++;
13595
+ }
13596
+ if (n >= 3 && n > length) {
13597
+ length = n;
13598
+ source = candidate;
13599
+ if (n === 18)
13600
+ break;
13601
+ }
13602
+ candidate = previous[candidate];
13603
+ }
13604
+ }
13605
+ return { length, source };
13606
+ }
13607
+ for (let position = 0; position < input.length; ) {
13608
+ let { length, source } = match(position);
13609
+ if (length >= 3 && length < 18 && position + 1 < input.length && match(position + 1).length > length + 1)
13610
+ length = 0;
13611
+ const slot = tokens % tailSize;
13612
+ positions[slot] = position;
13613
+ lengths[slot] = length >= 3 ? length : 1;
13614
+ sources[slot] = source;
13615
+ starts[slot] = cursor;
13616
+ if (length >= 3) {
13617
+ const address = source - 18 & 4095;
13618
+ if (!emit(false, address & 255, address >> 4 & 240 | length - 3))
13619
+ return void 0;
13620
+ } else {
13621
+ length = 1;
13622
+ if (!emit(true, input[position]))
13623
+ return void 0;
13624
+ }
13625
+ for (let i = 0; i < length; i++)
13626
+ remember(position + i);
13627
+ position += length;
13628
+ }
13629
+ const remaining = capacity - cursor;
13630
+ if (remaining) {
13631
+ if (remaining > MAX_GAP || !tokens)
13632
+ return void 0;
13633
+ const baseTokens = tokens, tailStart = Math.ceil(Math.max(0, tokens - tailSize) / 8) * 8;
13634
+ let states2 = [{ extra: 0, count: 0, cost: 0, index: -1, k: 0 }], answer, planningWork = 0, nodes = 0, references = 0;
13635
+ for (let index = tokens - 1; index >= tailStart && !answer; index--) {
13636
+ const length = lengths[index % tailSize];
13637
+ if (length < 3)
13638
+ continue;
13639
+ if (++references > 512)
13640
+ break;
13641
+ const next = /* @__PURE__ */ new Map();
13642
+ for (const state of states2)
13643
+ next.set(state.cost * 8 + (baseTokens + state.count) % 8, state);
13644
+ for (const state of states2) {
13645
+ for (let k = 1; k <= length; k++) {
13646
+ if (++planningWork > 1024 * 1024 || nodes >= 65536)
13647
+ throw new VsdCompressionFitError("work-limit");
13648
+ if (k > length - 3 && k !== length)
13649
+ continue;
13650
+ const count = state.count + (k === length ? k - 1 : k), extra = state.extra + (k === length ? k - 2 : k), cost = extra + Math.ceil((baseTokens + count) / 8) - Math.ceil(baseTokens / 8);
13651
+ if (cost > remaining)
13652
+ continue;
13653
+ const key2 = cost * 8 + (baseTokens + count) % 8;
13654
+ if (next.has(key2))
13655
+ continue;
13656
+ const node = { extra, count, cost, parent: state, index, k };
13657
+ nodes++;
13658
+ if (cost === remaining) {
13659
+ answer = node;
13660
+ break;
13661
+ }
13662
+ next.set(key2, node);
13663
+ }
13664
+ if (answer)
13665
+ break;
13666
+ }
13667
+ states2 = [...next.values()].sort((a, b) => b.cost - a.cost).slice(0, 63);
13668
+ if (!states2.some((p) => p.cost === 0))
13669
+ states2.push({ extra: 0, count: 0, cost: 0, index: -1, k: 0 });
13670
+ }
13671
+ if (!answer)
13672
+ return void 0;
13673
+ const changes = /* @__PURE__ */ new Map();
13674
+ for (let node = answer; node?.parent; node = node.parent)
13675
+ changes.set(node.index, node.k);
13676
+ cursor = starts[tailStart % tailSize];
13677
+ bit = 8;
13678
+ flagOffset = -1;
13679
+ tokens = tailStart;
13680
+ for (let index = tailStart; index < baseTokens; index++) {
13681
+ const slot = index % tailSize, position = positions[slot], length = lengths[slot], k = changes.get(index) ?? 0;
13682
+ for (let j = 0; j < k; j++)
13683
+ if (!emit(true, input[position + j]))
13684
+ return void 0;
13685
+ if (k < length) {
13686
+ if (length === 1) {
13687
+ if (!emit(true, input[position]))
13688
+ return void 0;
13689
+ } else {
13690
+ const address = sources[slot] + k - 18 & 4095;
13691
+ if (!emit(false, address & 255, address >> 4 & 240 | length - k - 3))
13692
+ return void 0;
13693
+ }
13694
+ }
13695
+ }
13696
+ }
13697
+ if (cursor !== capacity)
13698
+ return void 0;
13699
+ const decoded = decodeVsdBlock(output, input.length);
13700
+ if (decoded.length !== input.length || !input.every((v, i) => decoded[i] === v))
13701
+ throw new VsdCompressionFitError("verification");
13702
+ return { bytes: output, paddingBytes: 0 };
13703
+ }
13704
+
13705
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-writer.js
13706
+ function replaceRecord(input, drawing, record5, replacement) {
11957
13707
  if (!drawing.writable)
11958
13708
  throw new VsdError("shared-or-overlapping-allocation");
11959
- let block = record4.block, decoded = block.bytes.slice();
11960
- decoded.set(replacement, record4.offset);
11961
- const appended = [];
11962
- let size = drawing.stream.length;
11963
- const header = drawing.stream.slice();
11964
- for (; ; ) {
11965
- const stored = block.format & 2 ? encodeVsdBlock(decoded) : decoded;
11966
- if (stored.length > VSD_MAX_BYTES - size)
11967
- throw new VsdError("writer-size-limit");
11968
- const offset2 = size;
11969
- appended.push(stored);
11970
- size += stored.length;
11971
- const owner = block.parent ? block.parent.bytes.slice() : header;
11972
- const view2 = new DataView(owner.buffer, owner.byteOffset, owner.byteLength);
11973
- view2.setUint32(block.pointerOffset + 8, offset2, true);
11974
- view2.setUint32(block.pointerOffset + 12, stored.length, true);
11975
- if (!block.parent)
11976
- break;
11977
- block = block.parent;
11978
- decoded = owner;
11979
- }
11980
- const stream = new Uint8Array(size);
11981
- stream.set(header);
11982
- let offset = header.length;
11983
- for (const bytes of appended) {
11984
- stream.set(bytes, offset);
11985
- offset += bytes.length;
13709
+ if (record5.block.format & 2 && (record5.block.bytes.length > VSD_COMPRESSION_FIT_MAX_BYTES || record5.block.length > VSD_COMPRESSION_FIT_MAX_BYTES))
13710
+ throw new VsdError("compression-input-budget");
13711
+ const block = record5.block, decoded = block.bytes.slice();
13712
+ decoded.set(replacement, record5.offset);
13713
+ let stored = block.format & 2 ? encodeVsdBlock(decoded) : decoded;
13714
+ if (stored.length !== block.length) {
13715
+ if (!(block.format & 2) || ![8, 12, 13].includes(block.format >>> 4))
13716
+ throw new VsdError("unsafe-block-relocation");
13717
+ try {
13718
+ const fit = encodeVsdBlockToSize(decoded, block.length);
13719
+ if (!fit)
13720
+ throw new VsdError("unsafe-block-relocation");
13721
+ stored = fit.bytes;
13722
+ } catch (error) {
13723
+ if (error instanceof VsdCompressionFitError)
13724
+ throw new VsdError(`compression-${error.reason}`);
13725
+ throw error;
13726
+ }
11986
13727
  }
11987
- new DataView(stream.buffer).setUint32(28, stream.length, true);
13728
+ const stream = drawing.stream.slice();
13729
+ stream.set(stored, block.offset);
11988
13730
  const result = resizeCompoundFileStream(input, drawing.streamPath, stream);
11989
13731
  if (!result.ok)
11990
13732
  throw new VsdError(`compound-resize-${result.reason}`);
@@ -12044,7 +13786,7 @@ function replaceVsdShapeTransform(input, pageId, shapeId, transform2) {
12044
13786
  return candidate;
12045
13787
  }
12046
13788
 
12047
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/vsd-document.js
13789
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/vsd-document.js
12048
13790
  var VsdShape = class {
12049
13791
  id;
12050
13792
  #read;
@@ -12091,6 +13833,14 @@ var VsdShape = class {
12091
13833
  set transform(value) {
12092
13834
  this.#editTransform(value);
12093
13835
  }
13836
+ /** Validated drawing order of this owner's explicit children; undefined when unresolved. */
13837
+ get childShapeIds() {
13838
+ const ids = this.#read().childShapeIds;
13839
+ return ids && Object.freeze([...ids]);
13840
+ }
13841
+ get shapeOrderIssue() {
13842
+ return this.#read().shapeOrderIssue;
13843
+ }
12094
13844
  get geometry() {
12095
13845
  return Object.freeze(this.#read().geometry.map((row) => Object.freeze({ ...row })));
12096
13846
  }
@@ -12105,6 +13855,14 @@ var VsdPage = class {
12105
13855
  this.shapes = Object.freeze(shapes);
12106
13856
  Object.freeze(this);
12107
13857
  }
13858
+ /** Validated top-level drawing order. The existing shapes array remains flat. */
13859
+ get topLevelShapeIds() {
13860
+ const ids = this.#read().topLevelShapeIds;
13861
+ return ids && Object.freeze([...ids]);
13862
+ }
13863
+ get shapeOrderIssue() {
13864
+ return this.#read().shapeOrderIssue;
13865
+ }
12108
13866
  get background() {
12109
13867
  return this.#read().background;
12110
13868
  }
@@ -12119,7 +13877,7 @@ var VsdPage = class {
12119
13877
  return this.#read().scale;
12120
13878
  }
12121
13879
  };
12122
- var CAPABILITIES = Object.freeze({ read: Object.freeze(["v11-pages", "explicit-shape-transform", "utf16-shape-text", "move-to-line-to"]), write: Object.freeze(["equal-length-shape-text", "literal-shape-transform"]), limitations: Object.freeze(["Version 11 only; stored values without master/style/formula evaluation.", "No added/deleted shapes, text length changes or text field edits.", "Shared/overlapping VSD blocks cannot be edited; no native Visio fidelity claim."]) });
13880
+ var CAPABILITIES = Object.freeze({ read: Object.freeze(["v11-pages", "validated-page-and-group-order", "explicit-shape-transform", "utf16-shape-text", "move-to-line-to"]), write: Object.freeze(["equal-length-shape-text", "literal-shape-transform"]), limitations: Object.freeze(["Version 11 only; stored values without master/style/formula evaluation.", "Drawing order may be unresolved; flat shape arrays retain physical order and group coordinates stay local.", "Edits require an exact stored-block fit at the original offset; relocation is refused. Bounded compression preserves exact decoded length and supports at most 8 MiB decoded leaf/allocation, with bounded token-fit search and no added decoded bytes.", "No added/deleted shapes, text length changes or text field edits.", "Shared/overlapping VSD blocks cannot be edited; native evidence covers only declared fixture edits, not full Visio fidelity."]) });
12123
13881
  var VsdDocument = class extends Ole2DocumentBase {
12124
13882
  #drawing;
12125
13883
  #pages;
@@ -12179,7 +13937,7 @@ var VsdDocument = class extends Ole2DocumentBase {
12179
13937
  }
12180
13938
  };
12181
13939
 
12182
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/ole2-document.js
13940
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/ole2-document.js
12183
13941
  var CfbDocument = class extends Ole2DocumentBase {
12184
13942
  get kind() {
12185
13943
  return "cfb";
@@ -12292,7 +14050,7 @@ function parseVsd(input) {
12292
14050
  return parseOle22(input, { expect: "vsd" });
12293
14051
  }
12294
14052
 
12295
- // node_modules/.bun/@christophervr+ole2@0.8.0/node_modules/@christophervr/ole2/dist/utils/png-encoder.js
14053
+ // node_modules/.bun/@christophervr+ole2@0.12.0/node_modules/@christophervr/ole2/dist/utils/png-encoder.js
12296
14054
  (() => {
12297
14055
  const table = new Uint32Array(256);
12298
14056
  for (let n = 0; n < 256; n++) {
@@ -14540,7 +16298,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
14540
16298
  return result;
14541
16299
  };
14542
16300
  let steps = 1e5;
14543
- const inspect4 = (binding, name) => {
16301
+ const inspect6 = (binding, name) => {
14544
16302
  check();
14545
16303
  if (--steps < 0) problem("Master dependency proof exceeded its cell budget.");
14546
16304
  name = name.toLowerCase();
@@ -14565,7 +16323,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
14565
16323
  txtlocpiny: "txtheight"
14566
16324
  };
14567
16325
  const dimension = defaults[name];
14568
- if (dimension) inspect4(binding, dimension);
16326
+ if (dimension) inspect6(binding, dimension);
14569
16327
  else if (!themeCell.test(name)) problem(`Missing effective master reference ${name}.`);
14570
16328
  } else {
14571
16329
  const formula = executableCellFormula(attribute2(source.node, "F"));
@@ -14586,17 +16344,17 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
14586
16344
  for (const ref of analysis.references) {
14587
16345
  if (analysis.readsText && ref.shapeId === void 0 && ref.cell.toLowerCase() === "thetext")
14588
16346
  continue;
14589
- if (ref.shapeId === void 0) inspect4(binding, ref.cell);
16347
+ if (ref.shapeId === void 0) inspect6(binding, ref.cell);
14590
16348
  else if (source.kind === "template") {
14591
16349
  const target = binding.context.get(ref.shapeId);
14592
16350
  if (!target) problem("Missing master-local Sheet reference.");
14593
- inspect4(target, ref.cell);
16351
+ inspect6(target, ref.cell);
14594
16352
  } else {
14595
16353
  if (source.kind === "style")
14596
16354
  problem("Explicit sheet references in inherited master styles are ambiguous.");
14597
16355
  if (directAffected(binding.pageId, ref.shapeId, ref.cell) || query({ pageId: binding.pageId, shapeId: ref.shapeId, cell: ref.cell }, changed))
14598
16356
  problem("Effective master cache depends on an edited page shape.");
14599
- inspect4(pageInput(binding.pageId, ref.shapeId), ref.cell);
16357
+ inspect6(pageInput(binding.pageId, ref.shapeId), ref.cell);
14600
16358
  }
14601
16359
  }
14602
16360
  if (analysis.readsText) {
@@ -14604,7 +16362,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
14604
16362
  if (/^(character\.|paragraph\.|tabs\.|leftmargin$|rightmargin$|topmargin$|bottommargin$)/i.test(
14605
16363
  cell
14606
16364
  ))
14607
- inspect4(binding, cell);
16365
+ inspect6(binding, cell);
14608
16366
  }
14609
16367
  }
14610
16368
  }
@@ -14616,7 +16374,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
14616
16374
  const source = binding.cells.get(name);
14617
16375
  if (["pinx", "piny"].includes(name) && source?.kind === "instance" && movePins.pins.has(source.node))
14618
16376
  continue;
14619
- inspect4(binding, name);
16377
+ inspect6(binding, name);
14620
16378
  }
14621
16379
  return movePins;
14622
16380
  }