ooxml-core 1.2.1 → 1.3.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 (149) hide show
  1. package/dist/{PptxHandler-VQQS4VS6.mjs → PptxHandler-ZPJNHEZZ.mjs} +2 -2
  2. package/dist/automation/index.cjs +2235 -333
  3. package/dist/automation/index.mjs +2235 -333
  4. package/dist/{chunk-5U27IVB7.mjs → chunk-BB55ASTX.mjs} +3 -3
  5. package/dist/{chunk-V2BIGIH4.mjs → chunk-H4TPDZV4.mjs} +1 -1
  6. package/dist/{chunk-5VLNF4OX.mjs → chunk-IVDC75E5.mjs} +1 -1
  7. package/dist/{chunk-XBNSBDNT.mjs → chunk-QPQDLSJQ.mjs} +1 -1
  8. package/dist/{chunk-XSFHGZFH.mjs → chunk-XGLKW3JJ.mjs} +5 -3
  9. package/dist/pptx/automation/index.cjs +4 -2
  10. package/dist/pptx/automation/index.mjs +5 -5
  11. package/dist/pptx/cli/index.cjs +4 -2
  12. package/dist/pptx/cli/index.mjs +4 -4
  13. package/dist/pptx/converter/index.mjs +2 -2
  14. package/dist/pptx/index.cjs +4 -2
  15. package/dist/pptx/index.mjs +5 -5
  16. package/dist/teams/index.cjs +19 -10
  17. package/dist/teams/index.mjs +19 -10
  18. package/dist/visio/clipboard-resources.d.ts +11 -0
  19. package/dist/visio/clipboard-resources.d.ts.map +1 -0
  20. package/dist/visio/clipboard-types.d.ts +26 -0
  21. package/dist/visio/clipboard-types.d.ts.map +1 -0
  22. package/dist/visio/clipboard-xml.d.ts +8 -0
  23. package/dist/visio/clipboard-xml.d.ts.map +1 -0
  24. package/dist/visio/clipboard.d.ts +7 -0
  25. package/dist/visio/clipboard.d.ts.map +1 -0
  26. package/dist/visio/create-document.d.ts +8 -0
  27. package/dist/visio/create-document.d.ts.map +1 -0
  28. package/dist/visio/edit-commands.d.ts +19 -2
  29. package/dist/visio/edit-commands.d.ts.map +1 -1
  30. package/dist/visio/edit-delete.d.ts +9 -0
  31. package/dist/visio/edit-delete.d.ts.map +1 -0
  32. package/dist/visio/edit-duplicate-commands.d.ts +14 -0
  33. package/dist/visio/edit-duplicate-commands.d.ts.map +1 -0
  34. package/dist/visio/edit-duplicate-scope.d.ts +4 -0
  35. package/dist/visio/edit-duplicate-scope.d.ts.map +1 -0
  36. package/dist/visio/edit-duplicate.d.ts +10 -0
  37. package/dist/visio/edit-duplicate.d.ts.map +1 -0
  38. package/dist/visio/edit-formatting-cell-admission.d.ts +3 -0
  39. package/dist/visio/edit-formatting-cell-admission.d.ts.map +1 -0
  40. package/dist/visio/edit-formatting-commands.d.ts +46 -0
  41. package/dist/visio/edit-formatting-commands.d.ts.map +1 -0
  42. package/dist/visio/edit-formatting-font.d.ts +6 -0
  43. package/dist/visio/edit-formatting-font.d.ts.map +1 -0
  44. package/dist/visio/edit-formatting-paint-scope.d.ts +6 -0
  45. package/dist/visio/edit-formatting-paint-scope.d.ts.map +1 -0
  46. package/dist/visio/edit-formatting-paint.d.ts +6 -0
  47. package/dist/visio/edit-formatting-paint.d.ts.map +1 -0
  48. package/dist/visio/edit-formatting-rows.d.ts +14 -0
  49. package/dist/visio/edit-formatting-rows.d.ts.map +1 -0
  50. package/dist/visio/edit-formatting-scope.d.ts +6 -0
  51. package/dist/visio/edit-formatting-scope.d.ts.map +1 -0
  52. package/dist/visio/edit-formatting-text.d.ts +8 -0
  53. package/dist/visio/edit-formatting-text.d.ts.map +1 -0
  54. package/dist/visio/edit-formatting.d.ts +12 -0
  55. package/dist/visio/edit-formatting.d.ts.map +1 -0
  56. package/dist/visio/edit-geometry.d.ts.map +1 -1
  57. package/dist/visio/edit-paste-commands.d.ts +15 -0
  58. package/dist/visio/edit-paste-commands.d.ts.map +1 -0
  59. package/dist/visio/edit-paste.d.ts +5 -0
  60. package/dist/visio/edit-paste.d.ts.map +1 -0
  61. package/dist/visio/edit-recalculate.d.ts +3 -1
  62. package/dist/visio/edit-recalculate.d.ts.map +1 -1
  63. package/dist/visio/edit-resize-anchor.d.ts +8 -0
  64. package/dist/visio/edit-resize-anchor.d.ts.map +1 -0
  65. package/dist/visio/edit-scope.d.ts.map +1 -1
  66. package/dist/visio/edit-shape-create.d.ts +1 -1
  67. package/dist/visio/edit-shape-create.d.ts.map +1 -1
  68. package/dist/visio/edit-shape-order.d.ts +7 -0
  69. package/dist/visio/edit-shape-order.d.ts.map +1 -0
  70. package/dist/visio/edit-style-admission.d.ts +17 -0
  71. package/dist/visio/edit-style-admission.d.ts.map +1 -0
  72. package/dist/visio/edit-text-scope.d.ts +7 -0
  73. package/dist/visio/edit-text-scope.d.ts.map +1 -0
  74. package/dist/visio/edit-text.d.ts +1 -1
  75. package/dist/visio/edit-text.d.ts.map +1 -1
  76. package/dist/visio/edit.d.ts +1 -1
  77. package/dist/visio/edit.d.ts.map +1 -1
  78. package/dist/visio/index.cjs +3245 -1077
  79. package/dist/visio/index.d.ts +3 -1
  80. package/dist/visio/index.d.ts.map +1 -1
  81. package/dist/visio/index.mjs +3241 -1079
  82. package/dist/visio/line-pattern.d.ts +1 -1
  83. package/dist/visio/line-pattern.d.ts.map +1 -1
  84. package/dist/visio/line-style.d.ts.map +1 -1
  85. package/dist/visio/model.d.ts +23 -3
  86. package/dist/visio/model.d.ts.map +1 -1
  87. package/dist/visio/parser.d.ts.map +1 -1
  88. package/dist/visio/plain-text.d.ts +5 -0
  89. package/dist/visio/plain-text.d.ts.map +1 -0
  90. package/dist/visio/resize-anchor.d.ts +27 -0
  91. package/dist/visio/resize-anchor.d.ts.map +1 -0
  92. package/dist/visio/source-paint.d.ts +5 -0
  93. package/dist/visio/source-paint.d.ts.map +1 -0
  94. package/dist/visio/style.d.ts.map +1 -1
  95. package/dist/visio/theme-root.d.ts.map +1 -1
  96. package/dist/visio/ui/contract.d.ts +10 -6
  97. package/dist/visio/ui/contract.d.ts.map +1 -1
  98. package/dist/visio/ui/draw-plan.d.ts +32 -0
  99. package/dist/visio/ui/draw-plan.d.ts.map +1 -0
  100. package/dist/visio/ui/edit-commands.d.ts.map +1 -1
  101. package/dist/visio/ui/formatting.d.ts +28 -0
  102. package/dist/visio/ui/formatting.d.ts.map +1 -0
  103. package/dist/visio/ui/index.cjs +1305 -15
  104. package/dist/visio/ui/index.d.ts +15 -0
  105. package/dist/visio/ui/index.d.ts.map +1 -1
  106. package/dist/visio/ui/index.mjs +1261 -16
  107. package/dist/visio/ui/line-dash.d.ts +4 -0
  108. package/dist/visio/ui/line-dash.d.ts.map +1 -0
  109. package/dist/visio/ui/marquee.d.ts +15 -0
  110. package/dist/visio/ui/marquee.d.ts.map +1 -0
  111. package/dist/visio/ui/page-edit.d.ts.map +1 -1
  112. package/dist/visio/ui/scene-validation.d.ts.map +1 -1
  113. package/dist/visio/ui/selection.d.ts +12 -0
  114. package/dist/visio/ui/selection.d.ts.map +1 -0
  115. package/dist/visio/ui/shape-arrange.d.ts +17 -0
  116. package/dist/visio/ui/shape-arrange.d.ts.map +1 -0
  117. package/dist/visio/ui/shape-clipboard.d.ts +10 -0
  118. package/dist/visio/ui/shape-clipboard.d.ts.map +1 -0
  119. package/dist/visio/ui/shape-duplicate.d.ts +5 -0
  120. package/dist/visio/ui/shape-duplicate.d.ts.map +1 -0
  121. package/dist/visio/ui/shape-formatting.d.ts +14 -0
  122. package/dist/visio/ui/shape-formatting.d.ts.map +1 -0
  123. package/dist/visio/ui/shape-move.d.ts +14 -0
  124. package/dist/visio/ui/shape-move.d.ts.map +1 -0
  125. package/dist/visio/ui/shape-order.d.ts +4 -0
  126. package/dist/visio/ui/shape-order.d.ts.map +1 -0
  127. package/dist/visio/ui/shape-resize.d.ts +61 -0
  128. package/dist/visio/ui/shape-resize.d.ts.map +1 -0
  129. package/dist/visio/ui/size-position.d.ts +19 -0
  130. package/dist/visio/ui/size-position.d.ts.map +1 -0
  131. package/dist/visio/ui/snapshot-scene.d.ts.map +1 -1
  132. package/dist/visio/ui/svg-stroke.d.ts +8 -0
  133. package/dist/visio/ui/svg-stroke.d.ts.map +1 -0
  134. package/dist/visio/ui/text-replace-selection.d.ts +9 -0
  135. package/dist/visio/ui/text-replace-selection.d.ts.map +1 -0
  136. package/dist/visio/ui/text-replace-snapshot.d.ts +14 -0
  137. package/dist/visio/ui/text-replace-snapshot.d.ts.map +1 -0
  138. package/dist/visio/ui/text-replace-types.d.ts +48 -0
  139. package/dist/visio/ui/text-replace-types.d.ts.map +1 -0
  140. package/dist/visio/ui/text-replace.d.ts +18 -0
  141. package/dist/visio/ui/text-replace.d.ts.map +1 -0
  142. package/dist/xlsx/formula/lexemes.d.ts.map +1 -1
  143. package/dist/xlsx/index.cjs +18 -9
  144. package/dist/xlsx/index.mjs +18 -9
  145. package/dist/xlsx/load/index.cjs +18 -9
  146. package/dist/xlsx/load/index.mjs +18 -9
  147. package/dist/xlsx/ui/index.cjs +18 -9
  148. package/dist/xlsx/ui/index.mjs +18 -9
  149. package/package.json +1 -1
@@ -259,14 +259,14 @@ function startTag(source2, from, namespaces) {
259
259
  while (q < n && isSpace(source2.charCodeAt(q))) q++;
260
260
  const quote2 = source2[q];
261
261
  if (quote2 !== '"' && quote2 !== "'") return void 0;
262
- const close = source2.indexOf(quote2, q + 1);
263
- if (close < 0) return void 0;
264
- const raw2 = source2.slice(q + 1, close);
262
+ const close2 = source2.indexOf(quote2, q + 1);
263
+ if (close2 < 0) return void 0;
264
+ const raw2 = source2.slice(q + 1, close2);
265
265
  if (raw2.includes("<") || element2.hasAttribute(name)) return void 0;
266
266
  const value = decode(/[\t\n\r]/.test(raw2) ? raw2.replace(/[\t\n\r]/g, " ") : raw2);
267
267
  if (value === void 0) return void 0;
268
268
  element2.attrs.push(name, value);
269
- i2 = close + 1;
269
+ i2 = close2 + 1;
270
270
  const after = source2.charCodeAt(i2);
271
271
  if (i2 < n && !isSpace(after) && after !== 62 && after !== 47) return void 0;
272
272
  }
