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
@@ -233,6 +233,19 @@ var attribute = new RegExp(
233
233
  "uy"
234
234
  );
235
235
  var xmlWhitespace = (value) => /^[ \t\r\n]*$/.test(value);
236
+ var reservedNamespaces = /* @__PURE__ */ new Map([
237
+ ["xml", "http://www.w3.org/XML/1998/namespace"],
238
+ ["xmlns", "http://www.w3.org/2000/xmlns/"]
239
+ ]);
240
+ function lookupNamespace(scope, prefix) {
241
+ const reserved = reservedNamespaces.get(prefix);
242
+ if (reserved !== void 0) return reserved;
243
+ for (; scope; scope = scope.parent) {
244
+ const uri = scope.bindings.get(prefix);
245
+ if (uri !== void 0) return uri;
246
+ }
247
+ return void 0;
248
+ }
236
249
  function inspectXml(xml, limits, check, encoding = "utf-8") {
237
250
  if (xml.length > limits.maxXmlChars) fail("LIMIT_XML", "XML character limit exceeded");
238
251
  if (/<!DOCTYPE|<!ENTITY/i.test(xml) || /[\u0000-\u0008\u000b\u000c\u000e-\u001f\ufffe\uffff]/.test(xml))
@@ -298,9 +311,7 @@ function inspectXml(xml, limits, check, encoding = "utf-8") {
298
311
  fail("INVALID_XML", "Mismatched XML closing tag");
299
312
  } else {
300
313
  const attrs = /* @__PURE__ */ new Set();
301
- const namespaces = Object.create(stack.at(-1)?.namespaces ?? null);
302
- namespaces["xml"] = "http://www.w3.org/XML/1998/namespace";
303
- namespaces["xmlns"] = "http://www.w3.org/2000/xmlns/";
314
+ const namespaces = { bindings: /* @__PURE__ */ new Map(), parent: stack.at(-1)?.namespaces };
304
315
  while (!xmlWhitespace(body.slice(cursor))) {
305
316
  attribute.lastIndex = cursor;
306
317
  const match = attribute.exec(body);
@@ -310,14 +321,14 @@ function inspectXml(xml, limits, check, encoding = "utf-8") {
310
321
  const value = match[2] ?? match[3] ?? "";
311
322
  text(value);
312
323
  if (match[1]?.startsWith("xmlns:"))
313
- namespaces[match[1].slice(6)] = decodeXmlAttribute(value);
324
+ namespaces.bindings.set(match[1].slice(6), decodeXmlAttribute(value));
314
325
  node();
315
326
  cursor = attribute.lastIndex;
316
327
  }
317
328
  const expanded = /* @__PURE__ */ new Set();
318
329
  for (const attr2 of attrs) {
319
330
  const colon = attr2.indexOf(":");
320
- const uri = colon < 0 ? "" : namespaces[attr2.slice(0, colon)];
331
+ const uri = colon < 0 ? "" : lookupNamespace(namespaces, attr2.slice(0, colon));
321
332
  if (uri === void 0) fail("INVALID_XML", "Unbound XML attribute prefix");
322
333
  const key2 = `${uri}\0${attr2.slice(colon + 1)}`;
323
334
  if (expanded.has(key2)) fail("INVALID_XML", "Duplicate expanded XML attribute name");
@@ -6601,11 +6612,23 @@ async function parseVsdx(input, options = {}) {
6601
6612
  };
6602
6613
  visit(shapes);
6603
6614
  const connectors = connections(root2, localReport);
6615
+ const pageModes = {};
6616
+ for (const [name, key2] of [
6617
+ ["DrawingSizeType", "drawingSizeType"],
6618
+ ["DrawingResizeType", "drawingResizeType"]
6619
+ ]) {
6620
+ const source = sheet.cells.get(name);
6621
+ if (!source || source.error !== void 0 || source.formula === "Inh" || source.unit !== void 0 && !["NUM", "BOOL"].includes(source.unit))
6622
+ continue;
6623
+ const value = number(sheet.cells, name, Number.NaN, localReport);
6624
+ if (Number.isSafeInteger(value) && value >= 0 && value <= 255) pageModes[key2] = value;
6625
+ }
6604
6626
  for (const connection of connectors)
6605
6627
  if (!seen.has(connection.fromShapeId) || !seen.has(connection.toShapeId))
6606
6628
  localReport("dangling-connection", "A connection references a missing shape.");
6607
6629
  pages.push({
6608
6630
  id,
6631
+ ...pageModes,
6609
6632
  ...drawingToPageScale === 1 ? {} : { drawingToPageScale },
6610
6633
  name: metadata(
6611
6634
  attribute2(page, "Name") ?? attribute2(page, "NameU") ?? `Page ${id}`,
@@ -15234,10 +15257,10 @@ function replaceRecord(input, drawing, record5, replacement) {
15234
15257
  if (!(block.format & 2) || ![8, 12, 13].includes(block.format >>> 4))
15235
15258
  throw new VsdError("unsafe-block-relocation");
15236
15259
  try {
15237
- const fit = encodeVsdBlockToSize(decoded, block.length);
15238
- if (!fit)
15260
+ const fit2 = encodeVsdBlockToSize(decoded, block.length);
15261
+ if (!fit2)
15239
15262
  throw new VsdError("unsafe-block-relocation");
15240
- stored = fit.bytes;
15263
+ stored = fit2.bytes;
15241
15264
  } catch (error) {
15242
15265
  if (error instanceof VsdCompressionFitError)
15243
15266
  throw new VsdError(`compression-${error.reason}`);
@@ -17417,8 +17440,8 @@ function assertUnlayeredShape(shape, document) {
17417
17440
  }
17418
17441
  }
17419
17442
 
17420
- // visio/edit-text.ts
17421
- async function replacePlainText(root2, document, shapeId, text, check, assertDependencies) {
17443
+ // visio/edit-text-target.ts
17444
+ function localTextTarget(root2, document, shapeId, check) {
17422
17445
  const shapeChildren = (parent) => {
17423
17446
  const containers = children2(parent, "Shapes");
17424
17447
  if (containers.length > 1)
@@ -17426,37 +17449,38 @@ async function replacePlainText(root2, document, shapeId, text, check, assertDep
17426
17449
  return children2(containers[0], "Shape");
17427
17450
  };
17428
17451
  const shapes = /* @__PURE__ */ new Map();
17429
- const pending = shapeChildren(root2).map((node2) => ({
17430
- node: node2,
17431
- inherited: false,
17432
- deleted: false
17433
- }));
17452
+ const pending = shapeChildren(root2).map((node) => ({ node, inherited: false, deleted: false }));
17434
17453
  while (pending.length) {
17435
17454
  check();
17436
- const item = pending.pop();
17437
- const id = attribute2(item.node, "ID");
17455
+ const item = pending.pop(), id = attribute2(item.node, "ID");
17438
17456
  if (!id || shapes.has(id))
17439
17457
  fail("INVALID_SHAPE_ID", "Local shape IDs must be present and unique.");
17440
17458
  const inherited = item.inherited || item.node.hasAttribute("Master") || item.node.hasAttribute("MasterShape");
17441
17459
  const deleted = item.deleted || ["1", "true"].includes(attribute2(item.node, "Del") ?? "");
17442
17460
  shapes.set(id, { node: item.node, inherited, deleted });
17443
- for (const node2 of shapeChildren(item.node)) pending.push({ node: node2, inherited, deleted });
17461
+ for (const node of shapeChildren(item.node)) pending.push({ node, inherited, deleted });
17444
17462
  }
17445
17463
  const target = shapes.get(shapeId);
17446
17464
  if (!target) fail("EDIT_TARGET_NOT_FOUND", "Local shape does not exist.");
17447
17465
  if (target.inherited || target.deleted)
17448
17466
  fail("UNSUPPORTED_TEXT_EDIT", "Master-linked or deleted shapes cannot be edited.");
17449
17467
  assertShapeLocks(target.node, document, ["LockTextEdit"]);
17450
- const texts = children2(target.node, "Text");
17468
+ return target.node;
17469
+ }
17470
+
17471
+ // visio/edit-text.ts
17472
+ async function replacePlainText(root2, document, shapeId, text, check, assertDependencies2) {
17473
+ const target = localTextTarget(root2, document, shapeId, check);
17474
+ const texts = children2(target, "Text");
17451
17475
  if (texts.length !== 1)
17452
17476
  fail("UNSUPPORTED_TEXT_EDIT", "Editing requires one existing local Text element.");
17453
17477
  const node = texts[0];
17454
17478
  if (Array.from(node.childNodes).some((item) => item.nodeType !== 3 && item.nodeType !== 4))
17455
17479
  fail("UNSUPPORTED_TEXT_EDIT", "Rich text, fields and unknown text markup cannot be edited.");
17456
- if (children2(target.node, "Section").some((section) => attribute2(section, "N") === "Field"))
17480
+ if (children2(target, "Section").some((section) => attribute2(section, "N") === "Field"))
17457
17481
  fail("UNSUPPORTED_TEXT_EDIT", "Shapes with text fields cannot be edited.");
17458
17482
  if (decodeVisioPlainText(node.textContent ?? "") === text) return false;
17459
- await assertDependencies(target.node, node);
17483
+ await assertDependencies2(target, node);
17460
17484
  check();
17461
17485
  while (node.firstChild) node.removeChild(node.firstChild);
17462
17486
  node.appendChild(node.ownerDocument.createTextNode(encodeVisioPlainText(text)));
@@ -17550,6 +17574,394 @@ function replaceScopedPlainText(pkg, pagePaths, roots, document, edit, check) {
17550
17574
  );
17551
17575
  }
17552
17576
 
17577
+ // visio/edit-text-range-plan.ts
17578
+ function textRangeNodes(node, edit) {
17579
+ const tokens2 = [];
17580
+ let stored = "";
17581
+ for (const part of Array.from(node.childNodes)) {
17582
+ const start = stored.length;
17583
+ if (part.nodeType === 3 || part.nodeType === 4) stored += part.nodeValue ?? "";
17584
+ tokens2.push({ node: part, start, end: stored.length });
17585
+ }
17586
+ if (decodeVisioPlainText(stored) !== edit.expectedText)
17587
+ fail("EDIT_STALE_TEXT", "Original text no longer matches the range command.");
17588
+ const changed = edit.ranges.some(
17589
+ (range) => edit.expectedText.slice(range.start, range.end) !== range.text
17590
+ );
17591
+ if (!changed) return { changed: false, nodes: [] };
17592
+ const starts = [], deltas = [];
17593
+ let delta = 0;
17594
+ for (const range of edit.ranges) {
17595
+ starts.push(range.start + delta);
17596
+ delta += range.text.length - (range.end - range.start);
17597
+ deltas.push(delta);
17598
+ }
17599
+ const length = edit.expectedText.length + delta;
17600
+ if (!length && tokens2.some((token) => token.node.nodeType === 1))
17601
+ fail(
17602
+ "UNSUPPORTED_TEXT_RANGE",
17603
+ "Deleting all rich text has unproven native insertion-style behavior."
17604
+ );
17605
+ if (tokens2.some((token) => token.node.nodeType === 1)) {
17606
+ let start = 0, index = 0;
17607
+ while (start < edit.expectedText.length) {
17608
+ const newline = edit.expectedText.indexOf("\n", start), end = newline < 0 ? edit.expectedText.length : newline;
17609
+ let bodyLength = end - start;
17610
+ while (index < edit.ranges.length && edit.ranges[index].start < end) {
17611
+ const range = edit.ranges[index++];
17612
+ bodyLength += range.text.length - (range.end - range.start);
17613
+ }
17614
+ if (end > start && !bodyLength)
17615
+ fail(
17616
+ "UNSUPPORTED_TEXT_RANGE",
17617
+ "Deleting an entire rich paragraph body has unproven native insertion-style behavior."
17618
+ );
17619
+ start = end + 1;
17620
+ }
17621
+ }
17622
+ const position = (offset) => {
17623
+ let low = 0, high = edit.ranges.length;
17624
+ while (low < high) {
17625
+ const middle = low + high >>> 1;
17626
+ if (edit.ranges[middle].start < offset) low = middle + 1;
17627
+ else high = middle;
17628
+ }
17629
+ const index = low - 1;
17630
+ if (index < 0) return offset;
17631
+ const range = edit.ranges[index];
17632
+ return offset <= range.end ? starts[index] + range.text.length : offset + deltas[index];
17633
+ };
17634
+ const output = [];
17635
+ const append = (token, start, end) => {
17636
+ if (end <= start) return;
17637
+ const part = start === token.start && end === token.end ? token.node : token.node.cloneNode(false);
17638
+ if (part !== token.node)
17639
+ part.nodeValue = (token.node.nodeValue ?? "").slice(start - token.start, end - token.start);
17640
+ output.push({ position: position(start), priority: 2, node: part });
17641
+ };
17642
+ let first2 = 0;
17643
+ for (const token of tokens2) {
17644
+ if (token.node.nodeType === 1) {
17645
+ output.push({ position: position(token.start), priority: 0, node: token.node });
17646
+ continue;
17647
+ }
17648
+ const end = length ? token.end : Math.min(token.end, edit.expectedText.length);
17649
+ let cursor = token.start;
17650
+ while (first2 < edit.ranges.length && edit.ranges[first2].end <= cursor) first2++;
17651
+ for (let index = first2; index < edit.ranges.length && edit.ranges[index].start < end; index++) {
17652
+ const range = edit.ranges[index];
17653
+ append(token, cursor, Math.min(end, range.start));
17654
+ cursor = Math.max(cursor, Math.min(end, range.end));
17655
+ }
17656
+ append(token, cursor, end);
17657
+ }
17658
+ for (let index = 0; index < edit.ranges.length; index++) {
17659
+ const text = edit.ranges[index].text;
17660
+ if (text)
17661
+ output.push({
17662
+ position: starts[index],
17663
+ priority: 1,
17664
+ node: node.ownerDocument.createTextNode(text)
17665
+ });
17666
+ }
17667
+ output.sort((a, b) => a.position - b.position || a.priority - b.priority);
17668
+ let characterPosition = -1, characterRow = null;
17669
+ for (const item of output) {
17670
+ if (item.node.nodeType !== 1 || item.node.localName !== "cp") continue;
17671
+ const row = item.node.getAttribute("IX");
17672
+ if (item.position === characterPosition && row !== characterRow)
17673
+ fail(
17674
+ "UNSUPPORTED_TEXT_RANGE",
17675
+ "Consuming complete character runs creates ambiguous native marker boundaries."
17676
+ );
17677
+ characterPosition = item.position;
17678
+ characterRow = row;
17679
+ }
17680
+ return { changed: true, nodes: output.map((item) => item.node) };
17681
+ }
17682
+
17683
+ // visio/edit-text-ranges.ts
17684
+ async function replaceScopedTextRanges(pkg, pagePaths, roots, document, edit, check) {
17685
+ const shape = localTextTarget(roots.get(edit.pageId), document, edit.shapeId, check);
17686
+ if (children2(shape, "Section").some((section) => attribute2(section, "N") === "Field"))
17687
+ fail("UNSUPPORTED_TEXT_RANGE", "Text range editing of shapes with fields is unsupported.");
17688
+ const texts = children2(shape, "Text");
17689
+ if (texts.length !== 1)
17690
+ fail("UNSUPPORTED_TEXT_RANGE", "Range editing requires one existing local Text element.");
17691
+ const text = texts[0];
17692
+ if (Array.from(text.childNodes).some((node) => ![3, 4].includes(node.nodeType))) {
17693
+ const characters = effectiveFormattingRows(shape, document, "Character"), paragraphs = effectiveFormattingRows(shape, document, "Paragraph");
17694
+ assertFormattingText(shape, characters, paragraphs);
17695
+ }
17696
+ if (Array.from(text.childNodes).some(
17697
+ (node) => node.nodeType === 1 && node.localName === "fld"
17698
+ ))
17699
+ fail("UNSUPPORTED_TEXT_RANGE", "Text range editing of fields is unsupported.");
17700
+ let preceding = "";
17701
+ for (const node of Array.from(text.childNodes)) {
17702
+ if (node.nodeType === 3 || node.nodeType === 4) preceding += node.nodeValue ?? "";
17703
+ else {
17704
+ const marker2 = node;
17705
+ if (marker2.localName === "pp" && preceding && !preceding.endsWith("\n") || marker2.localName === "tp" && attribute2(marker2, "IX") !== "0")
17706
+ fail(
17707
+ "UNSUPPORTED_TEXT_RANGE",
17708
+ "Noncanonical paragraph or tab marker placement cannot be edited."
17709
+ );
17710
+ }
17711
+ }
17712
+ const plan = textRangeNodes(text, edit);
17713
+ if (!plan.changed) return false;
17714
+ await assertFormattingDependencies(
17715
+ pkg,
17716
+ pagePaths,
17717
+ roots,
17718
+ edit.pageId,
17719
+ shape,
17720
+ /* @__PURE__ */ new Map([["TheText", text]]),
17721
+ check
17722
+ );
17723
+ check();
17724
+ while (text.firstChild) text.removeChild(text.firstChild);
17725
+ for (const node of plan.nodes) text.appendChild(node);
17726
+ return true;
17727
+ }
17728
+
17729
+ // visio/basic-shapes.ts
17730
+ var VISIO_BASIC_SHAPES = [
17731
+ "rectangle",
17732
+ "square",
17733
+ "triangle",
17734
+ "right-triangle",
17735
+ "pentagon",
17736
+ "hexagon",
17737
+ "octagon",
17738
+ "star",
17739
+ "diamond",
17740
+ "rounded-rectangle",
17741
+ "cross",
17742
+ "parallelogram",
17743
+ "trapezoid",
17744
+ "can",
17745
+ "cube",
17746
+ "chevron"
17747
+ ];
17748
+ var isVisioBasicShape = (value) => VISIO_BASIC_SHAPES.includes(value);
17749
+ function fit(points) {
17750
+ const xs = points.map(([x]) => x), ys = points.map(([, y]) => y);
17751
+ const left = Math.min(...xs), bottom = Math.min(...ys);
17752
+ const width = Math.max(...xs) - left, height = Math.max(...ys) - bottom;
17753
+ return points.map(([x, y]) => [(x - left) / width, (y - bottom) / height]);
17754
+ }
17755
+ function polygon(count, inner) {
17756
+ const steps = inner === void 0 ? count : count * 2;
17757
+ return fit(
17758
+ Array.from({ length: steps }, (_, index) => {
17759
+ const radius = inner !== void 0 && index % 2 ? inner : 1;
17760
+ const angle = Math.PI / 2 + index * 2 * Math.PI / steps;
17761
+ return [radius * Math.cos(angle), radius * Math.sin(angle)];
17762
+ })
17763
+ );
17764
+ }
17765
+ function arc(cy, ry, from, to) {
17766
+ const segments = 12;
17767
+ return Array.from({ length: segments + 1 }, (_, index) => {
17768
+ const angle = from + (to - from) * index / segments;
17769
+ return [0.5 + 0.5 * Math.cos(angle), cy + ry * Math.sin(angle)];
17770
+ });
17771
+ }
17772
+ var box = [
17773
+ [0, 0],
17774
+ [1, 0],
17775
+ [1, 1],
17776
+ [0, 1]
17777
+ ];
17778
+ var LID = 0.2;
17779
+ var CUT = 1 / (2 + Math.SQRT2);
17780
+ var OUTLINES = {
17781
+ rectangle: { paths: [box] },
17782
+ square: { paths: [box] },
17783
+ triangle: {
17784
+ paths: [
17785
+ [
17786
+ [0, 0],
17787
+ [1, 0],
17788
+ [0.5, 1]
17789
+ ]
17790
+ ]
17791
+ },
17792
+ "right-triangle": {
17793
+ paths: [
17794
+ [
17795
+ [0, 0],
17796
+ [1, 0],
17797
+ [0, 1]
17798
+ ]
17799
+ ]
17800
+ },
17801
+ pentagon: { paths: [polygon(5)] },
17802
+ hexagon: {
17803
+ paths: [
17804
+ [
17805
+ [0.25, 0],
17806
+ [0.75, 0],
17807
+ [1, 0.5],
17808
+ [0.75, 1],
17809
+ [0.25, 1],
17810
+ [0, 0.5]
17811
+ ]
17812
+ ]
17813
+ },
17814
+ octagon: {
17815
+ paths: [
17816
+ [
17817
+ [CUT, 0],
17818
+ [1 - CUT, 0],
17819
+ [1, CUT],
17820
+ [1, 1 - CUT],
17821
+ [1 - CUT, 1],
17822
+ [CUT, 1],
17823
+ [0, 1 - CUT],
17824
+ [0, CUT]
17825
+ ]
17826
+ ]
17827
+ },
17828
+ star: { paths: [polygon(5, 0.382)] },
17829
+ diamond: {
17830
+ paths: [
17831
+ [
17832
+ [0.5, 0],
17833
+ [1, 0.5],
17834
+ [0.5, 1],
17835
+ [0, 0.5]
17836
+ ]
17837
+ ]
17838
+ },
17839
+ "rounded-rectangle": { paths: [box], rounding: 0.15 },
17840
+ cross: {
17841
+ paths: [
17842
+ [
17843
+ [1 / 3, 0],
17844
+ [2 / 3, 0],
17845
+ [2 / 3, 1 / 3],
17846
+ [1, 1 / 3],
17847
+ [1, 2 / 3],
17848
+ [2 / 3, 2 / 3],
17849
+ [2 / 3, 1],
17850
+ [1 / 3, 1],
17851
+ [1 / 3, 2 / 3],
17852
+ [0, 2 / 3],
17853
+ [0, 1 / 3],
17854
+ [1 / 3, 1 / 3]
17855
+ ]
17856
+ ]
17857
+ },
17858
+ parallelogram: {
17859
+ paths: [
17860
+ [
17861
+ [0, 0],
17862
+ [0.75, 0],
17863
+ [1, 1],
17864
+ [0.25, 1]
17865
+ ]
17866
+ ]
17867
+ },
17868
+ trapezoid: {
17869
+ paths: [
17870
+ [
17871
+ [0, 0],
17872
+ [1, 0],
17873
+ [0.75, 1],
17874
+ [0.25, 1]
17875
+ ]
17876
+ ]
17877
+ },
17878
+ can: {
17879
+ paths: [
17880
+ // The body: down the left side, round the front of the base, up the right side and
17881
+ // back along the front of the lid.
17882
+ [...arc(LID / 2, LID / 2, Math.PI, 2 * Math.PI), ...arc(1 - LID / 2, LID / 2, 0, -Math.PI)],
17883
+ // The lid, drawn over the body.
17884
+ arc(1 - LID / 2, LID / 2, 0, 2 * Math.PI).slice(0, -1)
17885
+ ]
17886
+ },
17887
+ cube: {
17888
+ paths: [
17889
+ [
17890
+ [0, 0],
17891
+ [0.75, 0],
17892
+ [0.75, 0.75],
17893
+ [0, 0.75]
17894
+ ],
17895
+ [
17896
+ [0, 0.75],
17897
+ [0.75, 0.75],
17898
+ [1, 1],
17899
+ [0.25, 1]
17900
+ ],
17901
+ [
17902
+ [0.75, 0],
17903
+ [1, 0.25],
17904
+ [1, 1],
17905
+ [0.75, 0.75]
17906
+ ]
17907
+ ]
17908
+ },
17909
+ chevron: {
17910
+ paths: [
17911
+ [
17912
+ [0, 0],
17913
+ [0.75, 0],
17914
+ [1, 0.5],
17915
+ [0.75, 1],
17916
+ [0, 1],
17917
+ [0.25, 0.5]
17918
+ ]
17919
+ ]
17920
+ }
17921
+ };
17922
+ function visioBasicShapeOutline(shape) {
17923
+ return OUTLINES[shape];
17924
+ }
17925
+
17926
+ // visio/edit-text-range-commands.ts
17927
+ var invalidXmlText = /[\u0000-\u0008\u000b\u000c\u000d\u000e-\u001f\ufffe\uffff]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/u;
17928
+ function textRangeBoundary(text, offset) {
17929
+ return !(offset > 0 && offset < text.length && /[\ud800-\udbff]/.test(text[offset - 1]) && /[\udc00-\udfff]/.test(text[offset]));
17930
+ }
17931
+ function snapshotTextRanges(edit, consume) {
17932
+ let characters = 0;
17933
+ const text = (value) => {
17934
+ if (typeof value !== "string" || invalidXmlText.test(value))
17935
+ fail("INVALID_EDIT_TEXT", "Range replacement requires valid XML text.");
17936
+ characters += value.length;
17937
+ if (characters > 1e6)
17938
+ fail("LIMIT_EDIT_TEXT", "Range replacement text exceeds input limits.");
17939
+ return consume ? consume(value) : value;
17940
+ };
17941
+ const pageId = edit.pageId, shapeId = edit.shapeId;
17942
+ if ([pageId, shapeId].some((id) => typeof id !== "string" || !id || id.length > 256))
17943
+ fail("INVALID_EDIT", "Invalid text range target.");
17944
+ const expectedText = text(edit.expectedText), original = edit.ranges;
17945
+ if (!Array.isArray(original)) fail("INVALID_EDIT", "Text ranges require an array.");
17946
+ const length = original.length;
17947
+ if (!Number.isSafeInteger(length) || length < 1 || length > 1e4)
17948
+ fail("LIMIT_EDITS", "Range replacement requires 1-10000 ranges.");
17949
+ const ranges = [];
17950
+ let end = 0, output = expectedText.length;
17951
+ for (let index = 0; index < length; index++) {
17952
+ const input = original[index], start = input.start, nextEnd = input.end, replacement = text(input.text);
17953
+ if (!Number.isSafeInteger(start) || !Number.isSafeInteger(nextEnd) || start < end || nextEnd <= start || nextEnd > expectedText.length || !textRangeBoundary(expectedText, start) || !textRangeBoundary(expectedText, nextEnd))
17954
+ fail("INVALID_EDIT", "Text ranges require ascending nonoverlapping UTF16 scalar boundaries.");
17955
+ if (replacement.includes("\n") || expectedText.slice(start, nextEnd).includes("\n"))
17956
+ fail("UNSUPPORTED_TEXT_RANGE", "Range replacement across paragraph breaks is unsupported.");
17957
+ ranges.push({ start, end: nextEnd, text: replacement });
17958
+ end = nextEnd;
17959
+ output += replacement.length - (nextEnd - start);
17960
+ }
17961
+ if (output > 1e6) fail("LIMIT_EDIT_TEXT", "Range replacement output exceeds limits.");
17962
+ return { type: "replace-text-ranges", pageId, shapeId, expectedText, ranges };
17963
+ }
17964
+
17553
17965
  // visio/resize-anchor.ts
17554
17966
  function snapshotResizeAnchor(value) {
17555
17967
  if (value === void 0) return void 0;
@@ -17782,7 +18194,7 @@ function snapshotFormatting(edit) {
17782
18194
  }
17783
18195
 
17784
18196
  // visio/edit-commands.ts
17785
- var isVisioPageEdit = (edit) => edit.type === "insert-page" || edit.type === "reorder-page" || edit.type === "rename-page" || edit.type === "delete-page";
18197
+ var isVisioPageEdit = (edit) => edit.type === "insert-page" || edit.type === "reorder-page" || edit.type === "rename-page" || edit.type === "delete-page" || edit.type === "set-page-size";
17786
18198
  function geometryChangedCells(edit) {
17787
18199
  if (edit.type === "create-line")
17788
18200
  return [
@@ -17840,6 +18252,13 @@ function snapshotVisioEdits(edits, maxEdits, maxText) {
17840
18252
  if (edit.type === "duplicate-shapes") return snapshotDuplicateShapes(edit);
17841
18253
  if (edit.type === "paste-shapes") return snapshotPasteShapes(edit);
17842
18254
  if (edit.type === "delete-page") return { type: edit.type, pageId: edit.pageId };
18255
+ if (edit.type === "set-page-size")
18256
+ return {
18257
+ type: edit.type,
18258
+ pageId: edit.pageId,
18259
+ width: numeric5(edit.width, true),
18260
+ height: numeric5(edit.height, true)
18261
+ };
17843
18262
  if (edit.type === "reorder-page") {
17844
18263
  if (!Number.isSafeInteger(edit.index) || edit.index < 0 || edit.index > 1e6)
17845
18264
  fail("INVALID_EDIT", "Page order requires a bounded zero-based integer index.");
@@ -17862,6 +18281,7 @@ function snapshotVisioEdits(edits, maxEdits, maxText) {
17862
18281
  const target = { pageId: edit.pageId, shapeId: edit.shapeId };
17863
18282
  if (edit.type === "replace-plain-text")
17864
18283
  return { ...target, type: edit.type, text: text(edit.text) };
18284
+ if (edit.type === "replace-text-ranges") return snapshotTextRanges(edit, text);
17865
18285
  if (isVisioFormatEdit(edit)) return snapshotFormatting(edit);
17866
18286
  if (edit.type === "reorder-shape") {
17867
18287
  if (!["front", "back", "forward", "backward"].includes(edit.order))
@@ -17888,7 +18308,10 @@ function snapshotVisioEdits(edits, maxEdits, maxText) {
17888
18308
  return { ...target, type: edit.type, beginX, beginY, endX, endY };
17889
18309
  }
17890
18310
  case "create-rectangle":
17891
- case "create-ellipse":
18311
+ case "create-ellipse": {
18312
+ const shape = edit.type === "create-rectangle" ? edit.shape : void 0;
18313
+ if (shape !== void 0 && !isVisioBasicShape(shape))
18314
+ fail("INVALID_EDIT", "Unknown basic shape.");
17892
18315
  return {
17893
18316
  ...target,
17894
18317
  type: edit.type,
@@ -17896,8 +18319,10 @@ function snapshotVisioEdits(edits, maxEdits, maxText) {
17896
18319
  y: numeric5(edit.y),
17897
18320
  width: numeric5(edit.width, true),
17898
18321
  height: numeric5(edit.height, true),
17899
- ...edit.text === void 0 ? {} : { text: text(edit.text) }
18322
+ ...edit.text === void 0 ? {} : { text: text(edit.text) },
18323
+ ...shape === void 0 ? {} : { shape }
17900
18324
  };
18325
+ }
17901
18326
  case "rotate-shape":
17902
18327
  return { ...target, type: edit.type, angle: numeric5(edit.angle) };
17903
18328
  case "flip-shape":
@@ -18311,24 +18736,25 @@ function createRectangle(root2, document, edit) {
18311
18736
  }
18312
18737
  const doc = root2.ownerDocument;
18313
18738
  const node = (name) => doc.createElementNS(root2.namespaceURI, name);
18314
- const section = node("Section");
18315
- section.setAttribute("N", "Geometry");
18316
- section.setAttribute("IX", "0");
18317
- for (const [index, [x, y]] of [
18318
- [0, 0],
18319
- [1, 0],
18320
- [1, 1],
18321
- [0, 1],
18322
- [0, 0]
18323
- ].entries()) {
18324
- const row = node("Row");
18325
- row.setAttribute("IX", String(index + 1));
18326
- row.setAttribute("T", index ? "RelLineTo" : "RelMoveTo");
18327
- setCell(row, "X", x);
18328
- setCell(row, "Y", y);
18329
- section.appendChild(row);
18739
+ const outline = visioBasicShapeOutline(
18740
+ edit.type === "create-rectangle" ? edit.shape ?? "rectangle" : "rectangle"
18741
+ );
18742
+ if (outline.rounding)
18743
+ setCell(shape, "Rounding", outline.rounding * Math.min(edit.width, edit.height));
18744
+ for (const [sectionIndex, points] of outline.paths.entries()) {
18745
+ const section = node("Section");
18746
+ section.setAttribute("N", "Geometry");
18747
+ section.setAttribute("IX", String(sectionIndex));
18748
+ for (const [index, [x, y]] of [...points, points[0]].entries()) {
18749
+ const row = node("Row");
18750
+ row.setAttribute("IX", String(index + 1));
18751
+ row.setAttribute("T", index ? "RelLineTo" : "RelMoveTo");
18752
+ setCell(row, "X", x);
18753
+ setCell(row, "Y", y);
18754
+ section.appendChild(row);
18755
+ }
18756
+ shape.appendChild(section);
18330
18757
  }
18331
- shape.appendChild(section);
18332
18758
  const text = node("Text");
18333
18759
  text.appendChild(doc.createTextNode(encodeVisioPlainText(edit.text ?? "")));
18334
18760
  shape.appendChild(text);
@@ -20560,6 +20986,145 @@ function addReplacementPage(pagesPart, pages, rels, types, pagePaths, parts, dir
20560
20986
  );
20561
20987
  }
20562
20988
 
20989
+ // visio/edit-page-size.ts
20990
+ function constant(node, length) {
20991
+ if (!node || node.hasAttribute("E") || attribute2(node, "F") === "Inh")
20992
+ fail("EDIT_UNSUPPORTED_PAGE_SIZE", "A valid explicit page size or mode cache is required.");
20993
+ const value = visioFormulaCachedValue(attribute2(node, "V") ?? "", attribute2(node, "U"));
20994
+ if (!Number.isFinite(value.value) || !["scalar", ...length ? ["length"] : []].includes(value.unit))
20995
+ fail("EDIT_UNSUPPORTED_PAGE_SIZE", "Page size or mode has incompatible units.");
20996
+ const formula = executableCellFormula(attribute2(node, "F"));
20997
+ if (formula) {
20998
+ const analysis = analyzeVisioFormula(formula);
20999
+ if (analysis.guarded || analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length)
21000
+ fail("EDIT_PROTECTED_CELL", "Protected or dependent page settings cannot be overwritten.");
21001
+ const result = evaluateVisioFormula(
21002
+ formula,
21003
+ () => fail("EDIT_PROTECTED_CELL", "Unsupported page dependency.")
21004
+ );
21005
+ if (result.value !== value.value || !["scalar", ...length ? ["length"] : []].includes(result.unit))
21006
+ fail("EDIT_PROTECTED_CELL", "Page setting formula cache cannot be proven.");
21007
+ }
21008
+ return value.value;
21009
+ }
21010
+ var escape3 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
21011
+ function assertDependencies(roots, pagesPart, pages, pagePaths, pageId, changed, check) {
21012
+ const page = children2(pages, "Page").find((node) => attribute2(node, "ID") === pageId);
21013
+ const targetNames = new Set(
21014
+ ["Name", "NameU"].map((name) => attribute2(page, name)?.toLowerCase())
21015
+ );
21016
+ 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()));
21017
+ const cells4 = changed.map(escape3).join("|");
21018
+ const reference = new RegExp(`(?:^|[^a-z0-9_.])(?:${cells4})(?:$|[^a-z0-9_.])`, "i");
21019
+ const other = otherNames.length ? new RegExp(
21020
+ `Pages\\[(?:${otherNames.map(escape3).join("|")})\\]!(?:ThePage!)?(?:${cells4})(?![a-z0-9_.])`,
21021
+ "gi"
21022
+ ) : void 0;
21023
+ const paths = new Map([...pagePaths].map(([id, path]) => [path, id]));
21024
+ for (const [path, root2] of roots)
21025
+ for (const node of [root2, ...Array.from(root2.getElementsByTagName("*"))]) {
21026
+ check();
21027
+ const formula = executableCellFormula(attribute2(node, "F"));
21028
+ if (!formula) continue;
21029
+ let code = unquotedVisioFormula(formula);
21030
+ const name = attribute2(node, "N") ?? "";
21031
+ if (inertDoubleClickFormula(name, formula)) continue;
21032
+ const owner = node.parentNode, container = owner?.parentNode;
21033
+ const ownerId = attribute2(owner ?? void 0, "ID");
21034
+ 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(
21035
+ (name2) => children2(owner, "Cell").filter((cell) => attribute2(cell, "N") === name2).length === 1
21036
+ ) && container?.localName === "Shapes" && container.parentNode === root2 && children2(root2, "Connects").some(
21037
+ (connections2) => children2(connections2, "Connect").some(
21038
+ (connection) => attribute2(connection, "FromSheet") === ownerId
21039
+ )
21040
+ );
21041
+ 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(
21042
+ code
21043
+ ) || /^(BegTrigger|EndTrigger)$/.test(name) && /^\s*_XFTRIGGER\(Sheet\.[1-9]\d*!EventXFMod\)\s*$/i.test(code));
21044
+ let dynamic2 = false;
21045
+ if (!nativeGlue) {
21046
+ try {
21047
+ dynamic2 = analyzeVisioFormula(
21048
+ mapVisioFormulaSyntax(
21049
+ formula,
21050
+ (part) => (other ? part.replace(other, "0") : part).replace(/Pages\[[^\]]+\]!/gi, "").replace(/ThePage!/gi, "")
21051
+ )
21052
+ ).dynamic;
21053
+ } catch {
21054
+ dynamic2 = true;
21055
+ }
21056
+ }
21057
+ if (dynamic2)
21058
+ fail(
21059
+ "EDIT_UNSUPPORTED_PAGE_SIZE_DEPENDENCY",
21060
+ "Dynamic or unknown page-size dependencies cannot be safely refreshed."
21061
+ );
21062
+ let local = paths.get(path);
21063
+ if (path === pagesPart) {
21064
+ let ancestor = node;
21065
+ while (ancestor && ancestor.localName !== "Page")
21066
+ ancestor = ancestor.parentNode;
21067
+ local = ancestor ? attribute2(ancestor, "ID") : void 0;
21068
+ }
21069
+ if (other) code = code.replace(other, "0");
21070
+ if (!reference.test(code)) continue;
21071
+ if (local && local !== pageId && !/\bPages\[/i.test(code)) continue;
21072
+ fail(
21073
+ "EDIT_UNSUPPORTED_PAGE_SIZE_DEPENDENCY",
21074
+ "Page-size formula caches cannot be safely refreshed."
21075
+ );
21076
+ }
21077
+ }
21078
+ async function setVisioPageSize(pkg, pagesPart, pages, pagePaths, dirty, command2, check) {
21079
+ const page = children2(pages, "Page").find((node) => attribute2(node, "ID") === command2.pageId);
21080
+ if (!page) fail("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
21081
+ if (children2(page, "PageSheet").length !== 1)
21082
+ fail("EDIT_UNSUPPORTED_PAGE_SIZE", "One explicit PageSheet is required.");
21083
+ const sheet = child(page, "PageSheet"), cells4 = uniqueFormattingCells(sheet);
21084
+ for (const name of [
21085
+ "PageWidth",
21086
+ "PageHeight",
21087
+ "PageScale",
21088
+ "DrawingScale",
21089
+ "DrawingSizeType",
21090
+ "DrawingResizeType"
21091
+ ])
21092
+ if (!cells4.has(name) && [...cells4.keys()].some((key2) => key2.toLowerCase() === name.toLowerCase()))
21093
+ fail("EDIT_AMBIGUOUS_CELL", "Page settings require canonical cell names.");
21094
+ const pageScale = constant(cells4.get("PageScale"), true), drawingScale = constant(cells4.get("DrawingScale"), true);
21095
+ if (pageScale <= 0 || drawingScale <= 0)
21096
+ fail("EDIT_UNSUPPORTED_PAGE_SIZE", "Page and drawing scales must be positive.");
21097
+ const width = constant(cells4.get("PageWidth"), true), height = constant(cells4.get("PageHeight"), true);
21098
+ const size = constant(cells4.get("DrawingSizeType"), false);
21099
+ const resize = cells4.has("DrawingResizeType") ? constant(cells4.get("DrawingResizeType"), false) : void 0;
21100
+ if (width <= 0 || height <= 0 || ![0, 1, 2, 3, 4].includes(size) || resize !== void 0 && ![0, 1, 2].includes(resize))
21101
+ fail("EDIT_UNSUPPORTED_PAGE_SIZE", "Page dimensions or size modes are unsupported.");
21102
+ const targetWidth = command2.width === width * (pageScale / drawingScale) ? width : command2.width * drawingScale / pageScale, targetHeight = command2.height === height * (pageScale / drawingScale) ? height : command2.height * drawingScale / pageScale;
21103
+ if (![targetWidth, targetHeight].every(
21104
+ (value) => Number.isFinite(value) && value > 0 && value <= 1e6
21105
+ ))
21106
+ fail("INVALID_PAGE_SIZE", "Converted drawing-page dimensions exceed limits.");
21107
+ const values = /* @__PURE__ */ new Map([
21108
+ ["PageWidth", targetWidth],
21109
+ ["PageHeight", targetHeight],
21110
+ ["DrawingSizeType", 3],
21111
+ ["DrawingResizeType", 0]
21112
+ ]);
21113
+ const changed = [...values.keys()].filter(
21114
+ (name) => name === "PageWidth" ? width !== targetWidth : name === "PageHeight" ? height !== targetHeight : name === "DrawingSizeType" ? size !== 3 : resize !== 0
21115
+ );
21116
+ if (!changed.length) return;
21117
+ const roots = await editableVisioPageRoots(pkg, pagesPart, pages, pagePaths, dirty, check);
21118
+ for (const path of pkg.paths())
21119
+ if (/^visio\/.*\.xml$/i.test(path) && !roots.has(path)) {
21120
+ check();
21121
+ roots.set(path, dirty.get(path) ?? await pkg.readXml(path));
21122
+ }
21123
+ assertDependencies(roots, pagesPart, pages, pagePaths, command2.pageId, changed, check);
21124
+ for (const name of changed) setCell(sheet, name, values.get(name));
21125
+ dirty.set(pagesPart, pages);
21126
+ }
21127
+
20563
21128
  // visio/edit-pages.ts
20564
21129
  var officeRel2 = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
20565
21130
  var pageType2 = "http://schemas.microsoft.com/visio/2010/relationships/page";
@@ -20595,6 +21160,10 @@ async function editVsdxPages(original, pkg, parts, commands, limits, maxOutput,
20595
21160
  for (const command2 of commands) {
20596
21161
  check();
20597
21162
  const existing = children2(pages, "Page");
21163
+ if (command2.type === "set-page-size") {
21164
+ await setVisioPageSize(pkg, pagesPart, pages, pagePaths, dirty, command2, check);
21165
+ continue;
21166
+ }
20598
21167
  if (command2.type === "delete-page") {
20599
21168
  await deleteVisioPage(
20600
21169
  pkg,
@@ -20698,8 +21267,10 @@ async function editVsdxPages(original, pkg, parts, commands, limits, maxOutput,
20698
21267
  fail("LIMIT_EDIT_OUTPUT", "Saved package exceeds output limit.");
20699
21268
  return { bytes: original, changedParts: [], diagnostics: [] };
20700
21269
  }
20701
- await updatePageAppProperties(pkg, pages, priorCount, dirty, limits, check);
20702
- await recalculatePageFormulas(pkg, pagesPart, pages, pagePaths, dirty, check);
21270
+ if (commands.some((command2) => command2.type !== "set-page-size")) {
21271
+ await updatePageAppProperties(pkg, pages, priorCount, dirty, limits, check);
21272
+ await recalculatePageFormulas(pkg, pagesPart, pages, pagePaths, dirty, check);
21273
+ }
20703
21274
  if ((/* @__PURE__ */ new Set([...parts.keys(), ...dirty.keys()])).size > limits.maxEntries)
20704
21275
  fail("LIMIT_ENTRIES", "Page insertion exceeds package entry limit.");
20705
21276
  let total = [...parts.values()].reduce((sum, bytes2) => sum + bytes2.length, 0), nodes = 0;
@@ -20727,8 +21298,8 @@ async function editVsdxPages(original, pkg, parts, commands, limits, maxOutput,
20727
21298
  changedParts: [.../* @__PURE__ */ new Set([...removed, ...dirty.keys()])],
20728
21299
  diagnostics: [
20729
21300
  {
20730
- code: "edit-pages-experimental",
20731
- message: "Page metadata and supported local numeric page-dependent caches were updated. Inherited, string and background-render-context formulas remain unsupported."
21301
+ code: commands.every((command2) => command2.type === "set-page-size") ? "edit-page-size-experimental" : "edit-pages-experimental",
21302
+ 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."
20732
21303
  }
20733
21304
  ]
20734
21305
  };
@@ -21557,12 +22128,12 @@ async function editVsdx(input, edits, options = {}) {
21557
22128
  const dirty = /* @__PURE__ */ new Map();
21558
22129
  const roots = /* @__PURE__ */ new Map();
21559
22130
  const geometryCommands = commands.filter(
21560
- (command2) => command2.type !== "replace-plain-text" && command2.type !== "reorder-shape" && command2.type !== "duplicate-shapes" && command2.type !== "paste-shapes" && !isVisioFormatEdit(command2)
22131
+ (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)
21561
22132
  );
21562
22133
  let document;
21563
22134
  let masterMovePins = emptyMasterMoveProof();
21564
22135
  if (geometryCommands.length || commands.some(
21565
- (command2) => command2.type === "replace-plain-text" || isVisioFormatEdit(command2) || command2.type === "reorder-shape" || command2.type === "duplicate-shapes" || command2.type === "paste-shapes"
22136
+ (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"
21566
22137
  )) {
21567
22138
  for (const [pageId, path2] of pages) {
21568
22139
  const sourceRoot = await visioXml(pkg, path2, "PageContents");
@@ -21609,8 +22180,8 @@ async function editVsdx(input, edits, options = {}) {
21609
22180
  root2 = sourceRoot.ownerDocument.cloneNode(true).documentElement;
21610
22181
  roots.set(command2.pageId, root2);
21611
22182
  }
21612
- if (command2.type === "replace-plain-text") {
21613
- if (await replaceScopedPlainText(pkg, new Set(pages.values()), roots, document, command2, check)) {
22183
+ if (command2.type === "replace-plain-text" || command2.type === "replace-text-ranges") {
22184
+ 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))) {
21614
22185
  dirty.set(path, root2);
21615
22186
  textChanged = true;
21616
22187
  }
@@ -22057,6 +22628,7 @@ function trimVisioArrowLine(path, start, end, beginExtension = 0) {
22057
22628
  return `M ${point2(start)}${base > start ? ` L ${point2(base)}` : ""} L ${point2(length - end)}`;
22058
22629
  }
22059
22630
 
22631
+ exports.VISIO_BASIC_SHAPES = VISIO_BASIC_SHAPES;
22060
22632
  exports.VISIO_CLIPBOARD_MAGIC = VISIO_CLIPBOARD_MAGIC;
22061
22633
  exports.VISIO_CLIPBOARD_MAX_CHARS = VISIO_CLIPBOARD_MAX_CHARS;
22062
22634
  exports.VISIO_EMF_ADMISSION_LIMITS = VISIO_EMF_ADMISSION_LIMITS;
@@ -22077,6 +22649,7 @@ exports.evaluateVisioFormula = evaluateVisioFormula;
22077
22649
  exports.getVisioPageLayers = getVisioPageLayers;
22078
22650
  exports.inspectVisioEmfAdmission = inspectVisioEmfAdmission;
22079
22651
  exports.inspectVisioRasterImage = inspectVisioRasterImage;
22652
+ exports.isVisioBasicShape = isVisioBasicShape;
22080
22653
  exports.layoutVisioFilledArrowLine = layoutVisioFilledArrowLine;
22081
22654
  exports.loadVisio = loadVisio;
22082
22655
  exports.parseLegacyVsd = parseLegacyVsd;
@@ -22087,6 +22660,7 @@ exports.sanitizeVisioForeignVectorTree = sanitizeVisioForeignVectorTree;
22087
22660
  exports.serializeVisioClipboard = serializeVisioClipboard;
22088
22661
  exports.trimVisioArrowLine = trimVisioArrowLine;
22089
22662
  exports.validateVisioForeignVector = validateVisioForeignVector;
22663
+ exports.visioBasicShapeOutline = visioBasicShapeOutline;
22090
22664
  exports.visioFilledArrow = visioFilledArrow;
22091
22665
  exports.visioFormulaCachedValue = visioFormulaCachedValue;
22092
22666
  exports.visioOpenArrowExtent = visioOpenArrowExtent;