ooxml-core 1.3.0 → 1.5.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 (94) hide show
  1. package/README.md +2 -0
  2. package/dist/automation/index.cjs +6089 -5381
  3. package/dist/automation/index.mjs +6089 -5381
  4. package/dist/teams/index.cjs +73 -23
  5. package/dist/teams/index.mjs +73 -23
  6. package/dist/visio/basic-shapes.d.ts +18 -0
  7. package/dist/visio/basic-shapes.d.ts.map +1 -0
  8. package/dist/visio/edit-commands.d.ts +13 -2
  9. package/dist/visio/edit-commands.d.ts.map +1 -1
  10. package/dist/visio/edit-page-size.d.ts +5 -0
  11. package/dist/visio/edit-page-size.d.ts.map +1 -0
  12. package/dist/visio/edit-pages.d.ts.map +1 -1
  13. package/dist/visio/edit-shape-create.d.ts.map +1 -1
  14. package/dist/visio/edit-text-range-commands.d.ts +21 -0
  15. package/dist/visio/edit-text-range-commands.d.ts.map +1 -0
  16. package/dist/visio/edit-text-range-plan.d.ts +7 -0
  17. package/dist/visio/edit-text-range-plan.d.ts.map +1 -0
  18. package/dist/visio/edit-text-ranges.d.ts +4 -0
  19. package/dist/visio/edit-text-ranges.d.ts.map +1 -0
  20. package/dist/visio/edit-text-target.d.ts +3 -0
  21. package/dist/visio/edit-text-target.d.ts.map +1 -0
  22. package/dist/visio/edit-text.d.ts.map +1 -1
  23. package/dist/visio/edit.d.ts +1 -1
  24. package/dist/visio/edit.d.ts.map +1 -1
  25. package/dist/visio/index.cjs +623 -49
  26. package/dist/visio/index.d.ts +2 -1
  27. package/dist/visio/index.d.ts.map +1 -1
  28. package/dist/visio/index.mjs +621 -50
  29. package/dist/visio/model.d.ts +3 -0
  30. package/dist/visio/model.d.ts.map +1 -1
  31. package/dist/visio/parser.d.ts.map +1 -1
  32. package/dist/visio/ui/draw-plan.d.ts +4 -1
  33. package/dist/visio/ui/draw-plan.d.ts.map +1 -1
  34. package/dist/visio/ui/edit-commands.d.ts.map +1 -1
  35. package/dist/visio/ui/index.cjs +139 -14
  36. package/dist/visio/ui/index.d.ts +1 -0
  37. package/dist/visio/ui/index.d.ts.map +1 -1
  38. package/dist/visio/ui/index.mjs +135 -15
  39. package/dist/visio/ui/page-size.d.ts +31 -0
  40. package/dist/visio/ui/page-size.d.ts.map +1 -0
  41. package/dist/visio/ui/scene-validation.d.ts.map +1 -1
  42. package/dist/visio/ui/snapshot-scene.d.ts.map +1 -1
  43. package/dist/visio/ui/text-replace-types.d.ts +6 -2
  44. package/dist/visio/ui/text-replace-types.d.ts.map +1 -1
  45. package/dist/visio/ui/text-replace.d.ts +3 -4
  46. package/dist/visio/ui/text-replace.d.ts.map +1 -1
  47. package/dist/visio/xml-validation.d.ts.map +1 -1
  48. package/dist/xlsx/collab/codec.d.ts +2 -0
  49. package/dist/xlsx/collab/codec.d.ts.map +1 -1
  50. package/dist/xlsx/collab/index.cjs +5 -0
  51. package/dist/xlsx/collab/index.mjs +5 -0
  52. package/dist/xlsx/display-text.d.ts +4 -0
  53. package/dist/xlsx/display-text.d.ts.map +1 -0
  54. package/dist/xlsx/edit/cell-values.d.ts +4 -3
  55. package/dist/xlsx/edit/cell-values.d.ts.map +1 -1
  56. package/dist/xlsx/edit/clipboard.d.ts.map +1 -1
  57. package/dist/xlsx/edit/context.d.ts +7 -5
  58. package/dist/xlsx/edit/context.d.ts.map +1 -1
  59. package/dist/xlsx/edit/deps.d.ts +1 -1
  60. package/dist/xlsx/edit/deps.d.ts.map +1 -1
  61. package/dist/xlsx/edit/dimensions.d.ts.map +1 -1
  62. package/dist/xlsx/edit/fill.d.ts.map +1 -1
  63. package/dist/xlsx/edit/filter.d.ts.map +1 -1
  64. package/dist/xlsx/edit/find.d.ts.map +1 -1
  65. package/dist/xlsx/edit/paste-selection.d.ts.map +1 -1
  66. package/dist/xlsx/edit/shift-formulas.d.ts +10 -4
  67. package/dist/xlsx/edit/shift-formulas.d.ts.map +1 -1
  68. package/dist/xlsx/edit/shift-sheet.d.ts.map +1 -1
  69. package/dist/xlsx/edit/structure.d.ts +1 -1
  70. package/dist/xlsx/edit/structure.d.ts.map +1 -1
  71. package/dist/xlsx/edit/table-header-names.d.ts +3 -0
  72. package/dist/xlsx/edit/table-header-names.d.ts.map +1 -0
  73. package/dist/xlsx/edit/tables.d.ts +1 -2
  74. package/dist/xlsx/edit/tables.d.ts.map +1 -1
  75. package/dist/xlsx/filter-rows.d.ts +12 -0
  76. package/dist/xlsx/filter-rows.d.ts.map +1 -0
  77. package/dist/xlsx/formula/functions/math-sum.d.ts.map +1 -1
  78. package/dist/xlsx/formula/table-refs.d.ts +2 -0
  79. package/dist/xlsx/formula/table-refs.d.ts.map +1 -1
  80. package/dist/xlsx/index.cjs +466 -329
  81. package/dist/xlsx/index.mjs +466 -329
  82. package/dist/xlsx/load/index.cjs +7622 -7585
  83. package/dist/xlsx/load/index.mjs +7622 -7585
  84. package/dist/xlsx/model.d.ts +4 -0
  85. package/dist/xlsx/model.d.ts.map +1 -1
  86. package/dist/xlsx/read/load.d.ts.map +1 -1
  87. package/dist/xlsx/ui/index.cjs +464 -329
  88. package/dist/xlsx/ui/index.mjs +464 -329
  89. package/dist/xlsx/ui/locales/de/shell.d.ts.map +1 -1
  90. package/dist/xlsx/ui/locales/en/shell.d.ts.map +1 -1
  91. package/dist/xlsx/ui/locales/es/shell.d.ts.map +1 -1
  92. package/dist/xlsx/ui/locales/fr/shell.d.ts.map +1 -1
  93. package/dist/xlsx/ui/locales/zh-CN/shell.d.ts.map +1 -1
  94. package/package.json +1 -1
@@ -227,6 +227,19 @@ var attribute = new RegExp(
227
227
  "uy"
228
228
  );
229
229
  var xmlWhitespace = (value) => /^[ \t\r\n]*$/.test(value);
