ooxml-core 1.2.0 → 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-SJTINPU4.mjs → PptxHandler-ZPJNHEZZ.mjs} +2 -2
- package/dist/automation/index.cjs +3294 -661
- package/dist/automation/index.mjs +3294 -661
- package/dist/chart/bar-cluster-geometry.d.ts +6 -0
- package/dist/chart/bar-cluster-geometry.d.ts.map +1 -1
- package/dist/chart/index.cjs +5 -2
- package/dist/chart/index.mjs +5 -3
- package/dist/chart/render/chart-spacing.d.ts.map +1 -1
- package/dist/{chunk-TEOAOAIF.mjs → chunk-BB55ASTX.mjs} +3 -3
- package/dist/{chunk-CQQAPUAG.mjs → chunk-H4TPDZV4.mjs} +11 -9
- package/dist/{chunk-VYTA2OUN.mjs → chunk-IVDC75E5.mjs} +1 -1
- package/dist/{chunk-FI4RSJ24.mjs → chunk-QPQDLSJQ.mjs} +1 -1
- package/dist/{chunk-XCZ7U3GZ.mjs → chunk-XGLKW3JJ.mjs} +13 -9
- package/dist/docx/index.cjs +4 -2
- package/dist/docx/index.mjs +4 -2
- package/dist/docx/layout/index.cjs +4 -2
- package/dist/docx/layout/index.mjs +4 -2
- package/dist/docx/ui/index.cjs +4 -2
- package/dist/docx/ui/index.mjs +4 -2
- package/dist/index.cjs +5 -2
- package/dist/index.mjs +5 -2
- package/dist/pptx/automation/index.cjs +29 -17
- package/dist/pptx/automation/index.mjs +5 -5
- package/dist/pptx/chunks/index-EZJZ7USt.d.ts.map +1 -1
- package/dist/pptx/cli/index.cjs +29 -17
- package/dist/pptx/cli/index.mjs +4 -4
- package/dist/pptx/converter/index.mjs +2 -2
- package/dist/pptx/index.cjs +29 -17
- package/dist/pptx/index.mjs +5 -5
- package/dist/teams/index.cjs +176 -92
- package/dist/teams/index.mjs +176 -92
- 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/edit/context.d.ts +3 -1
- package/dist/xlsx/edit/context.d.ts.map +1 -1
- package/dist/xlsx/edit/history.d.ts +18 -0
- package/dist/xlsx/edit/history.d.ts.map +1 -1
- package/dist/xlsx/edit/session-calc.d.ts +30 -8
- package/dist/xlsx/edit/session-calc.d.ts.map +1 -1
- package/dist/xlsx/edit/session.d.ts.map +1 -1
- package/dist/xlsx/edit/sheets.d.ts.map +1 -1
- package/dist/xlsx/edit/types.d.ts +23 -3
- package/dist/xlsx/edit/types.d.ts.map +1 -1
- package/dist/xlsx/formula/engine-core.d.ts.map +1 -1
- package/dist/xlsx/formula/engine-host.d.ts +6 -2
- package/dist/xlsx/formula/engine-host.d.ts.map +1 -1
- package/dist/xlsx/formula/engine-prepare.d.ts +33 -0
- package/dist/xlsx/formula/engine-prepare.d.ts.map +1 -0
- package/dist/xlsx/formula/engine-structure.d.ts +40 -0
- package/dist/xlsx/formula/engine-structure.d.ts.map +1 -0
- package/dist/xlsx/formula/engine-types.d.ts +26 -0
- package/dist/xlsx/formula/engine-types.d.ts.map +1 -1
- package/dist/xlsx/formula/engine.d.ts.map +1 -1
- package/dist/xlsx/formula/formula-shape.d.ts +28 -0
- package/dist/xlsx/formula/formula-shape.d.ts.map +1 -0
- package/dist/xlsx/formula/graph-index.d.ts +3 -1
- package/dist/xlsx/formula/graph-index.d.ts.map +1 -1
- package/dist/xlsx/formula/graph.d.ts +5 -0
- package/dist/xlsx/formula/graph.d.ts.map +1 -1
- package/dist/xlsx/formula/lexemes.d.ts.map +1 -1
- package/dist/xlsx/formula/parse-cache.d.ts +9 -0
- package/dist/xlsx/formula/parse-cache.d.ts.map +1 -0
- package/dist/xlsx/formula/parser.d.ts +3 -0
- package/dist/xlsx/formula/parser.d.ts.map +1 -1
- package/dist/xlsx/formula/ref-text.d.ts +14 -0
- package/dist/xlsx/formula/ref-text.d.ts.map +1 -0
- package/dist/xlsx/formula/references.d.ts.map +1 -1
- package/dist/xlsx/formula/shift-formula.d.ts +19 -0
- package/dist/xlsx/formula/shift-formula.d.ts.map +1 -0
- package/dist/xlsx/formula/shift-graph.d.ts +42 -0
- package/dist/xlsx/formula/shift-graph.d.ts.map +1 -0
- package/dist/xlsx/formula/transform.d.ts +2 -23
- package/dist/xlsx/formula/transform.d.ts.map +1 -1
- package/dist/xlsx/index.cjs +1087 -338
- package/dist/xlsx/index.mjs +1087 -339
- package/dist/xlsx/layout/index.d.ts +1 -1
- package/dist/xlsx/layout/index.d.ts.map +1 -1
- package/dist/xlsx/layout/sheet-queries.d.ts +7 -0
- package/dist/xlsx/layout/sheet-queries.d.ts.map +1 -1
- package/dist/xlsx/load/index.cjs +170 -99
- package/dist/xlsx/load/index.mjs +170 -99
- package/dist/xlsx/ui/index.cjs +1072 -332
- package/dist/xlsx/ui/index.mjs +1072 -332
- 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))}`,
|
|
@@ -8618,9 +8618,9 @@ function rejectUnsafeRunSegmentation(paragraph2, base, oldRuns) {
|
|
|
8618
8618
|
(run2) => !run2.image && !run2.equation && (run2.restoredRunPropertiesXml || run2.sourceRunPropertiesXml)
|
|
8619
8619
|
))
|
|
8620
8620
|
return;
|
|
8621
|
-
const
|
|
8621
|
+
const sameText2 = paragraph2.runs.map((run2) => run2.text).join("") === base.runs.map((run2) => run2.text).join("");
|
|
8622
8622
|
const sameBoundaries = paragraph2.runs.length === base.runs.length && paragraph2.runs.every((run2, index2) => run2.text === base.runs[index2]?.text);
|
|
8623
|
-
if (sameBoundaries || !
|
|
8623
|
+
if (sameBoundaries || !sameText2 && paragraph2.runs.length === base.runs.length) return;
|
|
8624
8624
|
throw new Error(
|
|
8625
8625
|
`Cannot edit paragraph ${paragraph2.id}: changing run boundaries could drop unsupported run properties. The original DOCX package remains unchanged.`
|
|
8626
8626
|
);
|
|
@@ -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];
|
|
@@ -12492,7 +12492,7 @@ var NAME_RE = /^[A-Za-z_\\\u00A1-\uFFFF][A-Za-z0-9_.?\\\u00A1-\uFFFF]*/;
|
|
|
12492
12492
|
var CELL_RE = /^(\$?)([A-Za-z]{1,3})(\$?)(\d{1,7})/;
|
|
12493
12493
|
var COLS_RE = /^(\$?)([A-Za-z]{1,3}):(\$?)([A-Za-z]{1,3})/;
|
|
12494
12494
|
var ROWS_RE = /^(\$?)(\d{1,7}):(\$?)(\d{1,7})/;
|
|
12495
|
-
var NUMBER_RE = /^(?:\d
|
|
12495
|
+
var NUMBER_RE = /^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/;
|
|
12496
12496
|
var sticky = (re) => new RegExp(re.source.replace(/^\^/, ""), "y");
|
|
12497
12497
|
var CELL_AT = sticky(CELL_RE);
|
|
12498
12498
|
var COLS_AT = sticky(COLS_RE);
|
|
@@ -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);
|
|
@@ -12839,7 +12848,7 @@ function readName(source2, at2, start, prefix) {
|
|
|
12839
12848
|
}
|
|
12840
12849
|
var joinTokens = (tokens3) => tokens3.map((t) => t.text).join("");
|
|
12841
12850
|
|
|
12842
|
-
// xlsx/formula/
|
|
12851
|
+
// xlsx/formula/ref-text.ts
|
|
12843
12852
|
function safeTokens(formula) {
|
|
12844
12853
|
try {
|
|
12845
12854
|
return tokenize(formula);
|
|
@@ -12858,50 +12867,26 @@ function formatRefSpec(spec2) {
|
|
|
12858
12867
|
if (spec2.kind === "cell") return a2;
|
|
12859
12868
|
return `${a2}:${cornerText(spec2.end, spec2.kind)}`;
|
|
12860
12869
|
}
|
|
12861
|
-
function
|
|
12870
|
+
function rewriteRef(token, ref) {
|
|
12862
12871
|
const prefix = token.prefix?.text ?? "";
|
|
12863
12872
|
if (!ref) return `${prefix}#REF!`;
|
|
12864
12873
|
return `${prefix}${formatRefSpec(ref)}${token.spill ? "#" : ""}`;
|
|
12865
12874
|
}
|
|
12866
12875
|
var sameSpec = (a2, b) => a2.kind === b.kind && a2.start.row === b.start.row && a2.start.col === b.start.col && a2.end.row === b.end.row && a2.end.col === b.end.col;
|
|
12867
|
-
|
|
12868
|
-
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
|
|
12872
|
-
|
|
12873
|
-
const move = (c2) => {
|
|
12874
|
-
const row2 = spec2.kind === "cols" || c2.rowAbs ? c2.row : c2.row + dRow;
|
|
12875
|
-
const col = spec2.kind === "rows" || c2.colAbs ? c2.col : c2.col + dCol;
|
|
12876
|
-
if (row2 < 0 || row2 > MAX_ROW || col < 0 || col > MAX_COL) return void 0;
|
|
12877
|
-
return { ...c2, row: row2, col };
|
|
12878
|
-
};
|
|
12879
|
-
const start = move(spec2.start);
|
|
12880
|
-
const end = move(spec2.end);
|
|
12881
|
-
const next = start && end ? { kind: spec2.kind, start, end } : void 0;
|
|
12882
|
-
if (next && sameSpec(next, spec2)) continue;
|
|
12883
|
-
token.text = rewrite(token, next);
|
|
12884
|
-
}
|
|
12885
|
-
return joinTokens(tokens3);
|
|
12876
|
+
var needsQuote = (name) => !/^[A-Za-z_¡-][A-Za-z0-9_.¡-]*$/.test(name) || /^[A-Za-z]{1,3}\d+$/.test(name) || /^(?:R\d*C?\d*|C\d*)$/i.test(name) || /^(?:TRUE|FALSE)$/i.test(name);
|
|
12877
|
+
function prefixText(prefix) {
|
|
12878
|
+
const sheets = prefix.sheet2 !== void 0 ? `${prefix.sheet}:${prefix.sheet2}` : prefix.sheet;
|
|
12879
|
+
const book = prefix.book !== void 0 ? `[${prefix.book}]` : "";
|
|
12880
|
+
const quote2 = needsQuote(prefix.sheet) || prefix.sheet2 !== void 0 && needsQuote(prefix.sheet2);
|
|
12881
|
+
return quote2 ? `'${(book + sheets).replace(/'/g, "''")}'!` : `${book}${sheets}!`;
|
|
12886
12882
|
}
|
|
12887
|
-
|
|
12888
|
-
|
|
12889
|
-
|
|
12890
|
-
|
|
12891
|
-
|
|
12892
|
-
|
|
12893
|
-
|
|
12894
|
-
const na2 = a2 >= at2 ? a2 + count2 : a2;
|
|
12895
|
-
const nb2 = b >= at2 ? b + count2 : b;
|
|
12896
|
-
if (nb2 > max) return na2 > max ? void 0 : [na2, max];
|
|
12897
|
-
return [na2, nb2];
|
|
12898
|
-
}
|
|
12899
|
-
const n = -count2;
|
|
12900
|
-
const last = at2 + n - 1;
|
|
12901
|
-
if (a2 >= at2 && b <= last) return void 0;
|
|
12902
|
-
const na = a2 < at2 ? a2 : a2 <= last ? at2 : a2 - n;
|
|
12903
|
-
const nb = b < at2 ? b : b <= last ? at2 - 1 : b - n;
|
|
12904
|
-
return [na, nb];
|
|
12883
|
+
|
|
12884
|
+
// xlsx/formula/shift-formula.ts
|
|
12885
|
+
var templates = /* @__PURE__ */ new Map();
|
|
12886
|
+
var MAX_TEMPLATES = 2e5;
|
|
12887
|
+
function remember2(text2, template) {
|
|
12888
|
+
if (templates.size >= MAX_TEMPLATES) templates.clear();
|
|
12889
|
+
templates.set(text2, template);
|
|
12905
12890
|
}
|
|
12906
12891
|
function mergeSpacedAreas(tokens3) {
|
|
12907
12892
|
const out = [];
|
|
@@ -12928,63 +12913,145 @@ function mergeSpacedAreas(tokens3) {
|
|
|
12928
12913
|
}
|
|
12929
12914
|
return out;
|
|
12930
12915
|
}
|
|
12931
|
-
function
|
|
12932
|
-
|
|
12916
|
+
function templateOf(formula) {
|
|
12917
|
+
const cached3 = templates.get(formula);
|
|
12918
|
+
if (cached3 !== void 0) return cached3;
|
|
12933
12919
|
const raw2 = safeTokens(formula);
|
|
12934
|
-
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
|
|
12947
|
-
|
|
12948
|
-
|
|
12949
|
-
|
|
12950
|
-
|
|
12951
|
-
|
|
12952
|
-
|
|
12953
|
-
if (shifted2) {
|
|
12954
|
-
const [a2, b] = shifted2;
|
|
12955
|
-
const nlo = isRow ? { ...lo, row: a2 } : { ...lo, col: a2 };
|
|
12956
|
-
const nhi = isRow ? { ...hi, row: b } : { ...hi, col: b };
|
|
12957
|
-
next = { kind: ref.kind, start: startFirst ? nlo : nhi, end: startFirst ? nhi : nlo };
|
|
12958
|
-
if (ref.kind === "cell") next.end = next.start;
|
|
12920
|
+
let template = null;
|
|
12921
|
+
if (raw2) {
|
|
12922
|
+
template = [];
|
|
12923
|
+
let literal2 = "";
|
|
12924
|
+
for (const token of mergeSpacedAreas(raw2)) {
|
|
12925
|
+
if (token.kind !== "ref" && !(token.kind === "name" && token.prefix)) {
|
|
12926
|
+
literal2 += token.text;
|
|
12927
|
+
continue;
|
|
12928
|
+
}
|
|
12929
|
+
if (literal2) template.push(literal2);
|
|
12930
|
+
literal2 = "";
|
|
12931
|
+
const part = { kind: token.kind, text: token.text };
|
|
12932
|
+
if (token.prefix) {
|
|
12933
|
+
part.prefix = token.prefix;
|
|
12934
|
+
if (token.prefix.book === void 0) part.sheet = token.prefix.sheet.toLowerCase();
|
|
12935
|
+
}
|
|
12936
|
+
if (token.ref) part.ref = token.ref;
|
|
12937
|
+
if (token.spill) part.spill = true;
|
|
12938
|
+
template.push(part);
|
|
12959
12939
|
}
|
|
12960
|
-
if (
|
|
12961
|
-
token.text = rewrite(token, next);
|
|
12940
|
+
if (literal2) template.push(literal2);
|
|
12962
12941
|
}
|
|
12963
|
-
|
|
12942
|
+
remember2(formula, template);
|
|
12943
|
+
return template;
|
|
12964
12944
|
}
|
|
12965
|
-
|
|
12966
|
-
|
|
12967
|
-
|
|
12968
|
-
|
|
12969
|
-
|
|
12970
|
-
|
|
12945
|
+
function rewriteTemplate(formula, rewrite2) {
|
|
12946
|
+
const template = templateOf(formula);
|
|
12947
|
+
if (!template) return formula;
|
|
12948
|
+
let next;
|
|
12949
|
+
for (let i2 = 0; i2 < template.length; i2++) {
|
|
12950
|
+
const part = template[i2];
|
|
12951
|
+
if (typeof part === "string") continue;
|
|
12952
|
+
const changed = rewrite2(part);
|
|
12953
|
+
if (!changed) continue;
|
|
12954
|
+
next ??= template.slice();
|
|
12955
|
+
next[i2] = changed;
|
|
12956
|
+
}
|
|
12957
|
+
if (!next) return formula;
|
|
12958
|
+
const text2 = next.map((part) => typeof part === "string" ? part : part.text).join("");
|
|
12959
|
+
remember2(text2, next);
|
|
12960
|
+
return text2;
|
|
12961
|
+
}
|
|
12962
|
+
function shiftInterval(a2, b, at2, count2, max) {
|
|
12963
|
+
if (count2 > 0) {
|
|
12964
|
+
const na2 = a2 >= at2 ? a2 + count2 : a2;
|
|
12965
|
+
const nb2 = b >= at2 ? b + count2 : b;
|
|
12966
|
+
if (nb2 > max) return na2 > max ? void 0 : [na2, max];
|
|
12967
|
+
return [na2, nb2];
|
|
12968
|
+
}
|
|
12969
|
+
const n = -count2;
|
|
12970
|
+
const last = at2 + n - 1;
|
|
12971
|
+
if (a2 >= at2 && b <= last) return void 0;
|
|
12972
|
+
const na = a2 < at2 ? a2 : a2 <= last ? at2 : a2 - n;
|
|
12973
|
+
const nb = b < at2 ? b : b <= last ? at2 - 1 : b - n;
|
|
12974
|
+
return [na, nb];
|
|
12975
|
+
}
|
|
12976
|
+
function shiftRef(ref, spec2) {
|
|
12977
|
+
const isRow = spec2.axis === "row";
|
|
12978
|
+
if (isRow && ref.kind === "cols" || !isRow && ref.kind === "rows") return ref;
|
|
12979
|
+
const startFirst = isRow ? ref.start.row <= ref.end.row : ref.start.col <= ref.end.col;
|
|
12980
|
+
const lo = startFirst ? ref.start : ref.end;
|
|
12981
|
+
const hi = startFirst ? ref.end : ref.start;
|
|
12982
|
+
const shifted2 = shiftInterval(
|
|
12983
|
+
isRow ? lo.row : lo.col,
|
|
12984
|
+
isRow ? hi.row : hi.col,
|
|
12985
|
+
spec2.at,
|
|
12986
|
+
spec2.count,
|
|
12987
|
+
isRow ? MAX_ROW : MAX_COL
|
|
12988
|
+
);
|
|
12989
|
+
if (!shifted2) return void 0;
|
|
12990
|
+
const [a2, b] = shifted2;
|
|
12991
|
+
const nlo = isRow ? { ...lo, row: a2 } : { ...lo, col: a2 };
|
|
12992
|
+
const nhi = isRow ? { ...hi, row: b } : { ...hi, col: b };
|
|
12993
|
+
const next = {
|
|
12994
|
+
kind: ref.kind,
|
|
12995
|
+
start: startFirst ? nlo : nhi,
|
|
12996
|
+
end: startFirst ? nhi : nlo
|
|
12997
|
+
};
|
|
12998
|
+
if (ref.kind === "cell") next.end = next.start;
|
|
12999
|
+
return sameSpec(next, ref) ? ref : next;
|
|
13000
|
+
}
|
|
13001
|
+
function shiftFormula(formula, formulaSheet, spec2) {
|
|
13002
|
+
if (spec2.count === 0) return formula;
|
|
13003
|
+
const sheet = spec2.sheet.toLowerCase();
|
|
13004
|
+
const own = formulaSheet.toLowerCase() === sheet;
|
|
13005
|
+
return rewriteTemplate(formula, (part) => {
|
|
13006
|
+
if (part.kind !== "ref" || !part.ref || (part.prefix ? part.sheet !== sheet : !own))
|
|
13007
|
+
return void 0;
|
|
13008
|
+
const next = shiftRef(part.ref, spec2);
|
|
13009
|
+
if (next === part.ref) return void 0;
|
|
13010
|
+
const out = { kind: "ref", text: rewriteRef(part, next) };
|
|
13011
|
+
if (part.prefix) out.prefix = part.prefix;
|
|
13012
|
+
if (part.sheet !== void 0) out.sheet = part.sheet;
|
|
13013
|
+
if (next) out.ref = next;
|
|
13014
|
+
if (part.spill) out.spill = true;
|
|
13015
|
+
return out;
|
|
13016
|
+
});
|
|
12971
13017
|
}
|
|
12972
13018
|
function renameSheetInFormula(formula, oldName, newName) {
|
|
12973
|
-
const tokens3 = safeTokens(formula);
|
|
12974
|
-
if (!tokens3) return formula;
|
|
12975
13019
|
const lower2 = oldName.toLowerCase();
|
|
12976
|
-
|
|
12977
|
-
const prefix =
|
|
12978
|
-
if (!prefix ||
|
|
12979
|
-
const first3 =
|
|
13020
|
+
return rewriteTemplate(formula, (part) => {
|
|
13021
|
+
const prefix = part.prefix;
|
|
13022
|
+
if (!prefix || part.sheet === void 0) return void 0;
|
|
13023
|
+
const first3 = part.sheet === lower2;
|
|
12980
13024
|
const second = prefix.sheet2?.toLowerCase() === lower2;
|
|
12981
|
-
if (!first3 && !second)
|
|
13025
|
+
if (!first3 && !second) return void 0;
|
|
12982
13026
|
const renamed = { ...prefix, sheet: first3 ? newName : prefix.sheet };
|
|
12983
13027
|
if (prefix.sheet2 !== void 0) renamed.sheet2 = second ? newName : prefix.sheet2;
|
|
12984
13028
|
const text2 = prefixText(renamed);
|
|
12985
|
-
token.text = text2 + token.text.slice(prefix.text.length);
|
|
12986
13029
|
renamed.text = text2;
|
|
12987
|
-
|
|
13030
|
+
const out = { ...part, text: text2 + part.text.slice(prefix.text.length) };
|
|
13031
|
+
out.prefix = renamed;
|
|
13032
|
+
out.sheet = renamed.sheet.toLowerCase();
|
|
13033
|
+
return out;
|
|
13034
|
+
});
|
|
13035
|
+
}
|
|
13036
|
+
|
|
13037
|
+
// xlsx/formula/transform.ts
|
|
13038
|
+
function translateFormula(formula, dRow, dCol) {
|
|
13039
|
+
const tokens3 = safeTokens(formula);
|
|
13040
|
+
if (!tokens3) return formula;
|
|
13041
|
+
for (const token of tokens3) {
|
|
13042
|
+
if (token.kind !== "ref" || !token.ref) continue;
|
|
13043
|
+
const spec2 = token.ref;
|
|
13044
|
+
const move = (c2) => {
|
|
13045
|
+
const row2 = spec2.kind === "cols" || c2.rowAbs ? c2.row : c2.row + dRow;
|
|
13046
|
+
const col = spec2.kind === "rows" || c2.colAbs ? c2.col : c2.col + dCol;
|
|
13047
|
+
if (row2 < 0 || row2 > MAX_ROW || col < 0 || col > MAX_COL) return void 0;
|
|
13048
|
+
return { ...c2, row: row2, col };
|
|
13049
|
+
};
|
|
13050
|
+
const start = move(spec2.start);
|
|
13051
|
+
const end = move(spec2.end);
|
|
13052
|
+
const next = start && end ? { kind: spec2.kind, start, end } : void 0;
|
|
13053
|
+
if (next && sameSpec(next, spec2)) continue;
|
|
13054
|
+
token.text = rewriteRef(token, next);
|
|
12988
13055
|
}
|
|
12989
13056
|
return joinTokens(tokens3);
|
|
12990
13057
|
}
|
|
@@ -13054,14 +13121,14 @@ function fromStoredSyntax(formula) {
|
|
|
13054
13121
|
if (name !== "ANCHORARRAY" && name !== "SINGLE") continue;
|
|
13055
13122
|
const open = nextIndex(list, i2 + 1);
|
|
13056
13123
|
const arg = nextIndex(list, open + 1);
|
|
13057
|
-
const
|
|
13124
|
+
const close2 = nextIndex(list, arg + 1);
|
|
13058
13125
|
const target = list[arg];
|
|
13059
|
-
if (list[open]?.kind !== "open" || list[
|
|
13126
|
+
if (list[open]?.kind !== "open" || list[close2]?.kind !== "close" || !target) continue;
|
|
13060
13127
|
const single = target.kind === "ref" || target.kind === "name" || target.kind === "structured";
|
|
13061
13128
|
if (name === "ANCHORARRAY" && !(target.kind === "ref" && target.ref?.kind === "cell")) continue;
|
|
13062
13129
|
if (name === "SINGLE" && !single) continue;
|
|
13063
13130
|
const text2 = name === "ANCHORARRAY" ? `${target.text}#` : `@${target.text}`;
|
|
13064
|
-
for (let k = i2; k <=
|
|
13131
|
+
for (let k = i2; k <= close2; k++) list[k].text = "";
|
|
13065
13132
|
token.text = text2;
|
|
13066
13133
|
changed = true;
|
|
13067
13134
|
}
|
|
@@ -13073,7 +13140,7 @@ var FUTURE_FUNCTIONS = new Set(
|
|
|
13073
13140
|
"AGGREGATE BETA.DIST BETA.INV BINOM.DIST BINOM.INV CEILING.PRECISE CHISQ.DIST CHISQ.DIST.RT CHISQ.INV CHISQ.INV.RT CHISQ.TEST CONFIDENCE.NORM CONFIDENCE.T COVARIANCE.P COVARIANCE.S ERF.PRECISE ERFC.PRECISE EXPON.DIST F.DIST F.DIST.RT F.INV F.INV.RT F.TEST FLOOR.PRECISE GAMMA.DIST GAMMA.INV GAMMALN.PRECISE HYPGEOM.DIST LOGNORM.DIST LOGNORM.INV MODE.MULT MODE.SNGL NEGBINOM.DIST NETWORKDAYS.INTL NORM.DIST NORM.INV NORM.S.DIST NORM.S.INV PERCENTILE.EXC PERCENTILE.INC PERCENTRANK.EXC PERCENTRANK.INC POISSON.DIST QUARTILE.EXC QUARTILE.INC RANK.AVG RANK.EQ STDEV.P STDEV.S T.DIST T.DIST.2T T.DIST.RT T.INV T.INV.2T T.TEST VAR.P VAR.S WEIBULL.DIST WORKDAY.INTL ACOT ACOTH ARABIC BASE BINOM.DIST.RANGE BITAND BITLSHIFT BITOR BITRSHIFT BITXOR CEILING.MATH COMBINA COT COTH CSC CSCH DAYS DECIMAL ENCODEURL FILTERXML FLOOR.MATH FORMULATEXT GAMMA GAUSS IFNA IMCOSH IMCOT IMCSC IMCSCH IMSEC IMSECH IMSINH IMTAN ISFORMULA ISOWEEKNUM MUNIT NUMBERVALUE PDURATION PERMUTATIONA PHI RRI SEC SECH SHEET SHEETS SKEW.P UNICHAR UNICODE WEBSERVICE XOR CONCAT FORECAST.ETS FORECAST.ETS.CONFINT FORECAST.ETS.SEASONALITY FORECAST.ETS.STAT FORECAST.LINEAR IFS MAXIFS MINIFS SWITCH TEXTJOIN XLOOKUP XMATCH FILTER SORT SORTBY UNIQUE SEQUENCE RANDARRAY LET LAMBDA TEXTBEFORE TEXTAFTER TEXTSPLIT VSTACK HSTACK TAKE DROP CHOOSEROWS CHOOSECOLS TOCOL TOROW WRAPROWS WRAPCOLS EXPAND ARRAYTOTEXT VALUETOTEXT ISOMITTED BYROW BYCOL MAP REDUCE SCAN MAKEARRAY IMAGE GROUPBY PIVOTBY PERCENTOF REGEXTEST REGEXEXTRACT REGEXREPLACE TRIMRANGE ANCHORARRAY SINGLE STOCKHISTORY FIELDVALUE".split(" ")
|
|
13074
13141
|
);
|
|
13075
13142
|
var WORKSHEET_PREFIXED = /* @__PURE__ */ new Set(["FILTER", "SORT"]);
|
|
13076
|
-
function
|
|
13143
|
+
function rewrite(formula, visit2) {
|
|
13077
13144
|
const out = [];
|
|
13078
13145
|
let i2 = 0;
|
|
13079
13146
|
while (i2 < formula.length) {
|
|
@@ -13116,7 +13183,7 @@ function rewrite2(formula, visit2) {
|
|
|
13116
13183
|
}
|
|
13117
13184
|
function stripFuturePrefixes(formula) {
|
|
13118
13185
|
if (!formula.includes("_xl")) return formula;
|
|
13119
|
-
const plain2 =
|
|
13186
|
+
const plain2 = rewrite(formula, (token, next, out) => {
|
|
13120
13187
|
if (!next.startsWith("(")) return false;
|
|
13121
13188
|
const stripped = token.replace(/^(_xlfn\.)?(_xlws\.)?/i, "");
|
|
13122
13189
|
if (stripped === token) return false;
|
|
@@ -13126,7 +13193,7 @@ function stripFuturePrefixes(formula) {
|
|
|
13126
13193
|
return fromStoredSyntax(plain2);
|
|
13127
13194
|
}
|
|
13128
13195
|
function addFuturePrefixes(formula) {
|
|
13129
|
-
return
|
|
13196
|
+
return rewrite(toStoredSyntax(formula), (token, next, out) => {
|
|
13130
13197
|
if (!next.startsWith("(")) return false;
|
|
13131
13198
|
const upper2 = token.toUpperCase();
|
|
13132
13199
|
if (!FUTURE_FUNCTIONS.has(upper2)) return false;
|
|
@@ -13779,13 +13846,13 @@ function dataBarLengths(rule2, node) {
|
|
|
13779
13846
|
maxLength: rule2.maxLength ?? numAttr(bar, "maxLength") ?? 90
|
|
13780
13847
|
};
|
|
13781
13848
|
}
|
|
13782
|
-
function rewriteConditionalExtension(rule2,
|
|
13849
|
+
function rewriteConditionalExtension(rule2, rewrite2) {
|
|
13783
13850
|
if (!rule2.extensionXml) return;
|
|
13784
13851
|
const doc = parseXml(rule2.extensionXml);
|
|
13785
13852
|
let changed = false;
|
|
13786
13853
|
for (const formula of descendants3(doc.documentElement, "f", XM)) {
|
|
13787
13854
|
const before = formula.textContent ?? "";
|
|
13788
|
-
const next =
|
|
13855
|
+
const next = rewrite2(before);
|
|
13789
13856
|
if (before !== next) {
|
|
13790
13857
|
formula.textContent = next;
|
|
13791
13858
|
changed = true;
|
|
@@ -14409,12 +14476,12 @@ function splitSheetData(xml) {
|
|
|
14409
14476
|
if (openEnd < 0) return void 0;
|
|
14410
14477
|
const attributes = xml.slice(open.index + tagName2.length + 1, openEnd);
|
|
14411
14478
|
if (attributes.trimEnd().endsWith("/") || attributes.includes("xmlns")) return void 0;
|
|
14412
|
-
const
|
|
14413
|
-
if (
|
|
14479
|
+
const close2 = xml.indexOf(`</${tagName2}`, openEnd);
|
|
14480
|
+
if (close2 < 0 || OPEN.test(xml.slice(openEnd))) return void 0;
|
|
14414
14481
|
const container = new LiteElement(tagName2, "sheetData", ns || null);
|
|
14415
|
-
const data = parseLiteFragment(xml.slice(openEnd + 1,
|
|
14482
|
+
const data = parseLiteFragment(xml.slice(openEnd + 1, close2), container, namespaces);
|
|
14416
14483
|
if (!data) return void 0;
|
|
14417
|
-
return { xml: xml.slice(0, openEnd + 1) + xml.slice(
|
|
14484
|
+
return { xml: xml.slice(0, openEnd + 1) + xml.slice(close2), sheetData: data.asElement() };
|
|
14418
14485
|
}
|
|
14419
14486
|
|
|
14420
14487
|
// xlsx/read/print-options.ts
|
|
@@ -14957,10 +15024,10 @@ function hls240ToRgb({ h: h2, l, s }) {
|
|
|
14957
15024
|
var parseHex = parseArgbHex;
|
|
14958
15025
|
var toHexColor = rgbToUpperHex;
|
|
14959
15026
|
function applyTint(hex, tint) {
|
|
14960
|
-
const
|
|
14961
|
-
if (!tint) return toHexColor(
|
|
15027
|
+
const rgb3 = parseHex(hex) ?? [0, 0, 0];
|
|
15028
|
+
if (!tint) return toHexColor(rgb3);
|
|
14962
15029
|
const t = Math.max(-1, Math.min(1, tint));
|
|
14963
|
-
const hls = rgbToHls240(...
|
|
15030
|
+
const hls = rgbToHls240(...rgb3);
|
|
14964
15031
|
const l = t < 0 ? Math.trunc(hls.l * (1 + t)) : Math.round(hls.l * (1 - t) + HLSMAX * t);
|
|
14965
15032
|
return toHexColor(hls240ToRgb({ ...hls, l: Math.max(0, Math.min(HLSMAX, l)) }));
|
|
14966
15033
|
}
|
|
@@ -17018,7 +17085,9 @@ var PREC_INTERSECT = 9;
|
|
|
17018
17085
|
var PREC_RANGE = 10;
|
|
17019
17086
|
var OPERAND_START = /* @__PURE__ */ new Set(["ref", "name", "func", "open", "structured"]);
|
|
17020
17087
|
function parseFormula(formula) {
|
|
17021
|
-
|
|
17088
|
+
return parseTokens(tokenize(formula));
|
|
17089
|
+
}
|
|
17090
|
+
function parseTokens(all2) {
|
|
17022
17091
|
const tokens3 = [];
|
|
17023
17092
|
const wsBefore = [];
|
|
17024
17093
|
let sawWs = false;
|
|
@@ -17359,6 +17428,222 @@ function localDateToSerial(date, date1904 = date1904Mode) {
|
|
|
17359
17428
|
return base + (utc - dayStart) / DAY_MS2;
|
|
17360
17429
|
}
|
|
17361
17430
|
|
|
17431
|
+
// xlsx/formula/area-index.ts
|
|
17432
|
+
var BUCKET_WIDTH = 64;
|
|
17433
|
+
var CHUNK_SHIFT = 6;
|
|
17434
|
+
var CHUNKS = 64;
|
|
17435
|
+
function push(map, key2, value) {
|
|
17436
|
+
const list = map.get(key2);
|
|
17437
|
+
if (list) list.push(value);
|
|
17438
|
+
else map.set(key2, [value]);
|
|
17439
|
+
}
|
|
17440
|
+
function inner(map, sheet) {
|
|
17441
|
+
let found = map.get(sheet);
|
|
17442
|
+
if (!found) map.set(sheet, found = /* @__PURE__ */ new Map());
|
|
17443
|
+
return found;
|
|
17444
|
+
}
|
|
17445
|
+
var AreaIndex = class {
|
|
17446
|
+
cells = /* @__PURE__ */ new Map();
|
|
17447
|
+
chunked = /* @__PURE__ */ new Map();
|
|
17448
|
+
tall = /* @__PURE__ */ new Map();
|
|
17449
|
+
wide = /* @__PURE__ */ new Map();
|
|
17450
|
+
add(area, node) {
|
|
17451
|
+
const { start, end } = area.range;
|
|
17452
|
+
if (start.row === end.row && end.col - start.col + 1 <= BUCKET_WIDTH) {
|
|
17453
|
+
const cells3 = inner(this.cells, area.sheet);
|
|
17454
|
+
for (let col = start.col; col <= end.col; col++) push(cells3, cellKey(start.row, col), node);
|
|
17455
|
+
return;
|
|
17456
|
+
}
|
|
17457
|
+
const entry3 = { range: area.range, node };
|
|
17458
|
+
if (end.col - start.col + 1 > BUCKET_WIDTH) {
|
|
17459
|
+
const list = this.wide.get(area.sheet);
|
|
17460
|
+
if (list) list.push(entry3);
|
|
17461
|
+
else this.wide.set(area.sheet, [entry3]);
|
|
17462
|
+
return;
|
|
17463
|
+
}
|
|
17464
|
+
const first3 = start.row >> CHUNK_SHIFT;
|
|
17465
|
+
const last = end.row >> CHUNK_SHIFT;
|
|
17466
|
+
if (last - first3 + 1 > CHUNKS) {
|
|
17467
|
+
const cols2 = inner(this.tall, area.sheet);
|
|
17468
|
+
for (let c2 = start.col; c2 <= end.col; c2++) push(cols2, c2, entry3);
|
|
17469
|
+
return;
|
|
17470
|
+
}
|
|
17471
|
+
const cols = inner(this.chunked, area.sheet);
|
|
17472
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
17473
|
+
let chunks = cols.get(c2);
|
|
17474
|
+
if (!chunks) cols.set(c2, chunks = /* @__PURE__ */ new Map());
|
|
17475
|
+
for (let k = first3; k <= last; k++) push(chunks, k, entry3);
|
|
17476
|
+
}
|
|
17477
|
+
}
|
|
17478
|
+
/** Items whose areas intersect `range` on `sheet` (each once). */
|
|
17479
|
+
dependents(sheet, range, out) {
|
|
17480
|
+
const found = out instanceof Set ? out : /* @__PURE__ */ new Set();
|
|
17481
|
+
this.collect(sheet, range, found);
|
|
17482
|
+
if (Array.isArray(out)) for (const node of found) out.push(node);
|
|
17483
|
+
}
|
|
17484
|
+
collect(sheet, range, out) {
|
|
17485
|
+
const { start, end } = range;
|
|
17486
|
+
const check3 = (list) => {
|
|
17487
|
+
if (list) {
|
|
17488
|
+
for (const entry3 of list) if (rangesIntersect(entry3.range, range)) out.add(entry3.node);
|
|
17489
|
+
}
|
|
17490
|
+
};
|
|
17491
|
+
const cells3 = this.cells.get(sheet);
|
|
17492
|
+
if (cells3) {
|
|
17493
|
+
const size = (end.row - start.row + 1) * (end.col - start.col + 1);
|
|
17494
|
+
if (size <= 4096) {
|
|
17495
|
+
for (let r = start.row; r <= end.row; r++) {
|
|
17496
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
17497
|
+
const list = cells3.get(cellKey(r, c2));
|
|
17498
|
+
if (list) for (const node of list) out.add(node);
|
|
17499
|
+
}
|
|
17500
|
+
}
|
|
17501
|
+
} else {
|
|
17502
|
+
for (const [key2, list] of cells3) {
|
|
17503
|
+
const { row: row2, col } = keyToAddress(key2);
|
|
17504
|
+
if (row2 >= start.row && row2 <= end.row && col >= start.col && col <= end.col)
|
|
17505
|
+
for (const node of list) out.add(node);
|
|
17506
|
+
}
|
|
17507
|
+
}
|
|
17508
|
+
}
|
|
17509
|
+
const columns = (map, visit2) => {
|
|
17510
|
+
if (!map) return;
|
|
17511
|
+
if (end.col - start.col + 1 <= map.size) {
|
|
17512
|
+
for (let c2 = start.col; c2 <= end.col; c2++) if (map.has(c2)) visit2(c2);
|
|
17513
|
+
} else for (const c2 of map.keys()) if (c2 >= start.col && c2 <= end.col) visit2(c2);
|
|
17514
|
+
};
|
|
17515
|
+
const chunked = this.chunked.get(sheet);
|
|
17516
|
+
const first3 = start.row >> CHUNK_SHIFT;
|
|
17517
|
+
const last = end.row >> CHUNK_SHIFT;
|
|
17518
|
+
columns(chunked, (c2) => {
|
|
17519
|
+
const chunks = chunked?.get(c2);
|
|
17520
|
+
if (last - first3 + 1 <= chunks.size) {
|
|
17521
|
+
for (let k = first3; k <= last; k++) check3(chunks.get(k));
|
|
17522
|
+
} else for (const [k, list] of chunks) if (k >= first3 && k <= last) check3(list);
|
|
17523
|
+
});
|
|
17524
|
+
const tall = this.tall.get(sheet);
|
|
17525
|
+
columns(tall, (c2) => check3(tall?.get(c2)));
|
|
17526
|
+
check3(this.wide.get(sheet));
|
|
17527
|
+
}
|
|
17528
|
+
};
|
|
17529
|
+
|
|
17530
|
+
// xlsx/formula/graph-index.ts
|
|
17531
|
+
var ColumnIndex = class {
|
|
17532
|
+
sheets = /* @__PURE__ */ new Map();
|
|
17533
|
+
constructor(nodes) {
|
|
17534
|
+
for (const node of nodes) {
|
|
17535
|
+
let cols = this.sheets.get(node.sheet);
|
|
17536
|
+
if (!cols) this.sheets.set(node.sheet, cols = /* @__PURE__ */ new Map());
|
|
17537
|
+
let list = cols.get(node.col);
|
|
17538
|
+
if (!list) cols.set(node.col, list = []);
|
|
17539
|
+
list.push(node);
|
|
17540
|
+
}
|
|
17541
|
+
for (const cols of this.sheets.values())
|
|
17542
|
+
for (const list of cols.values()) list.sort((a2, b) => a2.row - b.row);
|
|
17543
|
+
}
|
|
17544
|
+
nodesIn(area, out) {
|
|
17545
|
+
const cols = this.sheets.get(area.sheet);
|
|
17546
|
+
if (!cols) return;
|
|
17547
|
+
const { start, end } = area.range;
|
|
17548
|
+
const width = end.col - start.col + 1;
|
|
17549
|
+
const scan3 = (list) => {
|
|
17550
|
+
let lo = 0;
|
|
17551
|
+
let hi = list.length;
|
|
17552
|
+
while (lo < hi) {
|
|
17553
|
+
const mid = lo + hi >> 1;
|
|
17554
|
+
if (list[mid].row < start.row) lo = mid + 1;
|
|
17555
|
+
else hi = mid;
|
|
17556
|
+
}
|
|
17557
|
+
for (let i2 = lo; i2 < list.length; i2++) {
|
|
17558
|
+
const node = list[i2];
|
|
17559
|
+
if (node.row > end.row) break;
|
|
17560
|
+
out.push(node);
|
|
17561
|
+
}
|
|
17562
|
+
};
|
|
17563
|
+
if (width <= cols.size) {
|
|
17564
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
17565
|
+
const list = cols.get(c2);
|
|
17566
|
+
if (list) scan3(list);
|
|
17567
|
+
}
|
|
17568
|
+
} else {
|
|
17569
|
+
for (const [c2, list] of cols) if (c2 >= start.col && c2 <= end.col) scan3(list);
|
|
17570
|
+
}
|
|
17571
|
+
}
|
|
17572
|
+
};
|
|
17573
|
+
var ReverseIndex = class extends AreaIndex {
|
|
17574
|
+
constructor(nodes = []) {
|
|
17575
|
+
super();
|
|
17576
|
+
for (const node of nodes) this.addNode(node);
|
|
17577
|
+
}
|
|
17578
|
+
/** Indexes one more formula's precedents. */
|
|
17579
|
+
addNode(node) {
|
|
17580
|
+
for (const dep of node.deps) this.add(dep, node);
|
|
17581
|
+
for (const dep of node.dynamicDeps) this.add(dep, node);
|
|
17582
|
+
}
|
|
17583
|
+
};
|
|
17584
|
+
|
|
17585
|
+
// xlsx/formula/engine-prepare.ts
|
|
17586
|
+
var CHECK_EVERY = 32;
|
|
17587
|
+
var GraphPreparation = class {
|
|
17588
|
+
constructor(workbook, create) {
|
|
17589
|
+
this.workbook = workbook;
|
|
17590
|
+
this.create = create;
|
|
17591
|
+
}
|
|
17592
|
+
workbook;
|
|
17593
|
+
create;
|
|
17594
|
+
reverse = new ReverseIndex();
|
|
17595
|
+
formulas = { dynamic: [], unvalued: [] };
|
|
17596
|
+
sheet = 0;
|
|
17597
|
+
rows;
|
|
17598
|
+
row = 0;
|
|
17599
|
+
cells;
|
|
17600
|
+
finished = false;
|
|
17601
|
+
/**
|
|
17602
|
+
* Adds formulas to the graph until `timeRemaining` (milliseconds, as an idle deadline reports
|
|
17603
|
+
* them) reaches zero, or until every formula is in. Returns true when the graph is complete.
|
|
17604
|
+
*/
|
|
17605
|
+
run(timeRemaining) {
|
|
17606
|
+
let visited = 0;
|
|
17607
|
+
while (!this.finished) {
|
|
17608
|
+
const cells3 = this.cells ?? this.nextRow();
|
|
17609
|
+
if (!cells3) continue;
|
|
17610
|
+
const next = cells3.next();
|
|
17611
|
+
if (next.done) {
|
|
17612
|
+
this.cells = void 0;
|
|
17613
|
+
continue;
|
|
17614
|
+
}
|
|
17615
|
+
const [col, cell] = next.value;
|
|
17616
|
+
if (cell.formula) this.add(this.create(this.sheet, this.row, col, cell), cell);
|
|
17617
|
+
if (timeRemaining && ++visited % CHECK_EVERY === 0 && timeRemaining() <= 0) break;
|
|
17618
|
+
}
|
|
17619
|
+
return this.finished;
|
|
17620
|
+
}
|
|
17621
|
+
add(node, cell) {
|
|
17622
|
+
this.reverse.addNode(node);
|
|
17623
|
+
if (!node.legacy && !node.arrayRange) this.formulas.dynamic.push(node);
|
|
17624
|
+
if (cell.value === null && !node.keepCached) this.formulas.unvalued.push(node);
|
|
17625
|
+
}
|
|
17626
|
+
/** Moves to the next stored row (and sheet), or marks the walk finished. */
|
|
17627
|
+
nextRow() {
|
|
17628
|
+
for (; ; ) {
|
|
17629
|
+
const sheet = this.workbook.sheets[this.sheet];
|
|
17630
|
+
if (!sheet) {
|
|
17631
|
+
this.finished = true;
|
|
17632
|
+
return void 0;
|
|
17633
|
+
}
|
|
17634
|
+
this.rows ??= sheet.rows.entries();
|
|
17635
|
+
const next = this.rows.next();
|
|
17636
|
+
if (!next.done) {
|
|
17637
|
+
this.row = next.value[0];
|
|
17638
|
+
this.cells = next.value[1].entries();
|
|
17639
|
+
return this.cells;
|
|
17640
|
+
}
|
|
17641
|
+
this.rows = void 0;
|
|
17642
|
+
this.sheet++;
|
|
17643
|
+
}
|
|
17644
|
+
}
|
|
17645
|
+
};
|
|
17646
|
+
|
|
17362
17647
|
// xlsx/formula/text-number.ts
|
|
17363
17648
|
var MONTHS2 = [
|
|
17364
17649
|
"jan",
|
|
@@ -20493,8 +20778,10 @@ var FINANCIAL_FUNCTIONS = [
|
|
|
20493
20778
|
|
|
20494
20779
|
// xlsx/formula/references.ts
|
|
20495
20780
|
function sheetIndex(host, name) {
|
|
20781
|
+
const sheets = host.workbook.sheets;
|
|
20782
|
+
for (let i2 = 0; i2 < sheets.length; i2++) if (sheets[i2]?.name === name) return i2;
|
|
20496
20783
|
const lower2 = name.toLowerCase();
|
|
20497
|
-
return
|
|
20784
|
+
return sheets.findIndex((sheet) => sheet.name.toLowerCase() === lower2);
|
|
20498
20785
|
}
|
|
20499
20786
|
function prefixSheets(host, prefix, current) {
|
|
20500
20787
|
if (!prefix) return [current];
|
|
@@ -22108,9 +22395,9 @@ function readBlock(ctx, area, rows, cols) {
|
|
|
22108
22395
|
if (host.readBlock) return host.readBlock(area.sheet, range);
|
|
22109
22396
|
return Matrix.build(rows, cols, (r, c2) => ctx.readCell(area.sheet, row2 + r, col + c2));
|
|
22110
22397
|
}
|
|
22111
|
-
function shapedMatrices(ctx, values2,
|
|
22398
|
+
function shapedMatrices(ctx, values2, sameShape2) {
|
|
22112
22399
|
let { rows, cols } = shapeOf(values2[0] ?? null);
|
|
22113
|
-
if (
|
|
22400
|
+
if (sameShape2) {
|
|
22114
22401
|
for (const value of values2) {
|
|
22115
22402
|
const shape2 = shapeOf(value);
|
|
22116
22403
|
if (shape2.rows !== rows || shape2.cols !== cols) fail(ERR.VALUE);
|
|
@@ -22136,12 +22423,12 @@ function shapedMatrices(ctx, values2, sameShape) {
|
|
|
22136
22423
|
});
|
|
22137
22424
|
return { matrices, total: total2, block: rows * cols };
|
|
22138
22425
|
}
|
|
22139
|
-
function matchingCells(ctx, pairs, target,
|
|
22426
|
+
function matchingCells(ctx, pairs, target, sameShape2) {
|
|
22140
22427
|
const ranges = pairs.map((p) => p.range);
|
|
22141
22428
|
const { matrices, total: total2, block } = shapedMatrices(
|
|
22142
22429
|
ctx,
|
|
22143
22430
|
target === void 0 ? ranges : [...ranges, target],
|
|
22144
|
-
|
|
22431
|
+
sameShape2
|
|
22145
22432
|
);
|
|
22146
22433
|
const tests = pairs.map((p) => makeCriteria(scalar(p.criteria)));
|
|
22147
22434
|
const values2 = matrices[matrices.length - 1];
|
|
@@ -22180,7 +22467,7 @@ function indexedCandidates(pairs, matrices) {
|
|
|
22180
22467
|
}
|
|
22181
22468
|
return void 0;
|
|
22182
22469
|
}
|
|
22183
|
-
var matchingValues = (ctx, pairs, target,
|
|
22470
|
+
var matchingValues = (ctx, pairs, target, sameShape2) => matchingCells(ctx, pairs, target, sameShape2).values;
|
|
22184
22471
|
function criteriaPairs(args, from) {
|
|
22185
22472
|
if ((args.length - from) % 2 !== 0) fail(ERR.VALUE);
|
|
22186
22473
|
const pairs = [];
|
|
@@ -26074,7 +26361,7 @@ var REFERENCE_ARGUMENT = /* @__PURE__ */ new Set([
|
|
|
26074
26361
|
"AREAS",
|
|
26075
26362
|
"ISREF"
|
|
26076
26363
|
]);
|
|
26077
|
-
var
|
|
26364
|
+
var push2 = (c2, area) => {
|
|
26078
26365
|
(c2.dynamic > 0 ? c2.dynamicDeps : c2.deps).push(area);
|
|
26079
26366
|
};
|
|
26080
26367
|
function spans(areas) {
|
|
@@ -26100,7 +26387,7 @@ function visit(node, c2) {
|
|
|
26100
26387
|
if (!sheets) return;
|
|
26101
26388
|
const range = specRange(node.ref);
|
|
26102
26389
|
const target = node.spill ? { start: range.start, end: { ...range.start } } : range;
|
|
26103
|
-
for (const sheet of sheets)
|
|
26390
|
+
for (const sheet of sheets) push2(c2, { sheet, range: target });
|
|
26104
26391
|
return;
|
|
26105
26392
|
}
|
|
26106
26393
|
case "name": {
|
|
@@ -26174,7 +26461,7 @@ function visitBinary(node, c2) {
|
|
|
26174
26461
|
const list = c2.dynamic > 0 ? c2.dynamicDeps : c2.deps;
|
|
26175
26462
|
const l = list[list.length - 2];
|
|
26176
26463
|
const r = list[list.length - 1];
|
|
26177
|
-
if (l && r && l.sheet === r.sheet)
|
|
26464
|
+
if (l && r && l.sheet === r.sheet) push2(c2, spans([l, r])[0]);
|
|
26178
26465
|
continue;
|
|
26179
26466
|
}
|
|
26180
26467
|
const mentioned = [...c2.deps.slice(staticStart), ...c2.dynamicDeps.slice(dynamicStart)];
|
|
@@ -26190,7 +26477,7 @@ function addStructured(ref, c2) {
|
|
|
26190
26477
|
sheet: c2.sheet,
|
|
26191
26478
|
row: c2.row,
|
|
26192
26479
|
col: c2.col});
|
|
26193
|
-
if (value instanceof RefValue) for (const area of value.areas)
|
|
26480
|
+
if (value instanceof RefValue) for (const area of value.areas) push2(c2, area);
|
|
26194
26481
|
}
|
|
26195
26482
|
function analyze(ast, host, sheet, row2, col) {
|
|
26196
26483
|
const c2 = {
|
|
@@ -26214,155 +26501,191 @@ function analyze(ast, host, sheet, row2, col) {
|
|
|
26214
26501
|
};
|
|
26215
26502
|
}
|
|
26216
26503
|
|
|
26217
|
-
// xlsx/formula/
|
|
26218
|
-
var
|
|
26219
|
-
|
|
26220
|
-
|
|
26221
|
-
|
|
26222
|
-
|
|
26223
|
-
|
|
26224
|
-
|
|
26504
|
+
// xlsx/formula/formula-shape.ts
|
|
26505
|
+
var isDigit4 = (code) => code >= 48 && code <= 57;
|
|
26506
|
+
function formulaShape(formula) {
|
|
26507
|
+
const starts = [];
|
|
26508
|
+
const ends = [];
|
|
26509
|
+
let hash = 2166136261;
|
|
26510
|
+
for (let i2 = 0; i2 < formula.length; i2++) {
|
|
26511
|
+
let code = formula.charCodeAt(i2);
|
|
26512
|
+
if (isDigit4(code)) {
|
|
26513
|
+
let j = i2 + 1;
|
|
26514
|
+
while (j < formula.length && isDigit4(formula.charCodeAt(j))) j++;
|
|
26515
|
+
starts.push(i2);
|
|
26516
|
+
ends.push(j);
|
|
26517
|
+
i2 = j - 1;
|
|
26518
|
+
code = 0;
|
|
26519
|
+
}
|
|
26520
|
+
hash = Math.imul(hash ^ code, 16777619);
|
|
26521
|
+
}
|
|
26522
|
+
return { hash: hash >>> 0, starts, ends };
|
|
26225
26523
|
}
|
|
26226
|
-
function
|
|
26227
|
-
let
|
|
26228
|
-
|
|
26229
|
-
return
|
|
26524
|
+
function sameText(a2, from, b, at2, length) {
|
|
26525
|
+
for (let k = 0; k < length; k++)
|
|
26526
|
+
if (a2.charCodeAt(from + k) !== b.charCodeAt(at2 + k)) return false;
|
|
26527
|
+
return true;
|
|
26230
26528
|
}
|
|
26231
|
-
|
|
26232
|
-
|
|
26233
|
-
|
|
26234
|
-
|
|
26235
|
-
|
|
26236
|
-
|
|
26237
|
-
const
|
|
26238
|
-
|
|
26239
|
-
|
|
26240
|
-
|
|
26241
|
-
|
|
26529
|
+
function sameShape(a2, as, b, bs) {
|
|
26530
|
+
const runs = as.starts.length;
|
|
26531
|
+
if (runs !== bs.starts.length) return false;
|
|
26532
|
+
let fromA = 0;
|
|
26533
|
+
let fromB = 0;
|
|
26534
|
+
for (let i2 = 0; i2 <= runs; i2++) {
|
|
26535
|
+
const toA = i2 < runs ? as.starts[i2] : a2.length;
|
|
26536
|
+
const toB = i2 < runs ? bs.starts[i2] : b.length;
|
|
26537
|
+
if (toA - fromA !== toB - fromB || !sameText(a2, fromA, b, fromB, toA - fromA)) return false;
|
|
26538
|
+
fromA = as.ends[i2] ?? 0;
|
|
26539
|
+
fromB = bs.ends[i2] ?? 0;
|
|
26540
|
+
}
|
|
26541
|
+
return true;
|
|
26542
|
+
}
|
|
26543
|
+
function makeTemplate(formula, shape2) {
|
|
26544
|
+
let tokens3;
|
|
26545
|
+
let ast;
|
|
26546
|
+
try {
|
|
26547
|
+
tokens3 = tokenize(formula);
|
|
26548
|
+
ast = parseTokens(tokens3);
|
|
26549
|
+
} catch (e) {
|
|
26550
|
+
if (e instanceof RangeError) return new FormulaError(e.message, -1, "#VALUE!");
|
|
26551
|
+
if (e instanceof FormulaError) return e;
|
|
26552
|
+
throw e;
|
|
26553
|
+
}
|
|
26554
|
+
const { starts } = shape2;
|
|
26555
|
+
const slotted = starts.map(() => false);
|
|
26556
|
+
const refs = /* @__PURE__ */ new Map();
|
|
26557
|
+
let run2 = 0;
|
|
26558
|
+
for (const token of tokens3) {
|
|
26559
|
+
const end = token.start + token.text.length;
|
|
26560
|
+
const first3 = run2;
|
|
26561
|
+
while (run2 < starts.length && starts[run2] < end) run2++;
|
|
26562
|
+
const ref = token.kind === "ref" ? token.ref : void 0;
|
|
26563
|
+
if (!ref || ref.kind === "cols") continue;
|
|
26564
|
+
const count2 = ref.kind === "cell" ? 1 : 2;
|
|
26565
|
+
if (run2 - first3 < count2) continue;
|
|
26566
|
+
const at2 = run2 - count2;
|
|
26567
|
+
const indexes2 = count2 === 1 ? [at2] : [at2, at2 + 1];
|
|
26568
|
+
if (indexes2.some((i2) => formula.charCodeAt(starts[i2]) === 48)) continue;
|
|
26569
|
+
for (const i2 of indexes2) slotted[i2] = true;
|
|
26570
|
+
refs.set(ref, count2 === 1 ? { start: at2 } : { start: at2, end: at2 + 1 });
|
|
26571
|
+
}
|
|
26572
|
+
return { formula, shape: shape2, ast, slotted, refs };
|
|
26573
|
+
}
|
|
26574
|
+
function rowsFor(t, formula, shape2) {
|
|
26575
|
+
if (!sameShape(t.formula, t.shape, formula, shape2)) return void 0;
|
|
26576
|
+
const rows = [];
|
|
26577
|
+
for (let i2 = 0; i2 < shape2.starts.length; i2++) {
|
|
26578
|
+
const start = shape2.starts[i2];
|
|
26579
|
+
const length = shape2.ends[i2] - start;
|
|
26580
|
+
if (!t.slotted[i2]) {
|
|
26581
|
+
const own = t.shape.starts[i2];
|
|
26582
|
+
if (t.shape.ends[i2] - own !== length) return void 0;
|
|
26583
|
+
if (!sameText(t.formula, own, formula, start, length)) return void 0;
|
|
26584
|
+
rows.push(-1);
|
|
26585
|
+
continue;
|
|
26242
26586
|
}
|
|
26243
|
-
|
|
26244
|
-
|
|
26245
|
-
|
|
26246
|
-
|
|
26247
|
-
|
|
26248
|
-
|
|
26587
|
+
if (length > 7 || formula.charCodeAt(start) === 48) return void 0;
|
|
26588
|
+
let row2 = 0;
|
|
26589
|
+
for (let k = start; k < start + length; k++) row2 = row2 * 10 + formula.charCodeAt(k) - 48;
|
|
26590
|
+
if (row2 < 1 || row2 > MAX_ROW + 1) return void 0;
|
|
26591
|
+
rows.push(row2 - 1);
|
|
26592
|
+
}
|
|
26593
|
+
return rows;
|
|
26594
|
+
}
|
|
26595
|
+
function shiftSpec(spec2, slots, rows) {
|
|
26596
|
+
const startRow = rows[slots.start];
|
|
26597
|
+
const endRow = slots.end === void 0 ? startRow : rows[slots.end];
|
|
26598
|
+
if (startRow === spec2.start.row && endRow === spec2.end.row) return spec2;
|
|
26599
|
+
const { start: from, end: to } = spec2;
|
|
26600
|
+
const start = { row: startRow, col: from.col, rowAbs: from.rowAbs, colAbs: from.colAbs };
|
|
26601
|
+
if (slots.end === void 0) return { kind: spec2.kind, start, end: start };
|
|
26602
|
+
const end = { row: endRow, col: to.col, rowAbs: to.rowAbs, colAbs: to.colAbs };
|
|
26603
|
+
return { kind: spec2.kind, start, end };
|
|
26604
|
+
}
|
|
26605
|
+
function copyTree(node, t, rows) {
|
|
26606
|
+
switch (node.type) {
|
|
26607
|
+
case "ref": {
|
|
26608
|
+
const slots = node.ref ? t.refs.get(node.ref) : void 0;
|
|
26609
|
+
if (!slots || !node.ref) return node;
|
|
26610
|
+
const ref = shiftSpec(node.ref, slots, rows);
|
|
26611
|
+
if (ref === node.ref) return node;
|
|
26612
|
+
const copy2 = { type: "ref" };
|
|
26613
|
+
if (node.prefix) copy2.prefix = node.prefix;
|
|
26614
|
+
copy2.ref = ref;
|
|
26615
|
+
if (node.spill) copy2.spill = true;
|
|
26616
|
+
return copy2;
|
|
26249
26617
|
}
|
|
26250
|
-
|
|
26251
|
-
|
|
26252
|
-
|
|
26253
|
-
|
|
26254
|
-
|
|
26255
|
-
return;
|
|
26618
|
+
case "unary":
|
|
26619
|
+
case "percent": {
|
|
26620
|
+
const operand4 = copyTree(node.operand, t, rows);
|
|
26621
|
+
if (operand4 === node.operand) return node;
|
|
26622
|
+
return node.type === "unary" ? { type: "unary", op: node.op, operand: operand4 } : { type: "percent", operand: operand4 };
|
|
26256
26623
|
}
|
|
26257
|
-
|
|
26258
|
-
|
|
26259
|
-
|
|
26260
|
-
if (
|
|
26261
|
-
|
|
26624
|
+
case "binary": {
|
|
26625
|
+
const left2 = copyTree(node.left, t, rows);
|
|
26626
|
+
const right2 = copyTree(node.right, t, rows);
|
|
26627
|
+
if (left2 === node.left && right2 === node.right) return node;
|
|
26628
|
+
return { type: "binary", op: node.op, left: left2, right: right2 };
|
|
26262
26629
|
}
|
|
26263
|
-
|
|
26264
|
-
|
|
26265
|
-
|
|
26266
|
-
|
|
26267
|
-
this.collect(sheet, range, found);
|
|
26268
|
-
if (Array.isArray(out)) for (const node of found) out.push(node);
|
|
26269
|
-
}
|
|
26270
|
-
collect(sheet, range, out) {
|
|
26271
|
-
const { start, end } = range;
|
|
26272
|
-
const check3 = (list) => {
|
|
26273
|
-
if (list) {
|
|
26274
|
-
for (const entry3 of list) if (rangesIntersect(entry3.range, range)) out.add(entry3.node);
|
|
26275
|
-
}
|
|
26276
|
-
};
|
|
26277
|
-
const cells3 = this.cells.get(sheet);
|
|
26278
|
-
if (cells3) {
|
|
26279
|
-
const size = (end.row - start.row + 1) * (end.col - start.col + 1);
|
|
26280
|
-
if (size <= 4096) {
|
|
26281
|
-
for (let r = start.row; r <= end.row; r++) {
|
|
26282
|
-
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
26283
|
-
const list = cells3.get(cellKey(r, c2));
|
|
26284
|
-
if (list) for (const node of list) out.add(node);
|
|
26285
|
-
}
|
|
26286
|
-
}
|
|
26287
|
-
} else {
|
|
26288
|
-
for (const [key2, list] of cells3) {
|
|
26289
|
-
const { row: row2, col } = keyToAddress(key2);
|
|
26290
|
-
if (row2 >= start.row && row2 <= end.row && col >= start.col && col <= end.col)
|
|
26291
|
-
for (const node of list) out.add(node);
|
|
26292
|
-
}
|
|
26293
|
-
}
|
|
26630
|
+
case "call": {
|
|
26631
|
+
const args = copyAll(node.args, t, rows);
|
|
26632
|
+
if (args === node.args) return node;
|
|
26633
|
+
return { type: "call", name: node.name, rawName: node.rawName, args };
|
|
26294
26634
|
}
|
|
26295
|
-
|
|
26296
|
-
|
|
26297
|
-
|
|
26298
|
-
|
|
26299
|
-
|
|
26300
|
-
};
|
|
26301
|
-
const chunked = this.chunked.get(sheet);
|
|
26302
|
-
const first3 = start.row >> CHUNK_SHIFT;
|
|
26303
|
-
const last = end.row >> CHUNK_SHIFT;
|
|
26304
|
-
columns(chunked, (c2) => {
|
|
26305
|
-
const chunks = chunked?.get(c2);
|
|
26306
|
-
if (last - first3 + 1 <= chunks.size) {
|
|
26307
|
-
for (let k = first3; k <= last; k++) check3(chunks.get(k));
|
|
26308
|
-
} else for (const [k, list] of chunks) if (k >= first3 && k <= last) check3(list);
|
|
26309
|
-
});
|
|
26310
|
-
const tall = this.tall.get(sheet);
|
|
26311
|
-
columns(tall, (c2) => check3(tall?.get(c2)));
|
|
26312
|
-
check3(this.wide.get(sheet));
|
|
26313
|
-
}
|
|
26314
|
-
};
|
|
26315
|
-
|
|
26316
|
-
// xlsx/formula/graph-index.ts
|
|
26317
|
-
var ColumnIndex = class {
|
|
26318
|
-
sheets = /* @__PURE__ */ new Map();
|
|
26319
|
-
constructor(nodes) {
|
|
26320
|
-
for (const node of nodes) {
|
|
26321
|
-
let cols = this.sheets.get(node.sheet);
|
|
26322
|
-
if (!cols) this.sheets.set(node.sheet, cols = /* @__PURE__ */ new Map());
|
|
26323
|
-
let list = cols.get(node.col);
|
|
26324
|
-
if (!list) cols.set(node.col, list = []);
|
|
26325
|
-
list.push(node);
|
|
26635
|
+
case "invoke": {
|
|
26636
|
+
const callee = copyTree(node.callee, t, rows);
|
|
26637
|
+
const args = copyAll(node.args, t, rows);
|
|
26638
|
+
if (callee === node.callee && args === node.args) return node;
|
|
26639
|
+
return { type: "invoke", callee, args };
|
|
26326
26640
|
}
|
|
26327
|
-
|
|
26328
|
-
|
|
26641
|
+
default:
|
|
26642
|
+
return node;
|
|
26329
26643
|
}
|
|
26330
|
-
|
|
26331
|
-
|
|
26332
|
-
|
|
26333
|
-
|
|
26334
|
-
const
|
|
26335
|
-
const
|
|
26336
|
-
|
|
26337
|
-
|
|
26338
|
-
|
|
26339
|
-
|
|
26340
|
-
|
|
26341
|
-
|
|
26342
|
-
|
|
26343
|
-
|
|
26344
|
-
|
|
26345
|
-
|
|
26346
|
-
|
|
26347
|
-
|
|
26348
|
-
|
|
26349
|
-
|
|
26350
|
-
|
|
26351
|
-
|
|
26352
|
-
|
|
26353
|
-
|
|
26354
|
-
|
|
26355
|
-
|
|
26356
|
-
|
|
26644
|
+
}
|
|
26645
|
+
function copyAll(nodes, t, rows) {
|
|
26646
|
+
let out;
|
|
26647
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
26648
|
+
const node = nodes[i2];
|
|
26649
|
+
const copy2 = copyTree(node, t, rows);
|
|
26650
|
+
if (copy2 !== node && !out) out = nodes.slice(0, i2);
|
|
26651
|
+
out?.push(copy2);
|
|
26652
|
+
}
|
|
26653
|
+
return out ?? nodes;
|
|
26654
|
+
}
|
|
26655
|
+
function fromTemplate(t, formula, shape2) {
|
|
26656
|
+
const rows = rowsFor(t, formula, shape2);
|
|
26657
|
+
return rows ? copyTree(t.ast, t, rows) : void 0;
|
|
26658
|
+
}
|
|
26659
|
+
|
|
26660
|
+
// xlsx/formula/parse-cache.ts
|
|
26661
|
+
var MAX_TEMPLATE_LENGTH = 2048;
|
|
26662
|
+
var MAX_ENTRIES = 1e5;
|
|
26663
|
+
var MAX_TEMPLATES2 = 1e4;
|
|
26664
|
+
var NO_RUNS = { hash: 0, starts: [], ends: [] };
|
|
26665
|
+
var treeOf = (made) => "ast" in made ? made.ast : made;
|
|
26666
|
+
var ParseCache = class {
|
|
26667
|
+
byText = /* @__PURE__ */ new Map();
|
|
26668
|
+
templates = /* @__PURE__ */ new Map();
|
|
26669
|
+
parse(formula) {
|
|
26670
|
+
let ast = this.byText.get(formula);
|
|
26671
|
+
if (ast) return ast;
|
|
26672
|
+
ast = this.parseNew(formula);
|
|
26673
|
+
if (this.byText.size > MAX_ENTRIES) this.byText.clear();
|
|
26674
|
+
this.byText.set(formula, ast);
|
|
26675
|
+
return ast;
|
|
26357
26676
|
}
|
|
26358
|
-
|
|
26359
|
-
|
|
26360
|
-
|
|
26361
|
-
|
|
26362
|
-
|
|
26363
|
-
|
|
26364
|
-
|
|
26677
|
+
parseNew(formula) {
|
|
26678
|
+
if (formula.length > MAX_TEMPLATE_LENGTH) return treeOf(makeTemplate(formula, NO_RUNS));
|
|
26679
|
+
const shape2 = formulaShape(formula);
|
|
26680
|
+
const template = this.templates.get(shape2.hash);
|
|
26681
|
+
const reused = template && fromTemplate(template, formula, shape2);
|
|
26682
|
+
if (reused) return reused;
|
|
26683
|
+
const made = makeTemplate(formula, shape2);
|
|
26684
|
+
if (!template && "ast" in made) {
|
|
26685
|
+
if (this.templates.size > MAX_TEMPLATES2) this.templates.clear();
|
|
26686
|
+
this.templates.set(shape2.hash, made);
|
|
26365
26687
|
}
|
|
26688
|
+
return treeOf(made);
|
|
26366
26689
|
}
|
|
26367
26690
|
};
|
|
26368
26691
|
|
|
@@ -26502,7 +26825,7 @@ var EngineHost = class {
|
|
|
26502
26825
|
options;
|
|
26503
26826
|
nodes = /* @__PURE__ */ new Map();
|
|
26504
26827
|
footprints = /* @__PURE__ */ new Set();
|
|
26505
|
-
|
|
26828
|
+
parsed = new ParseCache();
|
|
26506
26829
|
boundsCache = /* @__PURE__ */ new Map();
|
|
26507
26830
|
inProgress = /* @__PURE__ */ new Set();
|
|
26508
26831
|
cycles = /* @__PURE__ */ new Set();
|
|
@@ -26526,6 +26849,8 @@ var EngineHost = class {
|
|
|
26526
26849
|
evaluations = 0;
|
|
26527
26850
|
built = false;
|
|
26528
26851
|
needsFull = false;
|
|
26852
|
+
/** No recalculation has run since the workbook was opened: stored values may stand. */
|
|
26853
|
+
fresh = true;
|
|
26529
26854
|
// ---- EvalHost ----
|
|
26530
26855
|
readCell(sheet, row2, col) {
|
|
26531
26856
|
const cell = this.workbook.sheets[sheet]?.rows.get(row2)?.get(col);
|
|
@@ -26614,19 +26939,7 @@ var EngineHost = class {
|
|
|
26614
26939
|
return this.workbook.sheets[sheet]?.rows.get(row2)?.get(col)?.formula;
|
|
26615
26940
|
}
|
|
26616
26941
|
parse(formula) {
|
|
26617
|
-
|
|
26618
|
-
if (!ast) {
|
|
26619
|
-
try {
|
|
26620
|
-
ast = parseFormula(formula);
|
|
26621
|
-
} catch (e) {
|
|
26622
|
-
if (e instanceof RangeError) ast = new FormulaError(e.message, -1, "#VALUE!");
|
|
26623
|
-
else if (!(e instanceof FormulaError)) throw e;
|
|
26624
|
-
else ast = e;
|
|
26625
|
-
}
|
|
26626
|
-
if (this.astCache.size > 1e5) this.astCache.clear();
|
|
26627
|
-
this.astCache.set(formula, ast);
|
|
26628
|
-
}
|
|
26629
|
-
return ast;
|
|
26942
|
+
return this.parsed.parse(formula);
|
|
26630
26943
|
}
|
|
26631
26944
|
now() {
|
|
26632
26945
|
return this.options.now ? this.options.now() : /* @__PURE__ */ new Date();
|
|
@@ -26635,20 +26948,6 @@ var EngineHost = class {
|
|
|
26635
26948
|
return this.options.random ? this.options.random() : Math.random();
|
|
26636
26949
|
}
|
|
26637
26950
|
// ---- graph ----
|
|
26638
|
-
build() {
|
|
26639
|
-
this.nodes.clear();
|
|
26640
|
-
this.footprints.clear();
|
|
26641
|
-
this.footprintIndex = void 0;
|
|
26642
|
-
this.workbook.sheets.forEach((sheet, s) => {
|
|
26643
|
-
for (const [row2, cells3] of sheet.rows) {
|
|
26644
|
-
for (const [col, cell] of cells3) {
|
|
26645
|
-
if (cell.formula) this.createNode(s, row2, col, cell, true);
|
|
26646
|
-
}
|
|
26647
|
-
}
|
|
26648
|
-
});
|
|
26649
|
-
this.built = true;
|
|
26650
|
-
this.graphChanged();
|
|
26651
|
-
}
|
|
26652
26951
|
createNode(sheet, row2, col, cell, initial) {
|
|
26653
26952
|
const formula = cell.formula ?? "";
|
|
26654
26953
|
const parsed = this.parse(formula);
|
|
@@ -26677,6 +26976,14 @@ var EngineHost = class {
|
|
|
26677
26976
|
map.set(cellKey(row2, col), node);
|
|
26678
26977
|
return node;
|
|
26679
26978
|
}
|
|
26979
|
+
/** Parses a node's text again after a structural edit rewrote it (see `FormulaNode.stale`). */
|
|
26980
|
+
refreshAst(node) {
|
|
26981
|
+
const parsed = this.parse(node.formula);
|
|
26982
|
+
delete node.stale;
|
|
26983
|
+
delete node.parseError;
|
|
26984
|
+
node.ast = parsed instanceof FormulaError ? void 0 : parsed;
|
|
26985
|
+
if (parsed instanceof FormulaError && parsed.code) node.parseError = err(parsed.code);
|
|
26986
|
+
}
|
|
26680
26987
|
removeNode(node, changed) {
|
|
26681
26988
|
const sheet = this.workbook.sheets[node.sheet];
|
|
26682
26989
|
if (node.spill && sheet) {
|
|
@@ -27107,6 +27414,7 @@ var EngineCore = class extends EngineHost {
|
|
|
27107
27414
|
return { host: this, sheet, row: row2, col, scope: void 0, depth: 0, root, legacy };
|
|
27108
27415
|
}
|
|
27109
27416
|
evaluateFormula(node) {
|
|
27417
|
+
if (node.stale) this.refreshAst(node);
|
|
27110
27418
|
if (!node.ast) return node.parseError ?? ERR.NAME;
|
|
27111
27419
|
const ast = node.ast;
|
|
27112
27420
|
const frame = this.frameFor(node.sheet, node.row, node.col, ast, node.legacy);
|
|
@@ -27124,20 +27432,363 @@ var EngineCore = class extends EngineHost {
|
|
|
27124
27432
|
}
|
|
27125
27433
|
};
|
|
27126
27434
|
|
|
27435
|
+
// xlsx/formula/shift-graph.ts
|
|
27436
|
+
var POSITIONAL = /* @__PURE__ */ new Set(["ROW", "COLUMN"]);
|
|
27437
|
+
var DESCRIPTIVE = /* @__PURE__ */ new Set(["FORMULATEXT", "CELL", "SHEET"]);
|
|
27438
|
+
var traitsCache = /* @__PURE__ */ new WeakMap();
|
|
27439
|
+
function astTraits(ast) {
|
|
27440
|
+
const cached3 = traitsCache.get(ast);
|
|
27441
|
+
if (cached3) return cached3;
|
|
27442
|
+
const sheets = /* @__PURE__ */ new Set();
|
|
27443
|
+
const traits = { complex: false, opaque: false, positional: false, descriptive: false, sheets };
|
|
27444
|
+
const stack2 = [ast];
|
|
27445
|
+
while (stack2.length) {
|
|
27446
|
+
const node = stack2.pop();
|
|
27447
|
+
switch (node.type) {
|
|
27448
|
+
case "ref":
|
|
27449
|
+
if (node.prefix) {
|
|
27450
|
+
sheets.add(node.prefix.sheet.toLowerCase());
|
|
27451
|
+
if (node.prefix.sheet2 !== void 0) {
|
|
27452
|
+
sheets.add(node.prefix.sheet2.toLowerCase());
|
|
27453
|
+
traits.complex = true;
|
|
27454
|
+
}
|
|
27455
|
+
}
|
|
27456
|
+
break;
|
|
27457
|
+
case "name":
|
|
27458
|
+
if (node.prefix) sheets.add(node.prefix.sheet.toLowerCase());
|
|
27459
|
+
traits.complex = true;
|
|
27460
|
+
break;
|
|
27461
|
+
case "structured":
|
|
27462
|
+
traits.complex = true;
|
|
27463
|
+
break;
|
|
27464
|
+
case "unary":
|
|
27465
|
+
case "percent":
|
|
27466
|
+
stack2.push(node.operand);
|
|
27467
|
+
break;
|
|
27468
|
+
case "binary":
|
|
27469
|
+
stack2.push(node.left, node.right);
|
|
27470
|
+
break;
|
|
27471
|
+
case "call":
|
|
27472
|
+
if (POSITIONAL.has(node.name)) traits.positional = true;
|
|
27473
|
+
if (DESCRIPTIVE.has(node.name)) traits.descriptive = true;
|
|
27474
|
+
if (!getFunction(node.name)) traits.complex = traits.opaque = true;
|
|
27475
|
+
stack2.push(...node.args);
|
|
27476
|
+
break;
|
|
27477
|
+
case "invoke":
|
|
27478
|
+
stack2.push(node.callee, ...node.args);
|
|
27479
|
+
break;
|
|
27480
|
+
}
|
|
27481
|
+
}
|
|
27482
|
+
traitsCache.set(ast, traits);
|
|
27483
|
+
return traits;
|
|
27484
|
+
}
|
|
27485
|
+
function intervalDelta(a2, b, shift2) {
|
|
27486
|
+
const { at: at2, count: count2 } = shift2;
|
|
27487
|
+
if (count2 > 0) {
|
|
27488
|
+
if (b < at2) return 0;
|
|
27489
|
+
if (a2 < at2) return void 0;
|
|
27490
|
+
return b + count2 > (shift2.axis === "row" ? MAX_ROW : MAX_COL) ? void 0 : count2;
|
|
27491
|
+
}
|
|
27492
|
+
const last = at2 - count2 - 1;
|
|
27493
|
+
if (b < at2) return 0;
|
|
27494
|
+
if (a2 > last) return count2;
|
|
27495
|
+
return void 0;
|
|
27496
|
+
}
|
|
27497
|
+
function areaDelta(area, sheet, shift2) {
|
|
27498
|
+
if (area.sheet !== sheet) return 0;
|
|
27499
|
+
const { start, end } = area.range;
|
|
27500
|
+
return shift2.axis === "row" ? intervalDelta(start.row, end.row, shift2) : intervalDelta(start.col, end.col, shift2);
|
|
27501
|
+
}
|
|
27502
|
+
function movedRange(range, axis, delta) {
|
|
27503
|
+
if (delta === 0) return range;
|
|
27504
|
+
return axis === "row" ? {
|
|
27505
|
+
start: { row: range.start.row + delta, col: range.start.col },
|
|
27506
|
+
end: { row: range.end.row + delta, col: range.end.col }
|
|
27507
|
+
} : {
|
|
27508
|
+
start: { row: range.start.row, col: range.start.col + delta },
|
|
27509
|
+
end: { row: range.end.row, col: range.end.col + delta }
|
|
27510
|
+
};
|
|
27511
|
+
}
|
|
27512
|
+
function reachesEdit(areas, sheet, shift2) {
|
|
27513
|
+
for (const area of areas) {
|
|
27514
|
+
if (area.sheet !== sheet) continue;
|
|
27515
|
+
if ((shift2.axis === "row" ? area.range.end.row : area.range.end.col) >= shift2.at) return true;
|
|
27516
|
+
}
|
|
27517
|
+
return false;
|
|
27518
|
+
}
|
|
27519
|
+
function intersectionMoves(area, delta, pos, nodeDelta, axis) {
|
|
27520
|
+
if (delta === nodeDelta) return false;
|
|
27521
|
+
const { start, end } = area.range;
|
|
27522
|
+
const a2 = axis === "row" ? start.row : start.col;
|
|
27523
|
+
const b = axis === "row" ? end.row : end.col;
|
|
27524
|
+
if (a2 === b) return false;
|
|
27525
|
+
return pos >= a2 && pos <= b || pos + nodeDelta >= a2 + delta && pos + nodeDelta <= b + delta;
|
|
27526
|
+
}
|
|
27527
|
+
|
|
27528
|
+
// xlsx/formula/engine-structure.ts
|
|
27529
|
+
var sameAreas = (a2, b) => a2.length === b.length && a2.every((x, i2) => {
|
|
27530
|
+
const y = b[i2];
|
|
27531
|
+
return x.sheet === y.sheet && sameRange(x.range, y.range);
|
|
27532
|
+
});
|
|
27533
|
+
var EngineStructure = class extends EngineCore {
|
|
27534
|
+
/** Formulas a structural edit left to recalculate (with their dependents) on the next pass. */
|
|
27535
|
+
structuralSeeds = /* @__PURE__ */ new Set();
|
|
27536
|
+
/** Whether the graph describes the workbook as it was before the edit just reported. */
|
|
27537
|
+
graphReady() {
|
|
27538
|
+
return this.built && !this.needsFull;
|
|
27539
|
+
}
|
|
27540
|
+
/** Parses a node's current text again and recomputes its precedents. */
|
|
27541
|
+
reanalyze(node) {
|
|
27542
|
+
const parsed = this.parse(node.formula);
|
|
27543
|
+
delete node.stale;
|
|
27544
|
+
delete node.parseError;
|
|
27545
|
+
if (parsed instanceof FormulaError) {
|
|
27546
|
+
node.ast = void 0;
|
|
27547
|
+
if (parsed.code) node.parseError = err(parsed.code);
|
|
27548
|
+
node.deps = [];
|
|
27549
|
+
node.dynamicDeps = [];
|
|
27550
|
+
return;
|
|
27551
|
+
}
|
|
27552
|
+
node.ast = parsed;
|
|
27553
|
+
const found = analyze(parsed, this, node.sheet, node.row, node.col);
|
|
27554
|
+
node.deps = found.deps;
|
|
27555
|
+
node.dynamicDeps = found.dynamicDeps;
|
|
27556
|
+
node.volatile = found.volatile;
|
|
27557
|
+
node.unsupported = found.unsupported;
|
|
27558
|
+
}
|
|
27559
|
+
/**
|
|
27560
|
+
* Moves the graph for rows or columns inserted or deleted on `sheet`, after the workbook was
|
|
27561
|
+
* changed (cells moved, formulas rewritten). Spills on the sheet, array formulas the edit cuts
|
|
27562
|
+
* and anything unexpected fall back to a rebuild on the next recalculation.
|
|
27563
|
+
*/
|
|
27564
|
+
shiftCells(sheet, shift2) {
|
|
27565
|
+
if (!this.graphReady() || !this.shiftable(sheet, shift2)) {
|
|
27566
|
+
this.invalidate();
|
|
27567
|
+
return;
|
|
27568
|
+
}
|
|
27569
|
+
const ws = this.workbook.sheets[sheet];
|
|
27570
|
+
const own = this.nodes.get(sheet);
|
|
27571
|
+
if (!ws) return;
|
|
27572
|
+
const moved = /* @__PURE__ */ new Map();
|
|
27573
|
+
if (own) {
|
|
27574
|
+
const next = /* @__PURE__ */ new Map();
|
|
27575
|
+
for (const node of own.values()) {
|
|
27576
|
+
const pos = shift2.axis === "row" ? node.row : node.col;
|
|
27577
|
+
const delta = intervalDelta(pos, pos, shift2);
|
|
27578
|
+
if (delta === void 0) {
|
|
27579
|
+
this.dropNode(node);
|
|
27580
|
+
continue;
|
|
27581
|
+
}
|
|
27582
|
+
if (delta !== 0) {
|
|
27583
|
+
moved.set(node, delta);
|
|
27584
|
+
if (shift2.axis === "row") node.row += delta;
|
|
27585
|
+
else node.col += delta;
|
|
27586
|
+
}
|
|
27587
|
+
next.set(cellKey(node.row, node.col), node);
|
|
27588
|
+
}
|
|
27589
|
+
this.nodes.set(sheet, next);
|
|
27590
|
+
}
|
|
27591
|
+
for (const map of this.nodes.values())
|
|
27592
|
+
for (const node of map.values()) {
|
|
27593
|
+
if (!this.shiftNode(node, sheet, shift2, moved.get(node) ?? 0)) {
|
|
27594
|
+
this.invalidate();
|
|
27595
|
+
return;
|
|
27596
|
+
}
|
|
27597
|
+
}
|
|
27598
|
+
this.boundsCache.clear();
|
|
27599
|
+
this.graphChanged();
|
|
27600
|
+
}
|
|
27601
|
+
/** No spill or stale spilled value on the sheet, and no array formula the edit cuts. */
|
|
27602
|
+
shiftable(sheet, shift2) {
|
|
27603
|
+
for (const node of this.footprints) {
|
|
27604
|
+
if (node.sheet !== sheet) continue;
|
|
27605
|
+
if (node.spill || node.blockedSpill) return false;
|
|
27606
|
+
if (node.arrayRange && areaDelta({ sheet, range: node.arrayRange }, sheet, shift2) === void 0)
|
|
27607
|
+
return false;
|
|
27608
|
+
}
|
|
27609
|
+
const ws = this.workbook.sheets[sheet];
|
|
27610
|
+
let spilled = false;
|
|
27611
|
+
ws?.rows.forEach((cells3) => {
|
|
27612
|
+
if (!spilled) cells3.forEach((cell) => spilled ||= isSpilledCell(cell));
|
|
27613
|
+
});
|
|
27614
|
+
return !spilled;
|
|
27615
|
+
}
|
|
27616
|
+
dropNode(node) {
|
|
27617
|
+
this.structuralSeeds.delete(node);
|
|
27618
|
+
this.cycles.delete(node);
|
|
27619
|
+
this.footprints.delete(node);
|
|
27620
|
+
}
|
|
27621
|
+
/** Updates one formula for the edit; false when the graph cannot follow it. */
|
|
27622
|
+
shiftNode(node, sheet, shift2, nodeDelta) {
|
|
27623
|
+
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
27624
|
+
if (cell?.formula === void 0) return false;
|
|
27625
|
+
if (node.arrayRange) {
|
|
27626
|
+
const delta = areaDelta({ sheet: node.sheet, range: node.arrayRange }, sheet, shift2);
|
|
27627
|
+
if (delta === void 0) return false;
|
|
27628
|
+
node.arrayRange = movedRange(node.arrayRange, shift2.axis, delta);
|
|
27629
|
+
if (!cell.arrayRange || !sameRange(node.arrayRange, normalizeRange(cell.arrayRange)))
|
|
27630
|
+
return false;
|
|
27631
|
+
}
|
|
27632
|
+
const changed = cell.formula !== node.formula;
|
|
27633
|
+
const traits = node.ast && astTraits(node.ast);
|
|
27634
|
+
const reached = reachesEdit(node.deps, sheet, shift2) || reachesEdit(node.dynamicDeps, sheet, shift2);
|
|
27635
|
+
if (!changed && !reached && nodeDelta === 0 && !traits?.descriptive && !traits?.opaque)
|
|
27636
|
+
return true;
|
|
27637
|
+
if (traits?.complex) {
|
|
27638
|
+
node.formula = cell.formula;
|
|
27639
|
+
this.reanalyze(node);
|
|
27640
|
+
this.structuralSeeds.add(node);
|
|
27641
|
+
return true;
|
|
27642
|
+
}
|
|
27643
|
+
const pos = shift2.axis === "row" ? node.row - nodeDelta : node.col - nodeDelta;
|
|
27644
|
+
const moves = { seed: !!traits?.descriptive, moved: false, cut: false };
|
|
27645
|
+
const deps = this.moveAreas(node.deps, sheet, shift2, pos, nodeDelta, moves);
|
|
27646
|
+
const dynamicDeps = this.moveAreas(node.dynamicDeps, sheet, shift2, pos, nodeDelta, moves);
|
|
27647
|
+
const { cut, moved: anyMoved } = moves;
|
|
27648
|
+
let seed = moves.seed;
|
|
27649
|
+
if (cut || changed !== anyMoved) {
|
|
27650
|
+
node.formula = cell.formula;
|
|
27651
|
+
this.reanalyze(node);
|
|
27652
|
+
this.structuralSeeds.add(node);
|
|
27653
|
+
return true;
|
|
27654
|
+
}
|
|
27655
|
+
if (traits?.positional && (anyMoved || nodeDelta !== 0)) seed = true;
|
|
27656
|
+
node.deps = deps;
|
|
27657
|
+
node.dynamicDeps = dynamicDeps;
|
|
27658
|
+
if (changed) {
|
|
27659
|
+
node.formula = cell.formula;
|
|
27660
|
+
node.stale = true;
|
|
27661
|
+
}
|
|
27662
|
+
if (seed) this.structuralSeeds.add(node);
|
|
27663
|
+
return true;
|
|
27664
|
+
}
|
|
27665
|
+
/**
|
|
27666
|
+
* Areas moved for the edit (the same list when none moves). Records in `moves` whether one
|
|
27667
|
+
* moved, one was cut (deleted, widened, pushed off the grid) and whether implicit intersection
|
|
27668
|
+
* with one can now pick another cell.
|
|
27669
|
+
*/
|
|
27670
|
+
moveAreas(list, sheet, shift2, pos, nodeDelta, moves) {
|
|
27671
|
+
let out;
|
|
27672
|
+
for (let i2 = 0; i2 < list.length; i2++) {
|
|
27673
|
+
const area = list[i2];
|
|
27674
|
+
const delta = areaDelta(area, sheet, shift2);
|
|
27675
|
+
if (delta === void 0) {
|
|
27676
|
+
moves.cut = true;
|
|
27677
|
+
continue;
|
|
27678
|
+
}
|
|
27679
|
+
if (intersectionMoves(area, delta, pos, nodeDelta, shift2.axis)) moves.seed = true;
|
|
27680
|
+
if (delta === 0) continue;
|
|
27681
|
+
moves.moved = true;
|
|
27682
|
+
out ??= list.slice();
|
|
27683
|
+
out[i2] = { sheet: area.sheet, range: movedRange(area.range, shift2.axis, delta) };
|
|
27684
|
+
}
|
|
27685
|
+
return out ?? list;
|
|
27686
|
+
}
|
|
27687
|
+
/**
|
|
27688
|
+
* Follows a sheet rename (`from` to `to`, formulas already rewritten): precedents are kept by
|
|
27689
|
+
* sheet index, so only rewritten formulas need their text parsed again, and only formulas that
|
|
27690
|
+
* name the new sheet without having been rewritten (previously unresolved), describe sheets
|
|
27691
|
+
* (CELL, SHEET, FORMULATEXT) or read defined names whose areas changed are recalculated.
|
|
27692
|
+
*/
|
|
27693
|
+
renameSheet(from, to) {
|
|
27694
|
+
if (!this.graphReady()) {
|
|
27695
|
+
this.invalidate();
|
|
27696
|
+
return;
|
|
27697
|
+
}
|
|
27698
|
+
const target = to.toLowerCase();
|
|
27699
|
+
let depsChanged = false;
|
|
27700
|
+
for (const map of this.nodes.values())
|
|
27701
|
+
for (const node of map.values()) {
|
|
27702
|
+
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
27703
|
+
if (cell?.formula === void 0) {
|
|
27704
|
+
this.invalidate();
|
|
27705
|
+
return;
|
|
27706
|
+
}
|
|
27707
|
+
const changed = cell.formula !== node.formula;
|
|
27708
|
+
const traits = node.ast && astTraits(node.ast);
|
|
27709
|
+
node.formula = cell.formula;
|
|
27710
|
+
if (traits?.complex || !changed && traits?.sheets.has(target)) {
|
|
27711
|
+
const deps = node.deps;
|
|
27712
|
+
const dynamicDeps = node.dynamicDeps;
|
|
27713
|
+
this.reanalyze(node);
|
|
27714
|
+
const same5 = sameAreas(deps, node.deps) && sameAreas(dynamicDeps, node.dynamicDeps);
|
|
27715
|
+
if (!same5) depsChanged = true;
|
|
27716
|
+
if (!same5 || !traits?.complex) this.structuralSeeds.add(node);
|
|
27717
|
+
} else if (changed) node.stale = true;
|
|
27718
|
+
if (traits?.descriptive || traits?.opaque) this.structuralSeeds.add(node);
|
|
27719
|
+
}
|
|
27720
|
+
if (depsChanged) this.graphChanged();
|
|
27721
|
+
}
|
|
27722
|
+
/** Takes the formulas queued by structural edits. */
|
|
27723
|
+
takeStructuralSeeds(into) {
|
|
27724
|
+
for (const node of this.structuralSeeds)
|
|
27725
|
+
if (this.nodes.get(node.sheet)?.get(cellKey(node.row, node.col)) === node) into.add(node);
|
|
27726
|
+
this.structuralSeeds.clear();
|
|
27727
|
+
}
|
|
27728
|
+
};
|
|
27729
|
+
|
|
27127
27730
|
// xlsx/formula/engine.ts
|
|
27128
|
-
var Engine = class extends
|
|
27731
|
+
var Engine = class extends EngineStructure {
|
|
27732
|
+
preparation;
|
|
27733
|
+
/** The prepared formulas the first recalculation checks (see `trustsStoredValues`). */
|
|
27734
|
+
prepared;
|
|
27735
|
+
// ---- the graph ----
|
|
27736
|
+
prepare(timeRemaining) {
|
|
27737
|
+
if (this.built || this.needsFull) return true;
|
|
27738
|
+
this.preparation ??= this.startPreparation();
|
|
27739
|
+
if (!this.preparation.run(timeRemaining)) return false;
|
|
27740
|
+
this.finishPreparation(this.preparation);
|
|
27741
|
+
return true;
|
|
27742
|
+
}
|
|
27743
|
+
discardPreparation() {
|
|
27744
|
+
if (!this.fresh || this.needsFull) return;
|
|
27745
|
+
this.preparation = void 0;
|
|
27746
|
+
this.prepared = void 0;
|
|
27747
|
+
this.structuralSeeds.clear();
|
|
27748
|
+
this.nodes.clear();
|
|
27749
|
+
this.footprints.clear();
|
|
27750
|
+
this.graphChanged();
|
|
27751
|
+
this.built = false;
|
|
27752
|
+
}
|
|
27753
|
+
/** Completes the graph, continuing a preparation that is under way. */
|
|
27754
|
+
build() {
|
|
27755
|
+
const preparation = this.preparation ?? this.startPreparation();
|
|
27756
|
+
preparation.run();
|
|
27757
|
+
this.finishPreparation(preparation);
|
|
27758
|
+
}
|
|
27759
|
+
startPreparation() {
|
|
27760
|
+
this.nodes.clear();
|
|
27761
|
+
this.footprints.clear();
|
|
27762
|
+
this.footprintIndex = void 0;
|
|
27763
|
+
this.prepared = void 0;
|
|
27764
|
+
return new GraphPreparation(
|
|
27765
|
+
this.workbook,
|
|
27766
|
+
(s, row2, col, cell) => this.createNode(s, row2, col, cell, true)
|
|
27767
|
+
);
|
|
27768
|
+
}
|
|
27769
|
+
finishPreparation(preparation) {
|
|
27770
|
+
this.preparation = void 0;
|
|
27771
|
+
this.built = true;
|
|
27772
|
+
this.graphChanged();
|
|
27773
|
+
this.reverseIndex = preparation.reverse;
|
|
27774
|
+
this.prepared = preparation.formulas;
|
|
27775
|
+
}
|
|
27129
27776
|
// ---- recalculation ----
|
|
27130
27777
|
recalculateAll() {
|
|
27778
|
+
this.fresh = false;
|
|
27779
|
+
this.prepared = void 0;
|
|
27131
27780
|
if (this.needsFull) this.releaseAllSpills();
|
|
27132
27781
|
if (!this.built || this.needsFull) this.build();
|
|
27133
27782
|
this.needsFull = false;
|
|
27783
|
+
this.structuralSeeds.clear();
|
|
27134
27784
|
this.cycles = /* @__PURE__ */ new Set();
|
|
27135
27785
|
this.run(new Set(this.allNodes()), true);
|
|
27136
27786
|
}
|
|
27137
27787
|
recalculateFrom(changes) {
|
|
27138
27788
|
const seeds = /* @__PURE__ */ new Set();
|
|
27139
|
-
if (
|
|
27140
|
-
this.
|
|
27789
|
+
if (this.fresh && !this.needsFull) {
|
|
27790
|
+
this.fresh = false;
|
|
27791
|
+
if (!this.built) this.build();
|
|
27141
27792
|
if (!this.trustsStoredValues(changes, seeds)) {
|
|
27142
27793
|
this.recalculateAll();
|
|
27143
27794
|
return;
|
|
@@ -27181,6 +27832,7 @@ var Engine = class extends EngineCore {
|
|
|
27181
27832
|
}
|
|
27182
27833
|
}
|
|
27183
27834
|
if (structural) this.graphChanged();
|
|
27835
|
+
this.takeStructuralSeeds(seeds);
|
|
27184
27836
|
const reverse2 = this.reverse();
|
|
27185
27837
|
for (const area of changed) reverse2.dependents(area.sheet, area.range, seeds);
|
|
27186
27838
|
for (const node of this.allNodes()) if (node.volatile) seeds.add(node);
|
|
@@ -27192,13 +27844,18 @@ var Engine = class extends EngineCore {
|
|
|
27192
27844
|
* without a value into `missing`.
|
|
27193
27845
|
*/
|
|
27194
27846
|
trustsStoredValues(changes, missing) {
|
|
27847
|
+
const prepared = this.prepared;
|
|
27848
|
+
this.prepared = void 0;
|
|
27849
|
+
if (!prepared) return false;
|
|
27195
27850
|
const changed = new Set(changes.map((c2) => `${c2.sheet}:${cellKey(c2.row, c2.col)}`));
|
|
27196
|
-
|
|
27197
|
-
|
|
27198
|
-
if (
|
|
27851
|
+
const current = (node) => this.nodes.get(node.sheet)?.get(cellKey(node.row, node.col)) === node;
|
|
27852
|
+
for (const node of prepared.dynamic) {
|
|
27853
|
+
if (current(node) && !changed.has(`${node.sheet}:${cellKey(node.row, node.col)}`))
|
|
27199
27854
|
return false;
|
|
27855
|
+
}
|
|
27856
|
+
for (const node of prepared.unvalued) {
|
|
27200
27857
|
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
27201
|
-
if (cell && cell.value === null
|
|
27858
|
+
if (current(node) && cell && cell.value === null) missing.add(node);
|
|
27202
27859
|
}
|
|
27203
27860
|
return true;
|
|
27204
27861
|
}
|
|
@@ -27212,7 +27869,10 @@ var Engine = class extends EngineCore {
|
|
|
27212
27869
|
return !!anchor?.spill && rangeHas(anchor.spill, row2, col);
|
|
27213
27870
|
}
|
|
27214
27871
|
invalidate() {
|
|
27872
|
+
this.structuralSeeds.clear();
|
|
27215
27873
|
this.releaseAllSpills();
|
|
27874
|
+
this.preparation = void 0;
|
|
27875
|
+
this.prepared = void 0;
|
|
27216
27876
|
this.nodes.clear();
|
|
27217
27877
|
this.footprints.clear();
|
|
27218
27878
|
this.graphChanged();
|
|
@@ -27236,8 +27896,8 @@ var Engine = class extends EngineCore {
|
|
|
27236
27896
|
evaluate(formula, at2) {
|
|
27237
27897
|
const value = this.evaluateAdHoc(formula, at2);
|
|
27238
27898
|
const frame = this.frameFor(at2.sheet, at2.row, at2.col, void 0);
|
|
27239
|
-
const
|
|
27240
|
-
return typeof
|
|
27899
|
+
const scalar4 = implicitIntersection(value, frame);
|
|
27900
|
+
return typeof scalar4 === "number" && !Number.isFinite(scalar4) ? ERR.NUM : scalar4;
|
|
27241
27901
|
}
|
|
27242
27902
|
evaluateArray(formula, at2) {
|
|
27243
27903
|
const value = this.evaluateAdHoc(formula, at2);
|
|
@@ -27701,7 +28361,7 @@ var attrPattern = (name) => new RegExp(`(\\s${name}\\s*=\\s*)(["'])(.*?)\\2`);
|
|
|
27701
28361
|
function patchWorksheetSource(xml, edits) {
|
|
27702
28362
|
const match2 = WORKSHEET_SOURCE.exec(xml);
|
|
27703
28363
|
if (!match2) return xml;
|
|
27704
|
-
const [whole, tag, attrs2 = "",
|
|
28364
|
+
const [whole, tag, attrs2 = "", close2] = match2;
|
|
27705
28365
|
if (/\sr:id\s*=/.test(attrs2)) return xml;
|
|
27706
28366
|
const sheetMatch = attrPattern("sheet").exec(attrs2);
|
|
27707
28367
|
const refMatch = attrPattern("ref").exec(attrs2);
|
|
@@ -27725,7 +28385,7 @@ function patchWorksheetSource(xml, edits) {
|
|
|
27725
28385
|
nextAttrs = nextAttrs.replace(attrPattern("sheet"), (_m, lead, q) => {
|
|
27726
28386
|
return `${lead}${q}${escapeXmlAttr(nextSheet)}${q}`;
|
|
27727
28387
|
});
|
|
27728
|
-
return xml.replace(whole, `<${tag}${nextAttrs}${
|
|
28388
|
+
return xml.replace(whole, `<${tag}${nextAttrs}${close2}>`);
|
|
27729
28389
|
}
|
|
27730
28390
|
function rootName(xml) {
|
|
27731
28391
|
const match2 = /<(?![?!])(?:[A-Za-z][\w.-]*:)?([A-Za-z][\w.-]*)/.exec(xml);
|
|
@@ -27919,7 +28579,7 @@ function writeMetadataPart(writer, rels, bookPart, plan, dynamicArraysUsed, sour
|
|
|
27919
28579
|
}
|
|
27920
28580
|
|
|
27921
28581
|
// xlsx/write/style-xml.ts
|
|
27922
|
-
var argb = (
|
|
28582
|
+
var argb = (rgb3) => (rgb3.length === 6 ? `FF${rgb3}` : rgb3).toUpperCase();
|
|
27923
28583
|
function colorXml(color2, name = "color") {
|
|
27924
28584
|
if (!color2) return "";
|
|
27925
28585
|
if (color2.rgb) return el3(name, { rgb: argb(color2.rgb), tint: color2.tint });
|
|
@@ -30143,13 +30803,13 @@ function linearTrend(values2) {
|
|
|
30143
30803
|
const slope = den ? num3 / den : 0;
|
|
30144
30804
|
return (k) => Number((meanY + slope * (k - meanX)).toPrecision(15));
|
|
30145
30805
|
}
|
|
30146
|
-
var
|
|
30806
|
+
var isDigit5 = (ch) => ch !== void 0 && ch >= "0" && ch <= "9";
|
|
30147
30807
|
function matchTextNumber(text2) {
|
|
30148
30808
|
let end = text2.length;
|
|
30149
|
-
while (end > 0 && !
|
|
30809
|
+
while (end > 0 && !isDigit5(text2[end - 1])) end--;
|
|
30150
30810
|
if (end === 0) return null;
|
|
30151
30811
|
let start = end;
|
|
30152
|
-
while (start > 0 &&
|
|
30812
|
+
while (start > 0 && isDigit5(text2[start - 1])) start--;
|
|
30153
30813
|
return [text2, text2.slice(0, start), text2.slice(start, end), text2.slice(end)];
|
|
30154
30814
|
}
|
|
30155
30815
|
var QUARTER = /^(q|qtr|quarter)(\s?)([1-4])$/i;
|
|
@@ -30332,10 +30992,10 @@ function removeValidationArea(rules, area) {
|
|
|
30332
30992
|
}
|
|
30333
30993
|
|
|
30334
30994
|
// xlsx/edit/conditional-formulas.ts
|
|
30335
|
-
function rewriteConditionalRule(rule2,
|
|
30995
|
+
function rewriteConditionalRule(rule2, rewrite2) {
|
|
30336
30996
|
const safe2 = (formula) => {
|
|
30337
30997
|
try {
|
|
30338
|
-
return
|
|
30998
|
+
return rewrite2(formula);
|
|
30339
30999
|
} catch {
|
|
30340
31000
|
return formula;
|
|
30341
31001
|
}
|
|
@@ -30854,7 +31514,7 @@ function shiftPreservedXml(sheet, shift2, moveRange, banded) {
|
|
|
30854
31514
|
(xml) => xml.includes("sqref")
|
|
30855
31515
|
);
|
|
30856
31516
|
}
|
|
30857
|
-
function rewritePreservedFormulas(sheet,
|
|
31517
|
+
function rewritePreservedFormulas(sheet, rewrite2) {
|
|
30858
31518
|
editEntries(
|
|
30859
31519
|
sheet,
|
|
30860
31520
|
"extLst",
|
|
@@ -30864,7 +31524,7 @@ function rewritePreservedFormulas(sheet, rewrite3) {
|
|
|
30864
31524
|
const text2 = f6.textContent ?? "";
|
|
30865
31525
|
let next = text2;
|
|
30866
31526
|
try {
|
|
30867
|
-
next =
|
|
31527
|
+
next = rewrite2(text2, sheet.name);
|
|
30868
31528
|
} catch {
|
|
30869
31529
|
next = text2;
|
|
30870
31530
|
}
|
|
@@ -30879,46 +31539,46 @@ function rewritePreservedFormulas(sheet, rewrite3) {
|
|
|
30879
31539
|
}
|
|
30880
31540
|
|
|
30881
31541
|
// xlsx/edit/shift-formulas.ts
|
|
30882
|
-
function safe(
|
|
31542
|
+
function safe(rewrite2, formula, formulaSheet) {
|
|
30883
31543
|
try {
|
|
30884
|
-
return
|
|
31544
|
+
return rewrite2(formula, formulaSheet);
|
|
30885
31545
|
} catch {
|
|
30886
31546
|
return formula;
|
|
30887
31547
|
}
|
|
30888
31548
|
}
|
|
30889
|
-
function rewriteFormulas(workbook,
|
|
30890
|
-
for (const sheet of workbook.sheets) rewriteSheetFormulas(sheet,
|
|
31549
|
+
function rewriteFormulas(workbook, rewrite2) {
|
|
31550
|
+
for (const sheet of workbook.sheets) rewriteSheetFormulas(sheet, rewrite2);
|
|
30891
31551
|
for (const definedName of workbook.definedNames) {
|
|
30892
31552
|
const local = definedName.localSheet === void 0 ? void 0 : workbook.sheets[definedName.localSheet];
|
|
30893
|
-
definedName.formula = safe(
|
|
31553
|
+
definedName.formula = safe(rewrite2, definedName.formula, local?.name ?? "");
|
|
30894
31554
|
}
|
|
30895
31555
|
}
|
|
30896
|
-
function rewriteSheetFormulas(sheet,
|
|
30897
|
-
rewritePreservedFormulas(sheet,
|
|
31556
|
+
function rewriteSheetFormulas(sheet, rewrite2) {
|
|
31557
|
+
rewritePreservedFormulas(sheet, rewrite2);
|
|
30898
31558
|
{
|
|
30899
31559
|
const name = sheet.name;
|
|
30900
31560
|
for (const table2 of sheet.tables)
|
|
30901
31561
|
for (const column of table2.columns)
|
|
30902
31562
|
if (column.calculatedColumnFormula !== void 0)
|
|
30903
|
-
column.calculatedColumnFormula = safe(
|
|
31563
|
+
column.calculatedColumnFormula = safe(rewrite2, column.calculatedColumnFormula, name);
|
|
30904
31564
|
for (const cells3 of sheet.rows.values())
|
|
30905
31565
|
for (const cell of cells3.values())
|
|
30906
|
-
if (cell.formula !== void 0) cell.formula = safe(
|
|
31566
|
+
if (cell.formula !== void 0) cell.formula = safe(rewrite2, cell.formula, name);
|
|
30907
31567
|
for (const cf of sheet.conditionalFormats)
|
|
30908
|
-
for (const rule2 of cf.rules) rewriteConditionalRule(rule2, (f6) =>
|
|
31568
|
+
for (const rule2 of cf.rules) rewriteConditionalRule(rule2, (f6) => rewrite2(f6, name));
|
|
30909
31569
|
for (const dv of sheet.dataValidations) {
|
|
30910
|
-
if (dv.formula1 !== void 0) dv.formula1 = safe(
|
|
30911
|
-
if (dv.formula2 !== void 0) dv.formula2 = safe(
|
|
31570
|
+
if (dv.formula1 !== void 0) dv.formula1 = safe(rewrite2, dv.formula1, name);
|
|
31571
|
+
if (dv.formula2 !== void 0) dv.formula2 = safe(rewrite2, dv.formula2, name);
|
|
30912
31572
|
}
|
|
30913
31573
|
for (const link of sheet.hyperlinks)
|
|
30914
31574
|
if (link.location && /![A-Za-z$]/.test(link.location))
|
|
30915
|
-
link.location = safe(
|
|
31575
|
+
link.location = safe(rewrite2, link.location, name);
|
|
30916
31576
|
for (const drawing of sheet.drawings) {
|
|
30917
31577
|
if (drawing.kind !== "chart") continue;
|
|
30918
31578
|
for (const series of drawing.series) {
|
|
30919
|
-
if (series.nameRef) series.nameRef = safe(
|
|
30920
|
-
if (series.categoriesRef) series.categoriesRef = safe(
|
|
30921
|
-
if (series.valuesRef) series.valuesRef = safe(
|
|
31579
|
+
if (series.nameRef) series.nameRef = safe(rewrite2, series.nameRef, name);
|
|
31580
|
+
if (series.categoriesRef) series.categoriesRef = safe(rewrite2, series.categoriesRef, name);
|
|
31581
|
+
if (series.valuesRef) series.valuesRef = safe(rewrite2, series.valuesRef, name);
|
|
30922
31582
|
}
|
|
30923
31583
|
}
|
|
30924
31584
|
}
|
|
@@ -31105,7 +31765,7 @@ function shiftAxis(ctx, s, axis, at2, count2, insert) {
|
|
|
31105
31765
|
applyAxisShift(ctx, sheet, shift2);
|
|
31106
31766
|
if (insert) inheritFormats(sheet, axis, at2, count2);
|
|
31107
31767
|
},
|
|
31108
|
-
{ sheet: s, structural: true }
|
|
31768
|
+
{ sheet: s, structural: true, calc: { kind: "shift", sheet: s, shift: shift2 } }
|
|
31109
31769
|
);
|
|
31110
31770
|
}
|
|
31111
31771
|
var insertRows = (ctx, s, at2, count2) => shiftAxis(ctx, s, "row", at2, count2, true);
|
|
@@ -31324,10 +31984,10 @@ function parseCssColor(text2) {
|
|
|
31324
31984
|
return {
|
|
31325
31985
|
rgb: (hex.length === 3 ? [...hex].map((ch) => ch + ch).join("") : hex).toUpperCase()
|
|
31326
31986
|
};
|
|
31327
|
-
const
|
|
31328
|
-
if (
|
|
31987
|
+
const rgb3 = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(value);
|
|
31988
|
+
if (rgb3)
|
|
31329
31989
|
return {
|
|
31330
|
-
rgb:
|
|
31990
|
+
rgb: rgb3.slice(1, 4).map((n) => Math.min(255, Number(n)).toString(16).padStart(2, "0")).join("").toUpperCase()
|
|
31331
31991
|
};
|
|
31332
31992
|
const named3 = NAMED_COLORS2[value];
|
|
31333
31993
|
return named3 ? { rgb: named3 } : void 0;
|
|
@@ -31412,10 +32072,10 @@ function removeComments(text2) {
|
|
|
31412
32072
|
let from = 0;
|
|
31413
32073
|
for (; ; ) {
|
|
31414
32074
|
const open = text2.indexOf("<!--", from);
|
|
31415
|
-
const
|
|
31416
|
-
if (
|
|
32075
|
+
const close2 = open < 0 ? -1 : text2.indexOf("-->", open + 4);
|
|
32076
|
+
if (close2 < 0) return out + text2.slice(from);
|
|
31417
32077
|
out += text2.slice(from, open);
|
|
31418
|
-
from =
|
|
32078
|
+
from = close2 + 3;
|
|
31419
32079
|
}
|
|
31420
32080
|
}
|
|
31421
32081
|
function removeTags(text2) {
|
|
@@ -31553,12 +32213,12 @@ function parseTsv(text2) {
|
|
|
31553
32213
|
while (i2 < body.length) {
|
|
31554
32214
|
const ch = body[i2] ?? "";
|
|
31555
32215
|
if (atFieldStart && ch === '"') {
|
|
31556
|
-
const
|
|
31557
|
-
if (
|
|
31558
|
-
const next = body[
|
|
32216
|
+
const close2 = findClosingQuote(body, i2 + 1);
|
|
32217
|
+
if (close2 >= 0) {
|
|
32218
|
+
const next = body[close2 + 1];
|
|
31559
32219
|
if (next === void 0 || next === " " || next === "\n") {
|
|
31560
|
-
field = body.slice(i2 + 1,
|
|
31561
|
-
i2 =
|
|
32220
|
+
field = body.slice(i2 + 1, close2).replace(/""/g, '"');
|
|
32221
|
+
i2 = close2 + 1;
|
|
31562
32222
|
atFieldStart = false;
|
|
31563
32223
|
continue;
|
|
31564
32224
|
}
|
|
@@ -32919,6 +33579,14 @@ function setCalcMode(ctx, mode) {
|
|
|
32919
33579
|
|
|
32920
33580
|
// xlsx/edit/session-calc.ts
|
|
32921
33581
|
var isStructural = (step) => step.structural || step.entries.some((entry3) => entry3.before.kind !== "cells");
|
|
33582
|
+
function hintFor(step, mode) {
|
|
33583
|
+
const hint = step.calc;
|
|
33584
|
+
if (!hint) return void 0;
|
|
33585
|
+
if (hint.kind === "rename")
|
|
33586
|
+
return mode === "undo" ? { kind: "rename", from: hint.to, to: hint.from } : hint;
|
|
33587
|
+
return mode === "undo" ? void 0 : hint;
|
|
33588
|
+
}
|
|
33589
|
+
var settingsOf = (workbook) => `${workbook.iterate ? `${workbook.iterate.count}:${workbook.iterate.delta}` : ""}|${workbook.date1904}`;
|
|
32922
33590
|
var SessionCalculator = class {
|
|
32923
33591
|
constructor(workbook, calc, enabled2) {
|
|
32924
33592
|
this.workbook = workbook;
|
|
@@ -32928,43 +33596,113 @@ var SessionCalculator = class {
|
|
|
32928
33596
|
workbook;
|
|
32929
33597
|
calc;
|
|
32930
33598
|
enabled;
|
|
32931
|
-
/** Structural edits
|
|
33599
|
+
/** Structural edits the engine could not follow leave the dependency graph stale (manual mode). */
|
|
32932
33600
|
staleGraph = false;
|
|
33601
|
+
/** Cells changed in manual mode since the last calculation. */
|
|
33602
|
+
dirty = [];
|
|
33603
|
+
/** The settings at the last calculation; undefined before the first. */
|
|
33604
|
+
calculated;
|
|
32933
33605
|
/** Recalculates after an applied, undone or redone step (failures become warnings). */
|
|
32934
|
-
afterStep(step) {
|
|
32935
|
-
if (!this.enabled)
|
|
33606
|
+
afterStep(step, mode = "apply") {
|
|
33607
|
+
if (!this.enabled) {
|
|
33608
|
+
this.calc.discardPreparation();
|
|
33609
|
+
return;
|
|
33610
|
+
}
|
|
33611
|
+
const structural = isStructural(step);
|
|
33612
|
+
const hint = structural ? hintFor(step, mode) : void 0;
|
|
32936
33613
|
if (calcModeOf(this.workbook) === "manual") {
|
|
32937
|
-
if (
|
|
33614
|
+
if (hint && !this.staleGraph && !this.dirty.length) {
|
|
33615
|
+
this.guard(() => this.follow(hint));
|
|
33616
|
+
return;
|
|
33617
|
+
}
|
|
33618
|
+
this.calc.discardPreparation();
|
|
33619
|
+
if (structural) this.staleGraph = true;
|
|
33620
|
+
else this.dirty.push(...touchedCells(step));
|
|
32938
33621
|
return;
|
|
32939
33622
|
}
|
|
32940
|
-
|
|
33623
|
+
if (hint && !this.staleGraph) {
|
|
33624
|
+
this.guard(() => {
|
|
33625
|
+
this.follow(hint);
|
|
33626
|
+
this.calc.recalculateFrom(touchedCells(step));
|
|
33627
|
+
this.calculated = settingsOf(this.workbook);
|
|
33628
|
+
});
|
|
33629
|
+
return;
|
|
33630
|
+
}
|
|
33631
|
+
this.recalc(structural, () => touchedCells(step));
|
|
32941
33632
|
}
|
|
32942
33633
|
/** Recalculates after a change applied outside the history (a collaborator's edit). */
|
|
32943
33634
|
afterExternal(structural, cells3) {
|
|
32944
|
-
if (!this.enabled)
|
|
32945
|
-
|
|
33635
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual") {
|
|
33636
|
+
this.calc.discardPreparation();
|
|
33637
|
+
if (!this.enabled) return;
|
|
32946
33638
|
if (structural) this.staleGraph = true;
|
|
33639
|
+
else this.dirty.push(...cells3);
|
|
32947
33640
|
return;
|
|
32948
33641
|
}
|
|
32949
33642
|
this.recalc(structural, () => cells3);
|
|
32950
33643
|
}
|
|
32951
|
-
|
|
33644
|
+
follow(hint) {
|
|
33645
|
+
if (hint.kind === "shift") this.calc.shiftCells(hint.sheet, hint.shift);
|
|
33646
|
+
else this.calc.renameSheet(hint.from, hint.to);
|
|
33647
|
+
}
|
|
33648
|
+
guard(run2) {
|
|
32952
33649
|
try {
|
|
33650
|
+
run2();
|
|
33651
|
+
} catch (error) {
|
|
33652
|
+
const message = `Recalculation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
33653
|
+
if (!this.workbook.warnings.includes(message)) this.workbook.warnings.push(message);
|
|
33654
|
+
}
|
|
33655
|
+
}
|
|
33656
|
+
/** Builds the dependency graph ahead of the first edit (see `EditSession.prepareCalculation`). */
|
|
33657
|
+
prepare(timeRemaining) {
|
|
33658
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual" || this.staleGraph) return true;
|
|
33659
|
+
try {
|
|
33660
|
+
return this.calc.prepare(timeRemaining);
|
|
33661
|
+
} catch {
|
|
33662
|
+
this.calc.discardPreparation();
|
|
33663
|
+
return true;
|
|
33664
|
+
}
|
|
33665
|
+
}
|
|
33666
|
+
/**
|
|
33667
|
+
* Before a structural edit the graph can follow in place: finishes a graph being prepared (or
|
|
33668
|
+
* builds it) while it still matches the workbook, so the edit moves it instead of rebuilding.
|
|
33669
|
+
*/
|
|
33670
|
+
beforeStructural() {
|
|
33671
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual" || this.staleGraph) return;
|
|
33672
|
+
this.prepare();
|
|
33673
|
+
}
|
|
33674
|
+
recalc(structural, cells3) {
|
|
33675
|
+
this.guard(() => {
|
|
32953
33676
|
if (this.staleGraph || structural) this.full();
|
|
32954
33677
|
else {
|
|
32955
33678
|
const changed = cells3();
|
|
32956
33679
|
if (changed.length) this.calc.recalculateFrom(changed);
|
|
33680
|
+
this.calculated = settingsOf(this.workbook);
|
|
32957
33681
|
}
|
|
32958
|
-
}
|
|
32959
|
-
const message = `Recalculation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
32960
|
-
if (!this.workbook.warnings.includes(message)) this.workbook.warnings.push(message);
|
|
32961
|
-
}
|
|
33682
|
+
});
|
|
32962
33683
|
}
|
|
32963
|
-
/** Rebuilds the dependency graph and recalculates every formula (F9). */
|
|
33684
|
+
/** Rebuilds the dependency graph and recalculates every formula (Ctrl+Alt+F9). */
|
|
32964
33685
|
full() {
|
|
32965
33686
|
this.staleGraph = false;
|
|
33687
|
+
this.dirty = [];
|
|
32966
33688
|
this.calc.invalidate();
|
|
32967
33689
|
this.calc.recalculateAll();
|
|
33690
|
+
this.calculated = settingsOf(this.workbook);
|
|
33691
|
+
}
|
|
33692
|
+
/**
|
|
33693
|
+
* Calculate Now (F9): the cells changed since the last calculation, the formulas structural
|
|
33694
|
+
* edits queued, their dependents and the volatile functions. Everything when `full`, before
|
|
33695
|
+
* the session's first calculation, after the iteration settings changed or while the graph
|
|
33696
|
+
* is stale.
|
|
33697
|
+
*/
|
|
33698
|
+
now(full) {
|
|
33699
|
+
if (full || this.staleGraph || this.calculated !== settingsOf(this.workbook)) {
|
|
33700
|
+
this.full();
|
|
33701
|
+
return;
|
|
33702
|
+
}
|
|
33703
|
+
const changed = this.dirty;
|
|
33704
|
+
this.dirty = [];
|
|
33705
|
+
this.calc.recalculateFrom(changed);
|
|
32968
33706
|
}
|
|
32969
33707
|
/**
|
|
32970
33708
|
* Recalculates one sheet's formulas and their dependents (Shift+F9); after structural edits
|
|
@@ -36768,12 +37506,12 @@ function renameSheet(ctx, index2, name) {
|
|
|
36768
37506
|
ctx.run(
|
|
36769
37507
|
"Rename sheet",
|
|
36770
37508
|
"sheets",
|
|
36771
|
-
[{ kind: "
|
|
37509
|
+
[{ kind: "refs" }],
|
|
36772
37510
|
() => {
|
|
36773
37511
|
rewriteFormulas(workbook, (formula) => renameSheetInFormula(formula, old, name));
|
|
36774
37512
|
sheet.name = name;
|
|
36775
37513
|
},
|
|
36776
|
-
{ sheet: index2, structural: true }
|
|
37514
|
+
{ sheet: index2, structural: true, calc: { kind: "rename", from: old, to: name } }
|
|
36777
37515
|
);
|
|
36778
37516
|
}
|
|
36779
37517
|
function moveSheet(ctx, from, to) {
|
|
@@ -37149,13 +37887,12 @@ function createEditSession(workbook, options = {}) {
|
|
|
37149
37887
|
for (const listener of [...listeners]) listener(change);
|
|
37150
37888
|
};
|
|
37151
37889
|
const calculator = new SessionCalculator(workbook, calc, autoRecalc);
|
|
37152
|
-
const recalc = (step) => calculator.afterStep(step);
|
|
37153
|
-
const begin = (label2, kind, info) =>
|
|
37154
|
-
step
|
|
37155
|
-
|
|
37156
|
-
sheet: info.sheet,
|
|
37157
|
-
|
|
37158
|
-
});
|
|
37890
|
+
const recalc = (step, mode = "apply") => calculator.afterStep(step, mode);
|
|
37891
|
+
const begin = (label2, kind, info) => {
|
|
37892
|
+
const step = { label: label2, entries: [], structural: info.structural ?? false };
|
|
37893
|
+
if (info.calc) step.calc = info.calc;
|
|
37894
|
+
return { step, kind, sheet: info.sheet, ranges: [...info.ranges ?? []] };
|
|
37895
|
+
};
|
|
37159
37896
|
const finish = (current) => {
|
|
37160
37897
|
if (!current.step.entries.length) return;
|
|
37161
37898
|
history.push(current.step);
|
|
@@ -37180,10 +37917,12 @@ function createEditSession(workbook, options = {}) {
|
|
|
37180
37917
|
const outer = !open;
|
|
37181
37918
|
const current = open ?? begin(label2, kind, info);
|
|
37182
37919
|
if (!outer) {
|
|
37920
|
+
delete current.step.calc;
|
|
37183
37921
|
if (info.structural) current.step.structural = true;
|
|
37184
37922
|
if (current.sheet === void 0 && info.sheet !== void 0) current.sheet = info.sheet;
|
|
37185
37923
|
current.ranges.push(...info.ranges ?? []);
|
|
37186
37924
|
}
|
|
37925
|
+
if (outer && info.calc) calculator.beforeStructural();
|
|
37187
37926
|
open = current;
|
|
37188
37927
|
const mark = current.step.entries.length;
|
|
37189
37928
|
const befores = scopes.map((scope) => captureScope(workbook, scope));
|
|
@@ -37231,7 +37970,7 @@ function createEditSession(workbook, options = {}) {
|
|
|
37231
37970
|
if (open) throw new Error(`Cannot ${kind} inside a batch`);
|
|
37232
37971
|
const step = kind === "undo" ? history.undo(workbook) : history.redo(workbook);
|
|
37233
37972
|
if (!step) return false;
|
|
37234
|
-
recalc(step);
|
|
37973
|
+
recalc(step, kind);
|
|
37235
37974
|
emit({ kind, label: step.label, structural: step.structural });
|
|
37236
37975
|
return true;
|
|
37237
37976
|
};
|
|
@@ -37310,10 +38049,11 @@ function createEditSession(workbook, options = {}) {
|
|
|
37310
38049
|
setDocumentProperties: (patch) => setDocumentProperties(ctx, patch),
|
|
37311
38050
|
setAutoRecalc: (enabled2) => setCalcMode(ctx, enabled2 ? "auto" : "manual"),
|
|
37312
38051
|
autoRecalc: () => autoRecalc && calcModeOf(workbook) === "auto",
|
|
37313
|
-
calculateNow() {
|
|
37314
|
-
calculator.full
|
|
38052
|
+
calculateNow(options2) {
|
|
38053
|
+
calculator.now(options2?.full ?? false);
|
|
37315
38054
|
emit({ kind: "cells", label: "Calculate now", structural: false });
|
|
37316
38055
|
},
|
|
38056
|
+
prepareCalculation: (opts) => calculator.prepare(opts?.timeRemaining),
|
|
37317
38057
|
calculateSheet(s) {
|
|
37318
38058
|
calculator.sheet(s);
|
|
37319
38059
|
emit({ kind: "cells", label: "Calculate sheet", sheet: s, structural: false });
|
|
@@ -40438,20 +41178,20 @@ function drawingPaint(node, colors, placeholder, depth = 0) {
|
|
|
40438
41178
|
(transform7) => !SUPPORTED_TRANSFORMS.has(transform7.name) || (integer3(transform7.value) ?? 100001) > 1e5
|
|
40439
41179
|
))
|
|
40440
41180
|
return void 0;
|
|
40441
|
-
let
|
|
41181
|
+
let rgb3;
|
|
40442
41182
|
let inherited;
|
|
40443
|
-
if (color2.kind === "srgb")
|
|
40444
|
-
else if (color2.kind === "system")
|
|
41183
|
+
if (color2.kind === "srgb") rgb3 = color2.value;
|
|
41184
|
+
else if (color2.kind === "system") rgb3 = color2.fallback;
|
|
40445
41185
|
else if (color2.kind === "scheme") {
|
|
40446
|
-
if (color2.value === "phClr")
|
|
41186
|
+
if (color2.value === "phClr") rgb3 = placeholder;
|
|
40447
41187
|
else {
|
|
40448
41188
|
inherited = drawingPaint(colors.get(color2.value), colors, placeholder, depth + 1);
|
|
40449
|
-
|
|
41189
|
+
rgb3 = inherited?.color;
|
|
40450
41190
|
}
|
|
40451
41191
|
}
|
|
40452
|
-
if (!
|
|
41192
|
+
if (!rgb3 || !/^#?[\da-f]{6}$/i.test(rgb3)) return void 0;
|
|
40453
41193
|
const resolved = resolveDrawingColor(
|
|
40454
|
-
{ kind: "srgb", value:
|
|
41194
|
+
{ kind: "srgb", value: rgb3.replace(/^#/, ""), transforms },
|
|
40455
41195
|
void 0,
|
|
40456
41196
|
{ }
|
|
40457
41197
|
);
|
|
@@ -41249,13 +41989,7 @@ function lineCap(cells3, resources, report) {
|
|
|
41249
41989
|
}
|
|
41250
41990
|
const value = number(cells3, "LineCap", NaN, report);
|
|
41251
41991
|
if (value === 0) return "round";
|
|
41252
|
-
if (value === 1 || value === 2)
|
|
41253
|
-
report(
|
|
41254
|
-
"inferred-line-cap",
|
|
41255
|
-
"Legacy square/extended cap geometry uses an inferred compatibility mapping."
|
|
41256
|
-
);
|
|
41257
|
-
return value === 1 ? "butt" : "square";
|
|
41258
|
-
}
|
|
41992
|
+
if (value === 1 || value === 2) return value === 1 ? "butt" : "square";
|
|
41259
41993
|
if (Number.isFinite(value))
|
|
41260
41994
|
report("invalid-line-cap", "The cached line cap is outside the supported enumeration.");
|
|
41261
41995
|
return void 0;
|
|
@@ -41263,13 +41997,12 @@ function lineCap(cells3, resources, report) {
|
|
|
41263
41997
|
|
|
41264
41998
|
// visio/line-pattern.ts
|
|
41265
41999
|
function builtinDash(pattern) {
|
|
41266
|
-
if (pattern === 23) return [2,
|
|
42000
|
+
if (pattern === 23) return [2, 1];
|
|
41267
42001
|
const band = Math.floor((pattern - 2) / 7);
|
|
41268
42002
|
const motif = (pattern - 2) % 7;
|
|
41269
|
-
const dash = [
|
|
41270
|
-
const gap = [
|
|
41271
|
-
const long = [
|
|
41272
|
-
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];
|
|
41273
42006
|
const lengths = [
|
|
41274
42007
|
[dash],
|
|
41275
42008
|
[1],
|
|
@@ -41279,9 +42012,9 @@ function builtinDash(pattern) {
|
|
|
41279
42012
|
[long, dash],
|
|
41280
42013
|
[long, dash, dash]
|
|
41281
42014
|
][motif];
|
|
41282
|
-
return lengths.flatMap((length) => [length,
|
|
42015
|
+
return lengths.flatMap((length) => [length, gap]);
|
|
41283
42016
|
}
|
|
41284
|
-
function linePattern(cells3, report) {
|
|
42017
|
+
function linePattern(cells3, report, cap = "round") {
|
|
41285
42018
|
const raw2 = cells3.get("LinePattern")?.value;
|
|
41286
42019
|
if (raw2 === "Themed") {
|
|
41287
42020
|
report(
|
|
@@ -41296,11 +42029,14 @@ function linePattern(cells3, report) {
|
|
|
41296
42029
|
}
|
|
41297
42030
|
const pattern = number(cells3, "LinePattern", 1, report);
|
|
41298
42031
|
if (Number.isInteger(pattern) && pattern >= 2 && pattern <= 23) {
|
|
41299
|
-
|
|
41300
|
-
"
|
|
41301
|
-
"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)
|
|
41302
42034
|
);
|
|
41303
|
-
return {
|
|
42035
|
+
return {
|
|
42036
|
+
linePattern: pattern,
|
|
42037
|
+
lineDash,
|
|
42038
|
+
...cap === "square" && lineDash.includes(0) ? { lineDashDotLength: 0.01 / 72 } : {}
|
|
42039
|
+
};
|
|
41304
42040
|
}
|
|
41305
42041
|
if (pattern === 254)
|
|
41306
42042
|
report(
|
|
@@ -41317,6 +42053,25 @@ function linePattern(cells3, report) {
|
|
|
41317
42053
|
return { linePattern: pattern };
|
|
41318
42054
|
}
|
|
41319
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
|
+
|
|
41320
42075
|
// visio/text-background.ts
|
|
41321
42076
|
function textBackground(cells3, resources, report) {
|
|
41322
42077
|
const raw2 = cells3.get("TextBkgnd")?.value;
|
|
@@ -41397,6 +42152,15 @@ function textParagraphs(text2, markers, sheet, fontFamily, fontSize, resources,
|
|
|
41397
42152
|
return paragraphs;
|
|
41398
42153
|
}
|
|
41399
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
|
+
|
|
41400
42164
|
// visio/nurbs-flatten.ts
|
|
41401
42165
|
var CURVE_TOLERANCE = 1e-4;
|
|
41402
42166
|
var MAX_WORK = 2e6;
|
|
@@ -42117,11 +42881,13 @@ function shapeStyle(sheet, resources, report, width = number(sheet.cells, "Width
|
|
|
42117
42881
|
fill: pattern === 0 ? "none" : color(cells3, "FillForegnd", "#ffffff", resources, report, cells3, !!fillGradient),
|
|
42118
42882
|
...fillGradient ? { fillGradient } : {},
|
|
42119
42883
|
...fillPattern ? { fillPattern } : {},
|
|
42884
|
+
...sourcePaint(cells3, (name, fallback) => color(cells3, name, fallback, resources, () => {
|
|
42885
|
+
})),
|
|
42120
42886
|
lineColor: color(cells3, "LineColor", "#000000", resources, report),
|
|
42121
42887
|
...lineGradient ? { lineGradient } : {},
|
|
42122
42888
|
lineWidth: themeLineWeight(cells3, resources, report) ?? Math.max(0, number(cells3, "LineWeight", 0.01, report)),
|
|
42123
42889
|
...cap === void 0 ? {} : { lineCap: cap },
|
|
42124
|
-
...themeSolidLinePattern(cells3, resources) ?? linePattern(cells3, report),
|
|
42890
|
+
...themeSolidLinePattern(cells3, resources) ?? linePattern(cells3, report, cap),
|
|
42125
42891
|
// Saved and legacy stop transparencies already supply the fill opacity.
|
|
42126
42892
|
fillOpacity: savedGradient || legacyGradient || fillPattern ? 1 : opacity(number(cells3, "FillForegndTrans", 0, report)),
|
|
42127
42893
|
lineOpacity: lineGradient ? 1 : opacity(number(cells3, "LineColorTrans", 0, report)),
|
|
@@ -42145,7 +42911,8 @@ function runStyle(cells3, resources, report, themeCells) {
|
|
|
42145
42911
|
...transparency > 0 ? { opacity: 1 - Math.round(transparency * 255) / 255 } : {},
|
|
42146
42912
|
bold: !!(bits & 1),
|
|
42147
42913
|
italic: !!(bits & 2),
|
|
42148
|
-
underline: !!(bits & 4)
|
|
42914
|
+
underline: !!(bits & 4),
|
|
42915
|
+
strikethrough: number(cells3, "Strikethru", 0, report) !== 0
|
|
42149
42916
|
};
|
|
42150
42917
|
}
|
|
42151
42918
|
function shapeText(sheet, node, width, height, resources, report, consume, consumeParagraph) {
|
|
@@ -42155,8 +42922,9 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
|
|
|
42155
42922
|
let currentCells = defaultCells;
|
|
42156
42923
|
const runs = [];
|
|
42157
42924
|
const paragraphMarkers = [];
|
|
42158
|
-
let textOffset = 0;
|
|
42159
|
-
const append = (text2) => {
|
|
42925
|
+
let textOffset = 0, terminalDirectText = false;
|
|
42926
|
+
const append = (text2, direct = false) => {
|
|
42927
|
+
terminalDirectText = direct;
|
|
42160
42928
|
if (text2) {
|
|
42161
42929
|
consume(text2.length);
|
|
42162
42930
|
runs.push({ text: text2, ...runStyle(currentCells, resources, report, cells3) });
|
|
@@ -42165,8 +42933,9 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
|
|
|
42165
42933
|
};
|
|
42166
42934
|
if (node && !number(cells3, "HideText", 0, report)) {
|
|
42167
42935
|
for (const part of Array.from(node.childNodes)) {
|
|
42168
|
-
if (part.nodeType === 3 || part.nodeType === 4)
|
|
42169
|
-
|
|
42936
|
+
if (part.nodeType === 3 || part.nodeType === 4) {
|
|
42937
|
+
if (part.nodeValue) append(part.nodeValue, true);
|
|
42938
|
+
} else if (part.nodeType === 1) {
|
|
42170
42939
|
const element2 = part;
|
|
42171
42940
|
if (element2.localName === "cp")
|
|
42172
42941
|
currentCells = characters.get(element2.getAttribute("IX") ?? "0") ?? defaultCells;
|
|
@@ -42187,10 +42956,10 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
|
|
|
42187
42956
|
const alignment = number(paragraph2, "HorzAlign", 1, report);
|
|
42188
42957
|
const textWidth = Math.max(0, number(cells3, "TxtWidth", width, report)), textHeight = Math.max(0, number(cells3, "TxtHeight", height, report));
|
|
42189
42958
|
const vertical = number(cells3, "VerticalAlign", 1, report);
|
|
42190
|
-
const
|
|
42959
|
+
const storedText = runs.map((r) => r.text).join("");
|
|
42191
42960
|
const defaultRun = runStyle(defaultCells, resources, report, cells3);
|
|
42192
42961
|
const paragraphs = textParagraphs(
|
|
42193
|
-
|
|
42962
|
+
storedText,
|
|
42194
42963
|
paragraphMarkers,
|
|
42195
42964
|
sheet,
|
|
42196
42965
|
defaultRun.fontFamily,
|
|
@@ -42200,13 +42969,16 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
|
|
|
42200
42969
|
runs,
|
|
42201
42970
|
consumeParagraph
|
|
42202
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("");
|
|
42203
42975
|
return {
|
|
42204
42976
|
plainText,
|
|
42205
42977
|
...textBackground(cells3, resources, report),
|
|
42206
42978
|
paragraphs,
|
|
42207
42979
|
runs,
|
|
42208
42980
|
...runStyle(defaultCells, resources, report, cells3),
|
|
42209
|
-
horizontalAlign: alignment === 1 ? "center" : alignment === 2 ? "right" : "left",
|
|
42981
|
+
horizontalAlign: alignment === 1 ? "center" : alignment === 2 ? "right" : alignment === 3 ? "justify" : "left",
|
|
42210
42982
|
verticalAlign: vertical === 0 ? "top" : vertical === 2 ? "bottom" : "middle",
|
|
42211
42983
|
width: textWidth,
|
|
42212
42984
|
height: textHeight,
|
|
@@ -42647,6 +43419,7 @@ var LINE_PROPERTIES = [
|
|
|
42647
43419
|
"LineCap",
|
|
42648
43420
|
"LinePattern",
|
|
42649
43421
|
"LineColorTrans",
|
|
43422
|
+
"LineGradientEnabled",
|
|
42650
43423
|
"BeginArrow",
|
|
42651
43424
|
"EndArrow",
|
|
42652
43425
|
"BeginArrowSize",
|
|
@@ -43218,12 +43991,26 @@ async function parseVsdx(input, options = {}) {
|
|
|
43218
43991
|
};
|
|
43219
43992
|
for (const color2 of children3(child5(documentRoot, "Colors"), "ColorEntry"))
|
|
43220
43993
|
resources.colors.set(attribute3(color2, "IX") ?? "", attribute3(color2, "RGB") ?? "");
|
|
43221
|
-
children3(child5(documentRoot, "FaceNames"), "FaceName")
|
|
43222
|
-
|
|
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(
|
|
43223
44010
|
metadata(attribute3(font2, "ID") ?? String(index2), 256, "Font ID"),
|
|
43224
44011
|
metadata(attribute3(font2, "Name") ?? attribute3(font2, "NameU") ?? "Arial", 1024, "Font name")
|
|
43225
|
-
)
|
|
43226
|
-
);
|
|
44012
|
+
);
|
|
44013
|
+
});
|
|
43227
44014
|
const styles = /* @__PURE__ */ new Map();
|
|
43228
44015
|
for (const style2 of children3(child5(documentRoot, "StyleSheets"), "StyleSheet"))
|
|
43229
44016
|
styles.set(metadata(attribute3(style2, "ID") ?? "", 256, "Style ID"), {
|
|
@@ -43390,7 +44177,12 @@ async function parseVsdx(input, options = {}) {
|
|
|
43390
44177
|
"ShapeSheet formulas, automatic connector routing, and external data are not evaluated; saved cached values and supported theme records are used.",
|
|
43391
44178
|
{ severity: "info" }
|
|
43392
44179
|
);
|
|
43393
|
-
return {
|
|
44180
|
+
return {
|
|
44181
|
+
format: "vsdx",
|
|
44182
|
+
pages,
|
|
44183
|
+
diagnostics: diagnosticState.finish(),
|
|
44184
|
+
fontFamilies: [...new Set(resources.fonts.values())]
|
|
44185
|
+
};
|
|
43394
44186
|
}
|
|
43395
44187
|
|
|
43396
44188
|
// automation/visio.ts
|
|
@@ -43545,203 +44337,12 @@ function writeEditedPackage(parts, maxBytes, deadline, check3) {
|
|
|
43545
44337
|
});
|
|
43546
44338
|
}
|
|
43547
44339
|
|
|
43548
|
-
// visio/
|
|
43549
|
-
function
|
|
43550
|
-
|
|
43551
|
-
const containers = children3(parent, "Shapes");
|
|
43552
|
-
if (containers.length > 1)
|
|
43553
|
-
fail2("INVALID_SHAPE_ID", "Duplicate Shapes containers are ambiguous.");
|
|
43554
|
-
return children3(containers[0], "Shape");
|
|
43555
|
-
};
|
|
43556
|
-
const shapes = /* @__PURE__ */ new Map();
|
|
43557
|
-
const pending2 = shapeChildren(root).map((node2) => ({
|
|
43558
|
-
node: node2,
|
|
43559
|
-
inherited: false,
|
|
43560
|
-
deleted: false
|
|
43561
|
-
}));
|
|
43562
|
-
while (pending2.length) {
|
|
43563
|
-
check3();
|
|
43564
|
-
const item = pending2.pop();
|
|
43565
|
-
const id = attribute3(item.node, "ID");
|
|
43566
|
-
if (!id || shapes.has(id))
|
|
43567
|
-
fail2("INVALID_SHAPE_ID", "Local shape IDs must be present and unique.");
|
|
43568
|
-
const inherited = item.inherited || item.node.hasAttribute("Master") || item.node.hasAttribute("MasterShape");
|
|
43569
|
-
const deleted = item.deleted || ["1", "true"].includes(attribute3(item.node, "Del") ?? "");
|
|
43570
|
-
shapes.set(id, { node: item.node, inherited, deleted });
|
|
43571
|
-
for (const node2 of shapeChildren(item.node)) pending2.push({ node: node2, inherited, deleted });
|
|
43572
|
-
}
|
|
43573
|
-
const target = shapes.get(shapeId);
|
|
43574
|
-
if (!target) fail2("EDIT_TARGET_NOT_FOUND", "Local shape does not exist.");
|
|
43575
|
-
if (target.inherited || target.deleted)
|
|
43576
|
-
fail2("UNSUPPORTED_TEXT_EDIT", "Master-linked or deleted shapes cannot be edited.");
|
|
43577
|
-
const texts = children3(target.node, "Text");
|
|
43578
|
-
if (texts.length !== 1)
|
|
43579
|
-
fail2("UNSUPPORTED_TEXT_EDIT", "Editing requires one existing local Text element.");
|
|
43580
|
-
const node = texts[0];
|
|
43581
|
-
if (Array.from(node.childNodes).some((item) => item.nodeType !== 3 && item.nodeType !== 4))
|
|
43582
|
-
fail2("UNSUPPORTED_TEXT_EDIT", "Rich text, fields and unknown text markup cannot be edited.");
|
|
43583
|
-
if (children3(target.node, "Section").some((section) => attribute3(section, "N") === "Field"))
|
|
43584
|
-
fail2("UNSUPPORTED_TEXT_EDIT", "Shapes with text fields cannot be edited.");
|
|
43585
|
-
if (node.textContent === text2) return false;
|
|
43586
|
-
while (node.firstChild) node.removeChild(node.firstChild);
|
|
43587
|
-
node.appendChild(node.ownerDocument.createTextNode(text2));
|
|
43588
|
-
return true;
|
|
43589
|
-
}
|
|
43590
|
-
function serializeEditedXml(root, limits, check3) {
|
|
43591
|
-
check3();
|
|
43592
|
-
const pending2 = [root.ownerDocument];
|
|
43593
|
-
while (pending2.length) {
|
|
43594
|
-
check3();
|
|
43595
|
-
const node = pending2.pop();
|
|
43596
|
-
if ((node.nodeType === 3 || node.nodeType === 4) && node.nodeValue?.includes("\r"))
|
|
43597
|
-
fail2("UNSUPPORTED_XML_EDIT", "Carriage-return text cannot be preserved by this writer.");
|
|
43598
|
-
if (node.nodeType === 1) {
|
|
43599
|
-
for (const attr3 of Array.from(node.attributes))
|
|
43600
|
-
if (/[\t\r\n]/.test(attr3.value))
|
|
43601
|
-
fail2("UNSUPPORTED_XML_EDIT", "Attribute whitespace cannot be preserved by this writer.");
|
|
43602
|
-
}
|
|
43603
|
-
for (const child6 of Array.from(node.childNodes)) pending2.push(child6);
|
|
43604
|
-
}
|
|
43605
|
-
let xml = buildXml(root.ownerDocument);
|
|
43606
|
-
xml = xml.replace(
|
|
43607
|
-
/^<\?xml\s[^?]*\?>/,
|
|
43608
|
-
(declaration) => declaration.replace(/encoding\s*=\s*(['"])[^'"]*\1/, 'encoding="UTF-8"')
|
|
43609
|
-
);
|
|
43610
|
-
const nodes = inspectXml(xml, limits, check3);
|
|
43611
|
-
inspectNamespaces(root, check3);
|
|
43612
|
-
const bytes = new TextEncoder().encode(xml);
|
|
43613
|
-
if (bytes.length > limits.maxEntryBytes)
|
|
43614
|
-
fail2("LIMIT_ENTRY", "Edited XML part exceeds byte limit.");
|
|
43615
|
-
return { bytes, nodes };
|
|
43616
|
-
}
|
|
43617
|
-
|
|
43618
|
-
// visio/edit-commands.ts
|
|
43619
|
-
var isVisioPageEdit = (edit) => edit.type === "insert-page" || edit.type === "reorder-page" || edit.type === "rename-page" || edit.type === "delete-page";
|
|
43620
|
-
function geometryChangedCells(edit) {
|
|
43621
|
-
if (edit.type === "create-line")
|
|
43622
|
-
return [
|
|
43623
|
-
"BeginX",
|
|
43624
|
-
"BeginY",
|
|
43625
|
-
"EndX",
|
|
43626
|
-
"EndY",
|
|
43627
|
-
"PinX",
|
|
43628
|
-
"PinY",
|
|
43629
|
-
"Width",
|
|
43630
|
-
"Height",
|
|
43631
|
-
"Angle",
|
|
43632
|
-
"LocPinX",
|
|
43633
|
-
"LocPinY"
|
|
43634
|
-
];
|
|
43635
|
-
if (edit.type === "delete-shape") return [];
|
|
43636
|
-
if (edit.type === "move-line-endpoint") {
|
|
43637
|
-
const prefix = edit.endpoint === "begin" ? "Begin" : "End";
|
|
43638
|
-
return [`${prefix}X`, `${prefix}Y`];
|
|
43639
|
-
}
|
|
43640
|
-
if (edit.type === "move-shape") return ["PinX", "PinY"];
|
|
43641
|
-
if (edit.type === "resize-shape") return ["Width", "Height"];
|
|
43642
|
-
if (edit.type === "rotate-shape") return ["Angle"];
|
|
43643
|
-
if (edit.type === "flip-shape") return ["Angle", edit.axis === "horizontal" ? "FlipX" : "FlipY"];
|
|
43644
|
-
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;
|
|
43645
44343
|
}
|
|
43646
|
-
function
|
|
43647
|
-
|
|
43648
|
-
fail2("LIMIT_EDITS", "Edit command count exceeds limit.");
|
|
43649
|
-
let textLength = 0;
|
|
43650
|
-
const text2 = (value) => {
|
|
43651
|
-
if (typeof value !== "string") fail2("INVALID_EDIT", "Edit text must be a string.");
|
|
43652
|
-
textLength += value.length;
|
|
43653
|
-
if (textLength > maxText) fail2("LIMIT_EDIT_TEXT", "Replacement text exceeds aggregate limit.");
|
|
43654
|
-
if (/[\u0000-\u0008\u000b\u000c\u000d\u000e-\u001f\ufffe\uffff]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/u.test(
|
|
43655
|
-
value
|
|
43656
|
-
))
|
|
43657
|
-
fail2("INVALID_EDIT_TEXT", "Replacement text contains invalid XML characters.");
|
|
43658
|
-
return value;
|
|
43659
|
-
};
|
|
43660
|
-
const numeric5 = (value, dimension2 = false, allowZero = false) => {
|
|
43661
|
-
if (typeof value !== "number" || !Number.isFinite(value) || Math.abs(value) > 1e6 || dimension2 && (value < 0 || !allowZero && value === 0))
|
|
43662
|
-
fail2(
|
|
43663
|
-
"INVALID_EDIT",
|
|
43664
|
-
"Geometry requires finite drawing inches within limits and positive dimensions."
|
|
43665
|
-
);
|
|
43666
|
-
return value;
|
|
43667
|
-
};
|
|
43668
|
-
return Array.from(edits, (edit) => {
|
|
43669
|
-
if (!edit || typeof edit.pageId !== "string" || !edit.pageId || edit.pageId.length > 256)
|
|
43670
|
-
fail2("INVALID_EDIT", "Invalid edit target.");
|
|
43671
|
-
if (edit.type === "delete-page") return { type: edit.type, pageId: edit.pageId };
|
|
43672
|
-
if (edit.type === "reorder-page") {
|
|
43673
|
-
if (!Number.isSafeInteger(edit.index) || edit.index < 0 || edit.index > 1e6)
|
|
43674
|
-
fail2("INVALID_EDIT", "Page order requires a bounded zero-based integer index.");
|
|
43675
|
-
return { type: edit.type, pageId: edit.pageId, index: edit.index };
|
|
43676
|
-
}
|
|
43677
|
-
if (edit.type === "insert-page") {
|
|
43678
|
-
const name = text2(edit.name);
|
|
43679
|
-
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))
|
|
43680
|
-
fail2("INVALID_EDIT", "Invalid new page ID, name or insertion target.");
|
|
43681
|
-
return { type: edit.type, pageId: edit.pageId, afterPageId: edit.afterPageId, name };
|
|
43682
|
-
}
|
|
43683
|
-
if (edit.type === "rename-page") {
|
|
43684
|
-
const name = text2(edit.name);
|
|
43685
|
-
if (!name.trim() || name.length > 255 || /[\t\n]/.test(name))
|
|
43686
|
-
fail2("INVALID_EDIT", "Invalid page name.");
|
|
43687
|
-
return { type: edit.type, pageId: edit.pageId, name };
|
|
43688
|
-
}
|
|
43689
|
-
if (typeof edit.shapeId !== "string" || !edit.shapeId || edit.shapeId.length > 256)
|
|
43690
|
-
fail2("INVALID_EDIT", "Invalid edit shape target.");
|
|
43691
|
-
const target = { pageId: edit.pageId, shapeId: edit.shapeId };
|
|
43692
|
-
if (edit.type === "replace-plain-text")
|
|
43693
|
-
return { ...target, type: edit.type, text: text2(edit.text) };
|
|
43694
|
-
if (!/^[1-9]\d{0,9}$/.test(edit.shapeId) || Number(edit.shapeId) > 4294967295)
|
|
43695
|
-
fail2("INVALID_EDIT", "Geometry shape IDs must be canonical positive unsigned integers.");
|
|
43696
|
-
switch (edit.type) {
|
|
43697
|
-
case "create-line": {
|
|
43698
|
-
const beginX = numeric5(edit.beginX), beginY = numeric5(edit.beginY);
|
|
43699
|
-
const endX = numeric5(edit.endX), endY = numeric5(edit.endY);
|
|
43700
|
-
numeric5(Math.hypot(endX - beginX, endY - beginY), true);
|
|
43701
|
-
return { ...target, type: edit.type, beginX, beginY, endX, endY };
|
|
43702
|
-
}
|
|
43703
|
-
case "create-rectangle":
|
|
43704
|
-
case "create-ellipse":
|
|
43705
|
-
return {
|
|
43706
|
-
...target,
|
|
43707
|
-
type: edit.type,
|
|
43708
|
-
x: numeric5(edit.x),
|
|
43709
|
-
y: numeric5(edit.y),
|
|
43710
|
-
width: numeric5(edit.width, true),
|
|
43711
|
-
height: numeric5(edit.height, true),
|
|
43712
|
-
...edit.text === void 0 ? {} : { text: text2(edit.text) }
|
|
43713
|
-
};
|
|
43714
|
-
case "rotate-shape":
|
|
43715
|
-
return { ...target, type: edit.type, angle: numeric5(edit.angle) };
|
|
43716
|
-
case "flip-shape":
|
|
43717
|
-
if (edit.axis !== "horizontal" && edit.axis !== "vertical")
|
|
43718
|
-
fail2("INVALID_EDIT", "Invalid flip axis.");
|
|
43719
|
-
return { ...target, type: edit.type, axis: edit.axis };
|
|
43720
|
-
case "move-shape":
|
|
43721
|
-
return { ...target, type: edit.type, x: numeric5(edit.x), y: numeric5(edit.y) };
|
|
43722
|
-
case "move-line-endpoint":
|
|
43723
|
-
if (edit.endpoint !== "begin" && edit.endpoint !== "end")
|
|
43724
|
-
fail2("INVALID_EDIT", "A line endpoint must be begin or end.");
|
|
43725
|
-
return {
|
|
43726
|
-
...target,
|
|
43727
|
-
type: edit.type,
|
|
43728
|
-
endpoint: edit.endpoint,
|
|
43729
|
-
x: numeric5(edit.x),
|
|
43730
|
-
y: numeric5(edit.y)
|
|
43731
|
-
};
|
|
43732
|
-
case "resize-shape":
|
|
43733
|
-
return {
|
|
43734
|
-
...target,
|
|
43735
|
-
type: edit.type,
|
|
43736
|
-
width: numeric5(edit.width, true),
|
|
43737
|
-
height: numeric5(edit.height, true, true)
|
|
43738
|
-
};
|
|
43739
|
-
case "delete-shape":
|
|
43740
|
-
return { ...target, type: edit.type };
|
|
43741
|
-
default:
|
|
43742
|
-
return fail2("INVALID_EDIT", "Unsupported edit command.");
|
|
43743
|
-
}
|
|
43744
|
-
});
|
|
44344
|
+
function inertDoubleClickFormula(cell, source2) {
|
|
44345
|
+
return cell === "EventDblClick" && /^\s*=?\s*(OPENTEXTWIN|DEFAULTEVENT)\(\s*\)\s*$/i.test(source2);
|
|
43745
44346
|
}
|
|
43746
44347
|
|
|
43747
44348
|
// visio/formula-theme.ts
|
|
@@ -43827,11 +44428,11 @@ function evaluateNumericFormulaFunction(name, args) {
|
|
|
43827
44428
|
if (args.length < min || args.length > max)
|
|
43828
44429
|
return formulaFailure("arity", `Invalid ${name} argument count`);
|
|
43829
44430
|
};
|
|
43830
|
-
const
|
|
44431
|
+
const scalar4 = (value) => ({ value, unit: "scalar" });
|
|
43831
44432
|
if (name === "AND" || name === "OR" || name === "NOT") {
|
|
43832
44433
|
arity(1, name === "NOT" ? 1 : 1024);
|
|
43833
44434
|
const values2 = args.map((arg) => finiteFormulaValue(arg).value !== 0);
|
|
43834
|
-
return
|
|
44435
|
+
return scalar4(
|
|
43835
44436
|
Number(
|
|
43836
44437
|
name === "AND" ? values2.every(Boolean) : name === "OR" ? values2.some(Boolean) : !values2[0]
|
|
43837
44438
|
)
|
|
@@ -43845,7 +44446,7 @@ function evaluateNumericFormulaFunction(name, args) {
|
|
|
43845
44446
|
return formulaFailure("value", `${name} requires an integer from 0 to 65535`);
|
|
43846
44447
|
return arg.value;
|
|
43847
44448
|
});
|
|
43848
|
-
return
|
|
44449
|
+
return scalar4(
|
|
43849
44450
|
name === "BITAND" ? values2[0] & values2[1] : name === "BITOR" ? values2[0] | values2[1] : values2[0] ^ values2[1]
|
|
43850
44451
|
);
|
|
43851
44452
|
}
|
|
@@ -44274,6 +44875,115 @@ function parseVisioFormula(source2, limits = {}) {
|
|
|
44274
44875
|
return ast;
|
|
44275
44876
|
}
|
|
44276
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
|
+
|
|
44277
44987
|
// visio/edit-geometry-cells.ts
|
|
44278
44988
|
var cells = (shape2) => new Map(children3(shape2, "Cell").map((node) => [attribute3(node, "N") ?? "", node]));
|
|
44279
44989
|
function numeric4(node, fallback) {
|
|
@@ -44346,14 +45056,6 @@ function assertEllipseResizeRow(shape2, row2) {
|
|
|
44346
45056
|
}
|
|
44347
45057
|
}
|
|
44348
45058
|
|
|
44349
|
-
// visio/cell-formula.ts
|
|
44350
|
-
function executableCellFormula(source2) {
|
|
44351
|
-
return !source2 || source2 === "No Formula" || source2 === "Inh" ? void 0 : source2;
|
|
44352
|
-
}
|
|
44353
|
-
function inertDoubleClickFormula(cell, source2) {
|
|
44354
|
-
return cell === "EventDblClick" && /^\s*=?\s*(OPENTEXTWIN|DEFAULTEVENT)\(\s*\)\s*$/i.test(source2);
|
|
44355
|
-
}
|
|
44356
|
-
|
|
44357
45059
|
// visio/edit-recalculate-index.ts
|
|
44358
45060
|
var key = (cell) => JSON.stringify([cell.pageId, cell.shapeId, cell.cell.toLowerCase()]);
|
|
44359
45061
|
function bound(value, fallback) {
|
|
@@ -44605,26 +45307,27 @@ function recalculateVisioCells(roots, changed, options = {}) {
|
|
|
44605
45307
|
}
|
|
44606
45308
|
return [...pages];
|
|
44607
45309
|
}
|
|
44608
|
-
function
|
|
45310
|
+
function assertVisioShapesUnreferenced(roots, removed, options = {}) {
|
|
44609
45311
|
const cells3 = indexCells(roots, options);
|
|
44610
45312
|
for (const cell of cells3.values()) {
|
|
44611
|
-
|
|
45313
|
+
options.check?.();
|
|
45314
|
+
if (removed.get(cell.pageId)?.has(cell.shapeId)) continue;
|
|
44612
45315
|
if (cell.dependencies.some((id) => {
|
|
44613
45316
|
const parts = JSON.parse(id);
|
|
44614
|
-
return parts[0]
|
|
45317
|
+
return removed.get(parts[0])?.has(parts[1]) ?? false;
|
|
44615
45318
|
}))
|
|
44616
45319
|
fail2("EDIT_REFERENCED_DELETE", "Shape is referenced by a ShapeSheet formula.");
|
|
44617
45320
|
}
|
|
44618
|
-
const
|
|
44619
|
-
|
|
44620
|
-
for (const connections2 of children3(root, "Connects"))
|
|
45321
|
+
for (const [pageId, ids] of removed)
|
|
45322
|
+
for (const connections2 of children3(roots.get(pageId), "Connects"))
|
|
44621
45323
|
for (const connection of children3(connections2, "Connect")) {
|
|
44622
|
-
|
|
45324
|
+
options.check?.();
|
|
45325
|
+
if (["FromSheet", "ToSheet"].some((name) => ids.has(attribute3(connection, name) ?? "")))
|
|
44623
45326
|
fail2("EDIT_REFERENCED_DELETE", "Shape participates in a Connect record.");
|
|
44624
45327
|
}
|
|
44625
45328
|
}
|
|
44626
|
-
function
|
|
44627
|
-
|
|
45329
|
+
function assertVisioShapeUnreferenced(roots, pageId, shapeId, options = {}) {
|
|
45330
|
+
assertVisioShapesUnreferenced(roots, /* @__PURE__ */ new Map([[pageId, /* @__PURE__ */ new Set([shapeId])]]), options);
|
|
44628
45331
|
}
|
|
44629
45332
|
function createVisioDependencyQuery(roots, options = {}) {
|
|
44630
45333
|
const cells3 = indexCells(roots, options);
|
|
@@ -44817,6 +45520,7 @@ function protectedShape(shape2, document, masterMovePins = /* @__PURE__ */ new S
|
|
|
44817
45520
|
}
|
|
44818
45521
|
function resizeGeometry(shape2, roots, edit, check3, lineEditShapes = /* @__PURE__ */ new Set()) {
|
|
44819
45522
|
const sections = children3(shape2, "Section").filter((node) => attribute3(node, "N") === "Geometry");
|
|
45523
|
+
let depends;
|
|
44820
45524
|
if (!sections.length)
|
|
44821
45525
|
fail2("UNSUPPORTED_GEOMETRY_EDIT", "Resizing requires explicit supported local geometry.");
|
|
44822
45526
|
for (const section of sections) {
|
|
@@ -44846,15 +45550,14 @@ function resizeGeometry(shape2, roots, edit, check3, lineEditShapes = /* @__PURE
|
|
|
44846
45550
|
const analysis = analyzeVisioFormula(formula);
|
|
44847
45551
|
if (!analysis.references.length && numeric4(node) === 0) continue;
|
|
44848
45552
|
const cell = `Geometry${Number(attribute3(section, "IX") ?? "0") + 1}.${attribute3(node, "N")}${attribute3(row2, "IX")}`;
|
|
44849
|
-
|
|
44850
|
-
|
|
45553
|
+
depends ??= createVisioDependencyQuery(roots, { check: check3, lineEditShapes });
|
|
45554
|
+
if (!depends(
|
|
44851
45555
|
{ pageId: edit.pageId, shapeId: edit.shapeId, cell },
|
|
44852
45556
|
["Width", "Height"].map((cell2) => ({
|
|
44853
45557
|
pageId: edit.pageId,
|
|
44854
45558
|
shapeId: edit.shapeId,
|
|
44855
45559
|
cell: cell2
|
|
44856
|
-
}))
|
|
44857
|
-
{ check: check3, lineEditShapes }
|
|
45560
|
+
}))
|
|
44858
45561
|
))
|
|
44859
45562
|
fail2(
|
|
44860
45563
|
"UNSUPPORTED_GEOMETRY_EDIT",
|
|
@@ -44872,6 +45575,704 @@ function assertLengthTransformCells(local) {
|
|
|
44872
45575
|
}
|
|
44873
45576
|
}
|
|
44874
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
|
+
|
|
44875
46276
|
// visio/edit-group-rotation.ts
|
|
44876
46277
|
function proveLocalGroupRotation(root, edit, check3) {
|
|
44877
46278
|
const groups = /* @__PURE__ */ new Set(), angleCells = /* @__PURE__ */ new Set();
|
|
@@ -44936,6 +46337,238 @@ function proveLocalGroupRotation(root, edit, check3) {
|
|
|
44936
46337
|
return { groups, angleCells };
|
|
44937
46338
|
}
|
|
44938
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
|
+
|
|
44939
46572
|
// visio/edit-transform-formula.ts
|
|
44940
46573
|
function editableTransformCell(roots, edit, node, check3, options = {}) {
|
|
44941
46574
|
const formula = executableCellFormula(attribute3(node, "F"));
|
|
@@ -45005,7 +46638,16 @@ function createBox(root, document, edit) {
|
|
|
45005
46638
|
return shape2;
|
|
45006
46639
|
}
|
|
45007
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
|
+
}
|
|
45008
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
|
+
}
|
|
45009
46651
|
const doc = root.ownerDocument;
|
|
45010
46652
|
const node = (name) => doc.createElementNS(root.namespaceURI, name);
|
|
45011
46653
|
const section = node("Section");
|
|
@@ -45027,7 +46669,7 @@ function createRectangle(root, document, edit) {
|
|
|
45027
46669
|
}
|
|
45028
46670
|
shape2.appendChild(section);
|
|
45029
46671
|
const text2 = node("Text");
|
|
45030
|
-
text2.appendChild(doc.createTextNode(edit.text ?? ""));
|
|
46672
|
+
text2.appendChild(doc.createTextNode(encodeVisioPlainText(edit.text ?? "")));
|
|
45031
46673
|
shape2.appendChild(text2);
|
|
45032
46674
|
return shape2;
|
|
45033
46675
|
}
|
|
@@ -45036,7 +46678,7 @@ function createEllipse(root, document, edit) {
|
|
|
45036
46678
|
appendEllipseGeometry(shape2, edit.width, edit.height);
|
|
45037
46679
|
if (edit.text !== void 0) {
|
|
45038
46680
|
const text2 = root.ownerDocument.createElementNS(root.namespaceURI, "Text");
|
|
45039
|
-
text2.appendChild(root.ownerDocument.createTextNode(edit.text));
|
|
46681
|
+
text2.appendChild(root.ownerDocument.createTextNode(encodeVisioPlainText(edit.text)));
|
|
45040
46682
|
shape2.appendChild(text2);
|
|
45041
46683
|
}
|
|
45042
46684
|
return shape2;
|
|
@@ -45406,6 +47048,8 @@ function moveLocalLineEndpoint(shape2, edit) {
|
|
|
45406
47048
|
function applyGeometryEdit(roots, document, edit, check3, masterMoveProof = emptyMasterMoveProof()) {
|
|
45407
47049
|
const masterMovePins = masterMoveProof.pins, masterDimensions = masterMoveProof.dimensions;
|
|
45408
47050
|
check3();
|
|
47051
|
+
if (edit.type === "resize-shape" && edit.anchor)
|
|
47052
|
+
return resizeVisioShapeAtAnchor(roots, document, edit, check3);
|
|
45409
47053
|
const root = roots.get(edit.pageId);
|
|
45410
47054
|
if (!root) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
|
|
45411
47055
|
const groupRotation = proveLocalGroupRotation(root, edit, check3);
|
|
@@ -45427,11 +47071,15 @@ function applyGeometryEdit(roots, document, edit, check3, masterMoveProof = empt
|
|
|
45427
47071
|
y: (edit.beginY + edit.endY) / 2
|
|
45428
47072
|
};
|
|
45429
47073
|
for (const name of geometryChangedCells(edit)) add3(name);
|
|
45430
|
-
} 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") {
|
|
45431
47075
|
if (edit.type === "create-ellipse") createEllipse(root, document, edit);
|
|
45432
47076
|
else createRectangle(root, document, edit);
|
|
45433
47077
|
expected = { width: edit.width, height: edit.height, x: edit.x, y: edit.y };
|
|
45434
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
|
+
}
|
|
45435
47083
|
} else {
|
|
45436
47084
|
const shape2 = admitted(
|
|
45437
47085
|
root,
|
|
@@ -45624,6 +47272,114 @@ function applyGeometryEdit(roots, document, edit, check3, masterMoveProof = empt
|
|
|
45624
47272
|
return [.../* @__PURE__ */ new Set([edit.pageId, ...affectedPages])];
|
|
45625
47273
|
}
|
|
45626
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
|
+
|
|
45627
47383
|
// visio/formula-master.ts
|
|
45628
47384
|
function analyzeVisioMasterFormula(source2, options) {
|
|
45629
47385
|
const ast = parseVisioFormula(source2);
|
|
@@ -45901,11 +47657,11 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check3) {
|
|
|
45901
47657
|
}
|
|
45902
47658
|
const tops = children3(children3(root, "Shapes")[0], "Shape");
|
|
45903
47659
|
if (tops.length !== 1) problem("Only a uniquely rooted master can prove independence.");
|
|
45904
|
-
const
|
|
47660
|
+
const templates2 = masterShapes(root), context = /* @__PURE__ */ new Map();
|
|
45905
47661
|
assertMasterMarkup(
|
|
45906
47662
|
root,
|
|
45907
47663
|
new Set(
|
|
45908
|
-
|
|
47664
|
+
templates2.flatMap((shape2) => {
|
|
45909
47665
|
charge();
|
|
45910
47666
|
return [...masterCells(shape2, charge).values()];
|
|
45911
47667
|
})
|
|
@@ -45927,7 +47683,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check3) {
|
|
|
45927
47683
|
if (byTemplate.has(id)) problem("MasterShape mappings are ambiguous.");
|
|
45928
47684
|
byTemplate.set(id, local);
|
|
45929
47685
|
}
|
|
45930
|
-
for (const template of
|
|
47686
|
+
for (const template of templates2) {
|
|
45931
47687
|
charge();
|
|
45932
47688
|
if (bindings.length >= 1e4) problem("Master effective binding limit exceeded.");
|
|
45933
47689
|
check3();
|
|
@@ -46255,10 +48011,17 @@ async function assertGeometryPackageScope(pkg, pagePaths, commands, check3, root
|
|
|
46255
48011
|
for (const [pageId, root] of roots) {
|
|
46256
48012
|
const shapes = Array.from(root.getElementsByTagNameNS(root.namespaceURI, "Shape"));
|
|
46257
48013
|
for (const command2 of commands)
|
|
46258
|
-
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)) {
|
|
46259
48015
|
const shape2 = root.ownerDocument.createElementNS(root.namespaceURI, "Shape");
|
|
46260
48016
|
shape2.setAttribute("ID", command2.shapeId);
|
|
46261
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
|
+
}
|
|
46262
48025
|
for (const name of ["PinX", "PinY", "Width", "Height", "LocPinX", "LocPinY", "Angle"]) {
|
|
46263
48026
|
const node = root.ownerDocument.createElementNS(root.namespaceURI, "Cell");
|
|
46264
48027
|
node.setAttribute("N", name);
|
|
@@ -46999,6 +48762,787 @@ async function editVsdxPages(original, pkg, parts, commands, limits, maxOutput,
|
|
|
46999
48762
|
};
|
|
47000
48763
|
}
|
|
47001
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
|
+
|
|
47002
49546
|
// visio/edit.ts
|
|
47003
49547
|
function positive3(value) {
|
|
47004
49548
|
if (!Number.isSafeInteger(value) || value <= 0)
|
|
@@ -47040,26 +49584,50 @@ async function editVsdx(input, edits, options = {}) {
|
|
|
47040
49584
|
}
|
|
47041
49585
|
const dirty = /* @__PURE__ */ new Map();
|
|
47042
49586
|
const roots = /* @__PURE__ */ new Map();
|
|
47043
|
-
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
|
+
);
|
|
47044
49590
|
let document;
|
|
47045
49591
|
let masterMovePins = emptyMasterMoveProof();
|
|
47046
|
-
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
|
+
)) {
|
|
47047
49595
|
for (const [pageId, path3] of pages) {
|
|
47048
49596
|
const sourceRoot = await visioXml(pkg, path3, "PageContents");
|
|
47049
49597
|
roots.set(pageId, sourceRoot.ownerDocument.cloneNode(true).documentElement);
|
|
47050
49598
|
}
|
|
47051
|
-
|
|
47052
|
-
|
|
47053
|
-
|
|
47054
|
-
|
|
47055
|
-
check3
|
|
47056
|
-
|
|
47057
|
-
)
|
|
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
|
+
);
|
|
47058
49613
|
const path2 = await related(pkg, "", "document");
|
|
47059
49614
|
document = await visioXml(pkg, path2, "VisioDocument");
|
|
47060
49615
|
}
|
|
47061
49616
|
let textChanged = false;
|
|
47062
|
-
|
|
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) {
|
|
47063
49631
|
check3();
|
|
47064
49632
|
const path2 = pages.get(command2.pageId);
|
|
47065
49633
|
if (!path2) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
|
|
@@ -47070,10 +49638,42 @@ async function editVsdx(input, edits, options = {}) {
|
|
|
47070
49638
|
roots.set(command2.pageId, root);
|
|
47071
49639
|
}
|
|
47072
49640
|
if (command2.type === "replace-plain-text") {
|
|
47073
|
-
if (
|
|
49641
|
+
if (await replaceScopedPlainText(pkg, new Set(pages.values()), roots, document, command2, check3)) {
|
|
47074
49642
|
dirty.set(path2, root);
|
|
47075
49643
|
textChanged = true;
|
|
47076
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;
|
|
47077
49677
|
} else {
|
|
47078
49678
|
for (const pageId of applyGeometryEdit(roots, document, command2, check3, masterMovePins))
|
|
47079
49679
|
dirty.set(pages.get(pageId), roots.get(pageId));
|
|
@@ -47108,17 +49708,50 @@ async function editVsdx(input, edits, options = {}) {
|
|
|
47108
49708
|
return {
|
|
47109
49709
|
bytes,
|
|
47110
49710
|
changedParts: [...dirty.keys()],
|
|
47111
|
-
diagnostics:
|
|
47112
|
-
|
|
47113
|
-
|
|
47114
|
-
|
|
47115
|
-
|
|
47116
|
-
|
|
47117
|
-
|
|
47118
|
-
|
|
47119
|
-
|
|
47120
|
-
|
|
47121
|
-
|
|
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
|
+
]
|
|
47122
49755
|
};
|
|
47123
49756
|
}
|
|
47124
49757
|
|