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.
- package/dist/{PptxHandler-VQQS4VS6.mjs → PptxHandler-ZPJNHEZZ.mjs} +2 -2
- package/dist/automation/index.cjs +2235 -333
- package/dist/automation/index.mjs +2235 -333
- package/dist/{chunk-5U27IVB7.mjs → chunk-BB55ASTX.mjs} +3 -3
- package/dist/{chunk-V2BIGIH4.mjs → chunk-H4TPDZV4.mjs} +1 -1
- package/dist/{chunk-5VLNF4OX.mjs → chunk-IVDC75E5.mjs} +1 -1
- package/dist/{chunk-XBNSBDNT.mjs → chunk-QPQDLSJQ.mjs} +1 -1
- package/dist/{chunk-XSFHGZFH.mjs → chunk-XGLKW3JJ.mjs} +5 -3
- package/dist/pptx/automation/index.cjs +4 -2
- package/dist/pptx/automation/index.mjs +5 -5
- package/dist/pptx/cli/index.cjs +4 -2
- package/dist/pptx/cli/index.mjs +4 -4
- package/dist/pptx/converter/index.mjs +2 -2
- package/dist/pptx/index.cjs +4 -2
- package/dist/pptx/index.mjs +5 -5
- package/dist/teams/index.cjs +19 -10
- package/dist/teams/index.mjs +19 -10
- package/dist/visio/clipboard-resources.d.ts +11 -0
- package/dist/visio/clipboard-resources.d.ts.map +1 -0
- package/dist/visio/clipboard-types.d.ts +26 -0
- package/dist/visio/clipboard-types.d.ts.map +1 -0
- package/dist/visio/clipboard-xml.d.ts +8 -0
- package/dist/visio/clipboard-xml.d.ts.map +1 -0
- package/dist/visio/clipboard.d.ts +7 -0
- package/dist/visio/clipboard.d.ts.map +1 -0
- package/dist/visio/create-document.d.ts +8 -0
- package/dist/visio/create-document.d.ts.map +1 -0
- package/dist/visio/edit-commands.d.ts +19 -2
- package/dist/visio/edit-commands.d.ts.map +1 -1
- package/dist/visio/edit-delete.d.ts +9 -0
- package/dist/visio/edit-delete.d.ts.map +1 -0
- package/dist/visio/edit-duplicate-commands.d.ts +14 -0
- package/dist/visio/edit-duplicate-commands.d.ts.map +1 -0
- package/dist/visio/edit-duplicate-scope.d.ts +4 -0
- package/dist/visio/edit-duplicate-scope.d.ts.map +1 -0
- package/dist/visio/edit-duplicate.d.ts +10 -0
- package/dist/visio/edit-duplicate.d.ts.map +1 -0
- package/dist/visio/edit-formatting-cell-admission.d.ts +3 -0
- package/dist/visio/edit-formatting-cell-admission.d.ts.map +1 -0
- package/dist/visio/edit-formatting-commands.d.ts +46 -0
- package/dist/visio/edit-formatting-commands.d.ts.map +1 -0
- package/dist/visio/edit-formatting-font.d.ts +6 -0
- package/dist/visio/edit-formatting-font.d.ts.map +1 -0
- package/dist/visio/edit-formatting-paint-scope.d.ts +6 -0
- package/dist/visio/edit-formatting-paint-scope.d.ts.map +1 -0
- package/dist/visio/edit-formatting-paint.d.ts +6 -0
- package/dist/visio/edit-formatting-paint.d.ts.map +1 -0
- package/dist/visio/edit-formatting-rows.d.ts +14 -0
- package/dist/visio/edit-formatting-rows.d.ts.map +1 -0
- package/dist/visio/edit-formatting-scope.d.ts +6 -0
- package/dist/visio/edit-formatting-scope.d.ts.map +1 -0
- package/dist/visio/edit-formatting-text.d.ts +8 -0
- package/dist/visio/edit-formatting-text.d.ts.map +1 -0
- package/dist/visio/edit-formatting.d.ts +12 -0
- package/dist/visio/edit-formatting.d.ts.map +1 -0
- package/dist/visio/edit-geometry.d.ts.map +1 -1
- package/dist/visio/edit-paste-commands.d.ts +15 -0
- package/dist/visio/edit-paste-commands.d.ts.map +1 -0
- package/dist/visio/edit-paste.d.ts +5 -0
- package/dist/visio/edit-paste.d.ts.map +1 -0
- package/dist/visio/edit-recalculate.d.ts +3 -1
- package/dist/visio/edit-recalculate.d.ts.map +1 -1
- package/dist/visio/edit-resize-anchor.d.ts +8 -0
- package/dist/visio/edit-resize-anchor.d.ts.map +1 -0
- package/dist/visio/edit-scope.d.ts.map +1 -1
- package/dist/visio/edit-shape-create.d.ts +1 -1
- package/dist/visio/edit-shape-create.d.ts.map +1 -1
- package/dist/visio/edit-shape-order.d.ts +7 -0
- package/dist/visio/edit-shape-order.d.ts.map +1 -0
- package/dist/visio/edit-style-admission.d.ts +17 -0
- package/dist/visio/edit-style-admission.d.ts.map +1 -0
- package/dist/visio/edit-text-scope.d.ts +7 -0
- package/dist/visio/edit-text-scope.d.ts.map +1 -0
- package/dist/visio/edit-text.d.ts +1 -1
- package/dist/visio/edit-text.d.ts.map +1 -1
- package/dist/visio/edit.d.ts +1 -1
- package/dist/visio/edit.d.ts.map +1 -1
- package/dist/visio/index.cjs +3245 -1077
- package/dist/visio/index.d.ts +3 -1
- package/dist/visio/index.d.ts.map +1 -1
- package/dist/visio/index.mjs +3241 -1079
- package/dist/visio/line-pattern.d.ts +1 -1
- package/dist/visio/line-pattern.d.ts.map +1 -1
- package/dist/visio/line-style.d.ts.map +1 -1
- package/dist/visio/model.d.ts +23 -3
- package/dist/visio/model.d.ts.map +1 -1
- package/dist/visio/parser.d.ts.map +1 -1
- package/dist/visio/plain-text.d.ts +5 -0
- package/dist/visio/plain-text.d.ts.map +1 -0
- package/dist/visio/resize-anchor.d.ts +27 -0
- package/dist/visio/resize-anchor.d.ts.map +1 -0
- package/dist/visio/source-paint.d.ts +5 -0
- package/dist/visio/source-paint.d.ts.map +1 -0
- package/dist/visio/style.d.ts.map +1 -1
- package/dist/visio/theme-root.d.ts.map +1 -1
- package/dist/visio/ui/contract.d.ts +10 -6
- package/dist/visio/ui/contract.d.ts.map +1 -1
- package/dist/visio/ui/draw-plan.d.ts +32 -0
- package/dist/visio/ui/draw-plan.d.ts.map +1 -0
- package/dist/visio/ui/edit-commands.d.ts.map +1 -1
- package/dist/visio/ui/formatting.d.ts +28 -0
- package/dist/visio/ui/formatting.d.ts.map +1 -0
- package/dist/visio/ui/index.cjs +1305 -15
- package/dist/visio/ui/index.d.ts +15 -0
- package/dist/visio/ui/index.d.ts.map +1 -1
- package/dist/visio/ui/index.mjs +1261 -16
- package/dist/visio/ui/line-dash.d.ts +4 -0
- package/dist/visio/ui/line-dash.d.ts.map +1 -0
- package/dist/visio/ui/marquee.d.ts +15 -0
- package/dist/visio/ui/marquee.d.ts.map +1 -0
- package/dist/visio/ui/page-edit.d.ts.map +1 -1
- package/dist/visio/ui/scene-validation.d.ts.map +1 -1
- package/dist/visio/ui/selection.d.ts +12 -0
- package/dist/visio/ui/selection.d.ts.map +1 -0
- package/dist/visio/ui/shape-arrange.d.ts +17 -0
- package/dist/visio/ui/shape-arrange.d.ts.map +1 -0
- package/dist/visio/ui/shape-clipboard.d.ts +10 -0
- package/dist/visio/ui/shape-clipboard.d.ts.map +1 -0
- package/dist/visio/ui/shape-duplicate.d.ts +5 -0
- package/dist/visio/ui/shape-duplicate.d.ts.map +1 -0
- package/dist/visio/ui/shape-formatting.d.ts +14 -0
- package/dist/visio/ui/shape-formatting.d.ts.map +1 -0
- package/dist/visio/ui/shape-move.d.ts +14 -0
- package/dist/visio/ui/shape-move.d.ts.map +1 -0
- package/dist/visio/ui/shape-order.d.ts +4 -0
- package/dist/visio/ui/shape-order.d.ts.map +1 -0
- package/dist/visio/ui/shape-resize.d.ts +61 -0
- package/dist/visio/ui/shape-resize.d.ts.map +1 -0
- package/dist/visio/ui/size-position.d.ts +19 -0
- package/dist/visio/ui/size-position.d.ts.map +1 -0
- package/dist/visio/ui/snapshot-scene.d.ts.map +1 -1
- package/dist/visio/ui/svg-stroke.d.ts +8 -0
- package/dist/visio/ui/svg-stroke.d.ts.map +1 -0
- package/dist/visio/ui/text-replace-selection.d.ts +9 -0
- package/dist/visio/ui/text-replace-selection.d.ts.map +1 -0
- package/dist/visio/ui/text-replace-snapshot.d.ts +14 -0
- package/dist/visio/ui/text-replace-snapshot.d.ts.map +1 -0
- package/dist/visio/ui/text-replace-types.d.ts +48 -0
- package/dist/visio/ui/text-replace-types.d.ts.map +1 -0
- package/dist/visio/ui/text-replace.d.ts +18 -0
- package/dist/visio/ui/text-replace.d.ts.map +1 -0
- package/dist/xlsx/formula/lexemes.d.ts.map +1 -1
- package/dist/xlsx/index.cjs +18 -9
- package/dist/xlsx/index.mjs +18 -9
- package/dist/xlsx/load/index.cjs +18 -9
- package/dist/xlsx/load/index.mjs +18 -9
- package/dist/xlsx/ui/index.cjs +18 -9
- package/dist/xlsx/ui/index.mjs +18 -9
- 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
|
|
263
|
-
if (
|
|
264
|
-
const raw2 = source2.slice(q + 1,
|
|
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 =
|
|
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
|
|
2241
|
-
if (!/^[0-9a-fA-F]{6}$/.test(
|
|
2242
|
-
return [0, 2, 4].map((i2) => parseInt(
|
|
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 = (
|
|
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
|
|
4574
|
-
if (!
|
|
4573
|
+
const rgb3 = base ? hexToRgbChannels(base) : null;
|
|
4574
|
+
if (!rgb3) return void 0;
|
|
4575
4575
|
{
|
|
4576
|
-
const value = orderedColorTransforms(
|
|
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
|
|
11980
|
+
const rgb3 = att(element2, "rgb");
|
|
11981
11981
|
const theme2 = numAttr(element2, "theme");
|
|
11982
11982
|
const indexed = numAttr(element2, "indexed");
|
|
11983
|
-
if (
|
|
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
|
|
12668
|
-
return { prefix: { text: source2.slice(at2, at2 +
|
|
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 (
|
|
12679
|
-
|
|
12680
|
-
if (
|
|
12681
|
-
|
|
12682
|
-
|
|
12683
|
-
|
|
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
|
|
13130
|
+
const close2 = nextIndex(list, arg + 1);
|
|
13122
13131
|
const target = list[arg];
|
|
13123
|
-
if (list[open]?.kind !== "open" || list[
|
|
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 <=
|
|
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
|
|
14477
|
-
if (
|
|
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,
|
|
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(
|
|
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
|
|
15025
|
-
if (!tint) return toHexColor(
|
|
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(...
|
|
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
|
|
27897
|
-
return typeof
|
|
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 = "",
|
|
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}${
|
|
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 = (
|
|
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
|
|
31985
|
-
if (
|
|
31993
|
+
const rgb3 = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(value);
|
|
31994
|
+
if (rgb3)
|
|
31986
31995
|
return {
|
|
31987
|
-
rgb:
|
|
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
|
|
32073
|
-
if (
|
|
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 =
|
|
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
|
|
32214
|
-
if (
|
|
32215
|
-
const next = body[
|
|
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,
|
|
32218
|
-
i2 =
|
|
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
|
|
41187
|
+
let rgb3;
|
|
41179
41188
|
let inherited;
|
|
41180
|
-
if (color2.kind === "srgb")
|
|
41181
|
-
else if (color2.kind === "system")
|
|
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")
|
|
41192
|
+
if (color2.value === "phClr") rgb3 = placeholder;
|
|
41184
41193
|
else {
|
|
41185
41194
|
inherited = drawingPaint(colors.get(color2.value), colors, placeholder, depth + 1);
|
|
41186
|
-
|
|
41195
|
+
rgb3 = inherited?.color;
|
|
41187
41196
|
}
|
|
41188
41197
|
}
|
|
41189
|
-
if (!
|
|
41198
|
+
if (!rgb3 || !/^#?[\da-f]{6}$/i.test(rgb3)) return void 0;
|
|
41190
41199
|
const resolved = resolveDrawingColor(
|
|
41191
|
-
{ kind: "srgb", value:
|
|
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,
|
|
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 = [
|
|
42007
|
-
const gap = [
|
|
42008
|
-
const long = [
|
|
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,
|
|
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
|
-
|
|
42037
|
-
"
|
|
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 {
|
|
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)
|
|
42906
|
-
|
|
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
|
|
42965
|
+
const storedText = runs.map((r) => r.text).join("");
|
|
42928
42966
|
const defaultRun = runStyle(defaultCells, resources, report, cells3);
|
|
42929
42967
|
const paragraphs = textParagraphs(
|
|
42930
|
-
|
|
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")
|
|
43959
|
-
|
|
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 {
|
|
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/
|
|
44286
|
-
function
|
|
44287
|
-
|
|
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
|
|
44384
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
45316
|
+
function assertVisioShapesUnreferenced(roots, removed, options = {}) {
|
|
45346
45317
|
const cells3 = indexCells(roots, options);
|
|
45347
45318
|
for (const cell of cells3.values()) {
|
|
45348
|
-
|
|
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]
|
|
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
|
|
45356
|
-
|
|
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
|
-
|
|
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
|
|
45364
|
-
|
|
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
|
-
|
|
45587
|
-
|
|
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
|
|
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 (
|
|
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
|
-
|
|
47789
|
-
|
|
47790
|
-
|
|
47791
|
-
|
|
47792
|
-
check3
|
|
47793
|
-
|
|
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
|
-
|
|
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 (
|
|
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:
|
|
47849
|
-
|
|
47850
|
-
|
|
47851
|
-
|
|
47852
|
-
|
|
47853
|
-
|
|
47854
|
-
|
|
47855
|
-
|
|
47856
|
-
|
|
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
|
|