@@ -2237,12 +2237,12 @@ function linearToSrgb255(linear) {
2237
2237
  // color/hex-rgb.ts
2238
2238
  function parseArgbHex(hex) {
2239
2239
  const clean3 = hex.replace(/^#/, "");
2240
- const rgb2 = clean3.length === 8 ? clean3.slice(2) : clean3;
2241
- if (!/^[0-9a-fA-F]{6}$/.test(rgb2)) return void 0;
2242
- return [0, 2, 4].map((i2) => parseInt(rgb2.slice(i2, i2 + 2), 16));
2240
+ const rgb3 = clean3.length === 8 ? clean3.slice(2) : clean3;
2241
+ if (!/^[0-9a-fA-F]{6}$/.test(rgb3)) return void 0;
2242
+ return [0, 2, 4].map((i2) => parseInt(rgb3.slice(i2, i2 + 2), 16));
2243
2243
  }
2244
2244
  var clamp255 = (v) => Math.max(0, Math.min(255, v));
2245
- var rgbToUpperHex = (rgb2) => `#${rgb2.map((v) => clamp255(Math.round(v)).toString(16).padStart(2, "0")).join("").toUpperCase()}`;
2245
+ var rgbToUpperHex = (rgb3) => `#${rgb3.map((v) => clamp255(Math.round(v)).toString(16).padStart(2, "0")).join("").toUpperCase()}`;
2246
2246
 
2247
2247
  // drawingml/theme-model.ts
2248
2248
  var THEME_COLOR_SLOTS = [
@@ -4570,10 +4570,10 @@ var APPLIED = /* @__PURE__ */ new Set([
4570
4570
  ]);
4571
4571
  function resolveDrawingColor(color2, theme2, options) {
4572
4572
  const base = baseHex(color2, theme2);
4573
- const rgb2 = base ? hexToRgbChannels(base) : null;
4574
- if (!rgb2) return void 0;
4573
+ const rgb3 = base ? hexToRgbChannels(base) : null;
4574
+ if (!rgb3) return void 0;
4575
4575
  {
4576
- const value = orderedColorTransforms(rgb2, color2.transforms);
4576
+ const value = orderedColorTransforms(rgb3, color2.transforms);
4577
4577
  const round3 = options.hslRounding === "halfDown" ? (channel) => Math.ceil(channel - 0.5) : Math.round;
4578
4578
  return {
4579
4579
  hex: `#${toHex(round3(value.r))}${toHex(round3(value.g))}${toHex(round3(value.b))}`,
@@ -11977,10 +11977,10 @@ function parseDynamicArrayMetadata(xml) {
11977
11977
  function parseColor(element2, palette) {
11978
11978
  if (!element2) return void 0;
11979
11979
  const color2 = {};
11980
- const rgb2 = att(element2, "rgb");
11980
+ const rgb3 = att(element2, "rgb");
11981
11981
  const theme2 = numAttr(element2, "theme");
11982
11982
  const indexed = numAttr(element2, "indexed");
11983
- if (rgb2 && /^[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/.test(rgb2)) color2.rgb = rgb2.toUpperCase();
11983
+ if (rgb3 && /^[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/.test(rgb3)) color2.rgb = rgb3.toUpperCase();
11984
11984
  else if (theme2 !== void 0) color2.theme = theme2;
11985
11985
  else if (indexed !== void 0) {
11986
11986
  const override = palette?.[indexed];
@@ -12658,14 +12658,13 @@ function splitSheets(text2) {
12658
12658
  if (book !== void 0) out.book = book;
12659
12659
  return out;
12660
12660
  }
12661
- var PREFIX_AT = /(\[\d+\])?([A-Za-z0-9_.\u00A1-\uFFFF]+)(?::([A-Za-z0-9_.\u00A1-\uFFFF]+))?!/y;
12662
12661
  function readPrefix(source2, at2) {
12663
12662
  const ch = source2[at2];
12664
12663
  if (ch === "'") {
12665
12664
  const quoted = readQuoted(source2, at2);
12666
12665
  if (source2[at2 + quoted.length] !== "!") return void 0;
12667
- const length = quoted.length + 1;
12668
- return { prefix: { text: source2.slice(at2, at2 + length), ...splitSheets(quoted.name) }, length };
12666
+ const length2 = quoted.length + 1;
12667
+ return { prefix: { text: source2.slice(at2, at2 + length2), ...splitSheets(quoted.name) }, length: length2 };
12669
12668
  }
12670
12669
  let i2 = at2;
12671
12670
  if (ch === "[") {
@@ -12674,13 +12673,23 @@ function readPrefix(source2, at2) {
12674
12673
  if (i2 === at2 + 1 || source2[i2] !== "]") return void 0;
12675
12674
  i2++;
12676
12675
  }
12676
+ const sheetFrom = i2;
12677
12677
  while (i2 < source2.length && isSheetCharCode(source2.charCodeAt(i2))) i2++;
12678
- if (source2[i2] !== "!" && source2[i2] !== ":") return void 0;
12679
- const m = matchAt(PREFIX_AT, source2, at2);
12680
- if (!m) return void 0;
12681
- if (!m[1] && /^\d/.test(m[2] ?? "") && !m[3]) return void 0;
12682
- const raw2 = m[0].slice(0, -1);
12683
- return { prefix: { text: m[0], ...splitSheets(raw2) }, length: m[0].length };
12678
+ if (i2 === sheetFrom) return void 0;
12679
+ let lastFrom = -1;
12680
+ if (source2[i2] === ":") {
12681
+ lastFrom = i2 + 1;
12682
+ i2 = lastFrom;
12683
+ while (i2 < source2.length && isSheetCharCode(source2.charCodeAt(i2))) i2++;
12684
+ if (i2 === lastFrom) return void 0;
12685
+ }
12686
+ if (source2[i2] !== "!") return void 0;
12687
+ if (ch !== "[" && lastFrom < 0 && isDigitCode(source2.charCodeAt(sheetFrom))) return void 0;
12688
+ const length = i2 + 1 - at2;
12689
+ return {
12690
+ prefix: { text: source2.slice(at2, at2 + length), ...splitSheets(source2.slice(at2, i2)) },
12691
+ length
12692
+ };
12684
12693
  }
12685
12694
  function numberLiteral(text2) {
12686
12695
  if (text2.length <= 15) return Number(text2);
@@ -13118,14 +13127,14 @@ function fromStoredSyntax(formula) {
13118
13127
  if (name !== "ANCHORARRAY" && name !== "SINGLE") continue;
13119
13128
  const open = nextIndex(list, i2 + 1);
13120
13129
  const arg = nextIndex(list, open + 1);
13121
- const close = nextIndex(list, arg + 1);
13130
+ const close2 = nextIndex(list, arg + 1);
13122
13131
  const target = list[arg];
13123
- if (list[open]?.kind !== "open" || list[close]?.kind !== "close" || !target) continue;
13132
+ if (list[open]?.kind !== "open" || list[close2]?.kind !== "close" || !target) continue;
13124
13133
  const single = target.kind === "ref" || target.kind === "name" || target.kind === "structured";
13125
13134
  if (name === "ANCHORARRAY" && !(target.kind === "ref" && target.ref?.kind === "cell")) continue;
13126
13135
  if (name === "SINGLE" && !single) continue;
13127
13136
  const text2 = name === "ANCHORARRAY" ? `${target.text}#` : `@${target.text}`;
13128
- for (let k = i2; k <= close; k++) list[k].text = "";
13137
+ for (let k = i2; k <= close2; k++) list[k].text = "";
13129
13138
  token.text = text2;
13130
13139
  changed = true;
13131
13140
  }
@@ -14473,12 +14482,12 @@ function splitSheetData(xml) {
14473
14482
  if (openEnd < 0) return void 0;
14474
14483
  const attributes = xml.slice(open.index + tagName2.length + 1, openEnd);
14475
14484
  if (attributes.trimEnd().endsWith("/") || attributes.includes("xmlns")) return void 0;
14476
- const close = xml.indexOf(`</${tagName2}`, openEnd);
14477
- if (close < 0 || OPEN.test(xml.slice(openEnd))) return void 0;
14485
+ const close2 = xml.indexOf(`</${tagName2}`, openEnd);
14486
+ if (close2 < 0 || OPEN.test(xml.slice(openEnd))) return void 0;
14478
14487
  const container = new LiteElement(tagName2, "sheetData", ns || null);
14479
- const data = parseLiteFragment(xml.slice(openEnd + 1, close), container, namespaces);
14488
+ const data = parseLiteFragment(xml.slice(openEnd + 1, close2), container, namespaces);
14480
14489
  if (!data) return void 0;
14481
- return { xml: xml.slice(0, openEnd + 1) + xml.slice(close), sheetData: data.asElement() };
14490
+ return { xml: xml.slice(0, openEnd + 1) + xml.slice(close2), sheetData: data.asElement() };
14482
14491
  }
14483
14492
 
14484
14493
  // xlsx/read/print-options.ts
@@ -15021,10 +15030,10 @@ function hls240ToRgb({ h: h2, l, s }) {
15021
15030
  var parseHex = parseArgbHex;
15022
15031
  var toHexColor = rgbToUpperHex;
15023
15032
  function applyTint(hex, tint) {
15024
- const rgb2 = parseHex(hex) ?? [0, 0, 0];
15025
- if (!tint) return toHexColor(rgb2);
15033
+ const rgb3 = parseHex(hex) ?? [0, 0, 0];
15034
+ if (!tint) return toHexColor(rgb3);
15026
15035
  const t = Math.max(-1, Math.min(1, tint));
15027
- const hls = rgbToHls240(...rgb2);
15036
+ const hls = rgbToHls240(...rgb3);
15028
15037
  const l = t < 0 ? Math.trunc(hls.l * (1 + t)) : Math.round(hls.l * (1 - t) + HLSMAX * t);
15029
15038
  return toHexColor(hls240ToRgb({ ...hls, l: Math.max(0, Math.min(HLSMAX, l)) }));
15030
15039
  }
@@ -27893,8 +27902,8 @@ var Engine = class extends EngineStructure {
27893
27902
  evaluate(formula, at2) {
27894
27903
  const value = this.evaluateAdHoc(formula, at2);
27895
27904
  const frame = this.frameFor(at2.sheet, at2.row, at2.col, void 0);
27896
- const scalar3 = implicitIntersection(value, frame);
27897
- return typeof scalar3 === "number" && !Number.isFinite(scalar3) ? ERR.NUM : scalar3;
27905
+ const scalar4 = implicitIntersection(value, frame);
27906
+ return typeof scalar4 === "number" && !Number.isFinite(scalar4) ? ERR.NUM : scalar4;
27898
27907
  }
27899
27908
  evaluateArray(formula, at2) {
27900
27909
  const value = this.evaluateAdHoc(formula, at2);
@@ -28358,7 +28367,7 @@ var attrPattern = (name) => new RegExp(`(\\s${name}\\s*=\\s*)(["'])(.*?)\\2`);
28358
28367
  function patchWorksheetSource(xml, edits) {
28359
28368
  const match2 = WORKSHEET_SOURCE.exec(xml);
28360
28369
  if (!match2) return xml;
28361
- const [whole, tag, attrs2 = "", close] = match2;
28370
+ const [whole, tag, attrs2 = "", close2] = match2;
28362
28371
  if (/\sr:id\s*=/.test(attrs2)) return xml;
28363
28372
  const sheetMatch = attrPattern("sheet").exec(attrs2);
28364
28373
  const refMatch = attrPattern("ref").exec(attrs2);
@@ -28382,7 +28391,7 @@ function patchWorksheetSource(xml, edits) {
28382
28391
  nextAttrs = nextAttrs.replace(attrPattern("sheet"), (_m, lead, q) => {
28383
28392
  return `${lead}${q}${escapeXmlAttr(nextSheet)}${q}`;
28384
28393
  });
28385
- return xml.replace(whole, `<${tag}${nextAttrs}${close}>`);
28394
+ return xml.replace(whole, `<${tag}${nextAttrs}${close2}>`);
28386
28395
  }
28387
28396
  function rootName(xml) {
28388
28397
  const match2 = /<(?![?!])(?:[A-Za-z][\w.-]*:)?([A-Za-z][\w.-]*)/.exec(xml);
@@ -28576,7 +28585,7 @@ function writeMetadataPart(writer, rels, bookPart, plan, dynamicArraysUsed, sour
28576
28585
  }
28577
28586
 
28578
28587
  // xlsx/write/style-xml.ts
28579
- var argb = (rgb2) => (rgb2.length === 6 ? `FF${rgb2}` : rgb2).toUpperCase();
28588
+ var argb = (rgb3) => (rgb3.length === 6 ? `FF${rgb3}` : rgb3).toUpperCase();
28580
28589
  function colorXml(color2, name = "color") {
28581
28590
  if (!color2) return "";
28582
28591
  if (color2.rgb) return el3(name, { rgb: argb(color2.rgb), tint: color2.tint });
@@ -31981,10 +31990,10 @@ function parseCssColor(text2) {
31981
31990
  return {
31982
31991
  rgb: (hex.length === 3 ? [...hex].map((ch) => ch + ch).join("") : hex).toUpperCase()
31983
31992
  };
31984
- const rgb2 = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(value);
31985
- if (rgb2)
31993
+ const rgb3 = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(value);
31994
+ if (rgb3)
31986
31995
  return {
31987
- rgb: rgb2.slice(1, 4).map((n) => Math.min(255, Number(n)).toString(16).padStart(2, "0")).join("").toUpperCase()
31996
+ rgb: rgb3.slice(1, 4).map((n) => Math.min(255, Number(n)).toString(16).padStart(2, "0")).join("").toUpperCase()
31988
31997
  };
31989
31998
  const named3 = NAMED_COLORS2[value];
31990
31999
  return named3 ? { rgb: named3 } : void 0;
@@ -32069,10 +32078,10 @@ function removeComments(text2) {
32069
32078
  let from = 0;
32070
32079
  for (; ; ) {
32071
32080
  const open = text2.indexOf("<!--", from);
32072
- const close = open < 0 ? -1 : text2.indexOf("-->", open + 4);
32073
- if (close < 0) return out + text2.slice(from);
32081
+ const close2 = open < 0 ? -1 : text2.indexOf("-->", open + 4);
32082
+ if (close2 < 0) return out + text2.slice(from);
32074
32083
  out += text2.slice(from, open);
32075
- from = close + 3;
32084
+ from = close2 + 3;
32076
32085
  }
32077
32086
  }
32078
32087
  function removeTags(text2) {
@@ -32210,12 +32219,12 @@ function parseTsv(text2) {
32210
32219
  while (i2 < body.length) {
32211
32220
  const ch = body[i2] ?? "";
32212
32221
  if (atFieldStart && ch === '"') {
32213
- const close = findClosingQuote(body, i2 + 1);
32214
- if (close >= 0) {
32215
- const next = body[close + 1];
32222
+ const close2 = findClosingQuote(body, i2 + 1);
32223
+ if (close2 >= 0) {
32224
+ const next = body[close2 + 1];
32216
32225
  if (next === void 0 || next === " " || next === "\n") {
32217
- field = body.slice(i2 + 1, close).replace(/""/g, '"');
32218
- i2 = close + 1;
32226
+ field = body.slice(i2 + 1, close2).replace(/""/g, '"');
32227
+ i2 = close2 + 1;
32219
32228
  atFieldStart = false;
32220
32229
  continue;
32221
32230
  }
@@ -41175,20 +41184,20 @@ function drawingPaint(node, colors, placeholder, depth = 0) {
41175
41184
  (transform7) => !SUPPORTED_TRANSFORMS.has(transform7.name) || (integer3(transform7.value) ?? 100001) > 1e5
41176
41185
  ))
41177
41186
  return void 0;
41178
- let rgb2;
41187
+ let rgb3;
41179
41188
  let inherited;
41180
- if (color2.kind === "srgb") rgb2 = color2.value;
41181
- else if (color2.kind === "system") rgb2 = color2.fallback;
41189
+ if (color2.kind === "srgb") rgb3 = color2.value;
41190
+ else if (color2.kind === "system") rgb3 = color2.fallback;
41182
41191
  else if (color2.kind === "scheme") {
41183
- if (color2.value === "phClr") rgb2 = placeholder;
41192
+ if (color2.value === "phClr") rgb3 = placeholder;
41184
41193
  else {
41185
41194
  inherited = drawingPaint(colors.get(color2.value), colors, placeholder, depth + 1);
41186
- rgb2 = inherited?.color;
41195
+ rgb3 = inherited?.color;
41187
41196
  }
41188
41197
  }
41189
- if (!rgb2 || !/^#?[\da-f]{6}$/i.test(rgb2)) return void 0;
41198
+ if (!rgb3 || !/^#?[\da-f]{6}$/i.test(rgb3)) return void 0;
41190
41199
  const resolved = resolveDrawingColor(
41191
- { kind: "srgb", value: rgb2.replace(/^#/, ""), transforms },
41200
+ { kind: "srgb", value: rgb3.replace(/^#/, ""), transforms },
41192
41201
  void 0,
41193
41202
  { }
41194
41203
  );
@@ -41986,13 +41995,7 @@ function lineCap(cells3, resources, report) {
41986
41995
  }
41987
41996
  const value = number(cells3, "LineCap", NaN, report);
41988
41997
  if (value === 0) return "round";
41989
- if (value === 1 || value === 2) {
41990
- report(
41991
- "inferred-line-cap",
41992
- "Legacy square/extended cap geometry uses an inferred compatibility mapping."
41993
- );
41994
- return value === 1 ? "butt" : "square";
41995
- }
41998
+ if (value === 1 || value === 2) return value === 1 ? "butt" : "square";
41996
41999
  if (Number.isFinite(value))
41997
42000
  report("invalid-line-cap", "The cached line cap is outside the supported enumeration.");
41998
42001
  return void 0;
@@ -42000,13 +42003,12 @@ function lineCap(cells3, resources, report) {
42000
42003
 
42001
42004
  // visio/line-pattern.ts
42002
42005
  function builtinDash(pattern) {
42003
- if (pattern === 23) return [2, 2];
42006
+ if (pattern === 23) return [2, 1];
42004
42007
  const band = Math.floor((pattern - 2) / 7);
42005
42008
  const motif = (pattern - 2) % 7;
42006
- const dash = [6, 3, 11][band];
42007
- const gap = [3, 2, 5][band];
42008
- const long = [14, 7, 27][band];
42009
- const longGap = [2, 2, 5][band];
42009
+ const dash = [8, 4, 16][band];
42010
+ const gap = [4, 2, 8][band];
42011
+ const long = [20, 10, 40][band];
42010
42012
  const lengths = [
42011
42013
  [dash],
42012
42014
  [1],
@@ -42016,9 +42018,9 @@ function builtinDash(pattern) {
42016
42018
  [long, dash],
42017
42019
  [long, dash, dash]
42018
42020
  ][motif];
42019
- return lengths.flatMap((length) => [length, motif >= 5 ? longGap : gap]);
42021
+ return lengths.flatMap((length) => [length, gap]);
42020
42022
  }
42021
- function linePattern(cells3, report) {
42023
+ function linePattern(cells3, report, cap = "round") {
42022
42024
  const raw2 = cells3.get("LinePattern")?.value;
42023
42025
  if (raw2 === "Themed") {
42024
42026
  report(
@@ -42033,11 +42035,14 @@ function linePattern(cells3, report) {
42033
42035
  }
42034
42036
  const pattern = number(cells3, "LinePattern", 1, report);
42035
42037
  if (Number.isInteger(pattern) && pattern >= 2 && pattern <= 23) {
42036
- report(
42037
- "inferred-line-pattern",
42038
- "Built-in line-pattern spacing uses inferred stroke-width ratios, not verified native spacing."
42038
+ const lineDash = builtinDash(pattern).map(
42039
+ (value, index2) => cap === "butt" ? value : value + (index2 % 2 ? 1 : -1)
42039
42040
  );
42040
- return { linePattern: pattern, lineDash: builtinDash(pattern) };
42041
+ return {
42042
+ linePattern: pattern,
42043
+ lineDash,
42044
+ ...cap === "square" && lineDash.includes(0) ? { lineDashDotLength: 0.01 / 72 } : {}
42045
+ };
42041
42046
  }
42042
42047
  if (pattern === 254)
42043
42048
  report(
@@ -42054,6 +42059,25 @@ function linePattern(cells3, report) {
42054
42059
  return { linePattern: pattern };
42055
42060
  }
42056
42061
 
42062
+ // visio/source-paint.ts
42063
+ function sourcePaint(cells3, resolveColor2) {
42064
+ const opacity2 = (name) => {
42065
+ if (cells3.get(name)?.error) return void 0;
42066
+ const cached3 = number(cells3, name, cells3.has(name) ? NaN : 0);
42067
+ return Number.isFinite(cached3) && cached3 >= 0 && cached3 <= 1 ? 1 - cached3 : void 0;
42068
+ };
42069
+ const foregroundOpacity = opacity2("FillForegndTrans"), backgroundOpacity = opacity2("FillBkgndTrans"), lineColorOpacity = opacity2("LineColorTrans");
42070
+ const pattern = cells3.get("FillPattern")?.error ? NaN : number(cells3, "FillPattern", cells3.has("FillPattern") ? NaN : 1);
42071
+ const backgroundColor = cells3.get("FillBkgnd")?.error ? "" : resolveColor2("FillBkgnd", cells3.has("FillBkgnd") ? "" : "#ffffff");
42072
+ return {
42073
+ ...Number.isInteger(pattern) && pattern >= 0 && pattern <= 65535 ? { fillPatternIndex: pattern } : {},
42074
+ ...foregroundOpacity === void 0 ? {} : { fillForegroundOpacity: foregroundOpacity },
42075
+ ...backgroundColor ? { fillBackgroundColor: backgroundColor } : {},
42076
+ ...backgroundOpacity === void 0 ? {} : { fillBackgroundOpacity: backgroundOpacity },
42077
+ ...lineColorOpacity === void 0 ? {} : { lineColorOpacity }
42078
+ };
42079
+ }
42080
+
42057
42081
  // visio/text-background.ts
42058
42082
  function textBackground(cells3, resources, report) {
42059
42083
  const raw2 = cells3.get("TextBkgnd")?.value;
@@ -42134,6 +42158,15 @@ function textParagraphs(text2, markers, sheet, fontFamily, fontSize, resources,
42134
42158
  return paragraphs;
42135
42159
  }
42136
42160
 
42161
+ // visio/plain-text.ts
42162
+ function encodeVisioPlainText(text2) {
42163
+ return text2 ? `${text2}
42164
+ ` : "";
42165
+ }
42166
+ function decodeVisioPlainText(text2) {
42167
+ return text2.endsWith("\n") ? text2.slice(0, -1) : text2;
42168
+ }
42169
+
42137
42170
  // visio/nurbs-flatten.ts
42138
42171
  var CURVE_TOLERANCE = 1e-4;
42139
42172
  var MAX_WORK = 2e6;
@@ -42854,11 +42887,13 @@ function shapeStyle(sheet, resources, report, width = number(sheet.cells, "Width
42854
42887
  fill: pattern === 0 ? "none" : color(cells3, "FillForegnd", "#ffffff", resources, report, cells3, !!fillGradient),
42855
42888
  ...fillGradient ? { fillGradient } : {},
42856
42889
  ...fillPattern ? { fillPattern } : {},
42890
+ ...sourcePaint(cells3, (name, fallback) => color(cells3, name, fallback, resources, () => {
42891
+ })),
42857
42892
  lineColor: color(cells3, "LineColor", "#000000", resources, report),
42858
42893
  ...lineGradient ? { lineGradient } : {},
42859
42894
  lineWidth: themeLineWeight(cells3, resources, report) ?? Math.max(0, number(cells3, "LineWeight", 0.01, report)),
42860
42895
  ...cap === void 0 ? {} : { lineCap: cap },
42861
- ...themeSolidLinePattern(cells3, resources) ?? linePattern(cells3, report),
42896
+ ...themeSolidLinePattern(cells3, resources) ?? linePattern(cells3, report, cap),
42862
42897
  // Saved and legacy stop transparencies already supply the fill opacity.
42863
42898
  fillOpacity: savedGradient || legacyGradient || fillPattern ? 1 : opacity(number(cells3, "FillForegndTrans", 0, report)),
42864
42899
  lineOpacity: lineGradient ? 1 : opacity(number(cells3, "LineColorTrans", 0, report)),
@@ -42882,7 +42917,8 @@ function runStyle(cells3, resources, report, themeCells) {
42882
42917
  ...transparency > 0 ? { opacity: 1 - Math.round(transparency * 255) / 255 } : {},
42883
42918
  bold: !!(bits & 1),
42884
42919
  italic: !!(bits & 2),
42885
- underline: !!(bits & 4)
42920
+ underline: !!(bits & 4),
42921
+ strikethrough: number(cells3, "Strikethru", 0, report) !== 0
42886
42922
  };
42887
42923
  }
42888
42924
  function shapeText(sheet, node, width, height, resources, report, consume, consumeParagraph) {
@@ -42892,8 +42928,9 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
42892
42928
  let currentCells = defaultCells;
42893
42929
  const runs = [];
42894
42930
  const paragraphMarkers = [];
42895
- let textOffset = 0;
42896
- const append = (text2) => {
42931
+ let textOffset = 0, terminalDirectText = false;
42932
+ const append = (text2, direct = false) => {
42933
+ terminalDirectText = direct;
42897
42934
  if (text2) {
42898
42935
  consume(text2.length);
42899
42936
  runs.push({ text: text2, ...runStyle(currentCells, resources, report, cells3) });
@@ -42902,8 +42939,9 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
42902
42939
  };
42903
42940
  if (node && !number(cells3, "HideText", 0, report)) {
42904
42941
  for (const part of Array.from(node.childNodes)) {
42905
- if (part.nodeType === 3 || part.nodeType === 4) append(part.nodeValue ?? "");
42906
- else if (part.nodeType === 1) {
42942
+ if (part.nodeType === 3 || part.nodeType === 4) {
42943
+ if (part.nodeValue) append(part.nodeValue, true);
42944
+ } else if (part.nodeType === 1) {
42907
42945
  const element2 = part;
42908
42946
  if (element2.localName === "cp")
42909
42947
  currentCells = characters.get(element2.getAttribute("IX") ?? "0") ?? defaultCells;
@@ -42924,10 +42962,10 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
42924
42962
  const alignment = number(paragraph2, "HorzAlign", 1, report);
42925
42963
  const textWidth = Math.max(0, number(cells3, "TxtWidth", width, report)), textHeight = Math.max(0, number(cells3, "TxtHeight", height, report));
42926
42964
  const vertical = number(cells3, "VerticalAlign", 1, report);
42927
- const plainText = runs.map((r) => r.text).join("");
42965
+ const storedText = runs.map((r) => r.text).join("");
42928
42966
  const defaultRun = runStyle(defaultCells, resources, report, cells3);
42929
42967
  const paragraphs = textParagraphs(
42930
- plainText,
42968
+ storedText,
42931
42969
  paragraphMarkers,
42932
42970
  sheet,
42933
42971
  defaultRun.fontFamily,
@@ -42937,13 +42975,16 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
42937
42975
  runs,
42938
42976
  consumeParagraph
42939
42977
  );
42978
+ const lastRun = runs.at(-1);
42979
+ if (terminalDirectText && lastRun) lastRun.text = decodeVisioPlainText(lastRun.text);
42980
+ const plainText = runs.map((run2) => run2.text).join("");
42940
42981
  return {
42941
42982
  plainText,
42942
42983
  ...textBackground(cells3, resources, report),
42943
42984
  paragraphs,
42944
42985
  runs,
42945
42986
  ...runStyle(defaultCells, resources, report, cells3),
42946
- horizontalAlign: alignment === 1 ? "center" : alignment === 2 ? "right" : "left",
42987
+ horizontalAlign: alignment === 1 ? "center" : alignment === 2 ? "right" : alignment === 3 ? "justify" : "left",
42947
42988
  verticalAlign: vertical === 0 ? "top" : vertical === 2 ? "bottom" : "middle",
42948
42989
  width: textWidth,
42949
42990
  height: textHeight,
@@ -43384,6 +43425,7 @@ var LINE_PROPERTIES = [
43384
43425
  "LineCap",
43385
43426
  "LinePattern",
43386
43427
  "LineColorTrans",
43428
+ "LineGradientEnabled",
43387
43429
  "BeginArrow",
43388
43430
  "EndArrow",
43389
43431
  "BeginArrowSize",
@@ -43955,12 +43997,26 @@ async function parseVsdx(input, options = {}) {
43955
43997
  };
43956
43998
  for (const color2 of children3(child5(documentRoot, "Colors"), "ColorEntry"))
43957
43999
  resources.colors.set(attribute3(color2, "IX") ?? "", attribute3(color2, "RGB") ?? "");
43958
- children3(child5(documentRoot, "FaceNames"), "FaceName").forEach(
43959
- (font2, index2) => resources.fonts.set(
44000
+ const faceNames = children3(child5(documentRoot, "FaceNames"), "FaceName");
44001
+ if (faceNames.length > 1e4)
44002
+ throw new VisioPackageError(
44003
+ "METADATA_LIMIT",
44004
+ "Document font count exceeds its metadata limit."
44005
+ );
44006
+ let fontCharacters = 0;
44007
+ faceNames.forEach((font2, index2) => {
44008
+ checkTime();
44009
+ fontCharacters += (attribute3(font2, "Name") ?? attribute3(font2, "NameU") ?? "Arial").length;
44010
+ if (fontCharacters > 1e6)
44011
+ throw new VisioPackageError(
44012
+ "METADATA_LIMIT",
44013
+ "Document fonts exceed aggregate metadata limits."
44014
+ );
44015
+ resources.fonts.set(
43960
44016
  metadata(attribute3(font2, "ID") ?? String(index2), 256, "Font ID"),
43961
44017
  metadata(attribute3(font2, "Name") ?? attribute3(font2, "NameU") ?? "Arial", 1024, "Font name")
43962
- )
43963
- );
44018
+ );
44019
+ });
43964
44020
  const styles = /* @__PURE__ */ new Map();
43965
44021
  for (const style2 of children3(child5(documentRoot, "StyleSheets"), "StyleSheet"))
43966
44022
  styles.set(metadata(attribute3(style2, "ID") ?? "", 256, "Style ID"), {
@@ -44127,7 +44183,12 @@ async function parseVsdx(input, options = {}) {
44127
44183
  "ShapeSheet formulas, automatic connector routing, and external data are not evaluated; saved cached values and supported theme records are used.",
44128
44184
  { severity: "info" }
44129
44185
  );
44130
- return { format: "vsdx", pages, diagnostics: diagnosticState.finish() };
44186
+ return {
44187
+ format: "vsdx",
44188
+ pages,
44189
+ diagnostics: diagnosticState.finish(),
44190
+ fontFamilies: [...new Set(resources.fonts.values())]
44191
+ };
44131
44192
  }
44132
44193
 
44133
44194
  // automation/visio.ts
@@ -44282,203 +44343,12 @@ function writeEditedPackage(parts, maxBytes, deadline, check3) {
44282
44343
  });
44283
44344
  }
44284
44345
 
44285
- // visio/edit-text.ts
44286
- function replacePlainText(root, shapeId, text2, check3) {
44287
- const shapeChildren = (parent) => {
44288
- const containers = children3(parent, "Shapes");
44289
- if (containers.length > 1)
44290
- fail2("INVALID_SHAPE_ID", "Duplicate Shapes containers are ambiguous.");
44291
- return children3(containers[0], "Shape");
44292
- };
44293
- const shapes = /* @__PURE__ */ new Map();
44294
- const pending2 = shapeChildren(root).map((node2) => ({
44295
- node: node2,
44296
- inherited: false,
44297
- deleted: false
44298
- }));
44299
- while (pending2.length) {
44300
- check3();
44301
- const item = pending2.pop();
44302
- const id = attribute3(item.node, "ID");
44303
- if (!id || shapes.has(id))
44304
- fail2("INVALID_SHAPE_ID", "Local shape IDs must be present and unique.");
44305
- const inherited = item.inherited || item.node.hasAttribute("Master") || item.node.hasAttribute("MasterShape");
44306
- const deleted = item.deleted || ["1", "true"].includes(attribute3(item.node, "Del") ?? "");
44307
- shapes.set(id, { node: item.node, inherited, deleted });
44308
- for (const node2 of shapeChildren(item.node)) pending2.push({ node: node2, inherited, deleted });
44309
- }
44310
- const target = shapes.get(shapeId);
44311
- if (!target) fail2("EDIT_TARGET_NOT_FOUND", "Local shape does not exist.");
44312
- if (target.inherited || target.deleted)
44313
- fail2("UNSUPPORTED_TEXT_EDIT", "Master-linked or deleted shapes cannot be edited.");
44314
- const texts = children3(target.node, "Text");
44315
- if (texts.length !== 1)
44316
- fail2("UNSUPPORTED_TEXT_EDIT", "Editing requires one existing local Text element.");
44317
- const node = texts[0];
44318
- if (Array.from(node.childNodes).some((item) => item.nodeType !== 3 && item.nodeType !== 4))
44319
- fail2("UNSUPPORTED_TEXT_EDIT", "Rich text, fields and unknown text markup cannot be edited.");
44320
- if (children3(target.node, "Section").some((section) => attribute3(section, "N") === "Field"))
44321
- fail2("UNSUPPORTED_TEXT_EDIT", "Shapes with text fields cannot be edited.");
44322
- if (node.textContent === text2) return false;
44323
- while (node.firstChild) node.removeChild(node.firstChild);
44324
- node.appendChild(node.ownerDocument.createTextNode(text2));
44325
- return true;
44326
- }
44327
- function serializeEditedXml(root, limits, check3) {
44328
- check3();
44329
- const pending2 = [root.ownerDocument];
44330
- while (pending2.length) {
44331
- check3();
44332
- const node = pending2.pop();
44333
- if ((node.nodeType === 3 || node.nodeType === 4) && node.nodeValue?.includes("\r"))
44334
- fail2("UNSUPPORTED_XML_EDIT", "Carriage-return text cannot be preserved by this writer.");
44335
- if (node.nodeType === 1) {
44336
- for (const attr3 of Array.from(node.attributes))
44337
- if (/[\t\r\n]/.test(attr3.value))
44338
- fail2("UNSUPPORTED_XML_EDIT", "Attribute whitespace cannot be preserved by this writer.");
44339
- }
44340
- for (const child6 of Array.from(node.childNodes)) pending2.push(child6);
44341
- }
44342
- let xml = buildXml(root.ownerDocument);
44343
- xml = xml.replace(
44344
- /^<\?xml\s[^?]*\?>/,
44345
- (declaration) => declaration.replace(/encoding\s*=\s*(['"])[^'"]*\1/, 'encoding="UTF-8"')
44346
- );
44347
- const nodes = inspectXml(xml, limits, check3);
44348
- inspectNamespaces(root, check3);
44349
- const bytes = new TextEncoder().encode(xml);
44350
- if (bytes.length > limits.maxEntryBytes)
44351
- fail2("LIMIT_ENTRY", "Edited XML part exceeds byte limit.");
44352
- return { bytes, nodes };
44353
- }
44354
-
44355
- // visio/edit-commands.ts
44356
- var isVisioPageEdit = (edit) => edit.type === "insert-page" || edit.type === "reorder-page" || edit.type === "rename-page" || edit.type === "delete-page";
44357
- function geometryChangedCells(edit) {
44358
- if (edit.type === "create-line")
44359
- return [
44360
- "BeginX",
44361
- "BeginY",
44362
- "EndX",
44363
- "EndY",
44364
- "PinX",
44365
- "PinY",
44366
- "Width",
44367
- "Height",
44368
- "Angle",
44369
- "LocPinX",
44370
- "LocPinY"
44371
- ];
44372
- if (edit.type === "delete-shape") return [];
44373
- if (edit.type === "move-line-endpoint") {
44374
- const prefix = edit.endpoint === "begin" ? "Begin" : "End";
44375
- return [`${prefix}X`, `${prefix}Y`];
44376
- }
44377
- if (edit.type === "move-shape") return ["PinX", "PinY"];
44378
- if (edit.type === "resize-shape") return ["Width", "Height"];
44379
- if (edit.type === "rotate-shape") return ["Angle"];
44380
- if (edit.type === "flip-shape") return ["Angle", edit.axis === "horizontal" ? "FlipX" : "FlipY"];
44381
- return ["PinX", "PinY", "Width", "Height"];
44346
+ // visio/cell-formula.ts
44347
+ function executableCellFormula(source2) {
44348
+ return !source2 || source2 === "No Formula" || source2 === "Inh" ? void 0 : source2;
44382
44349
  }
44383
- function snapshotVisioEdits(edits, maxEdits, maxText) {
44384
- if (!Array.isArray(edits) || edits.length > maxEdits)
44385
- fail2("LIMIT_EDITS", "Edit command count exceeds limit.");
44386
- let textLength = 0;
44387
- const text2 = (value) => {
44388
- if (typeof value !== "string") fail2("INVALID_EDIT", "Edit text must be a string.");
44389
- textLength += value.length;
44390
- if (textLength > maxText) fail2("LIMIT_EDIT_TEXT", "Replacement text exceeds aggregate limit.");
44391
- if (/[\u0000-\u0008\u000b\u000c\u000d\u000e-\u001f\ufffe\uffff]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/u.test(
44392
- value
44393
- ))
44394
- fail2("INVALID_EDIT_TEXT", "Replacement text contains invalid XML characters.");
44395
- return value;
44396
- };
44397
- const numeric5 = (value, dimension2 = false, allowZero = false) => {
44398
- if (typeof value !== "number" || !Number.isFinite(value) || Math.abs(value) > 1e6 || dimension2 && (value < 0 || !allowZero && value === 0))
44399
- fail2(
44400
- "INVALID_EDIT",
44401
- "Geometry requires finite drawing inches within limits and positive dimensions."
44402
- );
44403
- return value;
44404
- };
44405
- return Array.from(edits, (edit) => {
44406
- if (!edit || typeof edit.pageId !== "string" || !edit.pageId || edit.pageId.length > 256)
44407
- fail2("INVALID_EDIT", "Invalid edit target.");
44408
- if (edit.type === "delete-page") return { type: edit.type, pageId: edit.pageId };
44409
- if (edit.type === "reorder-page") {
44410
- if (!Number.isSafeInteger(edit.index) || edit.index < 0 || edit.index > 1e6)
44411
- fail2("INVALID_EDIT", "Page order requires a bounded zero-based integer index.");
44412
- return { type: edit.type, pageId: edit.pageId, index: edit.index };
44413
- }
44414
- if (edit.type === "insert-page") {
44415
- const name = text2(edit.name);
44416
- if (!/^(0|[1-9]\d{0,9})$/.test(edit.pageId) || Number(edit.pageId) > 4294967295 || typeof edit.afterPageId !== "string" || !edit.afterPageId || edit.afterPageId.length > 256 || !name.trim() || name.length > 256 || /[\t\n]/.test(name))
44417
- fail2("INVALID_EDIT", "Invalid new page ID, name or insertion target.");
44418
- return { type: edit.type, pageId: edit.pageId, afterPageId: edit.afterPageId, name };
44419
- }
44420
- if (edit.type === "rename-page") {
44421
- const name = text2(edit.name);
44422
- if (!name.trim() || name.length > 255 || /[\t\n]/.test(name))
44423
- fail2("INVALID_EDIT", "Invalid page name.");
44424
- return { type: edit.type, pageId: edit.pageId, name };
44425
- }
44426
- if (typeof edit.shapeId !== "string" || !edit.shapeId || edit.shapeId.length > 256)
44427
- fail2("INVALID_EDIT", "Invalid edit shape target.");
44428
- const target = { pageId: edit.pageId, shapeId: edit.shapeId };
44429
- if (edit.type === "replace-plain-text")
44430
- return { ...target, type: edit.type, text: text2(edit.text) };
44431
- if (!/^[1-9]\d{0,9}$/.test(edit.shapeId) || Number(edit.shapeId) > 4294967295)
44432
- fail2("INVALID_EDIT", "Geometry shape IDs must be canonical positive unsigned integers.");
44433
- switch (edit.type) {
44434
- case "create-line": {
44435
- const beginX = numeric5(edit.beginX), beginY = numeric5(edit.beginY);
44436
- const endX = numeric5(edit.endX), endY = numeric5(edit.endY);
44437
- numeric5(Math.hypot(endX - beginX, endY - beginY), true);
44438
- return { ...target, type: edit.type, beginX, beginY, endX, endY };
44439
- }
44440
- case "create-rectangle":
44441
- case "create-ellipse":
44442
- return {
44443
- ...target,
44444
- type: edit.type,
44445
- x: numeric5(edit.x),
44446
- y: numeric5(edit.y),
44447
- width: numeric5(edit.width, true),
44448
- height: numeric5(edit.height, true),
44449
- ...edit.text === void 0 ? {} : { text: text2(edit.text) }
44450
- };
44451
- case "rotate-shape":
44452
- return { ...target, type: edit.type, angle: numeric5(edit.angle) };
44453
- case "flip-shape":
44454
- if (edit.axis !== "horizontal" && edit.axis !== "vertical")
44455
- fail2("INVALID_EDIT", "Invalid flip axis.");
44456
- return { ...target, type: edit.type, axis: edit.axis };
44457
- case "move-shape":
44458
- return { ...target, type: edit.type, x: numeric5(edit.x), y: numeric5(edit.y) };
44459
- case "move-line-endpoint":
44460
- if (edit.endpoint !== "begin" && edit.endpoint !== "end")
44461
- fail2("INVALID_EDIT", "A line endpoint must be begin or end.");
44462
- return {
44463
- ...target,
44464
- type: edit.type,
44465
- endpoint: edit.endpoint,
44466
- x: numeric5(edit.x),
44467
- y: numeric5(edit.y)
44468
- };
44469
- case "resize-shape":
44470
- return {
44471
- ...target,
44472
- type: edit.type,
44473
- width: numeric5(edit.width, true),
44474
- height: numeric5(edit.height, true, true)
44475
- };
44476
- case "delete-shape":
44477
- return { ...target, type: edit.type };
44478
- default:
44479
- return fail2("INVALID_EDIT", "Unsupported edit command.");
44480
- }
44481
- });
44350
+ function inertDoubleClickFormula(cell, source2) {
44351
+ return cell === "EventDblClick" && /^\s*=?\s*(OPENTEXTWIN|DEFAULTEVENT)\(\s*\)\s*$/i.test(source2);
44482
44352
  }
44483
44353
 
44484
44354
  // visio/formula-theme.ts
@@ -44564,11 +44434,11 @@ function evaluateNumericFormulaFunction(name, args) {
44564
44434
  if (args.length < min || args.length > max)
44565
44435
  return formulaFailure("arity", `Invalid ${name} argument count`);
44566
44436
  };
44567
- const scalar3 = (value) => ({ value, unit: "scalar" });
44437
+ const scalar4 = (value) => ({ value, unit: "scalar" });
44568
44438
  if (name === "AND" || name === "OR" || name === "NOT") {
44569
44439
  arity(1, name === "NOT" ? 1 : 1024);
44570
44440
  const values2 = args.map((arg) => finiteFormulaValue(arg).value !== 0);
44571
- return scalar3(
44441
+ return scalar4(
44572
44442
  Number(
44573
44443
  name === "AND" ? values2.every(Boolean) : name === "OR" ? values2.some(Boolean) : !values2[0]
44574
44444
  )
@@ -44582,7 +44452,7 @@ function evaluateNumericFormulaFunction(name, args) {
44582
44452
  return formulaFailure("value", `${name} requires an integer from 0 to 65535`);
44583
44453
  return arg.value;
44584
44454
  });
44585
- return scalar3(
44455
+ return scalar4(
44586
44456
  name === "BITAND" ? values2[0] & values2[1] : name === "BITOR" ? values2[0] | values2[1] : values2[0] ^ values2[1]
44587
44457
  );
44588
44458
  }
@@ -45011,6 +44881,115 @@ function parseVisioFormula(source2, limits = {}) {
45011
44881
  return ast;
45012
44882
  }
45013
44883
 
44884
+ // visio/edit-formatting-rows.ts
44885
+ var delegatedSources = /* @__PURE__ */ new WeakMap();
44886
+ function delegatedFormattingCell(cell) {
44887
+ const seen = /* @__PURE__ */ new Set();
44888
+ while (cell && attribute3(cell, "F") === "Inh") {
44889
+ const ancestor = delegatedSources.get(cell);
44890
+ if (!ancestor || seen.has(cell) || seen.size >= 64 || cell.hasAttribute("E"))
44891
+ fail2("EDIT_PROTECTED_CELL", "Inherited formatting has no proven source.");
44892
+ seen.add(cell);
44893
+ const current = attribute3(cell, "V"), previous = attribute3(ancestor, "V");
44894
+ if (current !== previous || attribute3(cell, "U") !== attribute3(ancestor, "U")) {
44895
+ let agrees = false;
44896
+ try {
44897
+ const a2 = visioFormulaCachedValue(current ?? "", attribute3(cell, "U"));
44898
+ const b = visioFormulaCachedValue(previous ?? "", attribute3(ancestor, "U"));
44899
+ agrees = a2.value === b.value && a2.unit === b.unit;
44900
+ } catch {
44901
+ }
44902
+ if (!agrees)
44903
+ fail2(
44904
+ "EDIT_PROTECTED_CELL",
44905
+ "Inherited formatting cache is stale or has incompatible units."
44906
+ );
44907
+ }
44908
+ cell = ancestor;
44909
+ }
44910
+ return cell;
44911
+ }
44912
+ function formattingIndex(value) {
44913
+ if (value === void 0 || !/^(0|[1-9]\d{0,9})$/.test(value) || Number(value) > 4294967295)
44914
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting requires canonical unsigned row indices.");
44915
+ return value;
44916
+ }
44917
+ function formattingRows(sheet, sectionName) {
44918
+ const sections = children3(sheet, "Section").filter((section2) => {
44919
+ const name = attribute3(section2, "N");
44920
+ if (name?.toLowerCase() === sectionName.toLowerCase() && name !== sectionName)
44921
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Noncanonical formatting section names are unsupported.");
44922
+ return name === sectionName;
44923
+ });
44924
+ if (sections.length > 1) fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting section is ambiguous.");
44925
+ const section = sections[0];
44926
+ const result2 = /* @__PURE__ */ new Map();
44927
+ if (!section) return result2;
44928
+ if (section.hasAttribute("Del") || (attribute3(section, "IX") ?? "0") !== "0")
44929
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting requires one live section with index zero.");
44930
+ for (const row2 of children3(section, "Row")) {
44931
+ const index2 = formattingIndex(attribute3(row2, "IX") ?? "0");
44932
+ if (row2.hasAttribute("Del") || row2.hasAttribute("N") || row2.hasAttribute("T") || result2.has(index2))
44933
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting requires unique live indexed rows.");
44934
+ result2.set(index2, row2);
44935
+ if (result2.size > 1e4) fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting row limit exceeded.");
44936
+ }
44937
+ return result2;
44938
+ }
44939
+ function formattingRow(sheet, sectionName, index2 = "0") {
44940
+ return formattingRows(sheet, sectionName).get(index2);
44941
+ }
44942
+ function mergeFormattingRows(base, sheet, sectionName, cells3) {
44943
+ const result2 = new Map(base);
44944
+ for (const [index2, row2] of formattingRows(sheet, sectionName)) {
44945
+ const merged = new Map(base.get(index2) ?? base.get("0"));
44946
+ for (const [name, cell] of cells3(row2)) {
44947
+ if (attribute3(cell, "F") === "Inh" && !cell.hasAttribute("V") && !cell.hasAttribute("E"))
44948
+ continue;
44949
+ const ancestor = merged.get(name);
44950
+ const inheritedUnit = attribute3(ancestor, "U");
44951
+ let effective = cell;
44952
+ if (!cell.hasAttribute("U") && inheritedUnit !== void 0) {
44953
+ effective = cell.cloneNode(true);
44954
+ effective.setAttribute("U", inheritedUnit);
44955
+ }
44956
+ if (attribute3(cell, "F") === "Inh") delegatedSources.set(effective, ancestor);
44957
+ merged.set(name, effective);
44958
+ }
44959
+ result2.set(index2, merged);
44960
+ if (result2.size > 1e4) fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting row limit exceeded.");
44961
+ }
44962
+ return result2;
44963
+ }
44964
+ function assertFormattingText(shape2, characters, paragraphs) {
44965
+ const texts = children3(shape2, "Text");
44966
+ if (texts.length !== 1)
44967
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Text formatting requires one existing local Text.");
44968
+ let fields;
44969
+ for (const part of Array.from(texts[0].childNodes)) {
44970
+ if (part.nodeType === 3 || part.nodeType === 4) continue;
44971
+ const marker4 = part;
44972
+ if (part.nodeType !== 1 || marker4.namespaceURI !== shape2.namespaceURI || !["cp", "pp", "tp", "fld"].includes(marker4.localName))
44973
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Unknown text markup cannot be formatted.");
44974
+ const index2 = formattingIndex(attribute3(marker4, "IX"));
44975
+ if (marker4.localName === "fld") {
44976
+ fields ??= formattingRows(shape2, "Field");
44977
+ if (!fields.has(index2) || Array.from(marker4.childNodes).some((node) => ![3, 4].includes(node.nodeType)))
44978
+ fail2(
44979
+ "UNSUPPORTED_FORMAT_EDIT",
44980
+ "Text fields require a live local field row and plain cached text."
44981
+ );
44982
+ continue;
44983
+ }
44984
+ const rows = marker4.localName === "cp" ? characters : marker4.localName === "pp" ? paragraphs : void 0;
44985
+ if (marker4.childNodes.length || index2 !== "0" && rows && !rows.has(index2))
44986
+ fail2(
44987
+ "UNSUPPORTED_FORMAT_EDIT",
44988
+ "Formatting markers require existing rows and no nested markup."
44989
+ );
44990
+ }
44991
+ }
44992
+
45014
44993
  // visio/edit-geometry-cells.ts
45015
44994
  var cells = (shape2) => new Map(children3(shape2, "Cell").map((node) => [attribute3(node, "N") ?? "", node]));
45016
44995
  function numeric4(node, fallback) {
@@ -45083,14 +45062,6 @@ function assertEllipseResizeRow(shape2, row2) {
45083
45062
  }
45084
45063
  }
45085
45064
 
45086
- // visio/cell-formula.ts
45087
- function executableCellFormula(source2) {
45088
- return !source2 || source2 === "No Formula" || source2 === "Inh" ? void 0 : source2;
45089
- }
45090
- function inertDoubleClickFormula(cell, source2) {
45091
- return cell === "EventDblClick" && /^\s*=?\s*(OPENTEXTWIN|DEFAULTEVENT)\(\s*\)\s*$/i.test(source2);
45092
- }
45093
-
45094
45065
  // visio/edit-recalculate-index.ts
45095
45066
  var key = (cell) => JSON.stringify([cell.pageId, cell.shapeId, cell.cell.toLowerCase()]);
45096
45067
  function bound(value, fallback) {
@@ -45342,26 +45313,27 @@ function recalculateVisioCells(roots, changed, options = {}) {
45342
45313
  }
45343
45314
  return [...pages];
45344
45315
  }
45345
- function assertVisioShapeUnreferenced(roots, pageId, shapeId, options = {}) {
45316
+ function assertVisioShapesUnreferenced(roots, removed, options = {}) {
45346
45317
  const cells3 = indexCells(roots, options);
45347
45318
  for (const cell of cells3.values()) {
45348
- if (cell.pageId !== pageId || cell.shapeId === shapeId) continue;
45319
+ options.check?.();
45320
+ if (removed.get(cell.pageId)?.has(cell.shapeId)) continue;
45349
45321
  if (cell.dependencies.some((id) => {
45350
45322
  const parts = JSON.parse(id);
45351
- return parts[0] === pageId && parts[1] === shapeId;
45323
+ return removed.get(parts[0])?.has(parts[1]) ?? false;
45352
45324
  }))
45353
45325
  fail2("EDIT_REFERENCED_DELETE", "Shape is referenced by a ShapeSheet formula.");
45354
45326
  }
45355
- const root = roots.get(pageId);
45356
- if (root)
45357
- for (const connections2 of children3(root, "Connects"))
45327
+ for (const [pageId, ids] of removed)
45328
+ for (const connections2 of children3(roots.get(pageId), "Connects"))
45358
45329
  for (const connection of children3(connections2, "Connect")) {
45359
- if (["FromSheet", "ToSheet"].some((name) => attribute3(connection, name) === shapeId))
45330
+ options.check?.();
45331
+ if (["FromSheet", "ToSheet"].some((name) => ids.has(attribute3(connection, name) ?? "")))
45360
45332
  fail2("EDIT_REFERENCED_DELETE", "Shape participates in a Connect record.");
45361
45333
  }
45362
45334
  }
45363
- function visioCellDependsOn(roots, source2, targets, options = {}) {
45364
- return createVisioDependencyQuery(roots, options)(source2, targets);
45335
+ function assertVisioShapeUnreferenced(roots, pageId, shapeId, options = {}) {
45336
+ assertVisioShapesUnreferenced(roots, /* @__PURE__ */ new Map([[pageId, /* @__PURE__ */ new Set([shapeId])]]), options);
45365
45337
  }
45366
45338
  function createVisioDependencyQuery(roots, options = {}) {
45367
45339
  const cells3 = indexCells(roots, options);
@@ -45554,6 +45526,7 @@ function protectedShape(shape2, document, masterMovePins = /* @__PURE__ */ new S
45554
45526
  }
45555
45527
  function resizeGeometry(shape2, roots, edit, check3, lineEditShapes = /* @__PURE__ */ new Set()) {
45556
45528
  const sections = children3(shape2, "Section").filter((node) => attribute3(node, "N") === "Geometry");
45529
+ let depends;
45557
45530
  if (!sections.length)
45558
45531
  fail2("UNSUPPORTED_GEOMETRY_EDIT", "Resizing requires explicit supported local geometry.");
45559
45532
  for (const section of sections) {
@@ -45583,15 +45556,14 @@ function resizeGeometry(shape2, roots, edit, check3, lineEditShapes = /* @__PURE
45583
45556
  const analysis = analyzeVisioFormula(formula);
45584
45557
  if (!analysis.references.length && numeric4(node) === 0) continue;
45585
45558
  const cell = `Geometry${Number(attribute3(section, "IX") ?? "0") + 1}.${attribute3(node, "N")}${attribute3(row2, "IX")}`;
45586
- if (!visioCellDependsOn(
45587
- roots,
45559
+ depends ??= createVisioDependencyQuery(roots, { check: check3, lineEditShapes });
45560
+ if (!depends(
45588
45561
  { pageId: edit.pageId, shapeId: edit.shapeId, cell },
45589
45562
  ["Width", "Height"].map((cell2) => ({
45590
45563
  pageId: edit.pageId,
45591
45564
  shapeId: edit.shapeId,
45592
45565
  cell: cell2
45593
- })),
45594
- { check: check3, lineEditShapes }
45566
+ }))
45595
45567
  ))
45596
45568
  fail2(
45597
45569
  "UNSUPPORTED_GEOMETRY_EDIT",
@@ -45609,6 +45581,704 @@ function assertLengthTransformCells(local) {
45609
45581
  }
45610
45582
  }
45611
45583
 
45584
+ // visio/edit-formatting-cell-admission.ts
45585
+ function assertEditableFormattingCell(cell) {
45586
+ const source2 = executableCellFormula(attribute3(cell, "F"));
45587
+ const ast = source2 ? parseVisioFormula(source2) : void 0;
45588
+ const themeLiteral = (node) => {
45589
+ if (node.kind === "string" || node.kind === "number") return true;
45590
+ if (node.kind !== "call" || !node.args.every(themeLiteral)) return false;
45591
+ if (node.name === "THEMEGUARD") return node.args.length <= 1;
45592
+ if (node.name === "THEME")
45593
+ return node.args.length === 0 || node.args.length === 1 && node.args[0]?.kind === "string";
45594
+ if (node.name !== "THEMEVAL" || node.args.length > 2) return false;
45595
+ const selector = node.args[0];
45596
+ return !selector || selector.kind === "string" || selector.kind === "number" && selector.unit === "scalar" && Number.isInteger(selector.value) && selector.value >= 1 && selector.value <= 8;
45597
+ };
45598
+ if (ast?.kind === "call" && (ast.name === "FONT" && ast.args.length === 1 && ast.args[0]?.kind === "string" || ast.name === "RGB" && ast.args.length === 3 && ast.args.every(
45599
+ (arg) => arg.kind === "number" && arg.unit === "scalar" && Number.isInteger(arg.value) && arg.value >= 0 && arg.value <= 255
45600
+ ) || ["THEMEVAL", "THEME", "THEMEGUARD"].includes(ast.name) && themeLiteral(ast))) {
45601
+ if (cell?.hasAttribute("E"))
45602
+ fail2("EDIT_PROTECTED_CELL", "Cannot overwrite an error formatting cell.");
45603
+ return;
45604
+ }
45605
+ editableCell(cell);
45606
+ if (source2 && cell) {
45607
+ const actual = evaluateVisioFormula(
45608
+ source2,
45609
+ () => fail2("EDIT_PROTECTED_CELL", "Formatting dependencies cannot be overwritten.")
45610
+ );
45611
+ const cache3 = visioFormulaCachedValue(attribute3(cell, "V") ?? "", attribute3(cell, "U"));
45612
+ if (actual.value !== cache3.value || actual.unit !== cache3.unit && !(cache3.unit === "scalar" && actual.unit === "length" && !cell.hasAttribute("U")))
45613
+ fail2("EDIT_PROTECTED_CELL", "Formatting formula cache is stale or has incompatible units.");
45614
+ }
45615
+ }
45616
+
45617
+ // visio/edit-style-admission.ts
45618
+ function uniqueFormattingCells(sheet) {
45619
+ const result2 = /* @__PURE__ */ new Map();
45620
+ const seen = /* @__PURE__ */ new Set();
45621
+ for (const cell of children3(sheet, "Cell")) {
45622
+ const name = attribute3(cell, "N");
45623
+ if (!name || seen.has(name.toLowerCase()))
45624
+ fail2("EDIT_AMBIGUOUS_CELL", "Formatting requires unique named cells.");
45625
+ result2.set(name, cell);
45626
+ seen.add(name.toLowerCase());
45627
+ }
45628
+ return result2;
45629
+ }
45630
+ function formattingCell(sheet, name) {
45631
+ const cells3 = uniqueFormattingCells(sheet);
45632
+ if (!cells3.has(name) && [...cells3.keys()].some((key2) => key2.toLowerCase() === name.toLowerCase()))
45633
+ fail2("EDIT_AMBIGUOUS_CELL", "Noncanonical formatting cell names cannot be overridden.");
45634
+ return cells3.get(name);
45635
+ }
45636
+ function namedCell(sheet, name) {
45637
+ const [section, index2, cell] = name.split(".");
45638
+ if (!cell) return formattingCell(sheet, name);
45639
+ const row2 = formattingRow(sheet, section, index2);
45640
+ return row2 ? formattingCell(row2, cell) : void 0;
45641
+ }
45642
+ function categoryEnabled(style2, category) {
45643
+ const name = category === "TextStyle" ? "EnableTextProps" : category === "FillStyle" ? "EnableFillProps" : "EnableLineProps";
45644
+ const cell = formattingCell(style2, name);
45645
+ if (!cell) return true;
45646
+ if (cell.hasAttribute("E") || attribute3(cell, "F") === "Inh")
45647
+ fail2("EDIT_PROTECTED_CELL", "Style category enable state cannot be proven.");
45648
+ const cache3 = visioFormulaCachedValue(attribute3(cell, "V") ?? "", attribute3(cell, "U"));
45649
+ if (cache3.unit !== "scalar" || ![0, 1].includes(cache3.value))
45650
+ fail2("EDIT_PROTECTED_CELL", "Style category enable state must be a scalar boolean.");
45651
+ const source2 = executableCellFormula(attribute3(cell, "F"));
45652
+ if (source2) {
45653
+ const analysis = analyzeVisioFormula(source2);
45654
+ if (analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length)
45655
+ fail2("EDIT_PROTECTED_CELL", "Style category enable formula cannot be resolved safely.");
45656
+ const result2 = evaluateVisioFormula(
45657
+ source2,
45658
+ () => fail2("EDIT_PROTECTED_CELL", "Style category enable dependencies are unsupported.")
45659
+ );
45660
+ if (result2.unit !== "scalar" || result2.value !== cache3.value)
45661
+ fail2("EDIT_PROTECTED_CELL", "Style category enable formula cache is stale.");
45662
+ }
45663
+ return cache3.value !== 0;
45664
+ }
45665
+ function formattingStyles(shape2, document, category, gate) {
45666
+ const styles = /* @__PURE__ */ new Map();
45667
+ for (const container of children3(document, "StyleSheets"))
45668
+ for (const style2 of children3(container, "StyleSheet")) {
45669
+ const id2 = attribute3(style2, "ID");
45670
+ if (!id2 || styles.has(id2)) fail2("EDIT_PROTECTED_CELL", "Ambiguous formatting style IDs.");
45671
+ styles.set(id2, style2);
45672
+ }
45673
+ const sheets = children3(document, "DocumentSheet");
45674
+ if (sheets.length > 1) fail2("EDIT_PROTECTED_CELL", "Ambiguous document formatting defaults.");
45675
+ let id = attribute3(shape2, category) ?? attribute3(sheets[0], category) ?? (styles.has("0") ? "0" : void 0);
45676
+ const seen = /* @__PURE__ */ new Set();
45677
+ const result2 = [];
45678
+ while (id !== void 0) {
45679
+ if (seen.has(id) || seen.size >= 64)
45680
+ fail2("EDIT_PROTECTED_CELL", "Formatting style ancestry is cyclic or too deep.");
45681
+ seen.add(id);
45682
+ const style2 = styles.get(id);
45683
+ if (!style2) fail2("EDIT_PROTECTED_CELL", "Formatting style ancestry cannot be resolved.");
45684
+ if (gate && !categoryEnabled(style2, category)) break;
45685
+ result2.push(style2);
45686
+ const parent = attribute3(style2, category);
45687
+ id = parent !== id ? parent : void 0;
45688
+ }
45689
+ return result2;
45690
+ }
45691
+ function effectiveFormattingRows(shape2, document, section) {
45692
+ let result2 = /* @__PURE__ */ new Map();
45693
+ for (const style2 of formattingStyles(shape2, document, "TextStyle", true).reverse())
45694
+ result2 = mergeFormattingRows(result2, style2, section, uniqueFormattingCells);
45695
+ return mergeFormattingRows(result2, shape2, section, uniqueFormattingCells);
45696
+ }
45697
+ function formattingRowContext(shape2, document, section) {
45698
+ return {
45699
+ source: effectiveFormattingRows(shape2, document, section),
45700
+ local: formattingRows(shape2, section)
45701
+ };
45702
+ }
45703
+ function effectiveShapeCell(shape2, document, name, category, rows) {
45704
+ const [section, index2, cellName] = name.split(".");
45705
+ const localRow = rows?.local.get(index2);
45706
+ const local = rows ? localRow ? formattingCell(localRow, cellName) : void 0 : namedCell(shape2, name);
45707
+ const delegatedLocal = local && attribute3(local, "F") === "Inh";
45708
+ if (delegatedLocal && !(category === "TextStyle" && cellName && ["Character", "Paragraph"].includes(section)))
45709
+ fail2("EDIT_PROTECTED_CELL", "Inherited formatting cells cannot be overwritten.");
45710
+ if (local && !cellName) return local;
45711
+ if (cellName) {
45712
+ const sources = rows?.source ?? effectiveFormattingRows(shape2, document, section);
45713
+ const cells3 = sources.get(index2) ?? sources.get("0");
45714
+ if (cells3 && !cells3.has(cellName) && [...cells3.keys()].some((key2) => key2.toLowerCase() === cellName.toLowerCase()))
45715
+ fail2("EDIT_AMBIGUOUS_CELL", "Noncanonical formatting cell names cannot be overridden.");
45716
+ const effective = delegatedFormattingCell(cells3?.get(cellName));
45717
+ if (delegatedLocal) {
45718
+ if (!effective)
45719
+ fail2(
45720
+ "EDIT_PROTECTED_CELL",
45721
+ "Inherited formatting cannot be overwritten without a proven ancestor."
45722
+ );
45723
+ if (!local.hasAttribute("V") && local.hasAttribute("U") && visioFormulaCachedValue("0", attribute3(local, "U")).unit !== visioFormulaCachedValue("0", attribute3(effective, "U")).unit)
45724
+ fail2("EDIT_PROTECTED_CELL", "Inherited formatting has incompatible local units.");
45725
+ }
45726
+ return effective;
45727
+ }
45728
+ for (const style2 of formattingStyles(
45729
+ shape2,
45730
+ document,
45731
+ category,
45732
+ !/^(Lock|LayerMember$|DisplayLevel$)/.test(name)
45733
+ )) {
45734
+ const cell = namedCell(style2, name);
45735
+ if (cell && attribute3(cell, "F") !== "Inh") return cell;
45736
+ if (cell && (!attribute3(style2, category) || attribute3(style2, category) === attribute3(style2, "ID")))
45737
+ fail2("EDIT_PROTECTED_CELL", "Delegated formatting has no explicit ancestor.");
45738
+ }
45739
+ return void 0;
45740
+ }
45741
+ function assertShapeLocks(shape2, document, locks2) {
45742
+ const inheritedShape = shape2.cloneNode(true);
45743
+ for (const cell of children3(inheritedShape, "Cell"))
45744
+ if (locks2.includes(attribute3(cell, "N") ?? "")) inheritedShape.removeChild(cell);
45745
+ for (const lock of locks2)
45746
+ for (const [target, category] of [
45747
+ [shape2, "LineStyle"],
45748
+ [inheritedShape, "LineStyle"],
45749
+ [inheritedShape, "FillStyle"],
45750
+ [inheritedShape, "TextStyle"]
45751
+ ]) {
45752
+ const cell = effectiveShapeCell(target, document, lock, category);
45753
+ if (!cell) continue;
45754
+ if (cell.hasAttribute("E"))
45755
+ fail2("EDIT_PROTECTED_CELL", "Formatting protection has an error.");
45756
+ const cached3 = visioFormulaCachedValue(attribute3(cell, "V") ?? "", attribute3(cell, "U"));
45757
+ if (cached3.unit !== "scalar" || cached3.value !== 0)
45758
+ fail2("EDIT_PROTECTED_CELL", "Formatting protection is active or invalid.");
45759
+ const formula = executableCellFormula(attribute3(cell, "F"));
45760
+ if (!formula) continue;
45761
+ const analysis = analyzeVisioFormula(formula);
45762
+ if (analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length)
45763
+ fail2("EDIT_PROTECTED_CELL", "Formatting protection formula cannot be proven safe.");
45764
+ const value = evaluateVisioFormula(
45765
+ formula,
45766
+ () => fail2("EDIT_PROTECTED_CELL", "Formatting lock dependency is unsupported.")
45767
+ );
45768
+ if (value.unit !== "scalar" || value.value !== cached3.value)
45769
+ fail2("EDIT_PROTECTED_CELL", "Formatting protection cache is stale.");
45770
+ }
45771
+ }
45772
+ function assertUnlayeredShape(shape2, document) {
45773
+ for (const category of ["LineStyle", "FillStyle", "TextStyle"]) {
45774
+ const cell = effectiveShapeCell(shape2, document, "LayerMember", category);
45775
+ if (!cell) continue;
45776
+ if (attribute3(cell, "V") !== "" || cell.hasAttribute("E") || executableCellFormula(attribute3(cell, "F")))
45777
+ fail2(
45778
+ "UNSUPPORTED_FORMAT_EDIT",
45779
+ "Layered or unresolved layer membership is not yet supported."
45780
+ );
45781
+ }
45782
+ }
45783
+
45784
+ // visio/edit-text.ts
45785
+ async function replacePlainText(root, document, shapeId, text2, check3, assertDependencies) {
45786
+ const shapeChildren = (parent) => {
45787
+ const containers = children3(parent, "Shapes");
45788
+ if (containers.length > 1)
45789
+ fail2("INVALID_SHAPE_ID", "Duplicate Shapes containers are ambiguous.");
45790
+ return children3(containers[0], "Shape");
45791
+ };
45792
+ const shapes = /* @__PURE__ */ new Map();
45793
+ const pending2 = shapeChildren(root).map((node2) => ({
45794
+ node: node2,
45795
+ inherited: false,
45796
+ deleted: false
45797
+ }));
45798
+ while (pending2.length) {
45799
+ check3();
45800
+ const item = pending2.pop();
45801
+ const id = attribute3(item.node, "ID");
45802
+ if (!id || shapes.has(id))
45803
+ fail2("INVALID_SHAPE_ID", "Local shape IDs must be present and unique.");
45804
+ const inherited = item.inherited || item.node.hasAttribute("Master") || item.node.hasAttribute("MasterShape");
45805
+ const deleted = item.deleted || ["1", "true"].includes(attribute3(item.node, "Del") ?? "");
45806
+ shapes.set(id, { node: item.node, inherited, deleted });
45807
+ for (const node2 of shapeChildren(item.node)) pending2.push({ node: node2, inherited, deleted });
45808
+ }
45809
+ const target = shapes.get(shapeId);
45810
+ if (!target) fail2("EDIT_TARGET_NOT_FOUND", "Local shape does not exist.");
45811
+ if (target.inherited || target.deleted)
45812
+ fail2("UNSUPPORTED_TEXT_EDIT", "Master-linked or deleted shapes cannot be edited.");
45813
+ assertShapeLocks(target.node, document, ["LockTextEdit"]);
45814
+ const texts = children3(target.node, "Text");
45815
+ if (texts.length !== 1)
45816
+ fail2("UNSUPPORTED_TEXT_EDIT", "Editing requires one existing local Text element.");
45817
+ const node = texts[0];
45818
+ if (Array.from(node.childNodes).some((item) => item.nodeType !== 3 && item.nodeType !== 4))
45819
+ fail2("UNSUPPORTED_TEXT_EDIT", "Rich text, fields and unknown text markup cannot be edited.");
45820
+ if (children3(target.node, "Section").some((section) => attribute3(section, "N") === "Field"))
45821
+ fail2("UNSUPPORTED_TEXT_EDIT", "Shapes with text fields cannot be edited.");
45822
+ if (decodeVisioPlainText(node.textContent ?? "") === text2) return false;
45823
+ await assertDependencies(target.node, node);
45824
+ check3();
45825
+ while (node.firstChild) node.removeChild(node.firstChild);
45826
+ node.appendChild(node.ownerDocument.createTextNode(encodeVisioPlainText(text2)));
45827
+ return true;
45828
+ }
45829
+ function serializeEditedXml(root, limits, check3) {
45830
+ check3();
45831
+ const pending2 = [root.ownerDocument];
45832
+ while (pending2.length) {
45833
+ check3();
45834
+ const node = pending2.pop();
45835
+ if ((node.nodeType === 3 || node.nodeType === 4) && node.nodeValue?.includes("\r"))
45836
+ fail2("UNSUPPORTED_XML_EDIT", "Carriage-return text cannot be preserved by this writer.");
45837
+ if (node.nodeType === 1) {
45838
+ for (const attr3 of Array.from(node.attributes))
45839
+ if (/[\t\r\n]/.test(attr3.value))
45840
+ fail2("UNSUPPORTED_XML_EDIT", "Attribute whitespace cannot be preserved by this writer.");
45841
+ }
45842
+ for (const child6 of Array.from(node.childNodes)) pending2.push(child6);
45843
+ }
45844
+ let xml = buildXml(root.ownerDocument);
45845
+ xml = xml.replace(
45846
+ /^<\?xml\s[^?]*\?>/,
45847
+ (declaration) => declaration.replace(/encoding\s*=\s*(['"])[^'"]*\1/, 'encoding="UTF-8"')
45848
+ );
45849
+ const nodes = inspectXml(xml, limits, check3);
45850
+ inspectNamespaces(root, check3);
45851
+ const bytes = new TextEncoder().encode(xml);
45852
+ if (bytes.length > limits.maxEntryBytes)
45853
+ fail2("LIMIT_ENTRY", "Edited XML part exceeds byte limit.");
45854
+ return { bytes, nodes };
45855
+ }
45856
+
45857
+ // visio/edit-formatting-scope.ts
45858
+ async function assertFormattingDependencies(pkg, pagePaths, roots, pageId, shape2, changed, check3) {
45859
+ indexCells(roots, { check: check3 });
45860
+ const shapeId = attribute3(shape2, "ID");
45861
+ const changedNames = new Set([...changed.keys()].map((name) => name.toLowerCase()));
45862
+ const canonical = (name) => name.toLowerCase().replace(/^char\.([a-z]+)$/, "character.0.$1").replace(/^para\.([a-z]+)$/, "paragraph.0.$1");
45863
+ const replaced = new Set(changed.values());
45864
+ const inspect2 = (root, sourcePageId) => {
45865
+ for (const node of [root, ...Array.from(root.getElementsByTagName("*"))]) {
45866
+ check3();
45867
+ if (![VISIO_NS, VISIO_LEGACY_NS].includes(node.namespaceURI ?? "") || replaced.has(node))
45868
+ continue;
45869
+ const source2 = executableCellFormula(attribute3(node, "F"));
45870
+ if (!source2 || inertDoubleClickFormula(attribute3(node, "N") ?? "", source2)) continue;
45871
+ let localShapeId;
45872
+ let parent = node;
45873
+ while (parent?.nodeType === 1) {
45874
+ if (parent.localName === "Shape") {
45875
+ localShapeId = attribute3(parent, "ID");
45876
+ break;
45877
+ }
45878
+ parent = parent.parentNode;
45879
+ }
45880
+ const analysis = analyzeVisioFormula(source2);
45881
+ if (analysis.dynamic || analysis.references.some(
45882
+ (ref) => changedNames.has(canonical(ref.cell)) && (sourcePageId === void 0 || sourcePageId === pageId) && (ref.shapeId === shapeId || ref.shapeId === void 0 && (localShapeId === shapeId || sourcePageId === void 0))
45883
+ ))
45884
+ fail2(
45885
+ "EDIT_UNSUPPORTED_FORMAT_DEPENDENCY",
45886
+ "Formatting has affected or unknown formula dependencies; dependent caches cannot be recalculated safely."
45887
+ );
45888
+ }
45889
+ };
45890
+ for (const [id, root] of roots) inspect2(root, id);
45891
+ for (const path2 of pkg.paths()) {
45892
+ if (!/^visio\/.*\.xml$/i.test(path2) || pagePaths.has(path2)) continue;
45893
+ inspect2(await pkg.readXml(path2));
45894
+ }
45895
+ }
45896
+
45897
+ // visio/edit-text-scope.ts
45898
+ function replaceScopedPlainText(pkg, pagePaths, roots, document, edit, check3) {
45899
+ return replacePlainText(
45900
+ roots.get(edit.pageId),
45901
+ document,
45902
+ edit.shapeId,
45903
+ edit.text,
45904
+ check3,
45905
+ (shape2, text2) => assertFormattingDependencies(
45906
+ pkg,
45907
+ pagePaths,
45908
+ roots,
45909
+ edit.pageId,
45910
+ shape2,
45911
+ /* @__PURE__ */ new Map([["TheText", text2]]),
45912
+ check3
45913
+ )
45914
+ );
45915
+ }
45916
+
45917
+ // visio/resize-anchor.ts
45918
+ function snapshotResizeAnchor(value) {
45919
+ if (value === void 0) return void 0;
45920
+ if (!value || typeof value !== "object") fail2("INVALID_EDIT", "Invalid resize anchor.");
45921
+ const { x, y } = value;
45922
+ if (![0, 0.5, 1].includes(x) || ![0, 0.5, 1].includes(y))
45923
+ fail2("INVALID_EDIT", "Resize anchor coordinates must be 0, 0.5 or 1.");
45924
+ return { x, y };
45925
+ }
45926
+ function visioAnchoredResizeGeometry(current, size, anchor) {
45927
+ const [a2, b, c2, d, e, f6] = current.transform;
45928
+ const determinant = a2 * d - b * c2;
45929
+ if (![0, 0.5, 1].includes(anchor.x) || ![0, 0.5, 1].includes(anchor.y) || ![
45930
+ current.width,
45931
+ current.height,
45932
+ current.pinX,
45933
+ current.pinY,
45934
+ ...current.transform,
45935
+ size.width,
45936
+ size.height,
45937
+ anchor.x,
45938
+ anchor.y
45939
+ ].every(Number.isFinite) || !(current.width > 0 && current.height > 0 && size.width > 0 && size.height > 0) || Math.abs(Math.abs(determinant) - 1) > 1e-8 || Math.abs(a2 * a2 + b * b - 1) > 1e-8 || Math.abs(c2 * c2 + d * d - 1) > 1e-8 || Math.abs(a2 * c2 + b * d) > 1e-8)
45940
+ return void 0;
45941
+ const offsetX = current.pinX - e, offsetY = current.pinY - f6;
45942
+ const oldX = (d * offsetX - c2 * offsetY) / determinant;
45943
+ const oldY = (-b * offsetX + a2 * offsetY) / determinant;
45944
+ const locPinX = oldX / current.width * size.width, locPinY = oldY / current.height * size.height;
45945
+ const deltaX = anchor.x * (current.width - size.width) - oldX + locPinX;
45946
+ const deltaY = anchor.y * (current.height - size.height) - oldY + locPinY;
45947
+ const pinX = current.pinX + a2 * deltaX + c2 * deltaY, pinY = current.pinY + b * deltaX + d * deltaY;
45948
+ const matrix3 = [
45949
+ a2,
45950
+ b,
45951
+ c2,
45952
+ d,
45953
+ pinX - a2 * locPinX - c2 * locPinY,
45954
+ pinY - b * locPinX - d * locPinY
45955
+ ];
45956
+ return [pinX, pinY, locPinX, locPinY, ...matrix3].every(Number.isFinite) ? { pinX, pinY, locPinX, locPinY, transform: matrix3 } : void 0;
45957
+ }
45958
+
45959
+ // visio/edit-duplicate-commands.ts
45960
+ function snapshotDuplicateShapes(edit) {
45961
+ if (!Array.isArray(edit.copies) || !edit.copies.length || edit.copies.length > 1e3)
45962
+ fail2("INVALID_EDIT", "Duplication requires between one and 1000 shape mappings.");
45963
+ if ([edit.offsetX, edit.offsetY].some(
45964
+ (value) => typeof value !== "number" || !Number.isFinite(value) || Math.abs(value) > 1e6
45965
+ ))
45966
+ fail2("INVALID_EDIT", "Duplication offsets require bounded finite drawing inches.");
45967
+ const sources = /* @__PURE__ */ new Set(), targets = /* @__PURE__ */ new Set();
45968
+ const id = (value) => {
45969
+ if (typeof value !== "string" || !/^(0|[1-9]\d{0,9})$/.test(value) || Number(value) > 4294967295)
45970
+ fail2("INVALID_EDIT", "Duplicate shape IDs require canonical unsigned integers.");
45971
+ return value;
45972
+ };
45973
+ const copies = edit.copies.map((copy2) => {
45974
+ if (!copy2 || typeof copy2 !== "object") fail2("INVALID_EDIT", "Invalid duplicate shape mapping.");
45975
+ const shapeId = id(copy2.shapeId), newShapeId = id(copy2.newShapeId);
45976
+ if (sources.has(shapeId) || targets.has(newShapeId))
45977
+ fail2("INVALID_EDIT", "Duplicate shape mappings must have unique sources and targets.");
45978
+ sources.add(shapeId);
45979
+ targets.add(newShapeId);
45980
+ return { shapeId, newShapeId };
45981
+ });
45982
+ return {
45983
+ type: edit.type,
45984
+ pageId: edit.pageId,
45985
+ copies,
45986
+ offsetX: edit.offsetX,
45987
+ offsetY: edit.offsetY
45988
+ };
45989
+ }
45990
+
45991
+ // visio/clipboard-types.ts
45992
+ var VISIO_CLIPBOARD_MAX_CHARS = 8 * 1024 * 1024;
45993
+ function clipboardId(value) {
45994
+ if (typeof value !== "string" || !/^(0|[1-9]\d{0,9})$/.test(value) || Number(value) > 4294967295)
45995
+ fail2("INVALID_CLIPBOARD", "Clipboard IDs require canonical unsigned integers.");
45996
+ return value;
45997
+ }
45998
+ function snapshotVisioClipboard(value) {
45999
+ if (!value || typeof value !== "object" || value.format !== "ooxml.visio-shapes" || value.version !== 1)
46000
+ fail2("INVALID_CLIPBOARD", "Unsupported Visio clipboard format or version.");
46001
+ const sourcePageId = clipboardId(value.sourcePageId), sourceDrawingScale = value.sourceDrawingScale;
46002
+ if (!Number.isFinite(sourceDrawingScale) || sourceDrawingScale <= 0 || sourceDrawingScale > 1e6)
46003
+ fail2("INVALID_CLIPBOARD", "Invalid clipboard drawing ratio.");
46004
+ let characters = 0;
46005
+ const text2 = (input) => {
46006
+ if (typeof input !== "string" || (characters += input.length) > VISIO_CLIPBOARD_MAX_CHARS)
46007
+ fail2("LIMIT_CLIPBOARD", "Clipboard XML exceeds bounded text limits.");
46008
+ if (/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/.test(input))
46009
+ fail2("INVALID_CLIPBOARD", "Clipboard XML must contain well-formed Unicode.");
46010
+ return input;
46011
+ };
46012
+ const list = (input, max) => {
46013
+ if (!Array.isArray(input) || !input.length || input.length > max)
46014
+ fail2("INVALID_CLIPBOARD", "Invalid clipboard array length.");
46015
+ return input;
46016
+ };
46017
+ const selectionIds = list(value.selectionIds, 1e3).map(clipboardId);
46018
+ const shapes = list(value.shapes, 1e3).map((shape2) => {
46019
+ if (!shape2 || typeof shape2 !== "object") fail2("INVALID_CLIPBOARD", "Invalid captured shape.");
46020
+ return { shapeId: clipboardId(shape2.shapeId), xml: text2(shape2.xml) };
46021
+ });
46022
+ const resources = list(value.resources, 64).map((resource) => {
46023
+ const path2 = resource?.path;
46024
+ if (!resource || typeof resource !== "object" || typeof path2 !== "string" || path2.length > 1024 || !/^visio\/(?:document\.xml|_rels\/document\.xml\.rels|theme\/[^/]+\.(?:xml|rels)|theme\/_rels\/[^/]+\.rels)$/.test(
46025
+ path2
46026
+ ))
46027
+ fail2("INVALID_CLIPBOARD", "Invalid clipboard resource path.");
46028
+ return { path: text2(safePath(path2)), xml: text2(resource.xml) };
46029
+ });
46030
+ if (new Set(selectionIds).size !== selectionIds.length || new Set(shapes.map((shape2) => shape2.shapeId)).size !== shapes.length || selectionIds.length !== shapes.length || selectionIds.some((id) => !shapes.some((shape2) => shape2.shapeId === id)) || new Set(resources.map((resource) => resource.path)).size !== resources.length)
46031
+ fail2("INVALID_CLIPBOARD", "Clipboard mappings and resources must be unique and complete.");
46032
+ return {
46033
+ format: "ooxml.visio-shapes",
46034
+ version: 1,
46035
+ sourcePageId,
46036
+ sourceDrawingScale,
46037
+ selectionIds,
46038
+ shapes,
46039
+ resources: resources.sort((a2, b) => a2.path.localeCompare(b.path)),
46040
+ pageContext: text2(value.pageContext)
46041
+ };
46042
+ }
46043
+
46044
+ // visio/edit-paste-commands.ts
46045
+ function snapshotPasteShapes(edit) {
46046
+ const clipboard = snapshotVisioClipboard(edit.clipboard);
46047
+ const copies = snapshotDuplicateShapes({
46048
+ type: "duplicate-shapes",
46049
+ pageId: edit.pageId,
46050
+ copies: edit.copies,
46051
+ offsetX: edit.offsetX,
46052
+ offsetY: edit.offsetY
46053
+ });
46054
+ if (copies.copies.length !== clipboard.shapes.length || copies.copies.some((copy2) => !clipboard.selectionIds.includes(copy2.shapeId)))
46055
+ fail2("INVALID_CLIPBOARD", "Paste mappings must cover every captured shape exactly once.");
46056
+ return {
46057
+ type: "paste-shapes",
46058
+ pageId: copies.pageId,
46059
+ copies: copies.copies,
46060
+ offsetX: copies.offsetX,
46061
+ offsetY: copies.offsetY,
46062
+ clipboard
46063
+ };
46064
+ }
46065
+
46066
+ // visio/edit-formatting-commands.ts
46067
+ var isVisioFormatEdit = (edit) => edit.type === "format-text" || edit.type === "format-shape";
46068
+ function snapshotFormatting(edit) {
46069
+ const result2 = { type: edit.type, pageId: edit.pageId, shapeId: edit.shapeId };
46070
+ const points = (value, minimum, maximum) => {
46071
+ if (typeof value !== "number" || !Number.isFinite(value) || value < minimum || value > maximum)
46072
+ fail2("INVALID_EDIT", "Formatting point size is outside supported limits.");
46073
+ return value;
46074
+ };
46075
+ const color2 = (value, allowNone = false) => {
46076
+ if (typeof value !== "string" || !(allowNone && value === "none") && !/^#[0-9a-f]{6}$/i.test(value))
46077
+ fail2("INVALID_EDIT", "Formatting colors require six hexadecimal digits.");
46078
+ return value.toLowerCase();
46079
+ };
46080
+ if (edit.type === "format-text" && result2.type === "format-text") {
46081
+ if (edit.fontSize !== void 0) result2.fontSize = points(edit.fontSize, 1, 1e3);
46082
+ if (edit.fontColor !== void 0) result2.fontColor = color2(edit.fontColor);
46083
+ if (edit.indentLeft !== void 0) result2.indentLeft = points(edit.indentLeft, 0, 7200);
46084
+ if (edit.fontFamily !== void 0) {
46085
+ if (typeof edit.fontFamily !== "string" || !edit.fontFamily.trim() || edit.fontFamily.length > 256 || /[\u0000-\u001f\u007f]/.test(edit.fontFamily))
46086
+ fail2("INVALID_EDIT", "Invalid font family.");
46087
+ result2.fontFamily = edit.fontFamily;
46088
+ }
46089
+ for (const name of ["bold", "italic", "underline", "strikethrough", "bullets"]) {
46090
+ if (edit[name] === void 0) continue;
46091
+ if (typeof edit[name] !== "boolean") fail2("INVALID_EDIT", "Text styles require booleans.");
46092
+ result2[name] = edit[name];
46093
+ }
46094
+ if (edit.horizontalAlign !== void 0) {
46095
+ if (!["left", "center", "right", "justify"].includes(edit.horizontalAlign))
46096
+ fail2("INVALID_EDIT", "Invalid horizontal alignment.");
46097
+ result2.horizontalAlign = edit.horizontalAlign;
46098
+ }
46099
+ if (edit.verticalAlign !== void 0) {
46100
+ if (!["top", "middle", "bottom"].includes(edit.verticalAlign))
46101
+ fail2("INVALID_EDIT", "Invalid vertical alignment.");
46102
+ result2.verticalAlign = edit.verticalAlign;
46103
+ }
46104
+ } else if (edit.type === "format-shape" && result2.type === "format-shape") {
46105
+ if (edit.fillColor !== void 0) result2.fillColor = color2(edit.fillColor, true);
46106
+ if (edit.lineColor !== void 0) result2.lineColor = color2(edit.lineColor);
46107
+ if (edit.lineWeight !== void 0) result2.lineWeight = points(edit.lineWeight, 0, 100);
46108
+ for (const [name, maximum] of [
46109
+ ["linePattern", 23],
46110
+ ["fillPattern", 24]
46111
+ ]) {
46112
+ if (edit[name] === void 0) continue;
46113
+ const value = points(edit[name], 0, maximum);
46114
+ if (!Number.isInteger(value)) fail2("INVALID_EDIT", "Paint patterns require integers.");
46115
+ result2[name] = value;
46116
+ }
46117
+ for (const name of ["lineTransparency", "fillTransparency"])
46118
+ if (edit[name] !== void 0) result2[name] = Math.round(points(edit[name], 0, 100) * 2) / 2;
46119
+ if (edit.fillBackgroundColor !== void 0)
46120
+ result2.fillBackgroundColor = color2(edit.fillBackgroundColor);
46121
+ if (result2.fillColor === "none" && result2.fillPattern !== void 0 && result2.fillPattern !== 0)
46122
+ fail2("INVALID_EDIT", "No fill conflicts with a visible fill pattern.");
46123
+ }
46124
+ if (Object.keys(result2).length === 3)
46125
+ fail2("INVALID_EDIT", "Formatting requires at least one property.");
46126
+ return result2;
46127
+ }
46128
+
46129
+ // visio/edit-commands.ts
46130
+ var isVisioPageEdit = (edit) => edit.type === "insert-page" || edit.type === "reorder-page" || edit.type === "rename-page" || edit.type === "delete-page";
46131
+ function geometryChangedCells(edit) {
46132
+ if (edit.type === "create-line")
46133
+ return [
46134
+ "BeginX",
46135
+ "BeginY",
46136
+ "EndX",
46137
+ "EndY",
46138
+ "PinX",
46139
+ "PinY",
46140
+ "Width",
46141
+ "Height",
46142
+ "Angle",
46143
+ "LocPinX",
46144
+ "LocPinY"
46145
+ ];
46146
+ if (edit.type === "delete-shape") return [];
46147
+ if (edit.type === "create-text-box")
46148
+ return ["PinX", "PinY", "Width", "Height", "LinePattern", "FillPattern"];
46149
+ if (edit.type === "move-line-endpoint") {
46150
+ const prefix = edit.endpoint === "begin" ? "Begin" : "End";
46151
+ return [`${prefix}X`, `${prefix}Y`];
46152
+ }
46153
+ if (edit.type === "move-shape") return ["PinX", "PinY"];
46154
+ if (edit.type === "resize-shape")
46155
+ return edit.anchor ? ["Width", "Height", "PinX", "PinY", "LocPinX", "LocPinY"] : ["Width", "Height"];
46156
+ if (edit.type === "rotate-shape") return ["Angle"];
46157
+ if (edit.type === "flip-shape") return ["Angle", edit.axis === "horizontal" ? "FlipX" : "FlipY"];
46158
+ return ["PinX", "PinY", "Width", "Height"];
46159
+ }
46160
+ function snapshotVisioEdits(edits, maxEdits, maxText) {
46161
+ if (!Array.isArray(edits) || edits.length > maxEdits)
46162
+ fail2("LIMIT_EDITS", "Edit command count exceeds limit.");
46163
+ let textLength = 0;
46164
+ const text2 = (value) => {
46165
+ if (typeof value !== "string") fail2("INVALID_EDIT", "Edit text must be a string.");
46166
+ textLength += value.length;
46167
+ if (textLength > maxText) fail2("LIMIT_EDIT_TEXT", "Replacement text exceeds aggregate limit.");
46168
+ if (/[\u0000-\u0008\u000b\u000c\u000d\u000e-\u001f\ufffe\uffff]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/u.test(
46169
+ value
46170
+ ))
46171
+ fail2("INVALID_EDIT_TEXT", "Replacement text contains invalid XML characters.");
46172
+ return value;
46173
+ };
46174
+ const numeric5 = (value, dimension2 = false, allowZero = false) => {
46175
+ if (typeof value !== "number" || !Number.isFinite(value) || Math.abs(value) > 1e6 || dimension2 && (value < 0 || !allowZero && value === 0))
46176
+ fail2(
46177
+ "INVALID_EDIT",
46178
+ "Geometry requires finite drawing inches within limits and positive dimensions."
46179
+ );
46180
+ return value;
46181
+ };
46182
+ return Array.from(edits, (edit) => {
46183
+ if (!edit || typeof edit.pageId !== "string" || !edit.pageId || edit.pageId.length > 256)
46184
+ fail2("INVALID_EDIT", "Invalid edit target.");
46185
+ if (edit.type === "duplicate-shapes") return snapshotDuplicateShapes(edit);
46186
+ if (edit.type === "paste-shapes") return snapshotPasteShapes(edit);
46187
+ if (edit.type === "delete-page") return { type: edit.type, pageId: edit.pageId };
46188
+ if (edit.type === "reorder-page") {
46189
+ if (!Number.isSafeInteger(edit.index) || edit.index < 0 || edit.index > 1e6)
46190
+ fail2("INVALID_EDIT", "Page order requires a bounded zero-based integer index.");
46191
+ return { type: edit.type, pageId: edit.pageId, index: edit.index };
46192
+ }
46193
+ if (edit.type === "insert-page") {
46194
+ const name = text2(edit.name);
46195
+ if (!/^(0|[1-9]\d{0,9})$/.test(edit.pageId) || Number(edit.pageId) > 4294967295 || typeof edit.afterPageId !== "string" || !edit.afterPageId || edit.afterPageId.length > 256 || !name.trim() || name.length > 256 || /[\t\n]/.test(name))
46196
+ fail2("INVALID_EDIT", "Invalid new page ID, name or insertion target.");
46197
+ return { type: edit.type, pageId: edit.pageId, afterPageId: edit.afterPageId, name };
46198
+ }
46199
+ if (edit.type === "rename-page") {
46200
+ const name = text2(edit.name);
46201
+ if (!name.trim() || name.length > 255 || /[\t\n]/.test(name))
46202
+ fail2("INVALID_EDIT", "Invalid page name.");
46203
+ return { type: edit.type, pageId: edit.pageId, name };
46204
+ }
46205
+ if (typeof edit.shapeId !== "string" || !edit.shapeId || edit.shapeId.length > 256)
46206
+ fail2("INVALID_EDIT", "Invalid edit shape target.");
46207
+ const target = { pageId: edit.pageId, shapeId: edit.shapeId };
46208
+ if (edit.type === "replace-plain-text")
46209
+ return { ...target, type: edit.type, text: text2(edit.text) };
46210
+ if (isVisioFormatEdit(edit)) return snapshotFormatting(edit);
46211
+ if (edit.type === "reorder-shape") {
46212
+ if (!["front", "back", "forward", "backward"].includes(edit.order))
46213
+ fail2("INVALID_EDIT", "Invalid shape order.");
46214
+ return { ...target, type: edit.type, order: edit.order };
46215
+ }
46216
+ if (!/^[1-9]\d{0,9}$/.test(edit.shapeId) || Number(edit.shapeId) > 4294967295)
46217
+ fail2("INVALID_EDIT", "Geometry shape IDs must be canonical positive unsigned integers.");
46218
+ switch (edit.type) {
46219
+ case "create-text-box":
46220
+ return {
46221
+ ...target,
46222
+ type: edit.type,
46223
+ x: numeric5(edit.x),
46224
+ y: numeric5(edit.y),
46225
+ width: numeric5(edit.width, true),
46226
+ height: numeric5(edit.height, true),
46227
+ text: text2(edit.text)
46228
+ };
46229
+ case "create-line": {
46230
+ const beginX = numeric5(edit.beginX), beginY = numeric5(edit.beginY);
46231
+ const endX = numeric5(edit.endX), endY = numeric5(edit.endY);
46232
+ numeric5(Math.hypot(endX - beginX, endY - beginY), true);
46233
+ return { ...target, type: edit.type, beginX, beginY, endX, endY };
46234
+ }
46235
+ case "create-rectangle":
46236
+ case "create-ellipse":
46237
+ return {
46238
+ ...target,
46239
+ type: edit.type,
46240
+ x: numeric5(edit.x),
46241
+ y: numeric5(edit.y),
46242
+ width: numeric5(edit.width, true),
46243
+ height: numeric5(edit.height, true),
46244
+ ...edit.text === void 0 ? {} : { text: text2(edit.text) }
46245
+ };
46246
+ case "rotate-shape":
46247
+ return { ...target, type: edit.type, angle: numeric5(edit.angle) };
46248
+ case "flip-shape":
46249
+ if (edit.axis !== "horizontal" && edit.axis !== "vertical")
46250
+ fail2("INVALID_EDIT", "Invalid flip axis.");
46251
+ return { ...target, type: edit.type, axis: edit.axis };
46252
+ case "move-shape":
46253
+ return { ...target, type: edit.type, x: numeric5(edit.x), y: numeric5(edit.y) };
46254
+ case "move-line-endpoint":
46255
+ if (edit.endpoint !== "begin" && edit.endpoint !== "end")
46256
+ fail2("INVALID_EDIT", "A line endpoint must be begin or end.");
46257
+ return {
46258
+ ...target,
46259
+ type: edit.type,
46260
+ endpoint: edit.endpoint,
46261
+ x: numeric5(edit.x),
46262
+ y: numeric5(edit.y)
46263
+ };
46264
+ case "resize-shape": {
46265
+ const anchor = snapshotResizeAnchor(edit.anchor);
46266
+ return {
46267
+ ...target,
46268
+ type: edit.type,
46269
+ width: numeric5(edit.width, true),
46270
+ height: numeric5(edit.height, true, true),
46271
+ ...anchor === void 0 ? {} : { anchor }
46272
+ };
46273
+ }
46274
+ case "delete-shape":
46275
+ return { ...target, type: edit.type };
46276
+ default:
46277
+ return fail2("INVALID_EDIT", "Unsupported edit command.");
46278
+ }
46279
+ });
46280
+ }
46281
+
45612
46282
  // visio/edit-group-rotation.ts
45613
46283
  function proveLocalGroupRotation(root, edit, check3) {
45614
46284
  const groups = /* @__PURE__ */ new Set(), angleCells = /* @__PURE__ */ new Set();
@@ -45673,6 +46343,238 @@ function proveLocalGroupRotation(root, edit, check3) {
45673
46343
  return { groups, angleCells };
45674
46344
  }
45675
46345
 
46346
+ // visio/edit-resize-anchor.ts
46347
+ var close = (a2, b) => Math.abs(a2 - b) <= 1e-10 * Math.max(1, Math.abs(a2), Math.abs(b));
46348
+ function closure(graph, changed, check3) {
46349
+ const reverse2 = /* @__PURE__ */ new Map();
46350
+ for (const [id, item] of graph) {
46351
+ check3();
46352
+ for (const dependency of item.dependencies) {
46353
+ const list = reverse2.get(dependency) ?? [];
46354
+ list.push(id);
46355
+ reverse2.set(dependency, list);
46356
+ }
46357
+ }
46358
+ const affected = new Set(changed), pending2 = [...changed];
46359
+ for (let index2 = 0; index2 < pending2.length; index2++) {
46360
+ check3();
46361
+ for (const id of reverse2.get(pending2[index2]) ?? [])
46362
+ if (!affected.has(id)) {
46363
+ affected.add(id);
46364
+ pending2.push(id);
46365
+ }
46366
+ if (affected.size > 1e4)
46367
+ fail2("LIMIT_FORMULA_AFFECTED", "Affected ShapeSheet cell limit exceeded.");
46368
+ }
46369
+ return affected;
46370
+ }
46371
+ function resizeVisioShapeAtAnchor(roots, document, edit, check3) {
46372
+ check3();
46373
+ const root = roots.get(edit.pageId);
46374
+ if (!root) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
46375
+ const shape2 = admitted(root, edit.shapeId);
46376
+ const local = cells(shape2);
46377
+ const canonical = [
46378
+ "Width",
46379
+ "Height",
46380
+ "PinX",
46381
+ "PinY",
46382
+ "LocPinX",
46383
+ "LocPinY",
46384
+ "Angle",
46385
+ "FlipX",
46386
+ "FlipY",
46387
+ "LockMoveX",
46388
+ "LockMoveY",
46389
+ "LockWidth",
46390
+ "LockHeight",
46391
+ "LockAspect",
46392
+ "LockDelete"
46393
+ ];
46394
+ for (const name of local.keys())
46395
+ if (canonical.some(
46396
+ (expected) => expected.toLowerCase() === name.toLowerCase() && expected !== name
46397
+ ))
46398
+ fail2(
46399
+ "EDIT_AMBIGUOUS_CELL",
46400
+ "Noncanonical transform and protection cell names are unsupported."
46401
+ );
46402
+ if (!edit.anchor || isLineSheet(cells(shape2)) || edit.height <= 0)
46403
+ fail2("UNSUPPORTED_GEOMETRY_EDIT", "Anchored resizing requires an ordinary local 2D shape.");
46404
+ if (Array.from(shape2.getElementsByTagName("*")).some(
46405
+ (node) => node.localName === "Shape" && [VISIO_NS, VISIO_LEGACY_NS].includes(node.namespaceURI ?? "")
46406
+ ))
46407
+ fail2("UNSUPPORTED_GEOMETRY_EDIT", "Nested shape identities cannot be resized as a local leaf.");
46408
+ protectedShape(shape2, document);
46409
+ assertUnlayeredShape(shape2, document);
46410
+ for (const container of children3(root, "Connects"))
46411
+ for (const connection of children3(container, "Connect"))
46412
+ if (["FromSheet", "ToSheet"].some((name) => attribute3(connection, name) === edit.shapeId))
46413
+ fail2("UNSUPPORTED_GEOMETRY_EDIT", "Glued shapes require routing outside this subset.");
46414
+ const graph = indexCells(roots, { check: check3 });
46415
+ const id = (cell) => key({ pageId: edit.pageId, shapeId: edit.shapeId, cell });
46416
+ const source2 = createVisioCellEvaluator(graph, { check: check3 }, true);
46417
+ const read = (name, fallback) => graph.has(id(name)) ? source2(id(name)).value : numeric4(local.get(name), fallback);
46418
+ const width = read("Width"), height = read("Height");
46419
+ const pinX = read("PinX", width / 2), pinY = read("PinY", height / 2);
46420
+ const locX = read("LocPinX", width / 2), locY = read("LocPinY", height / 2);
46421
+ const angle = read("Angle", 0), flipX = read("FlipX", 0), flipY = read("FlipY", 0);
46422
+ for (const name of ["Angle", "FlipX", "FlipY"]) {
46423
+ const unit = attribute3(local.get(name), "U");
46424
+ if (unit && visioFormulaCachedValue("0", unit).unit !== (name === "Angle" ? "angle" : "scalar"))
46425
+ fail2("EDIT_FORMULA_UNIT", "Rotation and flip cells require their declared dimensions.");
46426
+ }
46427
+ if (![0, 1].includes(flipX) || ![0, 1].includes(flipY))
46428
+ fail2("EDIT_FORMULA_UNIT", "Flip cells must be scalar booleans.");
46429
+ if (width === edit.width && height === edit.height) return [];
46430
+ resizeGeometry(shape2, roots, edit, check3);
46431
+ if (numeric4(local.get("LockAspect"), 0) !== 0 && !close(edit.width / width, edit.height / height))
46432
+ fail2("EDIT_PROTECTED_CELL", "LockAspect prevents changing the aspect ratio.");
46433
+ const geometry = visioAnchoredResizeGeometry(
46434
+ {
46435
+ width,
46436
+ height,
46437
+ pinX,
46438
+ pinY,
46439
+ transform: transform6(pinX, pinY, locX, locY, angle, flipX === 1, flipY === 1)
46440
+ },
46441
+ edit,
46442
+ edit.anchor
46443
+ );
46444
+ if (!geometry || [geometry.pinX, geometry.pinY, geometry.locPinX, geometry.locPinY].some(
46445
+ (value) => Math.abs(value) > 1e6
46446
+ ))
46447
+ fail2("UNSUPPORTED_GEOMETRY_EDIT", "Anchored geometry exceeds coordinate limits.");
46448
+ const writes = [];
46449
+ const writable = (name) => editableCell(
46450
+ local.get(name),
46451
+ (reference2) => source2(
46452
+ key({
46453
+ pageId: edit.pageId,
46454
+ shapeId: reference2.shapeId ?? edit.shapeId,
46455
+ cell: reference2.cell
46456
+ })
46457
+ )
46458
+ );
46459
+ const unlocked = (name) => {
46460
+ if (numeric4(local.get(name), 0) !== 0)
46461
+ fail2("EDIT_PROTECTED_CELL", `${name} prevents this operation.`);
46462
+ };
46463
+ for (const [name, value, old] of [
46464
+ ["Width", edit.width, width],
46465
+ ["Height", edit.height, height]
46466
+ ])
46467
+ if (value !== old) {
46468
+ unlocked(`Lock${name}`);
46469
+ writable(name);
46470
+ writes.push({ name, value });
46471
+ }
46472
+ const changedDimensions = writes.map((write) => id(write.name));
46473
+ const dimensionClosure = closure(graph, changedDimensions, check3);
46474
+ for (const [name, value, old] of [
46475
+ ["PinX", geometry.pinX, pinX],
46476
+ ["PinY", geometry.pinY, pinY]
46477
+ ])
46478
+ if (!local.has(name) || !close(value, old) || dimensionClosure.has(id(name)) && !guardedCell(local.get(name))) {
46479
+ if (!close(value, old)) unlocked(name === "PinX" ? "LockMoveX" : "LockMoveY");
46480
+ writable(name);
46481
+ writes.push({ name, value: close(value, old) ? old : value });
46482
+ }
46483
+ const projected = new Map(graph);
46484
+ const install = (write) => {
46485
+ const original = local.get(write.name);
46486
+ const node = original ? original.cloneNode(true) : shape2.ownerDocument.createElementNS(shape2.namespaceURI, "Cell");
46487
+ node.setAttribute("N", write.name);
46488
+ node.setAttribute("V", String(write.value));
46489
+ if (write.formula) node.setAttribute("F", write.formula);
46490
+ else node.removeAttribute("F");
46491
+ const cell = {
46492
+ pageId: edit.pageId,
46493
+ shapeId: edit.shapeId,
46494
+ cell: write.name,
46495
+ node,
46496
+ unsafe: false,
46497
+ unit: "length",
46498
+ dependencies: []
46499
+ };
46500
+ if (write.formula) {
46501
+ cell.formula = parseVisioFormula(write.formula);
46502
+ cell.dependencies = [id(write.name === "LocPinX" ? "Width" : "Height")];
46503
+ }
46504
+ projected.set(id(write.name), cell);
46505
+ };
46506
+ for (const write of writes) install(write);
46507
+ const guardedPins = [];
46508
+ for (const [name, dimension2, old, oldDimension, next] of [
46509
+ ["LocPinX", "Width", locX, width, geometry.locPinX],
46510
+ ["LocPinY", "Height", locY, height, geometry.locPinY]
46511
+ ]) {
46512
+ if ((dimension2 === "Width" ? edit.width : edit.height) === oldDimension) continue;
46513
+ if (guardedCell(local.get(name))) {
46514
+ guardedPins.push({ name, value: next });
46515
+ } else {
46516
+ writable(name);
46517
+ const write = { name, value: next, formula: `${dimension2}*${old / oldDimension}` };
46518
+ writes.push(write);
46519
+ install(write);
46520
+ }
46521
+ }
46522
+ const projectedPins = createVisioCellEvaluator(projected, { check: check3 });
46523
+ for (const pin of guardedPins)
46524
+ if (!close(projectedPins(id(pin.name)).value, pin.value))
46525
+ fail2(
46526
+ "EDIT_PROTECTED_CELL",
46527
+ "Guarded local pin does not scale proportionally with the requested dimension."
46528
+ );
46529
+ const affected = closure(
46530
+ projected,
46531
+ writes.map((write) => id(write.name)),
46532
+ check3
46533
+ );
46534
+ for (const name of ["Angle", "FlipX", "FlipY"])
46535
+ if (affected.has(id(name)))
46536
+ fail2(
46537
+ "UNSUPPORTED_GEOMETRY_EDIT",
46538
+ "Anchored resizing cannot change dependent Angle or Flip formulas."
46539
+ );
46540
+ for (const cellId of affected)
46541
+ if (/^Field\./i.test(projected.get(cellId).cell))
46542
+ fail2(
46543
+ "UNSUPPORTED_GEOMETRY_EDIT",
46544
+ "Affected text fields need native display-cache regeneration."
46545
+ );
46546
+ const evaluate = createVisioCellEvaluator(projected, { check: check3 }), values2 = /* @__PURE__ */ new Map();
46547
+ for (const cellId of affected) {
46548
+ if (graph.has(cellId)) source2(cellId);
46549
+ values2.set(cellId, evaluate(cellId).value);
46550
+ }
46551
+ for (const [name, expected] of [
46552
+ ["Width", edit.width],
46553
+ ["Height", edit.height],
46554
+ ["PinX", geometry.pinX],
46555
+ ["PinY", geometry.pinY],
46556
+ ["LocPinX", geometry.locPinX],
46557
+ ["LocPinY", geometry.locPinY]
46558
+ ])
46559
+ if (!close(projected.has(id(name)) ? evaluate(id(name)).value : read(name), expected))
46560
+ fail2(
46561
+ "EDIT_UNSUPPORTED_DEPENDENCY",
46562
+ "Dependent formulas would violate the requested anchor or dimensions."
46563
+ );
46564
+ check3();
46565
+ for (const write of writes) setCell(shape2, write.name, write.value, write.formula);
46566
+ const dirty = /* @__PURE__ */ new Set([edit.pageId]);
46567
+ for (const [cellId, value] of values2) {
46568
+ const item = graph.get(cellId);
46569
+ if (!item?.node || !item.formula || writes.some((write) => id(write.name) === cellId)) continue;
46570
+ if (attribute3(item.node, "V") !== String(value)) {
46571
+ item.node.setAttribute("V", String(value));
46572
+ dirty.add(item.pageId);
46573
+ }
46574
+ }
46575
+ return [...dirty];
46576
+ }
46577
+
45676
46578
  // visio/edit-transform-formula.ts
45677
46579
  function editableTransformCell(roots, edit, node, check3, options = {}) {
45678
46580
  const formula = executableCellFormula(attribute3(node, "F"));
@@ -45742,7 +46644,16 @@ function createBox(root, document, edit) {
45742
46644
  return shape2;
45743
46645
  }
45744
46646
  function createRectangle(root, document, edit) {
46647
+ if (edit.type === "create-text-box") {
46648
+ const planned = root.ownerDocument.createElementNS(root.namespaceURI, "Shape");
46649
+ applyShapeCreationStyles(planned, document);
46650
+ assertShapeLocks(planned, document, ["LockTextEdit"]);
46651
+ }
45745
46652
  const shape2 = createBox(root, document, edit);
46653
+ if (edit.type === "create-text-box") {
46654
+ setCell(shape2, "LinePattern", 0);
46655
+ setCell(shape2, "FillPattern", 0);
46656
+ }
45746
46657
  const doc = root.ownerDocument;
45747
46658
  const node = (name) => doc.createElementNS(root.namespaceURI, name);
45748
46659
  const section = node("Section");
@@ -45764,7 +46675,7 @@ function createRectangle(root, document, edit) {
45764
46675
  }
45765
46676
  shape2.appendChild(section);
45766
46677
  const text2 = node("Text");
45767
- text2.appendChild(doc.createTextNode(edit.text ?? ""));
46678
+ text2.appendChild(doc.createTextNode(encodeVisioPlainText(edit.text ?? "")));
45768
46679
  shape2.appendChild(text2);
45769
46680
  return shape2;
45770
46681
  }
@@ -45773,7 +46684,7 @@ function createEllipse(root, document, edit) {
45773
46684
  appendEllipseGeometry(shape2, edit.width, edit.height);
45774
46685
  if (edit.text !== void 0) {
45775
46686
  const text2 = root.ownerDocument.createElementNS(root.namespaceURI, "Text");
45776
- text2.appendChild(root.ownerDocument.createTextNode(edit.text));
46687
+ text2.appendChild(root.ownerDocument.createTextNode(encodeVisioPlainText(edit.text)));
45777
46688
  shape2.appendChild(text2);
45778
46689
  }
45779
46690
  return shape2;
@@ -46143,6 +47054,8 @@ function moveLocalLineEndpoint(shape2, edit) {
46143
47054
  function applyGeometryEdit(roots, document, edit, check3, masterMoveProof = emptyMasterMoveProof()) {
46144
47055
  const masterMovePins = masterMoveProof.pins, masterDimensions = masterMoveProof.dimensions;
46145
47056
  check3();
47057
+ if (edit.type === "resize-shape" && edit.anchor)
47058
+ return resizeVisioShapeAtAnchor(roots, document, edit, check3);
46146
47059
  const root = roots.get(edit.pageId);
46147
47060
  if (!root) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
46148
47061
  const groupRotation = proveLocalGroupRotation(root, edit, check3);
@@ -46164,11 +47077,15 @@ function applyGeometryEdit(roots, document, edit, check3, masterMoveProof = empt
46164
47077
  y: (edit.beginY + edit.endY) / 2
46165
47078
  };
46166
47079
  for (const name of geometryChangedCells(edit)) add3(name);
46167
- } else if (edit.type === "create-rectangle" || edit.type === "create-ellipse") {
47080
+ } else if (edit.type === "create-rectangle" || edit.type === "create-ellipse" || edit.type === "create-text-box") {
46168
47081
  if (edit.type === "create-ellipse") createEllipse(root, document, edit);
46169
47082
  else createRectangle(root, document, edit);
46170
47083
  expected = { width: edit.width, height: edit.height, x: edit.x, y: edit.y };
46171
47084
  for (const name of ["Width", "Height", "PinX", "PinY"]) add3(name);
47085
+ if (edit.type === "create-text-box") {
47086
+ add3("LinePattern");
47087
+ add3("FillPattern");
47088
+ }
46172
47089
  } else {
46173
47090
  const shape2 = admitted(
46174
47091
  root,
@@ -46361,6 +47278,114 @@ function applyGeometryEdit(roots, document, edit, check3, masterMoveProof = empt
46361
47278
  return [.../* @__PURE__ */ new Set([edit.pageId, ...affectedPages])];
46362
47279
  }
46363
47280
 
47281
+ // visio/edit-shape-order.ts
47282
+ async function assertShapeOrderPackageScope(pkg, check3) {
47283
+ for (const path2 of pkg.paths()) {
47284
+ if (!/^visio\/.*\.xml$/i.test(path2)) continue;
47285
+ const pending2 = [await pkg.readXml(path2)];
47286
+ while (pending2.length) {
47287
+ check3();
47288
+ const node = pending2.pop();
47289
+ const source2 = executableCellFormula(attribute3(node, "F"));
47290
+ if (source2) {
47291
+ try {
47292
+ if (analyzeVisioFormula(source2, { onStep: check3 }).dynamic)
47293
+ fail2(
47294
+ "UNSUPPORTED_SHAPE_ORDER",
47295
+ "Dynamic or container formulas may depend on stacking order."
47296
+ );
47297
+ } catch {
47298
+ fail2(
47299
+ "UNSUPPORTED_SHAPE_ORDER",
47300
+ "Package formulas cannot be proven independent of stacking order."
47301
+ );
47302
+ }
47303
+ }
47304
+ for (const child6 of Array.from(node.childNodes))
47305
+ if (child6.nodeType === 1) pending2.push(child6);
47306
+ }
47307
+ }
47308
+ }
47309
+ function ordinaryDisplayBand(shape2, document) {
47310
+ for (const category of ["LineStyle", "FillStyle", "TextStyle"]) {
47311
+ const node = effectiveShapeCell(shape2, document, "DisplayLevel", category);
47312
+ if (!node) continue;
47313
+ const cached3 = visioFormulaCachedValue(attribute3(node, "V") ?? "", attribute3(node, "U"));
47314
+ if (node.hasAttribute("E") || cached3.unit !== "scalar" || cached3.value !== 0)
47315
+ fail2("UNSUPPORTED_SHAPE_ORDER", "Only the ordinary zero display band can be reordered.");
47316
+ const source2 = executableCellFormula(attribute3(node, "F"));
47317
+ if (!source2) continue;
47318
+ const analysis = analyzeVisioFormula(source2);
47319
+ if (analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length)
47320
+ fail2("UNSUPPORTED_SHAPE_ORDER", "Display band formulas must be constant.");
47321
+ const result2 = evaluateVisioFormula(
47322
+ source2,
47323
+ () => fail2("UNSUPPORTED_SHAPE_ORDER", "Display band dependencies cannot be resolved.")
47324
+ );
47325
+ if (result2.unit !== "scalar" || result2.value !== cached3.value)
47326
+ fail2("UNSUPPORTED_SHAPE_ORDER", "Display band formula cache is stale.");
47327
+ }
47328
+ }
47329
+ function reorderVisioShape(root, document, edit, check3) {
47330
+ check3();
47331
+ const containers = children3(root, "Shapes");
47332
+ if (containers.length !== 1)
47333
+ fail2("UNSUPPORTED_SHAPE_ORDER", "One local Shapes container is required.");
47334
+ const container = containers[0];
47335
+ const siblings = children3(container, "Shape");
47336
+ const ids = /* @__PURE__ */ new Set();
47337
+ for (const shape2 of siblings) {
47338
+ check3();
47339
+ const id = attribute3(shape2, "ID");
47340
+ if (!id || ids.has(id)) fail2("INVALID_SHAPE_ID", "Shape IDs must be present and unique.");
47341
+ ids.add(id);
47342
+ if (shape2.hasAttribute("Master") || shape2.hasAttribute("MasterShape") || shape2.hasAttribute("Del") || children3(shape2, "Shapes").length || children3(shape2, "ForeignData").length || children3(shape2, "Rel").length || attribute3(shape2, "Type") !== void 0 && attribute3(shape2, "Type") !== "Shape")
47343
+ fail2(
47344
+ "UNSUPPORTED_SHAPE_ORDER",
47345
+ "Ordering requires local ordinary shapes in one display band."
47346
+ );
47347
+ ordinaryDisplayBand(shape2, document);
47348
+ }
47349
+ const index2 = siblings.findIndex((shape2) => attribute3(shape2, "ID") === edit.shapeId);
47350
+ if (index2 < 0) fail2("EDIT_TARGET_NOT_FOUND", "A top-level local shape is required.");
47351
+ const target = siblings[index2];
47352
+ assertShapeLocks(target, document, ["LockSelect", "LockFormat"]);
47353
+ assertUnlayeredShape(target, document);
47354
+ const destination = edit.order === "front" ? siblings.length - 1 : edit.order === "back" ? 0 : edit.order === "forward" ? Math.min(siblings.length - 1, index2 + 1) : Math.max(0, index2 - 1);
47355
+ if (destination === index2) return false;
47356
+ const anchor = siblings[destination];
47357
+ container.insertBefore(target, destination > index2 ? anchor.nextSibling : anchor);
47358
+ return true;
47359
+ }
47360
+
47361
+ // visio/edit-duplicate-scope.ts
47362
+ async function assertDuplicateScope(pkg, pagePaths, targetPage, newIds, check3) {
47363
+ const existing = /* @__PURE__ */ new Set();
47364
+ for (const node of Array.from(targetPage.getElementsByTagName("*"))) {
47365
+ check3();
47366
+ if (node.localName !== "Shape" || node.namespaceURI !== targetPage.namespaceURI) continue;
47367
+ const id = attribute3(node, "ID");
47368
+ if (!id || existing.has(id)) fail2("INVALID_SHAPE_ID", "Source shape IDs must be unique.");
47369
+ if (newIds.has(id)) fail2("INVALID_SHAPE_ID", "New shape ID already exists.");
47370
+ existing.add(id);
47371
+ }
47372
+ await assertShapeOrderPackageScope(pkg, check3);
47373
+ const inspect2 = (root) => {
47374
+ for (const node of [root, ...Array.from(root.getElementsByTagName("*"))]) {
47375
+ check3();
47376
+ const source2 = executableCellFormula(attribute3(node, "F"));
47377
+ if (!source2) continue;
47378
+ if (analyzeVisioFormula(source2).references.some(
47379
+ (ref) => ref.shapeId !== void 0 && newIds.has(ref.shapeId)
47380
+ ))
47381
+ fail2("EDIT_DUPLICATE_DEPENDENCY", "New IDs are already referenced by existing formulas.");
47382
+ }
47383
+ };
47384
+ inspect2(targetPage);
47385
+ for (const path2 of pkg.paths())
47386
+ if (/^visio\/.*\.xml$/i.test(path2) && !pagePaths.has(path2)) inspect2(await pkg.readXml(path2));
47387
+ }
47388
+
46364
47389
  // visio/formula-master.ts
46365
47390
  function analyzeVisioMasterFormula(source2, options) {
46366
47391
  const ast = parseVisioFormula(source2);
@@ -46992,10 +48017,17 @@ async function assertGeometryPackageScope(pkg, pagePaths, commands, check3, root
46992
48017
  for (const [pageId, root] of roots) {
46993
48018
  const shapes = Array.from(root.getElementsByTagNameNS(root.namespaceURI, "Shape"));
46994
48019
  for (const command2 of commands)
46995
- if ((command2.type === "create-rectangle" || command2.type === "create-ellipse" || command2.type === "create-line") && command2.pageId === pageId && !shapes.some((shape2) => attribute3(shape2, "ID") === command2.shapeId)) {
48020
+ if ((command2.type === "create-rectangle" || command2.type === "create-ellipse" || command2.type === "create-text-box" || command2.type === "create-line") && command2.pageId === pageId && !shapes.some((shape2) => attribute3(shape2, "ID") === command2.shapeId)) {
46996
48021
  const shape2 = root.ownerDocument.createElementNS(root.namespaceURI, "Shape");
46997
48022
  shape2.setAttribute("ID", command2.shapeId);
46998
48023
  applyShapeCreationStyles(shape2, documentRoot);
48024
+ if (command2.type === "create-text-box")
48025
+ for (const name of ["LinePattern", "FillPattern"]) {
48026
+ const node = root.ownerDocument.createElementNS(root.namespaceURI, "Cell");
48027
+ node.setAttribute("N", name);
48028
+ node.setAttribute("V", "0");
48029
+ shape2.appendChild(node);
48030
+ }
46999
48031
  for (const name of ["PinX", "PinY", "Width", "Height", "LocPinX", "LocPinY", "Angle"]) {
47000
48032
  const node = root.ownerDocument.createElementNS(root.namespaceURI, "Cell");
47001
48033
  node.setAttribute("N", name);
@@ -47736,6 +48768,787 @@ async function editVsdxPages(original, pkg, parts, commands, limits, maxOutput,
47736
48768
  };
47737
48769
  }
47738
48770
 
48771
+ // visio/edit-formatting-font.ts
48772
+ function formattingFont(document, family) {
48773
+ const containers = children3(document, "FaceNames");
48774
+ if (containers.length !== 1)
48775
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Font family requires existing document FaceNames.");
48776
+ const fonts = children3(containers[0], "FaceName");
48777
+ const ids = /* @__PURE__ */ new Set();
48778
+ for (const font3 of fonts) {
48779
+ const id2 = attribute3(font3, "ID");
48780
+ if (id2 === void 0) continue;
48781
+ if (!/^\d+$/.test(id2) || ids.has(id2))
48782
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Explicit document font IDs must be numeric and unique.");
48783
+ ids.add(id2);
48784
+ }
48785
+ const matches2 = fonts.filter(
48786
+ (font3) => (attribute3(font3, "Name") ?? attribute3(font3, "NameU"))?.toLowerCase() === family.toLowerCase()
48787
+ );
48788
+ if (matches2.length !== 1)
48789
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Font family must match one existing document FaceName.");
48790
+ const font2 = matches2[0], id = attribute3(font2, "ID");
48791
+ if (id !== void 0) return { value: id };
48792
+ const name = attribute3(font2, "Name") ?? attribute3(font2, "NameU");
48793
+ return { value: name, formula: `FONT("${name.replaceAll('"', '""')}")` };
48794
+ }
48795
+
48796
+ // visio/edit-formatting-text.ts
48797
+ function textFormattingWrites(shape2, document, edit, check3) {
48798
+ const rows = /* @__PURE__ */ new Map();
48799
+ if (["fontSize", "fontFamily", "fontColor", "bold", "italic", "underline", "strikethrough"].some(
48800
+ (key2) => edit[key2] !== void 0
48801
+ ))
48802
+ rows.set("Character", formattingRowContext(shape2, document, "Character"));
48803
+ if (edit.bullets !== void 0 || edit.indentLeft !== void 0 || edit.horizontalAlign !== void 0)
48804
+ rows.set("Paragraph", formattingRowContext(shape2, document, "Paragraph"));
48805
+ const characters = rows.get("Character")?.source;
48806
+ const paragraphs = rows.get("Paragraph")?.source;
48807
+ if (rows.size) assertFormattingText(shape2, characters, paragraphs);
48808
+ const writes = [];
48809
+ const add3 = (name, value, unit, formula) => writes.push({
48810
+ name,
48811
+ value: String(value),
48812
+ category: "TextStyle",
48813
+ ...unit ? { unit } : {},
48814
+ ...formula ? { formula } : {}
48815
+ });
48816
+ const scalar4 = (name, max, description) => {
48817
+ const cell = effectiveShapeCell(
48818
+ shape2,
48819
+ document,
48820
+ name,
48821
+ "TextStyle",
48822
+ rows.get(name.split(".")[0])
48823
+ );
48824
+ const cached3 = cell ? visioFormulaCachedValue(attribute3(cell, "V") ?? "", attribute3(cell, "U")) : { value: 0, unit: "scalar" };
48825
+ if (cached3.unit !== "scalar" || !Number.isSafeInteger(cached3.value) || cached3.value < 0 || cached3.value > max)
48826
+ fail2("UNSUPPORTED_FORMAT_EDIT", `${description} requires a supported scalar value.`);
48827
+ return cached3.value;
48828
+ };
48829
+ const font2 = edit.fontFamily === void 0 ? void 0 : formattingFont(document, edit.fontFamily);
48830
+ for (const index2 of characters ? /* @__PURE__ */ new Set(["0", ...characters.keys()]) : []) {
48831
+ check3();
48832
+ const name = (cell) => `Character.${index2}.${cell}`;
48833
+ if (edit.fontSize !== void 0) add3(name("Size"), edit.fontSize / 72, "PT");
48834
+ if (font2) add3(name("Font"), font2.value, void 0, font2.formula);
48835
+ if (edit.fontColor !== void 0) {
48836
+ add3(
48837
+ name("Color"),
48838
+ edit.fontColor,
48839
+ void 0,
48840
+ `RGB(${[1, 3, 5].map((i2) => parseInt(edit.fontColor.slice(i2, i2 + 2), 16)).join(",")})`
48841
+ );
48842
+ add3(name("ColorTrans"), 0);
48843
+ }
48844
+ if (edit.strikethrough !== void 0) add3(name("Strikethru"), edit.strikethrough ? 1 : 0);
48845
+ if ([edit.bold, edit.italic, edit.underline].some((value) => value !== void 0)) {
48846
+ let bits = scalar4(name("Style"), 255, "Character style");
48847
+ for (const [value, bit] of [
48848
+ [edit.bold, 1],
48849
+ [edit.italic, 2],
48850
+ [edit.underline, 4]
48851
+ ])
48852
+ if (value !== void 0) bits = value ? bits | bit : bits & ~bit;
48853
+ add3(name("Style"), bits);
48854
+ }
48855
+ }
48856
+ for (const index2 of paragraphs ? /* @__PURE__ */ new Set(["0", ...paragraphs.keys()]) : []) {
48857
+ check3();
48858
+ const name = (cell) => `Paragraph.${index2}.${cell}`;
48859
+ if (edit.indentLeft !== void 0) add3(name("IndLeft"), edit.indentLeft / 72, "PT");
48860
+ if (edit.bullets !== void 0) {
48861
+ const bullet = scalar4(name("Bullet"), 7, "Paragraph bullet style");
48862
+ add3(name("Bullet"), edit.bullets ? bullet || 1 : 0);
48863
+ }
48864
+ if (edit.horizontalAlign !== void 0)
48865
+ add3(name("HorzAlign"), ["left", "center", "right", "justify"].indexOf(edit.horizontalAlign));
48866
+ }
48867
+ if (edit.verticalAlign !== void 0)
48868
+ add3("VerticalAlign", ["top", "middle", "bottom"].indexOf(edit.verticalAlign));
48869
+ return { writes, rows };
48870
+ }
48871
+
48872
+ // visio/edit-formatting-paint-scope.ts
48873
+ var selectors = [
48874
+ "ColorSchemeIndex",
48875
+ "EffectSchemeIndex",
48876
+ "ConnectorSchemeIndex",
48877
+ "VariationStyleIndex",
48878
+ "VariationColorIndex",
48879
+ "QuickStyleType",
48880
+ "QuickStyleVariation",
48881
+ "QuickStyleFillMatrix",
48882
+ "QuickStyleLineMatrix",
48883
+ "OneD"
48884
+ ];
48885
+ function scalar3(cell) {
48886
+ if (!cell) return void 0;
48887
+ if (cell.hasAttribute("E")) fail2("UNSUPPORTED_FORMAT_EDIT", "Paint state has an error cache.");
48888
+ const cached3 = visioFormulaCachedValue(attribute3(cell, "V") ?? "", attribute3(cell, "U"));
48889
+ if (cached3.unit !== "scalar") fail2("EDIT_FORMULA_UNIT", "Paint state requires scalar units.");
48890
+ const source2 = executableCellFormula(attribute3(cell, "F"));
48891
+ if (source2) {
48892
+ const analysis = analyzeVisioFormula(source2);
48893
+ if (analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length)
48894
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Paint state dependencies cannot be proven.");
48895
+ const actual = evaluateVisioFormula(
48896
+ source2,
48897
+ () => fail2("UNSUPPORTED_FORMAT_EDIT", "Unknown paint dependency.")
48898
+ );
48899
+ if (actual.unit !== "scalar" || actual.value !== cached3.value)
48900
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Paint state formula cache is stale.");
48901
+ }
48902
+ return cached3.value;
48903
+ }
48904
+ async function assertNonGradientPaint(pkg, document, shape2, pageId, paint2, check3) {
48905
+ const category = paint2 === "Fill" ? "FillStyle" : "LineStyle";
48906
+ const pattern = effectiveShapeCell(shape2, document, `${paint2}Pattern`, category);
48907
+ if (pattern && attribute3(pattern, "V") !== "Themed") {
48908
+ const value = scalar3(pattern);
48909
+ if (value === 0) return;
48910
+ if (paint2 === "Fill" && value !== void 0 && value >= 25)
48911
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Classic gradient and custom fill edits are unsupported.");
48912
+ }
48913
+ const enabled2 = effectiveShapeCell(shape2, document, `${paint2}GradientEnabled`, category);
48914
+ if (!enabled2) return;
48915
+ if (attribute3(enabled2, "V") !== "Themed") {
48916
+ if (scalar3(enabled2) === 0) return;
48917
+ fail2(
48918
+ "UNSUPPORTED_FORMAT_EDIT",
48919
+ "Gradient paint transparency and background edits are unsupported."
48920
+ );
48921
+ }
48922
+ assertEditableFormattingCell(enabled2);
48923
+ const report = () => fail2("UNSUPPORTED_FORMAT_EDIT", "Theme paint context cannot be resolved safely.");
48924
+ if (children3(document, "StyleSheets").length > 1)
48925
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Ambiguous style containers cannot supply theme paint.");
48926
+ const styles = /* @__PURE__ */ new Map();
48927
+ for (const container of children3(document, "StyleSheets"))
48928
+ for (const node of children3(container, "StyleSheet")) {
48929
+ check3();
48930
+ const id = attribute3(node, "ID");
48931
+ if (!id || styles.has(id)) fail2("UNSUPPORTED_FORMAT_EDIT", "Ambiguous style IDs.");
48932
+ uniqueFormattingCells(node);
48933
+ styles.set(id, {
48934
+ sheet: readSheet(node),
48935
+ attributes: new Map(Array.from(node.attributes).map((item) => [item.name, item.value]))
48936
+ });
48937
+ }
48938
+ const context = { styles, styleCache: /* @__PURE__ */ new Map(), report, checkTime: check3 };
48939
+ let sheet = emptySheet();
48940
+ for (const name of ["LineStyle", "FillStyle", "TextStyle"]) {
48941
+ for (const selector of selectors) scalar3(effectiveShapeCell(shape2, document, selector, name));
48942
+ const id = attribute3(shape2, name) ?? attribute3(child5(document, "DocumentSheet"), name) ?? (styles.has("0") ? "0" : void 0);
48943
+ if (id !== void 0) sheet = mergeSheets(sheet, styleSheet(id, name, context));
48944
+ }
48945
+ sheet = mergeSheets(sheet, readSheet(shape2));
48946
+ const documentPath = await related(pkg, "", "document");
48947
+ const pagesPath = await related(pkg, documentPath, "pages");
48948
+ const page = children3(await visioXml(pkg, pagesPath, "Pages"), "Page").find(
48949
+ (node) => attribute3(node, "ID") === pageId
48950
+ );
48951
+ const pageSheet = child5(page, "PageSheet");
48952
+ const pageCells = /* @__PURE__ */ new Map();
48953
+ if (pageSheet) uniqueFormattingCells(pageSheet);
48954
+ for (const name of ["LineStyle", "FillStyle", "TextStyle"]) {
48955
+ const id = attribute3(pageSheet, name);
48956
+ if (id !== void 0 && pageSheet) {
48957
+ for (const selector of selectors)
48958
+ scalar3(effectiveShapeCell(pageSheet, document, selector, name));
48959
+ for (const [key2, value] of styleSheet(id, name, context).cells)
48960
+ if (/^(ColorSchemeIndex|EffectSchemeIndex|ConnectorSchemeIndex|FontSchemeIndex|VariationColorIndex|VariationStyleIndex)$/.test(
48961
+ key2
48962
+ ))
48963
+ pageCells.set(key2, value);
48964
+ }
48965
+ }
48966
+ for (const node of children3(pageSheet, "Cell"))
48967
+ if (selectors.includes(attribute3(node, "N") ?? "")) scalar3(node);
48968
+ const root = styles.get("0");
48969
+ const resources = {
48970
+ themes: await loadVisioThemes(pkg, documentPath, report),
48971
+ pageCells: new Map([...pageCells, ...readSheet(pageSheet).cells]),
48972
+ ...root?.attributes.get("NameU") === "No Style" ? { rootSheet: root.sheet } : {}
48973
+ };
48974
+ sheet = rootThemeSheet(sheet, resources, report);
48975
+ const resolved = number(sheet.cells, `${paint2}GradientEnabled`, NaN);
48976
+ if (resolved === 0) {
48977
+ const source2 = styles.get("0");
48978
+ if (!source2 || root?.attributes.get("NameU") !== "No Style")
48979
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Root gradient context cannot be proven.");
48980
+ const node = children3(child5(document, "StyleSheets"), "StyleSheet").find(
48981
+ (item) => attribute3(item, "ID") === "0"
48982
+ );
48983
+ if (scalar3(node ? uniqueFormattingCells(node).get(`${paint2}GradientEnabled`) : void 0) !== 0)
48984
+ fail2("UNSUPPORTED_FORMAT_EDIT", "Root gradient state cannot be proven inactive.");
48985
+ return;
48986
+ }
48987
+ const selected2 = themeFormat(sheet.cells, paint2, resources);
48988
+ if (paint2 === "Fill" && selected2 && ["solidFill", "noFill"].includes(selected2.localName)) return;
48989
+ if (paint2 === "Line" && selected2 && !themeChild(selected2, "gradFill") && (themeChild(selected2, "solidFill") || themeChild(selected2, "noFill")))
48990
+ return;
48991
+ fail2(
48992
+ "UNSUPPORTED_FORMAT_EDIT",
48993
+ "Active or unresolved theme gradients cannot be edited through paint transparency."
48994
+ );
48995
+ }
48996
+
48997
+ // visio/edit-formatting-paint.ts
48998
+ function shapeFormattingWrites(edit) {
48999
+ const writes = /* @__PURE__ */ new Map();
49000
+ const add3 = (name, value, category, unit, formula) => writes.set(name, {
49001
+ name,
49002
+ value: String(value),
49003
+ category,
49004
+ ...unit ? { unit } : {},
49005
+ ...formula ? { formula } : {}
49006
+ });
49007
+ if (edit.fillColor !== void 0) {
49008
+ add3("FillPattern", edit.fillColor === "none" ? 0 : 1, "FillStyle");
49009
+ add3("FillGradientEnabled", 0, "FillStyle");
49010
+ if (edit.fillColor !== "none") {
49011
+ add3("FillForegnd", edit.fillColor, "FillStyle", void 0, rgb2(edit.fillColor));
49012
+ add3("FillForegndTrans", 0, "FillStyle");
49013
+ }
49014
+ }
49015
+ if (edit.fillPattern !== void 0) {
49016
+ add3("FillPattern", edit.fillPattern, "FillStyle");
49017
+ add3("FillGradientEnabled", 0, "FillStyle");
49018
+ }
49019
+ if (edit.fillBackgroundColor !== void 0) {
49020
+ add3(
49021
+ "FillBkgnd",
49022
+ edit.fillBackgroundColor,
49023
+ "FillStyle",
49024
+ void 0,
49025
+ rgb2(edit.fillBackgroundColor)
49026
+ );
49027
+ }
49028
+ if (edit.fillTransparency !== void 0) {
49029
+ for (const name of ["FillForegndTrans", "FillBkgndTrans"])
49030
+ add3(name, edit.fillTransparency / 100, "FillStyle");
49031
+ }
49032
+ if (edit.lineColor !== void 0) {
49033
+ add3("LineColor", edit.lineColor, "LineStyle", void 0, rgb2(edit.lineColor));
49034
+ add3("LineColorTrans", 0, "LineStyle");
49035
+ add3("LineGradientEnabled", 0, "LineStyle");
49036
+ }
49037
+ if (edit.linePattern !== void 0) add3("LinePattern", edit.linePattern, "LineStyle");
49038
+ if (edit.lineTransparency !== void 0) {
49039
+ add3("LineColorTrans", edit.lineTransparency / 100, "LineStyle");
49040
+ }
49041
+ if (edit.lineWeight !== void 0) add3("LineWeight", edit.lineWeight / 72, "LineStyle", "PT");
49042
+ return [...writes.values()];
49043
+ }
49044
+ async function assertShapeFormattingPaintScope(pkg, document, shape2, edit, changed, check3) {
49045
+ if (edit.fillColor === void 0 && edit.fillPattern === void 0 && ["FillBkgnd", "FillForegndTrans", "FillBkgndTrans"].some((name) => changed.has(name)))
49046
+ await assertNonGradientPaint(pkg, document, shape2, edit.pageId, "Fill", check3);
49047
+ if (edit.lineColor === void 0 && changed.has("LineColorTrans"))
49048
+ await assertNonGradientPaint(pkg, document, shape2, edit.pageId, "Line", check3);
49049
+ }
49050
+ function rgb2(color2) {
49051
+ return `RGB(${[1, 3, 5].map((index2) => parseInt(color2.slice(index2, index2 + 2), 16)).join(",")})`;
49052
+ }
49053
+
49054
+ // visio/edit-formatting.ts
49055
+ function targetShape(root, shapeId) {
49056
+ const containers = children3(root, "Shapes");
49057
+ if (containers.length !== 1)
49058
+ fail2("UNSUPPORTED_FORMAT_EDIT", "One local Shapes container is required.");
49059
+ const candidates = children3(containers[0], "Shape").filter(
49060
+ (shape3) => attribute3(shape3, "ID") === shapeId
49061
+ );
49062
+ if (candidates.length !== 1)
49063
+ fail2("EDIT_TARGET_NOT_FOUND", "A unique top-level local shape is required.");
49064
+ const shape2 = candidates[0];
49065
+ if (shape2.hasAttribute("Master") || shape2.hasAttribute("MasterShape") || shape2.hasAttribute("Del") || children3(shape2, "Shapes").length || children3(shape2, "ForeignData").length || children3(shape2, "Rel").length || !["Shape", void 0].includes(attribute3(shape2, "Type")))
49066
+ fail2(
49067
+ "UNSUPPORTED_FORMAT_EDIT",
49068
+ "Master, group, foreign, deleted and non-shape formatting is unsupported."
49069
+ );
49070
+ return shape2;
49071
+ }
49072
+ async function applyFormattingEdit(pkg, pagePaths, roots, document, edit, check3) {
49073
+ const root = roots.get(edit.pageId);
49074
+ if (!root) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
49075
+ const shape2 = targetShape(root, edit.shapeId);
49076
+ assertUnlayeredShape(shape2, document);
49077
+ assertShapeLocks(
49078
+ shape2,
49079
+ document,
49080
+ edit.type === "format-text" ? ["LockFormat", "LockTextEdit"] : ["LockFormat"]
49081
+ );
49082
+ let writes = [];
49083
+ let rows;
49084
+ if (edit.type === "format-text") {
49085
+ const plan = textFormattingWrites(shape2, document, edit, check3);
49086
+ writes = plan.writes;
49087
+ rows = plan.rows;
49088
+ } else {
49089
+ writes = shapeFormattingWrites(edit);
49090
+ }
49091
+ const changed = /* @__PURE__ */ new Map();
49092
+ for (const write of writes) {
49093
+ check3();
49094
+ const [section, index2, name] = write.name.split(".");
49095
+ const rowContext = rows?.get(section);
49096
+ const effective = effectiveShapeCell(shape2, document, write.name, write.category, rowContext);
49097
+ assertEditableFormattingCell(effective);
49098
+ if (/^(LinePattern|FillPattern|FillGradientEnabled|LineGradientEnabled|LineColorTrans|FillForegndTrans|FillBkgndTrans|FillBkgnd)$/.test(
49099
+ write.name
49100
+ ) && effective?.hasAttribute("U") && visioFormulaCachedValue("0", attribute3(effective, "U")).unit !== "scalar")
49101
+ fail2("EDIT_FORMULA_UNIT", "Paint patterns and transparency require scalar units.");
49102
+ if (write.unit && effective?.hasAttribute("U") && visioFormulaCachedValue("0", attribute3(effective, "U")).unit !== "length")
49103
+ fail2(
49104
+ "EDIT_FORMULA_UNIT",
49105
+ "Font size, paragraph indent and line weight require length units."
49106
+ );
49107
+ const parent = name ? rowContext.local.get(index2) : shape2;
49108
+ const local = parent ? formattingCell(parent, name ?? write.name) : void 0;
49109
+ if (local && attribute3(local, "F") !== "Inh" && attribute3(local, "V") === write.value && (!write.formula || attribute3(local, "F") === write.formula))
49110
+ continue;
49111
+ changed.set(write.name, local);
49112
+ }
49113
+ if (!changed.size) return false;
49114
+ if (edit.type === "format-shape")
49115
+ await assertShapeFormattingPaintScope(pkg, document, shape2, edit, changed, check3);
49116
+ await assertFormattingDependencies(pkg, pagePaths, roots, edit.pageId, shape2, changed, check3);
49117
+ for (const write of writes) {
49118
+ check3();
49119
+ if (!changed.has(write.name)) continue;
49120
+ const [sectionName, index2, cellName] = write.name.split(".");
49121
+ let parent = shape2;
49122
+ if (cellName) {
49123
+ const localRows = rows.get(sectionName).local;
49124
+ let row2 = localRows.get(index2);
49125
+ if (!row2) {
49126
+ let section = children3(shape2, "Section").find(
49127
+ (node) => attribute3(node, "N") === sectionName
49128
+ );
49129
+ if (!section) {
49130
+ section = shape2.ownerDocument.createElementNS(shape2.namespaceURI, "Section");
49131
+ section.setAttribute("N", sectionName);
49132
+ shape2.insertBefore(section, children3(shape2, "Text")[0] ?? null);
49133
+ }
49134
+ row2 = shape2.ownerDocument.createElementNS(shape2.namespaceURI, "Row");
49135
+ row2.setAttribute("IX", index2);
49136
+ section.appendChild(row2);
49137
+ localRows.set(index2, row2);
49138
+ }
49139
+ parent = row2;
49140
+ }
49141
+ let cell = formattingCell(parent, cellName ?? write.name);
49142
+ if (!cell) {
49143
+ cell = shape2.ownerDocument.createElementNS(shape2.namespaceURI, "Cell");
49144
+ cell.setAttribute("N", cellName ?? write.name);
49145
+ parent.insertBefore(
49146
+ cell,
49147
+ Array.from(parent.childNodes).find(
49148
+ (node) => node.nodeType === 1 && node.localName !== "Cell"
49149
+ ) ?? null
49150
+ );
49151
+ }
49152
+ cell.setAttribute("V", write.value);
49153
+ if (write.unit) cell.setAttribute("U", write.unit);
49154
+ if (write.formula) cell.setAttribute("F", write.formula);
49155
+ else if (attribute3(cell, "F") !== "No Formula") cell.removeAttribute("F");
49156
+ }
49157
+ return true;
49158
+ }
49159
+
49160
+ // visio/edit-duplicate.ts
49161
+ function copyIdentity(shape2, newId, names) {
49162
+ shape2.setAttribute("ID", newId);
49163
+ shape2.removeAttribute("UniqueID");
49164
+ for (const name of ["Name", "NameU"]) {
49165
+ const value = attribute3(shape2, name);
49166
+ if (value === void 0) continue;
49167
+ const occupied = names.get(name);
49168
+ let next = `${value.replace(/\.\d+$/, "")}.${newId}`;
49169
+ if (occupied.has(next.toLowerCase())) next = `Sheet.${newId}`;
49170
+ if (occupied.has(next.toLowerCase()))
49171
+ fail2("UNSUPPORTED_DUPLICATE", "Duplicated default shape name is already occupied.");
49172
+ if (next.length > 4096)
49173
+ fail2("UNSUPPORTED_DUPLICATE", "Duplicated name exceeds metadata limits.");
49174
+ shape2.setAttribute(name, next);
49175
+ occupied.add(next.toLowerCase());
49176
+ }
49177
+ }
49178
+ async function duplicateVisioShapes(pkg, pagePaths, roots, document, edit, check3, detached) {
49179
+ const root = roots.get(edit.pageId);
49180
+ if (!root) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
49181
+ const ids = /* @__PURE__ */ new Set();
49182
+ for (const node of Array.from(root.getElementsByTagName("*")))
49183
+ if (node.localName === "Shape" && node.namespaceURI === root.namespaceURI) {
49184
+ const id = attribute3(node, "ID");
49185
+ if (!id || ids.has(id)) fail2("INVALID_SHAPE_ID", "Source shape IDs must be unique.");
49186
+ ids.add(id);
49187
+ }
49188
+ const newIds = new Set(edit.copies.map((copy2) => copy2.newShapeId));
49189
+ if ([...newIds].some((id) => ids.has(id)))
49190
+ fail2("INVALID_SHAPE_ID", "Duplicate shape ID already exists.");
49191
+ await assertDuplicateScope(pkg, pagePaths, root, newIds, check3);
49192
+ const sourceRoot = detached?.root ?? root;
49193
+ const sourcePageId = detached?.pageId ?? edit.pageId;
49194
+ const indexed = indexCells(detached ? /* @__PURE__ */ new Map([[sourcePageId, sourceRoot]]) : roots, { check: check3 });
49195
+ const evaluate = createVisioCellEvaluator(indexed, { check: check3 }, true);
49196
+ const containers = children3(root, "Shapes");
49197
+ if (containers.length > 1) fail2("INVALID_SHAPE_ID", "Duplicate Shapes containers.");
49198
+ const container = containers[0] ?? root.ownerDocument.createElementNS(root.namespaceURI, "Shapes");
49199
+ const mapping = new Map(edit.copies.map((copy2) => [copy2.shapeId, copy2.newShapeId]));
49200
+ const names = new Map(["Name", "NameU"].map((name) => [name, /* @__PURE__ */ new Set()]));
49201
+ for (const node of Array.from(root.getElementsByTagName("*")))
49202
+ if (node.localName === "Shape")
49203
+ for (const [name, occupied] of names) {
49204
+ const value = attribute3(node, name);
49205
+ if (value !== void 0) occupied.add(value.toLowerCase());
49206
+ }
49207
+ const plans = [];
49208
+ let cloneNodes = 0, cloneCharacters = buildXml(root).length;
49209
+ for (const copy2 of edit.copies) {
49210
+ check3();
49211
+ const source2 = admitted(sourceRoot, copy2.shapeId);
49212
+ assertCloneLeaf(source2);
49213
+ assertUnlayeredShape(source2, document);
49214
+ assertShapeLocks(source2, document, ["LockSelect"]);
49215
+ for (const connects of children3(sourceRoot, "Connects"))
49216
+ for (const connection of children3(connects, "Connect"))
49217
+ if (["FromSheet", "ToSheet"].some((name) => attribute3(connection, name) === copy2.shapeId))
49218
+ fail2("UNSUPPORTED_DUPLICATE", "Glued shapes cannot be duplicated safely.");
49219
+ const x = numeric4(formattingCell(source2, "PinX")), y = numeric4(formattingCell(source2, "PinY"));
49220
+ for (const [name, offset2] of [
49221
+ ["PinX", edit.offsetX],
49222
+ ["PinY", edit.offsetY]
49223
+ ]) {
49224
+ if (offset2 !== 0) assertEditableFormattingCell(formattingCell(source2, name));
49225
+ evaluate(key({ pageId: sourcePageId, shapeId: copy2.shapeId, cell: name }));
49226
+ }
49227
+ if (Math.abs(x + edit.offsetX) > 1e6 || Math.abs(y + edit.offsetY) > 1e6)
49228
+ fail2("UNSUPPORTED_DUPLICATE", "Duplicated pins exceed coordinate limits.");
49229
+ cloneNodes += source2.getElementsByTagName("*").length + 1;
49230
+ cloneCharacters += buildXml(source2).length;
49231
+ if (cloneNodes > 1e5 || cloneCharacters > 16 * 1024 * 1024)
49232
+ fail2("LIMIT_DUPLICATE", "Duplicated XML exceeds bounded expansion limits.");
49233
+ plans.push({ source: source2, id: copy2.newShapeId, x: x + edit.offsetX, y: y + edit.offsetY });
49234
+ }
49235
+ const order = new Map(
49236
+ children3(children3(sourceRoot, "Shapes")[0], "Shape").map((source2, index2) => [source2, index2])
49237
+ );
49238
+ plans.sort((a2, b) => order.get(a2.source) - order.get(b.source));
49239
+ if (!container.parentNode) root.insertBefore(container, children3(root, "Connects")[0] ?? null);
49240
+ const changed = [];
49241
+ for (const plan of plans) {
49242
+ check3();
49243
+ const shape2 = root.ownerDocument.importNode(plan.source, true);
49244
+ copyIdentity(shape2, plan.id, names);
49245
+ for (const node of [shape2, ...Array.from(shape2.getElementsByTagName("*"))]) {
49246
+ const source2 = executableCellFormula(attribute3(node, "F"));
49247
+ if (!source2) continue;
49248
+ const analysis = analyzeVisioFormula(source2);
49249
+ if (analysis.references.some((ref) => ref.shapeId !== void 0 && mapping.has(ref.shapeId)))
49250
+ node.setAttribute(
49251
+ "F",
49252
+ mapVisioFormulaSyntax(
49253
+ source2,
49254
+ (segment) => segment.replace(
49255
+ /\bSheet\.(\d+)!/gi,
49256
+ (match2, id) => mapping.has(id) ? `Sheet.${mapping.get(id)}!` : match2
49257
+ )
49258
+ )
49259
+ );
49260
+ }
49261
+ for (const [name, value, offset2] of [
49262
+ ["PinX", plan.x, edit.offsetX],
49263
+ ["PinY", plan.y, edit.offsetY]
49264
+ ])
49265
+ if (offset2 !== 0) {
49266
+ setCell(shape2, name, value);
49267
+ changed.push({ pageId: edit.pageId, shapeId: plan.id, cell: name });
49268
+ }
49269
+ container.appendChild(shape2);
49270
+ }
49271
+ if (changed.length) {
49272
+ await assertGeometryPackageScope(
49273
+ pkg,
49274
+ pagePaths,
49275
+ plans.map((plan) => ({
49276
+ type: "move-shape",
49277
+ pageId: edit.pageId,
49278
+ shapeId: plan.id,
49279
+ x: plan.x,
49280
+ y: plan.y
49281
+ })),
49282
+ check3,
49283
+ roots
49284
+ );
49285
+ const depends = createVisioDependencyQuery(roots, { check: check3 });
49286
+ for (const plan of plans) {
49287
+ const clone = children3(container, "Shape").find((node) => attribute3(node, "ID") === plan.id);
49288
+ for (const section of children3(clone, "Section"))
49289
+ if (attribute3(section, "N") === "Field")
49290
+ for (const row2 of children3(section, "Row"))
49291
+ for (const cell of children3(row2, "Cell")) {
49292
+ check3();
49293
+ const name = `Field.${attribute3(row2, "N") ?? attribute3(row2, "IX") ?? "0"}.${attribute3(cell, "N") ?? ""}`;
49294
+ if (depends({ pageId: edit.pageId, shapeId: plan.id, cell: name }, changed))
49295
+ fail2(
49296
+ "UNSUPPORTED_DUPLICATE",
49297
+ "Pin-dependent text fields need native display-cache regeneration."
49298
+ );
49299
+ }
49300
+ }
49301
+ }
49302
+ const dirty = /* @__PURE__ */ new Set([edit.pageId]);
49303
+ for (const id of recalculateVisioCells(roots, changed, { check: check3 })) dirty.add(id);
49304
+ return [...dirty];
49305
+ }
49306
+ function assertCloneLeaf(source2) {
49307
+ if (Array.from(source2.getElementsByTagName("*")).some(
49308
+ (node) => node.localName === "Shape" && (node.namespaceURI === VISIO_NS || node.namespaceURI === VISIO_LEGACY_NS)
49309
+ ))
49310
+ fail2("UNSUPPORTED_DUPLICATE", "Nested Visio shape identities cannot be copied as leaf XML.");
49311
+ }
49312
+
49313
+ // visio/clipboard-resources.ts
49314
+ async function clipboardResources(pkg) {
49315
+ const path2 = await related(pkg, "", "document");
49316
+ if (path2 !== "visio/document.xml")
49317
+ fail2("UNSUPPORTED_CLIPBOARD", "Clipboard requires the conventional document part.");
49318
+ const document = (await visioXml(pkg, path2, "VisioDocument")).cloneNode(true);
49319
+ for (const node of Array.from(document.childNodes))
49320
+ if (node.nodeType !== 1 || !["Colors", "FaceNames", "StyleSheets", "DocumentSheet"].includes(node.localName))
49321
+ document.removeChild(node);
49322
+ const resources = [{ path: path2, xml: buildXml(document) }];
49323
+ const relationships = (await pkg.readXml("visio/_rels/document.xml.rels")).cloneNode(
49324
+ true
49325
+ );
49326
+ for (const node of Array.from(relationships.childNodes))
49327
+ if (node.nodeType !== 1 || !(attribute3(node, "Type") ?? "").endsWith("/theme"))
49328
+ relationships.removeChild(node);
49329
+ resources.push({ path: "visio/_rels/document.xml.rels", xml: buildXml(relationships) });
49330
+ for (const name of pkg.paths().sort())
49331
+ if (/^visio\/theme\/(?:[^/]+\.xml|_rels\/[^/]+\.rels)$/.test(name))
49332
+ resources.push({ path: name, xml: buildXml(await pkg.readXml(name)) });
49333
+ return resources.sort((a2, b) => a2.path.localeCompare(b.path));
49334
+ }
49335
+ async function clipboardPageContext(pkg, pageId) {
49336
+ const document = await related(pkg, "", "document");
49337
+ const pagesPath = await related(pkg, document, "pages");
49338
+ const pages = children3(await visioXml(pkg, pagesPath, "Pages"), "Page");
49339
+ const matches2 = pages.filter((page2) => attribute3(page2, "ID") === pageId);
49340
+ if (matches2.length !== 1) fail2("EDIT_TARGET_NOT_FOUND", "Clipboard page must exist uniquely.");
49341
+ const page = matches2[0], sheets = children3(page, "PageSheet");
49342
+ if (sheets.length !== 1) fail2("UNSUPPORTED_CLIPBOARD", "One explicit PageSheet is required.");
49343
+ const scale2 = visioPageGeometryScale(
49344
+ readSheet(sheets[0]).cells,
49345
+ () => fail2("UNSUPPORTED_CLIPBOARD", "Page drawing ratio is unresolved.")
49346
+ );
49347
+ const context = page.ownerDocument.createElementNS(page.namespaceURI, "PageContext");
49348
+ context.setAttribute("PageNumber", String(pages.indexOf(page) + 1));
49349
+ context.setAttribute("PageCount", String(pages.length));
49350
+ for (const name of ["Background", "BackPage"]) {
49351
+ const value = attribute3(page, name);
49352
+ if (value !== void 0) context.setAttribute(name, value);
49353
+ }
49354
+ context.appendChild(sheets[0].cloneNode(true));
49355
+ return { xml: buildXml(context), scale: scale2 };
49356
+ }
49357
+ function assertClipboardResourceReferences(root, document) {
49358
+ const styles = new Map(
49359
+ children3(children3(document, "StyleSheets")[0], "StyleSheet").map((style2) => [
49360
+ attribute3(style2, "ID"),
49361
+ style2
49362
+ ])
49363
+ );
49364
+ const fonts = children3(children3(document, "FaceNames")[0], "FaceName");
49365
+ const fontIds = new Set(fonts.map((font2, index2) => attribute3(font2, "ID") ?? String(index2)));
49366
+ const fontNames = new Set(
49367
+ fonts.map((font2) => attribute3(font2, "Name") ?? attribute3(font2, "NameU"))
49368
+ );
49369
+ const fontById = new Map(
49370
+ fonts.map((font2, index2) => [
49371
+ attribute3(font2, "ID") ?? String(index2),
49372
+ attribute3(font2, "Name") ?? attribute3(font2, "NameU")
49373
+ ])
49374
+ );
49375
+ if (fontIds.size !== fonts.length || fontNames.size !== fonts.length || new Set([...fontNames].map((name) => name?.toLowerCase())).size !== fonts.length)
49376
+ fail2(
49377
+ "UNSUPPORTED_CLIPBOARD",
49378
+ "Clipboard font definitions must have unique IDs and family names."
49379
+ );
49380
+ const pool = [root, ...Array.from(root.getElementsByTagName("*"))], included = /* @__PURE__ */ new Set();
49381
+ const validateStyle = (id, category, seen = /* @__PURE__ */ new Set()) => {
49382
+ if (seen.has(id) || seen.size >= 64)
49383
+ fail2("UNSUPPORTED_CLIPBOARD", "Cyclic clipboard style ancestry.");
49384
+ const style2 = styles.get(id);
49385
+ if (!style2)
49386
+ fail2("UNSUPPORTED_CLIPBOARD", "Clipboard style reference does not exist in target.");
49387
+ if (!included.has(style2)) {
49388
+ included.add(style2);
49389
+ pool.push(style2, ...Array.from(style2.getElementsByTagName("*")));
49390
+ }
49391
+ seen.add(id);
49392
+ const parent = attribute3(style2, category);
49393
+ if (parent !== void 0 && parent !== id) validateStyle(parent, category, seen);
49394
+ };
49395
+ for (const node of pool) {
49396
+ for (const attr3 of Array.from(node.attributes))
49397
+ if (attr3.namespaceURI === "http://schemas.openxmlformats.org/officeDocument/2006/relationships")
49398
+ fail2("UNSUPPORTED_CLIPBOARD", "Relationship-bearing clipboard fragments are unsupported.");
49399
+ for (const category of ["FillStyle", "LineStyle", "TextStyle"]) {
49400
+ const id = attribute3(node, category);
49401
+ if (id !== void 0) validateStyle(id, category);
49402
+ }
49403
+ if (node.localName === "Cell" && ["Font", "BulletFont"].includes(attribute3(node, "N") ?? "")) {
49404
+ const value = attribute3(node, "V");
49405
+ if (value !== void 0 && value !== "Themed" && attribute3(node, "F") !== "Inh" && !fontIds.has(value) && !fontNames.has(value))
49406
+ fail2("UNSUPPORTED_CLIPBOARD", "Clipboard font does not exist in target FaceNames.");
49407
+ const formula = executableCellFormula(attribute3(node, "F"));
49408
+ const ast = formula ? parseVisioFormula(formula) : void 0;
49409
+ if (ast?.kind === "call" && ast.name === "FONT") {
49410
+ const arg = ast.args[0];
49411
+ if (ast.args.length !== 1 || arg?.kind !== "string" || !fontNames.has(arg.value) || value !== void 0 && (fontById.get(value) ?? value) !== arg.value)
49412
+ fail2("UNSUPPORTED_CLIPBOARD", "Clipboard font formula and existing font cache disagree.");
49413
+ }
49414
+ }
49415
+ }
49416
+ }
49417
+
49418
+ // visio/clipboard-xml.ts
49419
+ function assertClipboardXmlLimits(snapshot, check3) {
49420
+ let nodes = 0;
49421
+ for (const xml of [
49422
+ snapshot.pageContext,
49423
+ ...snapshot.resources.map((resource) => resource.xml),
49424
+ ...snapshot.shapes.map((shape2) => shape2.xml)
49425
+ ]) {
49426
+ if (nodes >= 1e5) fail2("LIMIT_CLIPBOARD", "Clipboard aggregate node limit exceeded.");
49427
+ nodes += inspectXml(
49428
+ xml,
49429
+ { ...DEFAULTS2, maxXmlChars: 8 * 1024 * 1024, maxXmlNodes: 1e5 - nodes },
49430
+ check3
49431
+ );
49432
+ }
49433
+ }
49434
+ function clipboardXml(xml, check3) {
49435
+ inspectXml(xml, { ...DEFAULTS2, maxXmlChars: 8 * 1024 * 1024, maxXmlNodes: 1e5 }, check3);
49436
+ const root = parseXml(xml).documentElement;
49437
+ inspectNamespaces(root, check3);
49438
+ return root;
49439
+ }
49440
+ function assertClipboardFormulaScope(root, ids, check3) {
49441
+ for (const node of [root, ...Array.from(root.getElementsByTagName("*"))]) {
49442
+ check3();
49443
+ const formula = executableCellFormula(attribute3(node, "F"));
49444
+ if (!formula) continue;
49445
+ const analysis = analyzeVisioFormula(formula, { });
49446
+ if (analysis.dynamic || analysis.references.some((ref) => ref.shapeId !== void 0 && !ids.has(ref.shapeId)))
49447
+ fail2(
49448
+ "UNSUPPORTED_CLIPBOARD",
49449
+ "Clipboard formulas reference uncaptured shapes or dynamic lookup."
49450
+ );
49451
+ let pageFunction = false;
49452
+ mapVisioFormulaSyntax(formula, (segment) => {
49453
+ pageFunction ||= /\b(?:PAGENUMBER|PAGECOUNT|PAGES)\s*\(/i.test(segment);
49454
+ return segment;
49455
+ });
49456
+ if (pageFunction)
49457
+ fail2(
49458
+ "UNSUPPORTED_CLIPBOARD",
49459
+ "Page-context clipboard functions require native cache regeneration."
49460
+ );
49461
+ }
49462
+ }
49463
+ function clipboardShapeRoot(snapshot, check3) {
49464
+ assertClipboardXmlLimits(snapshot, check3);
49465
+ const parseShape2 = (shape2) => {
49466
+ const node = clipboardXml(shape2.xml, check3);
49467
+ if (node.localName !== "Shape" || ![VISIO_NS, VISIO_LEGACY_NS].includes(node.namespaceURI ?? "") || attribute3(node, "ID") !== shape2.shapeId)
49468
+ fail2("INVALID_CLIPBOARD", "Clipboard XML must contain the declared Visio Shape.");
49469
+ return node;
49470
+ };
49471
+ const first3 = parseShape2(snapshot.shapes[0]);
49472
+ const root = clipboardXml(
49473
+ `<PageContents xmlns="${first3.namespaceURI}"><Shapes/></PageContents>`,
49474
+ check3
49475
+ );
49476
+ const container = root.firstChild;
49477
+ container.appendChild(root.ownerDocument.importNode(first3, true));
49478
+ for (let index2 = 1; index2 < snapshot.shapes.length; index2++) {
49479
+ check3();
49480
+ container.appendChild(
49481
+ root.ownerDocument.importNode(parseShape2(snapshot.shapes[index2]), true)
49482
+ );
49483
+ }
49484
+ if (root.getElementsByTagName("*").length > 1e5)
49485
+ fail2("LIMIT_CLIPBOARD", "Clipboard node limit exceeded.");
49486
+ assertClipboardFormulaScope(root, new Set(snapshot.selectionIds), check3);
49487
+ return root;
49488
+ }
49489
+
49490
+ // visio/edit-paste.ts
49491
+ async function pasteVisioShapes(pkg, pagePaths, roots, document, edit, check3) {
49492
+ assertClipboardXmlLimits(edit.clipboard, check3);
49493
+ const context = await clipboardPageContext(pkg, edit.pageId);
49494
+ if (context.scale !== edit.clipboard.sourceDrawingScale || buildXml(clipboardXml(edit.clipboard.pageContext, check3)) !== context.xml)
49495
+ fail2(
49496
+ "CLIPBOARD_CONTEXT_MISMATCH",
49497
+ "Clipboard requires matching page settings, ordinal and drawing ratio."
49498
+ );
49499
+ const actual = await clipboardResources(pkg);
49500
+ if (actual.length !== edit.clipboard.resources.length || actual.some((resource, index2) => {
49501
+ const captured = edit.clipboard.resources[index2];
49502
+ return captured.path !== resource.path || buildXml(clipboardXml(captured.xml, check3)) !== resource.xml;
49503
+ }))
49504
+ fail2(
49505
+ "CLIPBOARD_RESOURCE_MISMATCH",
49506
+ "Clipboard font, style and theme definitions differ from target."
49507
+ );
49508
+ const source2 = clipboardShapeRoot(edit.clipboard, check3);
49509
+ assertClipboardResourceReferences(source2, document);
49510
+ return duplicateVisioShapes(
49511
+ pkg,
49512
+ pagePaths,
49513
+ roots,
49514
+ document,
49515
+ { ...edit},
49516
+ check3,
49517
+ { root: source2, pageId: edit.clipboard.sourcePageId }
49518
+ );
49519
+ }
49520
+
49521
+ // visio/edit-delete.ts
49522
+ function deleteVisioShapes(roots, document, edits, check3) {
49523
+ const removed = /* @__PURE__ */ new Map();
49524
+ const shapes = [];
49525
+ for (const edit of edits) {
49526
+ check3();
49527
+ const ids = removed.get(edit.pageId) ?? /* @__PURE__ */ new Set();
49528
+ if (ids.has(edit.shapeId)) fail2("INVALID_EDIT", "A deletion target must occur only once.");
49529
+ ids.add(edit.shapeId);
49530
+ removed.set(edit.pageId, ids);
49531
+ const root = roots.get(edit.pageId);
49532
+ if (!root) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
49533
+ const shape2 = admitted(root, edit.shapeId, void 0, void 0, "delete");
49534
+ if (Array.from(shape2.getElementsByTagName("*")).some(
49535
+ (node) => (node.namespaceURI === VISIO_NS || node.namespaceURI === VISIO_LEGACY_NS) && node.localName === "Shape"
49536
+ ))
49537
+ fail2(
49538
+ "UNSUPPORTED_GEOMETRY_EDIT",
49539
+ "Nested shape identities cannot be removed as a local leaf."
49540
+ );
49541
+ protectedShape(shape2, document);
49542
+ if (numeric4(cells(shape2).get("LockDelete"), 0) !== 0)
49543
+ fail2("EDIT_PROTECTED_CELL", "LockDelete prevents this operation.");
49544
+ shapes.push(shape2);
49545
+ }
49546
+ assertVisioShapesUnreferenced(roots, removed, { check: check3 });
49547
+ check3();
49548
+ for (const shape2 of shapes) shape2.parentNode.removeChild(shape2);
49549
+ return [...removed.keys()];
49550
+ }
49551
+
47739
49552
  // visio/edit.ts
47740
49553
  function positive3(value) {
47741
49554
  if (!Number.isSafeInteger(value) || value <= 0)
@@ -47777,26 +49590,50 @@ async function editVsdx(input, edits, options = {}) {
47777
49590
  }
47778
49591
  const dirty = /* @__PURE__ */ new Map();
47779
49592
  const roots = /* @__PURE__ */ new Map();
47780
- const geometry = commands.some((command2) => command2.type !== "replace-plain-text");
49593
+ const geometryCommands = commands.filter(
49594
+ (command2) => command2.type !== "replace-plain-text" && command2.type !== "reorder-shape" && command2.type !== "duplicate-shapes" && command2.type !== "paste-shapes" && !isVisioFormatEdit(command2)
49595
+ );
47781
49596
  let document;
47782
49597
  let masterMovePins = emptyMasterMoveProof();
47783
- if (geometry) {
49598
+ if (geometryCommands.length || commands.some(
49599
+ (command2) => command2.type === "replace-plain-text" || isVisioFormatEdit(command2) || command2.type === "reorder-shape" || command2.type === "duplicate-shapes" || command2.type === "paste-shapes"
49600
+ )) {
47784
49601
  for (const [pageId, path3] of pages) {
47785
49602
  const sourceRoot = await visioXml(pkg, path3, "PageContents");
47786
49603
  roots.set(pageId, sourceRoot.ownerDocument.cloneNode(true).documentElement);
47787
49604
  }
47788
- masterMovePins = await assertGeometryPackageScope(
47789
- pkg,
47790
- new Set(pages.values()),
47791
- commands.filter((command2) => command2.type !== "replace-plain-text"),
47792
- check3,
47793
- roots
47794
- );
49605
+ for (const [pageId, root] of roots) {
49606
+ const ids = new Set(
49607
+ geometryCommands.filter((command2) => command2.type === "create-text-box" && command2.pageId === pageId).map((command2) => command2.shapeId)
49608
+ );
49609
+ if (ids.size) await assertDuplicateScope(pkg, new Set(pages.values()), root, ids, check3);
49610
+ }
49611
+ if (geometryCommands.length)
49612
+ masterMovePins = await assertGeometryPackageScope(
49613
+ pkg,
49614
+ new Set(pages.values()),
49615
+ geometryCommands,
49616
+ check3,
49617
+ roots
49618
+ );
47795
49619
  const path2 = await related(pkg, "", "document");
47796
49620
  document = await visioXml(pkg, path2, "VisioDocument");
47797
49621
  }
47798
49622
  let textChanged = false;
47799
- for (const command2 of commands) {
49623
+ if (commands.some((command2) => command2.type === "reorder-shape"))
49624
+ await assertShapeOrderPackageScope(pkg, check3);
49625
+ let formatChanged = false;
49626
+ let orderChanged = false;
49627
+ let duplicateChanged = false;
49628
+ let pasteChanged = false;
49629
+ const deletions = commands.filter(
49630
+ (command2) => command2.type === "delete-shape"
49631
+ );
49632
+ const deleteOnly = deletions.length > 0 && deletions.length === commands.length;
49633
+ if (deleteOnly)
49634
+ for (const pageId of deleteVisioShapes(roots, document, deletions, check3))
49635
+ dirty.set(pages.get(pageId), roots.get(pageId));
49636
+ for (const command2 of deleteOnly ? [] : commands) {
47800
49637
  check3();
47801
49638
  const path2 = pages.get(command2.pageId);
47802
49639
  if (!path2) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
@@ -47807,10 +49644,42 @@ async function editVsdx(input, edits, options = {}) {
47807
49644
  roots.set(command2.pageId, root);
47808
49645
  }
47809
49646
  if (command2.type === "replace-plain-text") {
47810
- if (replacePlainText(root, command2.shapeId, command2.text, check3)) {
49647
+ if (await replaceScopedPlainText(pkg, new Set(pages.values()), roots, document, command2, check3)) {
47811
49648
  dirty.set(path2, root);
47812
49649
  textChanged = true;
47813
49650
  }
49651
+ } else if (isVisioFormatEdit(command2)) {
49652
+ if (await applyFormattingEdit(pkg, new Set(pages.values()), roots, document, command2, check3)) {
49653
+ dirty.set(path2, root);
49654
+ formatChanged = true;
49655
+ }
49656
+ } else if (command2.type === "reorder-shape") {
49657
+ if (reorderVisioShape(root, document, command2, check3)) {
49658
+ dirty.set(path2, root);
49659
+ orderChanged = true;
49660
+ }
49661
+ } else if (command2.type === "paste-shapes") {
49662
+ for (const pageId of await pasteVisioShapes(
49663
+ pkg,
49664
+ new Set(pages.values()),
49665
+ roots,
49666
+ document,
49667
+ command2,
49668
+ check3
49669
+ ))
49670
+ dirty.set(pages.get(pageId), roots.get(pageId));
49671
+ pasteChanged = true;
49672
+ } else if (command2.type === "duplicate-shapes") {
49673
+ for (const pageId of await duplicateVisioShapes(
49674
+ pkg,
49675
+ new Set(pages.values()),
49676
+ roots,
49677
+ document,
49678
+ command2,
49679
+ check3
49680
+ ))
49681
+ dirty.set(pages.get(pageId), roots.get(pageId));
49682
+ duplicateChanged = true;
47814
49683
  } else {
47815
49684
  for (const pageId of applyGeometryEdit(roots, document, command2, check3, masterMovePins))
47816
49685
  dirty.set(pages.get(pageId), roots.get(pageId));
@@ -47845,17 +49714,50 @@ async function editVsdx(input, edits, options = {}) {
47845
49714
  return {
47846
49715
  bytes,
47847
49716
  changedParts: [...dirty.keys()],
47848
- diagnostics: dirty.size && textChanged ? [
47849
- {
47850
- code: "edit-caches-not-recalculated",
47851
- message: "Text was replaced without recalculating formulas or dependent caches. Native Visio reopen and rendering compatibility are unverified."
47852
- }
47853
- ] : dirty.size ? [
47854
- {
47855
- code: "edit-geometry-experimental",
47856
- message: "Supported affected geometry caches were recalculated. Native Visio reopen and rendering fidelity remain unverified."
47857
- }
47858
- ] : []
49717
+ diagnostics: [
49718
+ ...pasteChanged ? [
49719
+ {
49720
+ code: "edit-paste-experimental",
49721
+ message: "Captured shape XML was pasted with compatible resources and page context. Clipboard placement and cross-document fidelity are limited to supported cases."
49722
+ }
49723
+ ] : [],
49724
+ ...duplicateChanged ? [
49725
+ {
49726
+ code: "edit-duplicate-experimental",
49727
+ message: "Local shape XML was copied and supported pin-dependent caches were recalculated. Native fidelity is limited to tested cases."
49728
+ }
49729
+ ] : [],
49730
+ ...dirty.size && textChanged ? [
49731
+ {
49732
+ code: "edit-caches-not-recalculated",
49733
+ message: "Plain text changed; affected or unknown formula dependencies were refused. Untouched caches were preserved. Native fidelity is limited to tested cases."
49734
+ }
49735
+ ] : [],
49736
+ ...dirty.size && deleteOnly ? [
49737
+ {
49738
+ code: "edit-delete-experimental",
49739
+ message: "Reference-closed local shapes were deleted. Retained formulas and caches were preserved; glue healing and inherited shape deletion remain unsupported."
49740
+ }
49741
+ ] : [],
49742
+ ...dirty.size && geometryCommands.length && !deleteOnly ? [
49743
+ {
49744
+ code: "edit-geometry-experimental",
49745
+ message: "Supported affected geometry caches were recalculated. Native Visio reopen and rendering fidelity remain unverified."
49746
+ }
49747
+ ] : [],
49748
+ ...formatChanged ? [
49749
+ {
49750
+ code: "edit-formatting-experimental",
49751
+ message: "Text and solid shape formatting was changed without recalculating text layout. Native Visio reopen and rendering fidelity remain unverified."
49752
+ }
49753
+ ] : [],
49754
+ ...orderChanged ? [
49755
+ {
49756
+ code: "edit-shape-order-experimental",
49757
+ message: "Local sibling shape order was changed. Native Visio reopen and rendering fidelity remain unverified."
49758
+ }
49759
+ ] : []
49760
+ ]
47859
49761
  };
47860
49762
  }
47861
49763