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