visio-react-viewer 0.1.1 → 0.2.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.
@@ -54911,7 +54911,7 @@ function recalculateVisioCells(roots, changed, options = {}) {
54911
54911
  if (active.has(id)) fail("EDIT_FORMULA_CYCLE", "Affected ShapeSheet dependency cycle.");
54912
54912
  if (active.size >= maxDepth) fail("LIMIT_FORMULA_DEPTH", "ShapeSheet dependency depth limit exceeded.");
54913
54913
  const item = cells3.get(id);
54914
- if (!item || item.unsafe) fail("EDIT_UNSUPPORTED_DEPENDENCY", "Affected formula references missing, inherited or grouped cells.");
54914
+ if (!item || item.unsafe && (!item.node || !options.masterMovePins?.has(item.node))) fail("EDIT_UNSUPPORTED_DEPENDENCY", "Affected formula references missing, inherited or grouped cells.");
54915
54915
  if (item.node?.hasAttribute("E")) fail("EDIT_FORMULA_ERROR", "Affected ShapeSheet cell has an error cache.");
54916
54916
  active.add(id);
54917
54917
  let result;
@@ -55030,13 +55030,16 @@ function setCell(shape, name, value, formula) {
55030
55030
  if (formula) node.setAttribute("F", formula);
55031
55031
  else if (attribute2(node, "F") !== "No Formula") node.removeAttribute("F");
55032
55032
  }
55033
- function admitted(root, shapeId) {
55033
+ function admitted(root, shapeId, masterMovePins = /* @__PURE__ */ new Set(), masterDimensions = /* @__PURE__ */ new Map()) {
55034
55034
  const containers = children(root, "Shapes");
55035
55035
  if (containers.length !== 1) fail("UNSUPPORTED_GEOMETRY_EDIT", "One local Shapes container is required.");
55036
55036
  const candidates = children(containers[0], "Shape").filter((node) => attribute2(node, "ID") === shapeId);
55037
55037
  if (candidates.length !== 1) fail("EDIT_TARGET_NOT_FOUND", "A unique top-level local shape is required.");
55038
55038
  const shape = candidates[0];
55039
- if (shape.hasAttribute("Master") || shape.hasAttribute("MasterShape") || ["1", "true"].includes(attribute2(shape, "Del") ?? "") || children(shape, "Shapes").length || children(shape, "ForeignData").length || children(shape, "Rel").length || attribute2(shape, "Type") && attribute2(shape, "Type") !== "Shape") fail("UNSUPPORTED_GEOMETRY_EDIT", "Master, group, foreign, deleted and non-shape operations are unsupported.");
55039
+ if ((shape.hasAttribute("Master") || shape.hasAttribute("MasterShape")) && !["PinX", "PinY"].every((name) => {
55040
+ const cell = cells(shape).get(name);
55041
+ return cell && masterMovePins.has(cell);
55042
+ }) || ["1", "true"].includes(attribute2(shape, "Del") ?? "") || children(shape, "Shapes").length || children(shape, "ForeignData").length || children(shape, "Rel").length || attribute2(shape, "Type") && attribute2(shape, "Type") !== "Shape") fail("UNSUPPORTED_GEOMETRY_EDIT", "Master, group, foreign, deleted and non-shape operations are unsupported.");
55040
55043
  const local = cells(shape);
55041
55044
  for (const name of [
55042
55045
  "Width",
@@ -55055,28 +55058,40 @@ function admitted(root, shapeId) {
55055
55058
  "EndX",
55056
55059
  "EndY"
55057
55060
  ].some((name) => local.has(name))) fail("UNSUPPORTED_GEOMETRY_EDIT", "Only local 2D shapes are admitted; line routing and glue are unsupported.");
55058
- if (!(numeric3(local.get("Width")) > 0) || !(numeric3(local.get("Height")) > 0)) fail("UNSUPPORTED_GEOMETRY_EDIT", "Positive local Width and Height caches are required.");
55061
+ const proven = masterDimensions.get(shape);
55062
+ if (!(numeric3(local.get("Width"), proven?.width) > 0) || !(numeric3(local.get("Height"), proven?.height) > 0)) fail("UNSUPPORTED_GEOMETRY_EDIT", "Positive proven Width and Height caches are required.");
55059
55063
  return shape;
55060
55064
  }
55061
- function protectedShape(shape, document) {
55065
+ function protectedShape(shape, document, masterMovePins = /* @__PURE__ */ new Set()) {
55062
55066
  const local = cells(shape);
55067
+ const certifiedMove = shape.hasAttribute("Master") && ["PinX", "PinY"].every((name) => {
55068
+ const node = local.get(name);
55069
+ return node !== void 0 && masterMovePins.has(node);
55070
+ });
55063
55071
  const styles = /* @__PURE__ */ new Map();
55064
55072
  for (const container of children(document, "StyleSheets")) for (const node of children(container, "StyleSheet")) {
55065
55073
  const id = attribute2(node, "ID");
55066
55074
  if (!id || styles.has(id)) fail("EDIT_PROTECTED_CELL", "Ambiguous protection style IDs.");
55067
55075
  styles.set(id, node);
55068
55076
  }
55069
- const inactive = (cell) => {
55077
+ const validateProtection = (cell) => {
55070
55078
  try {
55071
- if (cell.hasAttribute("E") || visioFormulaCachedValue(attribute2(cell, "V") ?? "", attribute2(cell, "U")).unit !== "scalar" || numeric3(cell) !== 0) fail("EDIT_PROTECTED_CELL", "Inherited protection is active or invalid.");
55079
+ const cached2 = numeric3(cell);
55080
+ const operationIndependent = certifiedMove && [
55081
+ "LockWidth",
55082
+ "LockHeight",
55083
+ "LockAspect",
55084
+ "LockDelete"
55085
+ ].includes(attribute2(cell, "N") ?? "");
55086
+ if (cell.hasAttribute("E") || visioFormulaCachedValue(attribute2(cell, "V") ?? "", attribute2(cell, "U")).unit !== "scalar" || !(cached2 === 0 || operationIndependent && cached2 === 1)) fail("EDIT_PROTECTED_CELL", "Inherited protection is active or invalid.");
55072
55087
  const source = executableCellFormula(attribute2(cell, "F"));
55073
55088
  if (!source) return;
55074
55089
  const analysis = analyzeVisioFormula(source);
55075
55090
  if (analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length) fail("EDIT_PROTECTED_CELL", "Inherited protection formula cannot be resolved safely.");
55076
55091
  const result = evaluateVisioFormula(source, () => fail("EDIT_PROTECTED_CELL", "Inherited protection has dependencies."));
55077
- if (result.unit !== "scalar" || result.value !== 0) fail("EDIT_PROTECTED_CELL", "Inherited protection formula is active or stale.");
55092
+ if (result.unit !== "scalar" || result.value !== cached2) fail("EDIT_PROTECTED_CELL", "Inherited protection formula cache is stale.");
55078
55093
  } catch (error) {
55079
- fail("EDIT_PROTECTED_CELL", `Inherited protection cannot be proven inactive: ${error instanceof Error ? error.message : "invalid cache"}`);
55094
+ fail("EDIT_PROTECTED_CELL", `Inherited protection cannot be proven safe for this operation: ${error instanceof Error ? error.message : "invalid cache"}`);
55080
55095
  }
55081
55096
  };
55082
55097
  const resolve = (id, category, lock, seen = /* @__PURE__ */ new Set()) => {
@@ -55086,14 +55101,15 @@ function protectedShape(shape, document) {
55086
55101
  if (!style) fail("EDIT_PROTECTED_CELL", "Protection style ancestry cannot be resolved.");
55087
55102
  const cell = cells(style).get(lock), parent = attribute2(style, category);
55088
55103
  if (cell && attribute2(cell, "F") !== "Inh") {
55089
- inactive(cell);
55104
+ validateProtection(cell);
55090
55105
  return cell;
55091
55106
  }
55092
55107
  if (cell) {
55093
- inactive(cell);
55108
+ validateProtection(cell);
55094
55109
  if (parent === void 0 || parent === id) fail("EDIT_PROTECTED_CELL", "Inherited protection has no provable parent.");
55095
55110
  const inherited = resolve(parent, category, lock, seen);
55096
- if (!inherited) fail("EDIT_PROTECTED_CELL", "Inherited protection has no explicit inactive ancestor.");
55111
+ if (!inherited) fail("EDIT_PROTECTED_CELL", "Inherited protection has no explicit provable ancestor.");
55112
+ if (numeric3(cell) !== numeric3(inherited)) fail("EDIT_PROTECTED_CELL", "Delegated protection cache disagrees with its ancestor.");
55097
55113
  return inherited;
55098
55114
  }
55099
55115
  return parent !== void 0 && parent !== id ? resolve(parent, category, lock, seen) : void 0;
@@ -55156,6 +55172,117 @@ function resizeGeometry(shape, roots, edit, check) {
55156
55172
  }
55157
55173
  }
55158
55174
  }
55175
+ var protection = [
55176
+ "LockMoveX",
55177
+ "LockMoveY",
55178
+ "LockWidth",
55179
+ "LockHeight",
55180
+ "LockAspect",
55181
+ "LockDelete"
55182
+ ];
55183
+ var dimensions2 = [
55184
+ "PinX",
55185
+ "PinY",
55186
+ "Width",
55187
+ "Height",
55188
+ "LocPinX",
55189
+ "LocPinY"
55190
+ ];
55191
+ var emptyMasterMoveProof = () => ({
55192
+ pins: /* @__PURE__ */ new Set(),
55193
+ dimensions: /* @__PURE__ */ new Map()
55194
+ });
55195
+ function prepareMasterMovePins(roots, commands, bindings, check) {
55196
+ const result = /* @__PURE__ */ new Set();
55197
+ const provenDimensions = /* @__PURE__ */ new Map();
55198
+ let work = 1e5;
55199
+ const charge = (amount = 1) => {
55200
+ check();
55201
+ work -= amount;
55202
+ if (work < 0) fail("EDIT_UNSUPPORTED_PACKAGE_DEPENDENCY", "Master move preparation budget exceeded.");
55203
+ };
55204
+ const analyze = (formula) => {
55205
+ charge(formula.length);
55206
+ return analyzeVisioFormula(formula);
55207
+ };
55208
+ for (const command2 of commands) {
55209
+ charge();
55210
+ const instance = children(children(roots.get(command2.pageId), "Shapes")[0], "Shape").find((shape) => attribute2(shape, "ID") === command2.shapeId);
55211
+ if (!instance?.hasAttribute("Master")) continue;
55212
+ if (command2.type !== "move-shape") fail("UNSUPPORTED_GEOMETRY_EDIT", "Master-linked resizing and deletion remain unsupported.");
55213
+ const binding = bindings.find((candidate) => candidate.instance === instance);
55214
+ if (!binding) fail("UNSUPPORTED_GEOMETRY_EDIT", "A unique effective master root is required.");
55215
+ for (const node of [instance, binding.template]) {
55216
+ charge();
55217
+ if (attribute2(node, "Type") !== "Shape" || children(node, "Shapes").length || children(node, "ForeignData").length || children(node, "Rel").length || ["1", "true"].includes(attribute2(node, "Del") ?? "")) fail("UNSUPPORTED_GEOMETRY_EDIT", "Master moves require top-level local 2D shape roots.");
55218
+ }
55219
+ for (const name of [
55220
+ "BeginX",
55221
+ "BeginY",
55222
+ "EndX",
55223
+ "EndY"
55224
+ ]) if (binding.cells.has(name.toLowerCase())) fail("UNSUPPORTED_GEOMETRY_EDIT", "Master lines and endpoint routing remain unsupported.");
55225
+ const oneD = binding.cells.get("oned")?.node;
55226
+ charge();
55227
+ if (oneD && (numeric3(oneD) !== 0 || visioFormulaCachedValue(attribute2(oneD, "V") ?? "", attribute2(oneD, "U")).unit !== "scalar" || executableCellFormula(attribute2(oneD, "F")))) fail("UNSUPPORTED_GEOMETRY_EDIT", "A static effective 2D master is required.");
55228
+ const local = cells(instance);
55229
+ for (const name of dimensions2) {
55230
+ const effective = binding.cells.get(name.toLowerCase())?.node;
55231
+ for (const node of /* @__PURE__ */ new Set([effective, ...local.has(name) ? [local.get(name)] : []])) {
55232
+ charge();
55233
+ numeric3(node);
55234
+ if (visioFormulaCachedValue("0", attribute2(node, "U") ?? "DL").unit !== "length") fail("EDIT_FORMULA_UNIT", "Master transform caches require length units.");
55235
+ }
55236
+ }
55237
+ const dimension = (name) => numeric3(local.get(name) ?? binding.cells.get(name.toLowerCase())?.node);
55238
+ const width = dimension("Width"), height = dimension("Height");
55239
+ if (width <= 0 || height <= 0) fail("UNSUPPORTED_GEOMETRY_EDIT", "Positive proven effective dimensions are required.");
55240
+ provenDimensions.set(instance, {
55241
+ width,
55242
+ height
55243
+ });
55244
+ for (const name of protection) {
55245
+ charge();
55246
+ const node = binding.cells.get(name.toLowerCase())?.node;
55247
+ const cached2 = node ? numeric3(node) : NaN;
55248
+ const moving = name === "LockMoveX" || name === "LockMoveY";
55249
+ if (!node || visioFormulaCachedValue(attribute2(node, "V") ?? "", attribute2(node, "U")).unit !== "scalar" || ![0, 1].includes(cached2) || moving && cached2 !== 0) fail("EDIT_PROTECTED_CELL", "Effective master protection must be proven boolean with inactive movement locks.");
55250
+ const formula = executableCellFormula(attribute2(node, "F"));
55251
+ if (formula) {
55252
+ const analysis = analyze(formula);
55253
+ if (analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length) fail("EDIT_PROTECTED_CELL", "Effective master protection dependencies are unsupported.");
55254
+ const value = evaluateVisioFormula(formula, () => fail("EDIT_PROTECTED_CELL", "Unexpected protection dependency."), { onStep: () => charge() });
55255
+ if (value.unit !== "scalar" || value.value !== cached2) fail("EDIT_PROTECTED_CELL", "Effective master protection cache is stale.");
55256
+ }
55257
+ }
55258
+ for (const name of ["PinX", "PinY"]) {
55259
+ charge();
55260
+ const node = local.get(name);
55261
+ if (!node) fail("EDIT_PROTECTED_CELL", "The rotation pin must be an explicit local override.");
55262
+ if (binding.cells.get(name.toLowerCase())?.node !== node) fail("EDIT_PROTECTED_CELL", "The rotation pin must be an explicit local override.");
55263
+ charge(executableCellFormula(attribute2(node, "F"))?.length ?? 0);
55264
+ editableCell(node);
55265
+ const inherited = binding.inheritedCells.get(name.toLowerCase())?.node;
55266
+ numeric3(inherited);
55267
+ if (visioFormulaCachedValue("0", attribute2(inherited, "U") ?? "DL").unit !== "length") fail("EDIT_FORMULA_UNIT", "Inherited rotation pins require length units.");
55268
+ const formula = executableCellFormula(attribute2(inherited, "F"));
55269
+ if (formula) {
55270
+ const analysis = analyze(formula);
55271
+ if (analysis.guarded || analysis.dynamic || analysis.unsupportedFunctions.length) fail("EDIT_PROTECTED_CELL", "Protected or redirected master pins cannot be overridden.");
55272
+ }
55273
+ result.add(node);
55274
+ }
55275
+ }
55276
+ if (result.size) {
55277
+ const indexed = indexCells(roots, { check });
55278
+ const pins = new Set([...indexed.values()].filter((cell) => cell.node && result.has(cell.node)).map(key));
55279
+ for (const cell of indexed.values()) if (charge(), cell.dependencies.some((dependency) => pins.has(dependency))) fail("EDIT_UNSUPPORTED_DEPENDENCY", "A page cache depends on a master rotation pin.");
55280
+ }
55281
+ return {
55282
+ pins: result,
55283
+ dimensions: provenDimensions
55284
+ };
55285
+ }
55159
55286
  function createRectangle(root, edit) {
55160
55287
  const doc = root.ownerDocument;
55161
55288
  const node = (name) => doc.createElementNS(root.namespaceURI, name);
@@ -55209,7 +55336,8 @@ function createRectangle(root, edit) {
55209
55336
  container.appendChild(shape);
55210
55337
  return shape;
55211
55338
  }
55212
- function applyGeometryEdit(roots, document, edit, check) {
55339
+ function applyGeometryEdit(roots, document, edit, check, masterMoveProof = emptyMasterMoveProof()) {
55340
+ const masterMovePins = masterMoveProof.pins, masterDimensions = masterMoveProof.dimensions;
55213
55341
  check();
55214
55342
  const root = roots.get(edit.pageId);
55215
55343
  if (!root) fail("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
@@ -55235,8 +55363,8 @@ function applyGeometryEdit(roots, document, edit, check) {
55235
55363
  "PinY"
55236
55364
  ]) add(name);
55237
55365
  } else {
55238
- const shape = admitted(root, edit.shapeId);
55239
- protectedShape(shape, document);
55366
+ const shape = admitted(root, edit.shapeId, edit.type === "move-shape" ? masterMovePins : /* @__PURE__ */ new Set(), edit.type === "move-shape" ? masterDimensions : /* @__PURE__ */ new Map());
55367
+ protectedShape(shape, document, edit.type === "move-shape" ? masterMovePins : /* @__PURE__ */ new Set());
55240
55368
  if (edit.type !== "delete-shape") {
55241
55369
  for (const connections2 of children(root, "Connects")) for (const connection of children(connections2, "Connect")) if (["FromSheet", "ToSheet"].some((name) => attribute2(connection, name) === edit.shapeId)) fail("UNSUPPORTED_GEOMETRY_EDIT", "Glued connections need routing and endpoint recalculation outside this subset.");
55242
55370
  }
@@ -55251,9 +55379,10 @@ function applyGeometryEdit(roots, document, edit, check) {
55251
55379
  return [edit.pageId];
55252
55380
  }
55253
55381
  if (edit.type === "move-shape") {
55382
+ const proven = masterDimensions.get(shape);
55254
55383
  expected = {
55255
- width: numeric3(local.get("Width")),
55256
- height: numeric3(local.get("Height")),
55384
+ width: numeric3(local.get("Width"), proven?.width),
55385
+ height: numeric3(local.get("Height"), proven?.height),
55257
55386
  x: edit.x,
55258
55387
  y: edit.y
55259
55388
  };
@@ -55266,7 +55395,7 @@ function applyGeometryEdit(roots, document, edit, check) {
55266
55395
  edit.y,
55267
55396
  "LockMoveY"
55268
55397
  ]]) {
55269
- if (numeric3(local.get(name), name === "PinX" ? numeric3(local.get("Width")) / 2 : numeric3(local.get("Height")) / 2) === value) continue;
55398
+ if (numeric3(local.get(name), name === "PinX" ? expected.width / 2 : expected.height / 2) === value) continue;
55270
55399
  unlocked(lock);
55271
55400
  editableCell(local.get(name));
55272
55401
  setCell(shape, name, value);
@@ -55311,9 +55440,13 @@ function applyGeometryEdit(roots, document, edit, check) {
55311
55440
  }
55312
55441
  }
55313
55442
  if (!changed.length) return [];
55314
- const affectedPages = recalculateVisioCells(roots, changed, { check });
55315
- const result = cells(admitted(root, edit.shapeId));
55316
- if (expected && (numeric3(result.get("Width")) !== expected.width || numeric3(result.get("Height")) !== expected.height || numeric3(result.get("PinX"), expected.width / 2) !== expected.x || numeric3(result.get("PinY"), expected.height / 2) !== expected.y)) fail("EDIT_UNSUPPORTED_DEPENDENCY", "Dependent formulas would violate the requested geometry or fixed rotation pin.");
55443
+ const affectedPages = recalculateVisioCells(roots, changed, {
55444
+ check,
55445
+ masterMovePins
55446
+ });
55447
+ const resultShape = admitted(root, edit.shapeId, edit.type === "move-shape" ? masterMovePins : /* @__PURE__ */ new Set(), edit.type === "move-shape" ? masterDimensions : /* @__PURE__ */ new Map());
55448
+ const result = cells(resultShape), provenResult = masterDimensions.get(resultShape);
55449
+ if (expected && (numeric3(result.get("Width"), provenResult?.width) !== expected.width || numeric3(result.get("Height"), provenResult?.height) !== expected.height || numeric3(result.get("PinX"), expected.width / 2) !== expected.x || numeric3(result.get("PinY"), expected.height / 2) !== expected.y)) fail("EDIT_UNSUPPORTED_DEPENDENCY", "Dependent formulas would violate the requested geometry or fixed rotation pin.");
55317
55450
  return [.../* @__PURE__ */ new Set([edit.pageId, ...affectedPages])];
55318
55451
  }
55319
55452
  function analyzeVisioMasterFormula(source, options) {
@@ -55373,6 +55506,19 @@ function analyzeVisioMasterFormula(source, options) {
55373
55506
  readsTheme
55374
55507
  };
55375
55508
  }
55509
+ function inheritedProtection(node, ancestor) {
55510
+ try {
55511
+ const boolean2 = (cell) => {
55512
+ if (!cell || cell.hasAttribute("E")) fail("EDIT_PROTECTED_CELL", "Inherited protection has an unresolved or error cache.");
55513
+ const value = visioFormulaCachedValue(attribute2(cell, "V") ?? "", attribute2(cell, "U"));
55514
+ if (value.unit !== "scalar" || ![0, 1].includes(value.value)) fail("EDIT_PROTECTED_CELL", "Inherited protection requires scalar boolean caches.");
55515
+ return value.value;
55516
+ };
55517
+ if (boolean2(node) !== boolean2(ancestor)) fail("EDIT_PROTECTED_CELL", "Delegated master style protection cache disagrees with its ancestor.");
55518
+ } catch (error) {
55519
+ fail("EDIT_PROTECTED_CELL", `Inherited master style protection cannot be proven: ${error instanceof Error ? error.message : "invalid cache"}`);
55520
+ }
55521
+ }
55376
55522
  function masterCells(sheet, charge = () => {}) {
55377
55523
  const result = /* @__PURE__ */ new Map();
55378
55524
  if (!sheet) return result;
@@ -55421,7 +55567,7 @@ function assertMasterMarkup(root, known, check) {
55421
55567
  if (node.namespaceURI === root.namespaceURI && node.hasAttribute("F") && !known.has(node)) fail("EDIT_UNSUPPORTED_PACKAGE_DEPENDENCY", "Master formula outside admitted sheet cells has unknown scope.");
55422
55568
  }
55423
55569
  }
55424
- function masterStyleCells(document, template, instance, check, charge = () => {}) {
55570
+ function masterStyleCells(document, template, instance, check, charge = () => {}, verifyMovementProtection = false) {
55425
55571
  const styles = /* @__PURE__ */ new Map();
55426
55572
  for (const container of children(document, "StyleSheets")) for (const style of children(container, "StyleSheet")) {
55427
55573
  charge();
@@ -55443,6 +55589,10 @@ function masterStyleCells(document, template, instance, check, charge = () => {}
55443
55589
  for (const [name, node] of own) {
55444
55590
  charge();
55445
55591
  if (attribute2(node, "F") !== "Inh") result2.set(name, node);
55592
+ else if (verifyMovementProtection && /^lock(move[xy]|width|height|aspect|delete)$/.test(name)) {
55593
+ charge();
55594
+ inheritedProtection(node, result2.get(name));
55595
+ }
55446
55596
  }
55447
55597
  return result2;
55448
55598
  };
@@ -55514,12 +55664,15 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
55514
55664
  pageId,
55515
55665
  instance
55516
55666
  })));
55517
- if (!instances.length) return;
55667
+ if (!instances.length) return emptyMasterMoveProof();
55518
55668
  const documentPart = await related(pkg, "", "document");
55519
55669
  if (!documentPart) problem("Missing master document relationship.");
55520
55670
  const document = await visioXml(pkg, documentPart, "VisioDocument");
55521
55671
  const mastersPart = await related(pkg, documentPart, "masters", false);
55522
- if (!mastersPart) problem("Active master definitions are missing.");
55672
+ if (!mastersPart) {
55673
+ if (commands.some((command2) => instances.some((item) => item.pageId === command2.pageId && attribute2(item.instance, "ID") === command2.shapeId))) fail("UNSUPPORTED_GEOMETRY_EDIT", "Active master definitions are missing.");
55674
+ problem("Active master definitions are missing.");
55675
+ }
55523
55676
  const definitions = /* @__PURE__ */ new Map();
55524
55677
  for (const node of children(await visioXml(pkg, mastersPart, "Masters"), "Master")) {
55525
55678
  const id = attribute2(node, "ID");
@@ -55534,6 +55687,11 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
55534
55687
  if (--buildWork < 0) problem("Master effective-cell construction budget exceeded.");
55535
55688
  };
55536
55689
  const pageBindings = /* @__PURE__ */ new Map();
55690
+ const movingTargets = /* @__PURE__ */ new Set();
55691
+ for (const command2 of commands) {
55692
+ charge();
55693
+ if (command2.type === "move-shape") movingTargets.add(JSON.stringify([command2.pageId, command2.shapeId]));
55694
+ }
55537
55695
  const pageShapes = /* @__PURE__ */ new Map();
55538
55696
  for (const [pageId, root] of roots) for (const shape of masterShapes(root)) {
55539
55697
  const id = attribute2(shape, "ID");
@@ -55580,17 +55738,20 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
55580
55738
  const templateId = attribute2(template, "ID");
55581
55739
  if (!templateId || context.has(templateId)) problem("Master-local sheet IDs are ambiguous.");
55582
55740
  const local = byTemplate.get(templateId), cells3 = /* @__PURE__ */ new Map();
55583
- for (const [name, node] of masterStyleCells(document, template, local, check, charge)) cells3.set(name, {
55741
+ const movedInstance = local === instance && movingTargets.has(JSON.stringify([pageId, attribute2(local, "ID")]));
55742
+ for (const [name, node] of masterStyleCells(document, template, local, check, charge, movedInstance)) cells3.set(name, {
55584
55743
  node,
55585
55744
  kind: "style"
55586
55745
  });
55587
55746
  overlay(cells3, masterCells(template, charge), "template", charge);
55747
+ const inheritedCells = new Map(cells3);
55588
55748
  overlay(cells3, masterCells(local, charge), "instance", charge);
55589
55749
  const binding = {
55590
55750
  id: `${pageId}:${attribute2(instance, "ID")}:${templateId}`,
55591
55751
  pageId,
55592
55752
  template,
55593
55753
  cells: cells3,
55754
+ inheritedCells,
55594
55755
  context,
55595
55756
  ...local ? { instance: local } : {}
55596
55757
  };
@@ -55600,6 +55761,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
55600
55761
  }
55601
55762
  for (const id of byTemplate.keys()) if (!context.has(id)) problem("MasterShape refers to a missing template.");
55602
55763
  }
55764
+ const movePins = prepareMasterMovePins(roots, commands, bindings, check);
55603
55765
  const changed = commands.flatMap((command2) => command2.type === "delete-shape" ? [] : (command2.type === "move-shape" ? ["PinX", "PinY"] : command2.type === "resize-shape" ? ["Width", "Height"] : [
55604
55766
  "Width",
55605
55767
  "Height",
@@ -55632,6 +55794,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
55632
55794
  template: shape,
55633
55795
  instance: shape,
55634
55796
  cells: cells3,
55797
+ inheritedCells: /* @__PURE__ */ new Map(),
55635
55798
  context: /* @__PURE__ */ new Map()
55636
55799
  };
55637
55800
  pageInputs.set(id, result);
@@ -55699,7 +55862,12 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check) {
55699
55862
  active.delete(id);
55700
55863
  done.add(id);
55701
55864
  };
55702
- for (const binding of bindings) for (const name of binding.cells.keys()) inspect2(binding, name);
55865
+ for (const binding of bindings) for (const name of binding.cells.keys()) {
55866
+ const source = binding.cells.get(name);
55867
+ if (["pinx", "piny"].includes(name) && source?.kind === "instance" && movePins.pins.has(source.node)) continue;
55868
+ inspect2(binding, name);
55869
+ }
55870
+ return movePins;
55703
55871
  }
55704
55872
  var admitted2 = (node) => node.namespaceURI === VISIO_NS || node.namespaceURI === VISIO_LEGACY_NS;
55705
55873
  function cells2(sheet) {
@@ -55807,16 +55975,18 @@ async function assertGeometryPackageScope(pkg, pagePaths, commands, check, roots
55807
55975
  });
55808
55976
  }
55809
55977
  }
55978
+ let movePins = emptyMasterMoveProof();
55810
55979
  if (hasMasterInstances) {
55811
55980
  for (const command2 of commands) {
55812
55981
  const root = roots.get(command2.pageId);
55813
55982
  if (!root) continue;
55814
55983
  const target = Array.from(root.getElementsByTagNameNS(root.namespaceURI, "Shape")).find((shape) => attribute2(shape, "ID") === command2.shapeId);
55815
- if (target?.hasAttribute("Master") || target?.hasAttribute("MasterShape")) fail("UNSUPPORTED_GEOMETRY_EDIT", "Editing master-linked shapes is unsupported.");
55984
+ if (target?.hasAttribute("MasterShape") && !target.hasAttribute("Master")) fail("UNSUPPORTED_GEOMETRY_EDIT", "Editing master-linked shapes is unsupported.");
55985
+ if (target?.hasAttribute("Master") && (command2.type !== "move-shape" || !["PinX", "PinY"].every((name) => children(target, "Cell").some((node) => attribute2(node, "N") === name)))) fail("UNSUPPORTED_GEOMETRY_EDIT", "Master moves require explicit local rotation pins.");
55816
55986
  }
55817
- await assertVisioMasterIndependence(pkg, roots, commands, check);
55987
+ movePins = await assertVisioMasterIndependence(pkg, roots, commands, check);
55818
55988
  }
55819
- if (!documentRoot) return;
55989
+ if (!documentRoot) return movePins;
55820
55990
  const styles = /* @__PURE__ */ new Map();
55821
55991
  for (const container of children(documentRoot, "StyleSheets")) for (const style of children(container, "StyleSheet")) {
55822
55992
  const id = attribute2(style, "ID");
@@ -55882,6 +56052,7 @@ async function assertGeometryPackageScope(pkg, pagePaths, commands, check, roots
55882
56052
  }
55883
56053
  }
55884
56054
  }
56055
+ return movePins;
55885
56056
  }
55886
56057
  function positive(value) {
55887
56058
  if (!Number.isSafeInteger(value) || value <= 0) fail("INVALID_LIMITS", "Edit limits must be positive safe integers.");
@@ -55909,12 +56080,13 @@ async function editVsdx(input, edits, options = {}) {
55909
56080
  const roots = /* @__PURE__ */ new Map();
55910
56081
  const geometry = commands.some((command2) => command2.type !== "replace-plain-text");
55911
56082
  let document;
56083
+ let masterMovePins = emptyMasterMoveProof();
55912
56084
  if (geometry) {
55913
56085
  for (const [pageId, path2] of pages) {
55914
56086
  const sourceRoot = await visioXml(pkg, path2, "PageContents");
55915
56087
  roots.set(pageId, sourceRoot.ownerDocument.cloneNode(true).documentElement);
55916
56088
  }
55917
- await assertGeometryPackageScope(pkg, new Set(pages.values()), commands.filter((command2) => command2.type !== "replace-plain-text"), check, roots);
56089
+ masterMovePins = await assertGeometryPackageScope(pkg, new Set(pages.values()), commands.filter((command2) => command2.type !== "replace-plain-text"), check, roots);
55918
56090
  document = await visioXml(pkg, await related(pkg, "", "document"), "VisioDocument");
55919
56091
  }
55920
56092
  let textChanged = false;
@@ -55932,7 +56104,7 @@ async function editVsdx(input, edits, options = {}) {
55932
56104
  dirty.set(path, root);
55933
56105
  textChanged = true;
55934
56106
  }
55935
- } else for (const pageId of applyGeometryEdit(roots, document, command2, check)) dirty.set(pages.get(pageId), roots.get(pageId));
56107
+ } else for (const pageId of applyGeometryEdit(roots, document, command2, check, masterMovePins)) dirty.set(pages.get(pageId), roots.get(pageId));
55936
56108
  }
55937
56109
  let totalBytes = [...parts.values()].reduce((sum, bytes2) => sum + bytes2.length, 0);
55938
56110
  let nodes = 0;