230
+ var reservedNamespaces = /* @__PURE__ */ new Map([
231
+ ["xml", "http://www.w3.org/XML/1998/namespace"],
232
+ ["xmlns", "http://www.w3.org/2000/xmlns/"]
233
+ ]);
234
+ function lookupNamespace(scope, prefix) {
235
+ const reserved = reservedNamespaces.get(prefix);
236
+ if (reserved !== void 0) return reserved;
237
+ for (; scope; scope = scope.parent) {
238
+ const uri = scope.bindings.get(prefix);
239
+ if (uri !== void 0) return uri;
240
+ }
241
+ return void 0;
242
+ }
230
243
  function inspectXml(xml, limits, check, encoding = "utf-8") {
231
244
  if (xml.length > limits.maxXmlChars) fail("LIMIT_XML", "XML character limit exceeded");
232
245
  if (/<!DOCTYPE|<!ENTITY/i.test(xml) || /[\u0000-\u0008\u000b\u000c\u000e-\u001f\ufffe\uffff]/.test(xml))
@@ -292,9 +305,7 @@ function inspectXml(xml, limits, check, encoding = "utf-8") {
292
305
  fail("INVALID_XML", "Mismatched XML closing tag");
293
306
  } else {
294
307
  const attrs = /* @__PURE__ */ new Set();
295
- const namespaces = Object.create(stack.at(-1)?.namespaces ?? null);
296
- namespaces["xml"] = "http://www.w3.org/XML/1998/namespace";
297
- namespaces["xmlns"] = "http://www.w3.org/2000/xmlns/";
308
+ const namespaces = { bindings: /* @__PURE__ */ new Map(), parent: stack.at(-1)?.namespaces };
298
309
  while (!xmlWhitespace(body.slice(cursor))) {
299
310
  attribute.lastIndex = cursor;
300
311
  const match = attribute.exec(body);
@@ -304,14 +315,14 @@ function inspectXml(xml, limits, check, encoding = "utf-8") {
304
315
  const value = match[2] ?? match[3] ?? "";
305
316
  text(value);
306
317
  if (match[1]?.startsWith("xmlns:"))
307
- namespaces[match[1].slice(6)] = decodeXmlAttribute(value);
318
+ namespaces.bindings.set(match[1].slice(6), decodeXmlAttribute(value));
308
319
  node();
309
320
  cursor = attribute.lastIndex;
310
321
  }
311
322
  const expanded = /* @__PURE__ */ new Set();
312
323
  for (const attr2 of attrs) {
313
324
  const colon = attr2.indexOf(":");
314
- const uri = colon < 0 ? "" : namespaces[attr2.slice(0, colon)];
325
+ const uri = colon < 0 ? "" : lookupNamespace(namespaces, attr2.slice(0, colon));
315
326
  if (uri === void 0) fail("INVALID_XML", "Unbound XML attribute prefix");
316
327
  const key2 = `${uri}\0${attr2.slice(colon + 1)}`;
317
328
  if (expanded.has(key2)) fail("INVALID_XML", "Duplicate expanded XML attribute name");
@@ -6595,11 +6606,23 @@ async function parseVsdx(input, options = {}) {
6595
6606
  };
6596
6607
  visit(shapes);
6597
6608
  const connectors = connections(root2, localReport);
6609
+ const pageModes = {};
6610
+ for (const [name, key2] of [
6611
+ ["DrawingSizeType", "drawingSizeType"],
6612
+ ["DrawingResizeType", "drawingResizeType"]
6613
+ ]) {
6614
+ const source = sheet.cells.get(name);
6615
+ if (!source || source.error !== void 0 || source.formula === "Inh" || source.unit !== void 0 && !["NUM", "BOOL"].includes(source.unit))
6616
+ continue;
6617
+ const value = number(sheet.cells, name, Number.NaN, localReport);
6618
+ if (Number.isSafeInteger(value) && value >= 0 && value <= 255) pageModes[key2] = value;
6619
+ }
6598
6620
  for (const connection of connectors)
6599
6621
  if (!seen.has(connection.fromShapeId) || !seen.has(connection.toShapeId))
6600
6622
  localReport("dangling-connection", "A connection references a missing shape.");
6601
6623
  pages.push({
6602
6624
  id,
6625
+ ...pageModes,
6603
6626
  ...drawingToPageScale === 1 ? {} : { drawingToPageScale },
6604
6627
  name: metadata(
6605
6628
  attribute2(page, "Name") ?? attribute2(page, "NameU") ?? `Page ${id}`,
@@ -15228,10 +15251,10 @@ function replaceRecord(input, drawing, record5, replacement) {
15228
15251
  if (!(block.format & 2) || ![8, 12, 13].includes(block.format >>> 4))
15229
15252
  throw new VsdError("unsafe-block-relocation");
15230
15253
  try {
15231
- const fit = encodeVsdBlockToSize(decoded, block.length);
15232
- if (!fit)
15254
+ const fit2 = encodeVsdBlockToSize(decoded, block.length);
15255
+ if (!fit2)
15233
15256
  throw new VsdError("unsafe-block-relocation");
15234
- stored = fit.bytes;
15257
+ stored = fit2.bytes;
15235
15258
  } catch (error) {
15236
15259
  if (error instanceof VsdCompressionFitError)
15237
15260
  throw new VsdError(`compression-${error.reason}`);
@@ -17411,8 +17434,8 @@ function assertUnlayeredShape(shape, document) {
17411
17434
  }
17412
17435
  }
17413
17436
 
17414
- // visio/edit-text.ts
17415
- async function replacePlainText(root2, document, shapeId, text, check, assertDependencies) {
17437
+ // visio/edit-text-target.ts
17438
+ function localTextTarget(root2, document, shapeId, check) {
17416
17439
  const shapeChildren = (parent) => {
17417
17440
  const containers = children2(parent, "Shapes");
17418
17441
  if (containers.length > 1)
@@ -17420,37 +17443,38 @@ async function replacePlainText(root2, document, shapeId, text, check, assertDep
17420
17443
  return children2(containers[0], "Shape");
17421
17444
  };
17422
17445
  const shapes = /* @__PURE__ */ new Map();
17423
- const pending = shapeChildren(root2).map((node2) => ({
17424
- node: node2,
17425
- inherited: false,
17426
- deleted: false
17427
- }));
17446
+ const pending = shapeChildren(root2).map((node) => ({ node, inherited: false, deleted: false }));
17428
17447
  while (pending.length) {
17429
17448
  check();
17430
- const item = pending.pop();
17431
- const id = attribute2(item.node, "ID");
17449
+ const item = pending.pop(), id = attribute2(item.node, "ID");
17432
17450
  if (!id || shapes.has(id))
17433
17451
  fail("INVALID_SHAPE_ID", "Local shape IDs must be present and unique.");
17434
17452
  const inherited = item.inherited || item.node.hasAttribute("Master") || item.node.hasAttribute("MasterShape");
17435
17453
  const deleted = item.deleted || ["1", "true"].includes(attribute2(item.node, "Del") ?? "");
17436
17454
  shapes.set(id, { node: item.node, inherited, deleted });
17437
- for (const node2 of shapeChildren(item.node)) pending.push({ node: node2, inherited, deleted });
17455
+ for (const node of shapeChildren(item.node)) pending.push({ node, inherited, deleted });
17438
17456
  }
17439
17457
  const target = shapes.get(shapeId);
17440
17458
  if (!target) fail("EDIT_TARGET_NOT_FOUND", "Local shape does not exist.");
17441
17459
  if (target.inherited || target.deleted)
17442
17460
  fail("UNSUPPORTED_TEXT_EDIT", "Master-linked or deleted shapes cannot be edited.");
17443
17461
  assertShapeLocks(target.node, document, ["LockTextEdit"]);
17444
- const texts = children2(target.node, "Text");
17462
+ return target.node;
17463
+ }
17464
+
17465
+ // visio/edit-text.ts
17466
+ async function replacePlainText(root2, document, shapeId, text, check, assertDependencies2) {
17467
+ const target = localTextTarget(root2, document, shapeId, check);
17468
+ const texts = children2(target, "Text");
17445
17469
  if (texts.length !== 1)
17446
17470
  fail("UNSUPPORTED_TEXT_EDIT", "Editing requires one existing local Text element.");
17447
17471
  const node = texts[0];
17448
17472
  if (Array.from(node.childNodes).some((item) => item.nodeType !== 3 && item.nodeType !== 4))
17449
17473
  fail("UNSUPPORTED_TEXT_EDIT", "Rich text, fields and unknown text markup cannot be edited.");
17450
- if (children2(target.node, "Section").some((section) => attribute2(section, "N") === "Field"))
17474
+ if (children2(target, "Section").some((section) => attribute2(section, "N") === "Field"))
17451
17475
  fail("UNSUPPORTED_TEXT_EDIT", "Shapes with text fields cannot be edited.");
17452
17476
  if (decodeVisioPlainText(node.textContent ?? "") === text) return false;
17453
- await assertDependencies(target.node, node);
17477
+ await assertDependencies2(target, node);
17454
17478
  check();
17455
17479
  while (node.firstChild) node.removeChild(node.firstChild);
17456
17480
  node.appendChild(node.ownerDocument.createTextNode(encodeVisioPlainText(text)));
@@ -17544,6 +17568,394 @@ function replaceScopedPlainText(pkg, pagePaths, roots, document, edit, check) {
17544
17568
  );
17545
17569
  }
17546
17570
 
17571
+ // visio/edit-text-range-plan.ts
17572
+ function textRangeNodes(node, edit) {
17573
+ const tokens2 = [];
17574
+ let stored = "";
17575
+ for (const part of Array.from(node.childNodes)) {
17576
+ const start = stored.length;
17577
+ if (part.nodeType === 3 || part.nodeType === 4) stored += part.nodeValue ?? "";
17578
+ tokens2.push({ node: part, start, end: stored.length });
17579
+ }
17580
+ if (decodeVisioPlainText(stored) !== edit.expectedText)
17581
+ fail("EDIT_STALE_TEXT", "Original text no longer matches the range command.");
17582
+ const changed = edit.ranges.some(
17583
+ (range) => edit.expectedText.slice(range.start, range.end) !== range.text
17584
+ );
17585
+ if (!changed) return { changed: false, nodes: [] };
17586
+ const starts = [], deltas = [];
17587
+ let delta = 0;
17588
+ for (const range of edit.ranges) {
17589
+ starts.push(range.start + delta);
17590
+ delta += range.text.length - (range.end - range.start);
17591
+ deltas.push(delta);
17592
+ }
17593
+ const length = edit.expectedText.length + delta;
17594
+ if (!length && tokens2.some((token) => token.node.nodeType === 1))
17595
+ fail(
17596
+ "UNSUPPORTED_TEXT_RANGE",
17597
+ "Deleting all rich text has unproven native insertion-style behavior."
17598
+ );
17599
+ if (tokens2.some((token) => token.node.nodeType === 1)) {
17600
+ let start = 0, index = 0;
17601
+ while (start < edit.expectedText.length) {
17602
+ const newline = edit.expectedText.indexOf("\n", start), end = newline < 0 ? edit.expectedText.length : newline;
17603
+ let bodyLength = end - start;
17604
+ while (index < edit.ranges.length && edit.ranges[index].start < end) {
17605
+ const range = edit.ranges[index++];
17606
+ bodyLength += range.text.length - (range.end - range.start);
17607
+ }
17608
+ if (end > start && !bodyLength)
17609
+ fail(
17610
+ "UNSUPPORTED_TEXT_RANGE",
17611
+ "Deleting an entire rich paragraph body has unproven native insertion-style behavior."
17612
+ );
17613
+ start = end + 1;
17614
+ }
17615
+ }
17616
+ const position = (offset) => {
17617
+ let low = 0, high = edit.ranges.length;
17618
+ while (low < high) {
17619
+ const middle = low + high >>> 1;
17620
+ if (edit.ranges[middle].start < offset) low = middle + 1;
17621
+ else high = middle;
17622
+ }
17623
+ const index = low - 1;
17624
+ if (index < 0) return offset;
17625
+ const range = edit.ranges[index];
17626
+ return offset <= range.end ? starts[index] + range.text.length : offset + deltas[index];
17627
+ };
17628
+ const output = [];
17629
+ const append = (token, start, end) => {
17630
+ if (end <= start) return;
17631
+ const part = start === token.start && end === token.end ? token.node : token.node.cloneNode(false);
17632
+ if (part !== token.node)
17633
+ part.nodeValue = (token.node.nodeValue ?? "").slice(start - token.start, end - token.start);
17634
+ output.push({ position: position(start), priority: 2, node: part });
17635
+ };
17636
+ let first2 = 0;
17637
+ for (const token of tokens2) {
17638
+ if (token.node.nodeType === 1) {
17639
+ output.push({ position: position(token.start), priority: 0, node: token.node });
17640
+ continue;
17641
+ }
17642
+ const end = length ? token.end : Math.min(token.end, edit.expectedText.length);
17643
+ let cursor = token.start;
17644
+ while (first2 < edit.ranges.length && edit.ranges[first2].end <= cursor) first2++;
17645
+ for (let index = first2; index < edit.ranges.length && edit.ranges[index].start < end; index++) {
17646
+ const range = edit.ranges[index];
17647
+ append(token, cursor, Math.min(end, range.start));
17648
+ cursor = Math.max(cursor, Math.min(end, range.end));
17649
+ }
17650
+ append(token, cursor, end);
17651
+ }
17652
+ for (let index = 0; index < edit.ranges.length; index++) {
17653
+ const text = edit.ranges[index].text;
17654
+ if (text)
17655
+ output.push({
17656
+ position: starts[index],
17657
+ priority: 1,
17658
+ node: node.ownerDocument.createTextNode(text)
17659
+ });
17660
+ }
17661
+ output.sort((a, b) => a.position - b.position || a.priority - b.priority);
17662
+ let characterPosition = -1, characterRow = null;
17663
+ for (const item of output) {
17664
+ if (item.node.nodeType !== 1 || item.node.localName !== "cp") continue;
17665
+ const row = item.node.getAttribute("IX");
17666
+ if (item.position === characterPosition && row !== characterRow)
17667
+ fail(
17668
+ "UNSUPPORTED_TEXT_RANGE",
17669
+ "Consuming complete character runs creates ambiguous native marker boundaries."
17670
+ );
17671
+ characterPosition = item.position;
17672
+ characterRow = row;
17673
+ }
17674
+ return { changed: true, nodes: output.map((item) => item.node) };
17675
+ }
17676
+
17677
+ // visio/edit-text-ranges.ts
17678
+ async function replaceScopedTextRanges(pkg, pagePaths, roots, document, edit, check) {
17679
+ const shape = localTextTarget(roots.get(edit.pageId), document, edit.shapeId, check);
17680
+ if (children2(shape, "Section").some((section) => attribute2(section, "N") === "Field"))
17681
+ fail("UNSUPPORTED_TEXT_RANGE", "Text range editing of shapes with fields is unsupported.");
17682
+ const texts = children2(shape, "Text");
17683
+ if (texts.length !== 1)
17684
+ fail("UNSUPPORTED_TEXT_RANGE", "Range editing requires one existing local Text element.");
17685
+ const text = texts[0];
17686
+ if (Array.from(text.childNodes).some((node) => ![3, 4].includes(node.nodeType))) {
17687
+ const characters = effectiveFormattingRows(shape, document, "Character"), paragraphs = effectiveFormattingRows(shape, document, "Paragraph");
17688
+ assertFormattingText(shape, characters, paragraphs);
17689
+ }
17690
+ if (Array.from(text.childNodes).some(
17691
+ (node) => node.nodeType === 1 && node.localName === "fld"
17692
+ ))
17693
+ fail("UNSUPPORTED_TEXT_RANGE", "Text range editing of fields is unsupported.");
17694
+ let preceding = "";
17695
+ for (const node of Array.from(text.childNodes)) {
17696
+ if (node.nodeType === 3 || node.nodeType === 4) preceding += node.nodeValue ?? "";
17697
+ else {
17698
+ const marker2 = node;
17699
+ if (marker2.localName === "pp" && preceding && !preceding.endsWith("\n") || marker2.localName === "tp" && attribute2(marker2, "IX") !== "0")
17700
+ fail(
17701
+ "UNSUPPORTED_TEXT_RANGE",
17702
+ "Noncanonical paragraph or tab marker placement cannot be edited."
17703
+ );
17704
+ }
17705
+ }
17706
+ const plan = textRangeNodes(text, edit);
17707
+ if (!plan.changed) return false;
17708
+ await assertFormattingDependencies(
17709
+ pkg,
17710
+ pagePaths,
17711
+ roots,
17712
+ edit.pageId,
17713
+ shape,
17714
+ /* @__PURE__ */ new Map([["TheText", text]]),
17715
+ check
17716
+ );
17717
+ check();
17718
+ while (text.firstChild) text.removeChild(text.firstChild);
17719
+ for (const node of plan.nodes) text.appendChild(node);
17720
+ return true;
17721
+ }
17722
+
17723
+ // visio/basic-shapes.ts
17724
+ var VISIO_BASIC_SHAPES = [
17725
+ "rectangle",
17726
+ "square",
17727
+ "triangle",
17728
+ "right-triangle",
17729
+ "pentagon",
17730
+ "hexagon",
17731
+ "octagon",
17732
+ "star",
17733
+ "diamond",
17734
+ "rounded-rectangle",
17735
+ "cross",
17736
+ "parallelogram",
17737
+ "trapezoid",
17738
+ "can",
17739
+ "cube",
17740
+ "chevron"
17741
+ ];
17742
+ var isVisioBasicShape = (value) => VISIO_BASIC_SHAPES.includes(value);
17743
+ function fit(points) {
17744
+ const xs = points.map(([x]) => x), ys = points.map(([, y]) => y);
17745
+ const left = Math.min(...xs), bottom = Math.min(...ys);
17746
+ const width = Math.max(...xs) - left, height = Math.max(...ys) - bottom;
17747
+ return points.map(([x, y]) => [(x - left) / width, (y - bottom) / height]);
17748
+ }
17749
+ function polygon(count, inner) {
17750
+ const steps = inner === void 0 ? count : count * 2;
17751
+ return fit(
17752
+ Array.from({ length: steps }, (_, index) => {
17753
+ const radius = inner !== void 0 && index % 2 ? inner : 1;
17754
+ const angle = Math.PI / 2 + index * 2 * Math.PI / steps;
17755
+ return [radius * Math.cos(angle), radius * Math.sin(angle)];
17756
+ })
17757
+ );
17758
+ }
17759
+ function arc(cy, ry, from, to) {
17760
+ const segments = 12;
17761
+ return Array.from({ length: segments + 1 }, (_, index) => {
17762
+ const angle = from + (to - from) * index / segments;
17763
+ return [0.5 + 0.5 * Math.cos(angle), cy + ry * Math.sin(angle)];
17764
+ });
17765
+ }
17766
+ var box = [
17767
+ [0, 0],
17768
+ [1, 0],
17769
+ [1, 1],
17770
+ [0, 1]
17771
+ ];
17772
+ var LID = 0.2;
17773
+ var CUT = 1 / (2 + Math.SQRT2);
17774
+ var OUTLINES = {
17775
+ rectangle: { paths: [box] },
17776
+ square: { paths: [box] },
17777
+ triangle: {
17778
+ paths: [
17779
+ [
17780
+ [0, 0],
17781
+ [1, 0],
17782
+ [0.5, 1]
17783
+ ]
17784
+ ]
17785
+ },
17786
+ "right-triangle": {
17787
+ paths: [
17788
+ [
17789
+ [0, 0],
17790
+ [1, 0],
17791
+ [0, 1]
17792
+ ]
17793
+ ]
17794
+ },
17795
+ pentagon: { paths: [polygon(5)] },
17796
+ hexagon: {
17797
+ paths: [
17798
+ [
17799
+ [0.25, 0],
17800
+ [0.75, 0],
17801
+ [1, 0.5],
17802
+ [0.75, 1],
17803
+ [0.25, 1],
17804
+ [0, 0.5]
17805
+ ]
17806
+ ]
17807
+ },
17808
+ octagon: {
17809
+ paths: [
17810
+ [
17811
+ [CUT, 0],
17812
+ [1 - CUT, 0],
17813
+ [1, CUT],
17814
+ [1, 1 - CUT],
17815
+ [1 - CUT, 1],
17816
+ [CUT, 1],
17817
+ [0, 1 - CUT],
17818
+ [0, CUT]
17819
+ ]
17820
+ ]
17821
+ },
17822
+ star: { paths: [polygon(5, 0.382)] },
17823
+ diamond: {
17824
+ paths: [
17825
+ [
17826
+ [0.5, 0],
17827
+ [1, 0.5],
17828
+ [0.5, 1],
17829
+ [0, 0.5]
17830
+ ]
17831
+ ]
17832
+ },
17833
+ "rounded-rectangle": { paths: [box], rounding: 0.15 },
17834
+ cross: {
17835
+ paths: [
17836
+ [
17837
+ [1 / 3, 0],
17838
+ [2 / 3, 0],
17839
+ [2 / 3, 1 / 3],
17840
+ [1, 1 / 3],
17841
+ [1, 2 / 3],
17842
+ [2 / 3, 2 / 3],
17843
+ [2 / 3, 1],
17844
+ [1 / 3, 1],
17845
+ [1 / 3, 2 / 3],
17846
+ [0, 2 / 3],
17847
+ [0, 1 / 3],
17848
+ [1 / 3, 1 / 3]
17849
+ ]
17850
+ ]
17851
+ },
17852
+ parallelogram: {
17853
+ paths: [
17854
+ [
17855
+ [0, 0],
17856
+ [0.75, 0],
17857
+ [1, 1],
17858
+ [0.25, 1]
17859
+ ]
17860
+ ]
17861
+ },
17862
+ trapezoid: {
17863
+ paths: [
17864
+ [
17865
+ [0, 0],
17866
+ [1, 0],
17867
+ [0.75, 1],
17868
+ [0.25, 1]
17869
+ ]
17870
+ ]
17871
+ },
17872
+ can: {
17873
+ paths: [
17874
+ // The body: down the left side, round the front of the base, up the right side and
17875
+ // back along the front of the lid.
17876
+ [...arc(LID / 2, LID / 2, Math.PI, 2 * Math.PI), ...arc(1 - LID / 2, LID / 2, 0, -Math.PI)],
17877
+ // The lid, drawn over the body.
17878
+ arc(1 - LID / 2, LID / 2, 0, 2 * Math.PI).slice(0, -1)
17879
+ ]
17880
+ },
17881
+ cube: {
17882
+ paths: [
17883
+ [
17884
+ [0, 0],
17885
+ [0.75, 0],
17886
+ [0.75, 0.75],
17887
+ [0, 0.75]
17888
+ ],
17889
+ [
17890
+ [0, 0.75],
17891
+ [0.75, 0.75],
17892
+ [1, 1],
17893
+ [0.25, 1]
17894
+ ],
17895
+ [
17896
+ [0.75, 0],
17897
+ [1, 0.25],
17898
+ [1, 1],
17899
+ [0.75, 0.75]
17900
+ ]
17901
+ ]
17902
+ },
17903
+ chevron: {
17904
+ paths: [
17905
+ [
17906
+ [0, 0],
17907
+ [0.75, 0],
17908
+ [1, 0.5],
17909
+ [0.75, 1],
17910
+ [0, 1],
17911
+ [0.25, 0.5]
17912
+ ]
17913
+ ]
17914
+ }
17915
+ };
17916
+ function visioBasicShapeOutline(shape) {
17917
+ return OUTLINES[shape];
17918
+ }
17919
+
17920
+ // visio/edit-text-range-commands.ts
17921
+ var invalidXmlText = /[\u0000-\u0008\u000b\u000c\u000d\u000e-\u001f\ufffe\uffff]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/u;
17922
+ function textRangeBoundary(text, offset) {
17923
+ return !(offset > 0 && offset < text.length && /[\ud800-\udbff]/.test(text[offset - 1]) && /[\udc00-\udfff]/.test(text[offset]));
17924
+ }
17925
+ function snapshotTextRanges(edit, consume) {
17926
+ let characters = 0;
17927
+ const text = (value) => {
17928
+ if (typeof value !== "string" || invalidXmlText.test(value))
17929
+ fail("INVALID_EDIT_TEXT", "Range replacement requires valid XML text.");
17930
+ characters += value.length;
17931
+ if (characters > 1e6)
17932
+ fail("LIMIT_EDIT_TEXT", "Range replacement text exceeds input limits.");
17933
+ return consume ? consume(value) : value;
17934
+ };
17935
+ const pageId = edit.pageId, shapeId = edit.shapeId;
17936
+ if ([pageId, shapeId].some((id) => typeof id !== "string" || !id || id.length > 256))
17937
+ fail("INVALID_EDIT", "Invalid text range target.");
17938
+ const expectedText = text(edit.expectedText), original = edit.ranges;
17939
+ if (!Array.isArray(original)) fail("INVALID_EDIT", "Text ranges require an array.");
17940
+ const length = original.length;
17941
+ if (!Number.isSafeInteger(length) || length < 1 || length > 1e4)
17942
+ fail("LIMIT_EDITS", "Range replacement requires 1-10000 ranges.");
17943
+ const ranges = [];
17944
+ let end = 0, output = expectedText.length;
17945
+ for (let index = 0; index < length; index++) {
17946
+ const input = original[index], start = input.start, nextEnd = input.end, replacement = text(input.text);
17947
+ if (!Number.isSafeInteger(start) || !Number.isSafeInteger(nextEnd) || start < end || nextEnd <= start || nextEnd > expectedText.length || !textRangeBoundary(expectedText, start) || !textRangeBoundary(expectedText, nextEnd))
17948
+ fail("INVALID_EDIT", "Text ranges require ascending nonoverlapping UTF16 scalar boundaries.");
17949
+ if (replacement.includes("\n") || expectedText.slice(start, nextEnd).includes("\n"))
17950
+ fail("UNSUPPORTED_TEXT_RANGE", "Range replacement across paragraph breaks is unsupported.");
17951
+ ranges.push({ start, end: nextEnd, text: replacement });
17952
+ end = nextEnd;
17953
+ output += replacement.length - (nextEnd - start);
17954
+ }
17955
+ if (output > 1e6) fail("LIMIT_EDIT_TEXT", "Range replacement output exceeds limits.");
17956
+ return { type: "replace-text-ranges", pageId, shapeId, expectedText, ranges };
17957
+ }
17958
+
17547
17959
  // visio/resize-anchor.ts
17548
17960
  function snapshotResizeAnchor(value) {
17549
17961
  if (value === void 0) return void 0;
@@ -17776,7 +18188,7 @@ function snapshotFormatting(edit) {
17776
18188
  }
17777
18189
 
17778
18190
  // visio/edit-commands.ts
17779
- var isVisioPageEdit = (edit) => edit.type === "insert-page" || edit.type === "reorder-page" || edit.type === "rename-page" || edit.type === "delete-page";
18191
+ var isVisioPageEdit = (edit) => edit.type === "insert-page" || edit.type === "reorder-page" || edit.type === "rename-page" || edit.type === "delete-page" || edit.type === "set-page-size";
17780
18192
  function geometryChangedCells(edit) {
17781
18193
  if (edit.type === "create-line")
17782
18194
  return [
@@ -17834,6 +18246,13 @@ function snapshotVisioEdits(edits, maxEdits, maxText) {
17834
18246
  if (edit.type === "duplicate-shapes") return snapshotDuplicateShapes(edit);
17835
18247
  if (edit.type === "paste-shapes") return snapshotPasteShapes(edit);
17836
18248
  if (edit.type === "delete-page") return { type: edit.type, pageId: edit.pageId };
18249
+ if (edit.type === "set-page-size")
18250
+ return {
18251
+ type: edit.type,
18252
+ pageId: edit.pageId,
18253
+ width: numeric5(edit.width, true),
18254
+ height: numeric5(edit.height, true)
18255
+ };
17837
18256
  if (edit.type === "reorder-page") {
17838
18257
  if (!Number.isSafeInteger(edit.index) || edit.index < 0 || edit.index > 1e6)
17839
18258
  fail("INVALID_EDIT", "Page order requires a bounded zero-based integer index.");
@@ -17856,6 +18275,7 @@ function snapshotVisioEdits(edits, maxEdits, maxText) {
17856
18275
  const target = { pageId: edit.pageId, shapeId: edit.shapeId };
17857
18276
  if (edit.type === "replace-plain-text")
17858
18277
  return { ...target, type: edit.type, text: text(edit.text) };
18278
+ if (edit.type === "replace-text-ranges") return snapshotTextRanges(edit, text);
17859
18279
  if (isVisioFormatEdit(edit)) return snapshotFormatting(edit);
17860
18280
  if (edit.type === "reorder-shape") {
17861
18281
  if (!["front", "back", "forward", "backward"].includes(edit.order))
@@ -17882,7 +18302,10 @@ function snapshotVisioEdits(edits, maxEdits, maxText) {
17882
18302
  return { ...target, type: edit.type, beginX, beginY, endX, endY };
17883
18303
  }
17884
18304
  case "create-rectangle":
17885
- case "create-ellipse":
18305
+ case "create-ellipse": {
18306
+ const shape = edit.type === "create-rectangle" ? edit.shape : void 0;
18307
+ if (shape !== void 0 && !isVisioBasicShape(shape))
18308
+ fail("INVALID_EDIT", "Unknown basic shape.");
17886
18309
  return {
17887
18310
  ...target,
17888
18311
  type: edit.type,
@@ -17890,8 +18313,10 @@ function snapshotVisioEdits(edits, maxEdits, maxText) {
17890
18313
  y: numeric5(edit.y),
17891
18314
  width: numeric5(edit.width, true),
17892
18315
  height: numeric5(edit.height, true),
17893
- ...edit.text === void 0 ? {} : { text: text(edit.text) }
18316
+ ...edit.text === void 0 ? {} : { text: text(edit.text) },
18317
+ ...shape === void 0 ? {} : { shape }
17894
18318
  };
18319
+ }
17895
18320
  case "rotate-shape":
17896
18321
  return { ...target, type: edit.type, angle: numeric5(edit.angle) };
17897
18322
  case "flip-shape":
@@ -18305,24 +18730,25 @@ function createRectangle(root2, document, edit) {
18305
18730
  }
18306
18731
  const doc = root2.ownerDocument;
18307
18732
  const node = (name) => doc.createElementNS(root2.namespaceURI, name);
18308
- const section = node("Section");
18309
- section.setAttribute("N", "Geometry");
18310
- section.setAttribute("IX", "0");
18311
- for (const [index, [x, y]] of [
18312
- [0, 0],
18313
- [1, 0],
18314
- [1, 1],
18315
- [0, 1],
18316
- [0, 0]
18317
- ].entries()) {
18318
- const row = node("Row");
18319
- row.setAttribute("IX", String(index + 1));
18320
- row.setAttribute("T", index ? "RelLineTo" : "RelMoveTo");
18321
- setCell(row, "X", x);
18322
- setCell(row, "Y", y);
18323
- section.appendChild(row);
18733
+ const outline = visioBasicShapeOutline(
18734
+ edit.type === "create-rectangle" ? edit.shape ?? "rectangle" : "rectangle"
18735
+ );
18736
+ if (outline.rounding)
18737
+ setCell(shape, "Rounding", outline.rounding * Math.min(edit.width, edit.height));
18738
+ for (const [sectionIndex, points] of outline.paths.entries()) {
18739
+ const section = node("Section");
18740
+ section.setAttribute("N", "Geometry");
18741
+ section.setAttribute("IX", String(sectionIndex));
18742
+ for (const [index, [x, y]] of [...points, points[0]].entries()) {
18743
+ const row = node("Row");
18744
+ row.setAttribute("IX", String(index + 1));
18745
+ row.setAttribute("T", index ? "RelLineTo" : "RelMoveTo");
18746
+ setCell(row, "X", x);
18747
+ setCell(row, "Y", y);
18748
+ section.appendChild(row);
18749
+ }
18750
+ shape.appendChild(section);
18324
18751
  }
18325
- shape.appendChild(section);
18326
18752
  const text = node("Text");
18327
18753
  text.appendChild(doc.createTextNode(encodeVisioPlainText(edit.text ?? "")));
18328
18754
  shape.appendChild(text);
@@ -20554,6 +20980,145 @@ function addReplacementPage(pagesPart, pages, rels, types, pagePaths, parts, dir
20554
20980
  );
20555
20981
  }
20556
20982
 
20983
+ // visio/edit-page-size.ts
20984
+ function constant(node, length) {
20985
+ if (!node || node.hasAttribute("E") || attribute2(node, "F") === "Inh")
20986
+ fail("EDIT_UNSUPPORTED_PAGE_SIZE", "A valid explicit page size or mode cache is required.");
20987
+ const value = visioFormulaCachedValue(attribute2(node, "V") ?? "", attribute2(node, "U"));
20988
+ if (!Number.isFinite(value.value) || !["scalar", ...length ? ["length"] : []].includes(value.unit))
20989
+ fail("EDIT_UNSUPPORTED_PAGE_SIZE", "Page size or mode has incompatible units.");
20990
+ const formula = executableCellFormula(attribute2(node, "F"));
20991
+ if (formula) {
20992
+ const analysis = analyzeVisioFormula(formula);
20993
+ if (analysis.guarded || analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length)
20994
+ fail("EDIT_PROTECTED_CELL", "Protected or dependent page settings cannot be overwritten.");
20995
+ const result = evaluateVisioFormula(
20996
+ formula,
20997
+ () => fail("EDIT_PROTECTED_CELL", "Unsupported page dependency.")
20998
+ );
20999
+ if (result.value !== value.value || !["scalar", ...length ? ["length"] : []].includes(result.unit))
21000
+ fail("EDIT_PROTECTED_CELL", "Page setting formula cache cannot be proven.");
21001
+ }
21002
+ return value.value;
21003
+ }
21004
+ var escape3 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
21005
+ function assertDependencies(roots, pagesPart, pages, pagePaths, pageId, changed, check) {
21006
+ const page = children2(pages, "Page").find((node) => attribute2(node, "ID") === pageId);
21007
+ const targetNames = new Set(
21008
+ ["Name", "NameU"].map((name) => attribute2(page, name)?.toLowerCase())
21009
+ );
21010
+ const otherNames = children2(pages, "Page").filter((node) => node !== page).flatMap((node) => ["Name", "NameU"].map((name) => attribute2(node, name))).filter((name) => !!name && !targetNames.has(name.toLowerCase()));
21011
+ const cells4 = changed.map(escape3).join("|");
21012
+ const reference = new RegExp(`(?:^|[^a-z0-9_.])(?:${cells4})(?:$|[^a-z0-9_.])`, "i");
21013
+ const other = otherNames.length ? new RegExp(
21014
+ `Pages\\[(?:${otherNames.map(escape3).join("|")})\\]!(?:ThePage!)?(?:${cells4})(?![a-z0-9_.])`,
21015
+ "gi"
21016
+ ) : void 0;
21017
+ const paths = new Map([...pagePaths].map(([id, path]) => [path, id]));
21018
+ for (const [path, root2] of roots)
21019
+ for (const node of [root2, ...Array.from(root2.getElementsByTagName("*"))]) {
21020
+ check();
21021
+ const formula = executableCellFormula(attribute2(node, "F"));
21022
+ if (!formula) continue;
21023
+ let code = unquotedVisioFormula(formula);
21024
+ const name = attribute2(node, "N") ?? "";
21025
+ if (inertDoubleClickFormula(name, formula)) continue;
21026
+ const owner = node.parentNode, container = owner?.parentNode;
21027
+ const ownerId = attribute2(owner ?? void 0, "ID");
21028
+ const connected = ownerId && /^[1-9]\d{0,9}$/.test(ownerId) && owner?.localName === "Shape" && owner.namespaceURI === root2.namespaceURI && (!attribute2(owner, "Type") || attribute2(owner, "Type") === "Shape") && !owner.hasAttribute("Master") && !owner.hasAttribute("MasterShape") && !children2(owner, "Shapes").length && ["BeginX", "BeginY", "EndX", "EndY"].every(
21029
+ (name2) => children2(owner, "Cell").filter((cell) => attribute2(cell, "N") === name2).length === 1
21030
+ ) && container?.localName === "Shapes" && container.parentNode === root2 && children2(root2, "Connects").some(
21031
+ (connections2) => children2(connections2, "Connect").some(
21032
+ (connection) => attribute2(connection, "FromSheet") === ownerId
21033
+ )
21034
+ );
21035
+ const nativeGlue = paths.has(path) && connected && node.localName === "Cell" && node.namespaceURI === root2.namespaceURI && (/^(BeginX|BeginY|EndX|EndY)$/.test(name) && /^\s*_WALKGLUE\((?:BegTrigger,EndTrigger|EndTrigger,BegTrigger),WalkPreference\)\s*$/i.test(
21036
+ code
21037
+ ) || /^(BegTrigger|EndTrigger)$/.test(name) && /^\s*_XFTRIGGER\(Sheet\.[1-9]\d*!EventXFMod\)\s*$/i.test(code));
21038
+ let dynamic2 = false;
21039
+ if (!nativeGlue) {
21040
+ try {
21041
+ dynamic2 = analyzeVisioFormula(
21042
+ mapVisioFormulaSyntax(
21043
+ formula,
21044
+ (part) => (other ? part.replace(other, "0") : part).replace(/Pages\[[^\]]+\]!/gi, "").replace(/ThePage!/gi, "")
21045
+ )
21046
+ ).dynamic;
21047
+ } catch {
21048
+ dynamic2 = true;
21049
+ }
21050
+ }
21051
+ if (dynamic2)
21052
+ fail(
21053
+ "EDIT_UNSUPPORTED_PAGE_SIZE_DEPENDENCY",
21054
+ "Dynamic or unknown page-size dependencies cannot be safely refreshed."
21055
+ );
21056
+ let local = paths.get(path);
21057
+ if (path === pagesPart) {
21058
+ let ancestor = node;
21059
+ while (ancestor && ancestor.localName !== "Page")
21060
+ ancestor = ancestor.parentNode;
21061
+ local = ancestor ? attribute2(ancestor, "ID") : void 0;
21062
+ }
21063
+ if (other) code = code.replace(other, "0");
21064
+ if (!reference.test(code)) continue;
21065
+ if (local && local !== pageId && !/\bPages\[/i.test(code)) continue;
21066
+ fail(
21067
+ "EDIT_UNSUPPORTED_PAGE_SIZE_DEPENDENCY",
21068
+ "Page-size formula caches cannot be safely refreshed."
21069
+ );
21070
+ }
21071
+ }
21072
+ async function setVisioPageSize(pkg, pagesPart, pages, pagePaths, dirty, command2, check) {
21073
+ const page = children2(pages, "Page").find((node) => attribute2(node, "ID") === command2.pageId);
21074
+ if (!page) fail("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
21075
+ if (children2(page, "PageSheet").length !== 1)
21076
+ fail("EDIT_UNSUPPORTED_PAGE_SIZE", "One explicit PageSheet is required.");
21077
+ const sheet = child(page, "PageSheet"), cells4 = uniqueFormattingCells(sheet);
21078
+ for (const name of [
21079
+ "PageWidth",
21080
+ "PageHeight",
21081
+ "PageScale",
21082
+ "DrawingScale",
21083
+ "DrawingSizeType",
21084
+ "DrawingResizeType"
21085
+ ])
21086
+ if (!cells4.has(name) && [...cells4.keys()].some((key2) => key2.toLowerCase() === name.toLowerCase()))
21087
+ fail("EDIT_AMBIGUOUS_CELL", "Page settings require canonical cell names.");
21088
+ const pageScale = constant(cells4.get("PageScale"), true), drawingScale = constant(cells4.get("DrawingScale"), true);
21089
+ if (pageScale <= 0 || drawingScale <= 0)
21090
+ fail("EDIT_UNSUPPORTED_PAGE_SIZE", "Page and drawing scales must be positive.");
21091
+ const width = constant(cells4.get("PageWidth"), true), height = constant(cells4.get("PageHeight"), true);
21092
+ const size = constant(cells4.get("DrawingSizeType"), false);
21093
+ const resize = cells4.has("DrawingResizeType") ? constant(cells4.get("DrawingResizeType"), false) : void 0;
21094
+ if (width <= 0 || height <= 0 || ![0, 1, 2, 3, 4].includes(size) || resize !== void 0 && ![0, 1, 2].includes(resize))
21095
+ fail("EDIT_UNSUPPORTED_PAGE_SIZE", "Page dimensions or size modes are unsupported.");
21096
+ const targetWidth = command2.width === width * (pageScale / drawingScale) ? width : command2.width * drawingScale / pageScale, targetHeight = command2.height === height * (pageScale / drawingScale) ? height : command2.height * drawingScale / pageScale;
21097
+ if (![targetWidth, targetHeight].every(
21098
+ (value) => Number.isFinite(value) && value > 0 && value <= 1e6
21099
+ ))
21100
+ fail("INVALID_PAGE_SIZE", "Converted drawing-page dimensions exceed limits.");
21101
+ const values = /* @__PURE__ */ new Map([
21102
+ ["PageWidth", targetWidth],
21103
+ ["PageHeight", targetHeight],
21104
+ ["DrawingSizeType", 3],
21105
+ ["DrawingResizeType", 0]
21106
+ ]);
21107
+ const changed = [...values.keys()].filter(
21108
+ (name) => name === "PageWidth" ? width !== targetWidth : name === "PageHeight" ? height !== targetHeight : name === "DrawingSizeType" ? size !== 3 : resize !== 0
21109
+ );
21110
+ if (!changed.length) return;
21111
+ const roots = await editableVisioPageRoots(pkg, pagesPart, pages, pagePaths, dirty, check);
21112
+ for (const path of pkg.paths())
21113
+ if (/^visio\/.*\.xml$/i.test(path) && !roots.has(path)) {
21114
+ check();
21115
+ roots.set(path, dirty.get(path) ?? await pkg.readXml(path));
21116
+ }
21117
+ assertDependencies(roots, pagesPart, pages, pagePaths, command2.pageId, changed, check);
21118
+ for (const name of changed) setCell(sheet, name, values.get(name));
21119
+ dirty.set(pagesPart, pages);
21120
+ }
21121
+
20557
21122
  // visio/edit-pages.ts
20558
21123
  var officeRel2 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
20559
21124
  var pageType2 = "http://schemas.microsoft.com/visio/2010/relationships/page";
@@ -20589,6 +21154,10 @@ async function editVsdxPages(original, pkg, parts, commands, limits, maxOutput,
20589
21154
  for (const command2 of commands) {
20590
21155
  check();
20591
21156
  const existing = children2(pages, "Page");
21157
+ if (command2.type === "set-page-size") {
21158
+ await setVisioPageSize(pkg, pagesPart, pages, pagePaths, dirty, command2, check);
21159
+ continue;
21160
+ }
20592
21161
  if (command2.type === "delete-page") {
20593
21162
  await deleteVisioPage(
20594
21163
  pkg,
@@ -20692,8 +21261,10 @@ async function editVsdxPages(original, pkg, parts, commands, limits, maxOutput,
20692
21261
  fail("LIMIT_EDIT_OUTPUT", "Saved package exceeds output limit.");
20693
21262
  return { bytes: original, changedParts: [], diagnostics: [] };
20694
21263
  }
20695
- await updatePageAppProperties(pkg, pages, priorCount, dirty, limits, check);
20696
- await recalculatePageFormulas(pkg, pagesPart, pages, pagePaths, dirty, check);
21264
+ if (commands.some((command2) => command2.type !== "set-page-size")) {
21265
+ await updatePageAppProperties(pkg, pages, priorCount, dirty, limits, check);
21266
+ await recalculatePageFormulas(pkg, pagesPart, pages, pagePaths, dirty, check);
21267
+ }
20697
21268
  if ((/* @__PURE__ */ new Set([...parts.keys(), ...dirty.keys()])).size > limits.maxEntries)
20698
21269
  fail("LIMIT_ENTRIES", "Page insertion exceeds package entry limit.");
20699
21270
  let total = [...parts.values()].reduce((sum, bytes2) => sum + bytes2.length, 0), nodes = 0;
@@ -20721,8 +21292,8 @@ async function editVsdxPages(original, pkg, parts, commands, limits, maxOutput,
20721
21292
  changedParts: [.../* @__PURE__ */ new Set([...removed, ...dirty.keys()])],
20722
21293
  diagnostics: [
20723
21294
  {
20724
- code: "edit-pages-experimental",
20725
- message: "Page metadata and supported local numeric page-dependent caches were updated. Inherited, string and background-render-context formulas remain unsupported."
21295
+ code: commands.every((command2) => command2.type === "set-page-size") ? "edit-page-size-experimental" : "edit-pages-experimental",
21296
+ message: commands.every((command2) => command2.type === "set-page-size") ? "Fixed custom drawing-page dimensions were updated. Shape positions and printer settings were retained; affected page-size formula caches remain unsupported." : "Page metadata and supported local numeric page-dependent caches were updated. Inherited, string and background-render-context formulas remain unsupported."
20726
21297
  }
20727
21298
  ]
20728
21299
  };
@@ -21551,12 +22122,12 @@ async function editVsdx(input, edits, options = {}) {
21551
22122
  const dirty = /* @__PURE__ */ new Map();
21552
22123
  const roots = /* @__PURE__ */ new Map();
21553
22124
  const geometryCommands = commands.filter(
21554
- (command2) => command2.type !== "replace-plain-text" && command2.type !== "reorder-shape" && command2.type !== "duplicate-shapes" && command2.type !== "paste-shapes" && !isVisioFormatEdit(command2)
22125
+ (command2) => command2.type !== "replace-plain-text" && command2.type !== "replace-text-ranges" && command2.type !== "reorder-shape" && command2.type !== "duplicate-shapes" && command2.type !== "paste-shapes" && !isVisioFormatEdit(command2)
21555
22126
  );
21556
22127
  let document;
21557
22128
  let masterMovePins = emptyMasterMoveProof();
21558
22129
  if (geometryCommands.length || commands.some(
21559
- (command2) => command2.type === "replace-plain-text" || isVisioFormatEdit(command2) || command2.type === "reorder-shape" || command2.type === "duplicate-shapes" || command2.type === "paste-shapes"
22130
+ (command2) => command2.type === "replace-plain-text" || command2.type === "replace-text-ranges" || isVisioFormatEdit(command2) || command2.type === "reorder-shape" || command2.type === "duplicate-shapes" || command2.type === "paste-shapes"
21560
22131
  )) {
21561
22132
  for (const [pageId, path2] of pages) {
21562
22133
  const sourceRoot = await visioXml(pkg, path2, "PageContents");
@@ -21603,8 +22174,8 @@ async function editVsdx(input, edits, options = {}) {
21603
22174
  root2 = sourceRoot.ownerDocument.cloneNode(true).documentElement;
21604
22175
  roots.set(command2.pageId, root2);
21605
22176
  }
21606
- if (command2.type === "replace-plain-text") {
21607
- if (await replaceScopedPlainText(pkg, new Set(pages.values()), roots, document, command2, check)) {
22177
+ if (command2.type === "replace-plain-text" || command2.type === "replace-text-ranges") {
22178
+ if (await (command2.type === "replace-plain-text" ? replaceScopedPlainText(pkg, new Set(pages.values()), roots, document, command2, check) : replaceScopedTextRanges(pkg, new Set(pages.values()), roots, document, command2, check))) {
21608
22179
  dirty.set(path, root2);
21609
22180
  textChanged = true;
21610
22181
  }
@@ -22051,4 +22622,4 @@ function trimVisioArrowLine(path, start, end, beginExtension = 0) {
22051
22622
  return `M ${point2(start)}${base > start ? ` L ${point2(base)}` : ""} L ${point2(length - end)}`;
22052
22623
  }
22053
22624
 
22054
- export { VISIO_CLIPBOARD_MAGIC, VISIO_CLIPBOARD_MAX_CHARS, VISIO_EMF_ADMISSION_LIMITS, VISIO_FOREIGN_VECTOR_LIMITS, VISIO_RASTER_IMAGE_LIMITS, VISIO_VISIBILITY_LIMITS, VisioForeignVectorError, VisioFormulaError, VisioImageError, VisioPackageError, analyzeVisioFormula, captureVisioClipboard, convertVisioMetafile, createVsdx, deserializeVisioClipboard, editVsdx, evaluateVisioFormula, getVisioPageLayers, inspectVisioEmfAdmission, inspectVisioRasterImage, layoutVisioFilledArrowLine, loadVisio, parseLegacyVsd, parseVisioFormula, parseVsdx, resolveVisioPageVisibility, sanitizeVisioForeignVectorTree, serializeVisioClipboard, trimVisioArrowLine, validateVisioForeignVector, visioFilledArrow, visioFormulaCachedValue, visioOpenArrowExtent, visioOpenArrowPath };
22625
+ export { VISIO_BASIC_SHAPES, VISIO_CLIPBOARD_MAGIC, VISIO_CLIPBOARD_MAX_CHARS, VISIO_EMF_ADMISSION_LIMITS, VISIO_FOREIGN_VECTOR_LIMITS, VISIO_RASTER_IMAGE_LIMITS, VISIO_VISIBILITY_LIMITS, VisioForeignVectorError, VisioFormulaError, VisioImageError, VisioPackageError, analyzeVisioFormula, captureVisioClipboard, convertVisioMetafile, createVsdx, deserializeVisioClipboard, editVsdx, evaluateVisioFormula, getVisioPageLayers, inspectVisioEmfAdmission, inspectVisioRasterImage, isVisioBasicShape, layoutVisioFilledArrowLine, loadVisio, parseLegacyVsd, parseVisioFormula, parseVsdx, resolveVisioPageVisibility, sanitizeVisioForeignVectorTree, serializeVisioClipboard, trimVisioArrowLine, validateVisioForeignVector, visioBasicShapeOutline, visioFilledArrow, visioFormulaCachedValue, visioOpenArrowExtent, visioOpenArrowPath };