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
|
@@ -259,14 +259,14 @@ function startTag(source2, from, namespaces) {
|
|
|
259
259
|
while (q < n && isSpace(source2.charCodeAt(q))) q++;
|
|
260
260
|
const quote2 = source2[q];
|
|
261
261
|
if (quote2 !== '"' && quote2 !== "'") return void 0;
|
|
262
|
-
const
|
|
263
|
-
if (
|
|
264
|
-
const raw2 = source2.slice(q + 1,
|
|
262
|
+
const close2 = source2.indexOf(quote2, q + 1);
|
|
263
|
+
if (close2 < 0) return void 0;
|
|
264
|
+
const raw2 = source2.slice(q + 1, close2);
|
|
265
265
|
if (raw2.includes("<") || element2.hasAttribute(name)) return void 0;
|
|
266
266
|
const value = decode(/[\t\n\r]/.test(raw2) ? raw2.replace(/[\t\n\r]/g, " ") : raw2);
|
|
267
267
|
if (value === void 0) return void 0;
|
|
268
268
|
element2.attrs.push(name, value);
|
|
269
|
-
i2 =
|
|
269
|
+
i2 = close2 + 1;
|
|
270
270
|
const after = source2.charCodeAt(i2);
|
|
271
271
|
if (i2 < n && !isSpace(after) && after !== 62 && after !== 47) return void 0;
|
|
272
272
|
}
|
|
@@ -2237,12 +2237,12 @@ function linearToSrgb255(linear) {
|
|
|
2237
2237
|
// color/hex-rgb.ts
|
|
2238
2238
|
function parseArgbHex(hex) {
|
|
2239
2239
|
const clean3 = hex.replace(/^#/, "");
|
|
2240
|
-
const
|
|
2241
|
-
if (!/^[0-9a-fA-F]{6}$/.test(
|
|
2242
|
-
return [0, 2, 4].map((i2) => parseInt(
|
|
2240
|
+
const rgb3 = clean3.length === 8 ? clean3.slice(2) : clean3;
|
|
2241
|
+
if (!/^[0-9a-fA-F]{6}$/.test(rgb3)) return void 0;
|
|
2242
|
+
return [0, 2, 4].map((i2) => parseInt(rgb3.slice(i2, i2 + 2), 16));
|
|
2243
2243
|
}
|
|
2244
2244
|
var clamp255 = (v) => Math.max(0, Math.min(255, v));
|
|
2245
|
-
var rgbToUpperHex = (
|
|
2245
|
+
var rgbToUpperHex = (rgb3) => `#${rgb3.map((v) => clamp255(Math.round(v)).toString(16).padStart(2, "0")).join("").toUpperCase()}`;
|
|
2246
2246
|
|
|
2247
2247
|
// drawingml/theme-model.ts
|
|
2248
2248
|
var THEME_COLOR_SLOTS = [
|
|
@@ -4570,10 +4570,10 @@ var APPLIED = /* @__PURE__ */ new Set([
|
|
|
4570
4570
|
]);
|
|
4571
4571
|
function resolveDrawingColor(color2, theme2, options) {
|
|
4572
4572
|
const base = baseHex(color2, theme2);
|
|
4573
|
-
const
|
|
4574
|
-
if (!
|
|
4573
|
+
const rgb3 = base ? hexToRgbChannels(base) : null;
|
|
4574
|
+
if (!rgb3) return void 0;
|
|
4575
4575
|
{
|
|
4576
|
-
const value = orderedColorTransforms(
|
|
4576
|
+
const value = orderedColorTransforms(rgb3, color2.transforms);
|
|
4577
4577
|
const round3 = options.hslRounding === "halfDown" ? (channel) => Math.ceil(channel - 0.5) : Math.round;
|
|
4578
4578
|
return {
|
|
4579
4579
|
hex: `#${toHex(round3(value.r))}${toHex(round3(value.g))}${toHex(round3(value.b))}`,
|
|
@@ -8624,9 +8624,9 @@ function rejectUnsafeRunSegmentation(paragraph2, base, oldRuns) {
|
|
|
8624
8624
|
(run2) => !run2.image && !run2.equation && (run2.restoredRunPropertiesXml || run2.sourceRunPropertiesXml)
|
|
8625
8625
|
))
|
|
8626
8626
|
return;
|
|
8627
|
-
const
|
|
8627
|
+
const sameText2 = paragraph2.runs.map((run2) => run2.text).join("") === base.runs.map((run2) => run2.text).join("");
|
|
8628
8628
|
const sameBoundaries = paragraph2.runs.length === base.runs.length && paragraph2.runs.every((run2, index2) => run2.text === base.runs[index2]?.text);
|
|
8629
|
-
if (sameBoundaries || !
|
|
8629
|
+
if (sameBoundaries || !sameText2 && paragraph2.runs.length === base.runs.length) return;
|
|
8630
8630
|
throw new Error(
|
|
8631
8631
|
`Cannot edit paragraph ${paragraph2.id}: changing run boundaries could drop unsupported run properties. The original DOCX package remains unchanged.`
|
|
8632
8632
|
);
|
|
@@ -11977,10 +11977,10 @@ function parseDynamicArrayMetadata(xml) {
|
|
|
11977
11977
|
function parseColor(element2, palette) {
|
|
11978
11978
|
if (!element2) return void 0;
|
|
11979
11979
|
const color2 = {};
|
|
11980
|
-
const
|
|
11980
|
+
const rgb3 = att(element2, "rgb");
|
|
11981
11981
|
const theme2 = numAttr(element2, "theme");
|
|
11982
11982
|
const indexed = numAttr(element2, "indexed");
|
|
11983
|
-
if (
|
|
11983
|
+
if (rgb3 && /^[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/.test(rgb3)) color2.rgb = rgb3.toUpperCase();
|
|
11984
11984
|
else if (theme2 !== void 0) color2.theme = theme2;
|
|
11985
11985
|
else if (indexed !== void 0) {
|
|
11986
11986
|
const override = palette?.[indexed];
|
|
@@ -12498,7 +12498,7 @@ var NAME_RE = /^[A-Za-z_\\\u00A1-\uFFFF][A-Za-z0-9_.?\\\u00A1-\uFFFF]*/;
|
|
|
12498
12498
|
var CELL_RE = /^(\$?)([A-Za-z]{1,3})(\$?)(\d{1,7})/;
|
|
12499
12499
|
var COLS_RE = /^(\$?)([A-Za-z]{1,3}):(\$?)([A-Za-z]{1,3})/;
|
|
12500
12500
|
var ROWS_RE = /^(\$?)(\d{1,7}):(\$?)(\d{1,7})/;
|
|
12501
|
-
var NUMBER_RE = /^(?:\d
|
|
12501
|
+
var NUMBER_RE = /^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/;
|
|
12502
12502
|
var sticky = (re) => new RegExp(re.source.replace(/^\^/, ""), "y");
|
|
12503
12503
|
var CELL_AT = sticky(CELL_RE);
|
|
12504
12504
|
var COLS_AT = sticky(COLS_RE);
|
|
@@ -12658,14 +12658,13 @@ function splitSheets(text2) {
|
|
|
12658
12658
|
if (book !== void 0) out.book = book;
|
|
12659
12659
|
return out;
|
|
12660
12660
|
}
|
|
12661
|
-
var PREFIX_AT = /(\[\d+\])?([A-Za-z0-9_.\u00A1-\uFFFF]+)(?::([A-Za-z0-9_.\u00A1-\uFFFF]+))?!/y;
|
|
12662
12661
|
function readPrefix(source2, at2) {
|
|
12663
12662
|
const ch = source2[at2];
|
|
12664
12663
|
if (ch === "'") {
|
|
12665
12664
|
const quoted = readQuoted(source2, at2);
|
|
12666
12665
|
if (source2[at2 + quoted.length] !== "!") return void 0;
|
|
12667
|
-
const
|
|
12668
|
-
return { prefix: { text: source2.slice(at2, at2 +
|
|
12666
|
+
const length2 = quoted.length + 1;
|
|
12667
|
+
return { prefix: { text: source2.slice(at2, at2 + length2), ...splitSheets(quoted.name) }, length: length2 };
|
|
12669
12668
|
}
|
|
12670
12669
|
let i2 = at2;
|
|
12671
12670
|
if (ch === "[") {
|
|
@@ -12674,13 +12673,23 @@ function readPrefix(source2, at2) {
|
|
|
12674
12673
|
if (i2 === at2 + 1 || source2[i2] !== "]") return void 0;
|
|
12675
12674
|
i2++;
|
|
12676
12675
|
}
|
|
12676
|
+
const sheetFrom = i2;
|
|
12677
12677
|
while (i2 < source2.length && isSheetCharCode(source2.charCodeAt(i2))) i2++;
|
|
12678
|
-
if (
|
|
12679
|
-
|
|
12680
|
-
if (
|
|
12681
|
-
|
|
12682
|
-
|
|
12683
|
-
|
|
12678
|
+
if (i2 === sheetFrom) return void 0;
|
|
12679
|
+
let lastFrom = -1;
|
|
12680
|
+
if (source2[i2] === ":") {
|
|
12681
|
+
lastFrom = i2 + 1;
|
|
12682
|
+
i2 = lastFrom;
|
|
12683
|
+
while (i2 < source2.length && isSheetCharCode(source2.charCodeAt(i2))) i2++;
|
|
12684
|
+
if (i2 === lastFrom) return void 0;
|
|
12685
|
+
}
|
|
12686
|
+
if (source2[i2] !== "!") return void 0;
|
|
12687
|
+
if (ch !== "[" && lastFrom < 0 && isDigitCode(source2.charCodeAt(sheetFrom))) return void 0;
|
|
12688
|
+
const length = i2 + 1 - at2;
|
|
12689
|
+
return {
|
|
12690
|
+
prefix: { text: source2.slice(at2, at2 + length), ...splitSheets(source2.slice(at2, i2)) },
|
|
12691
|
+
length
|
|
12692
|
+
};
|
|
12684
12693
|
}
|
|
12685
12694
|
function numberLiteral(text2) {
|
|
12686
12695
|
if (text2.length <= 15) return Number(text2);
|
|
@@ -12845,7 +12854,7 @@ function readName(source2, at2, start, prefix) {
|
|
|
12845
12854
|
}
|
|
12846
12855
|
var joinTokens = (tokens3) => tokens3.map((t) => t.text).join("");
|
|
12847
12856
|
|
|
12848
|
-
// xlsx/formula/
|
|
12857
|
+
// xlsx/formula/ref-text.ts
|
|
12849
12858
|
function safeTokens(formula) {
|
|
12850
12859
|
try {
|
|
12851
12860
|
return tokenize(formula);
|
|
@@ -12864,50 +12873,26 @@ function formatRefSpec(spec2) {
|
|
|
12864
12873
|
if (spec2.kind === "cell") return a2;
|
|
12865
12874
|
return `${a2}:${cornerText(spec2.end, spec2.kind)}`;
|
|
12866
12875
|
}
|
|
12867
|
-
function
|
|
12876
|
+
function rewriteRef(token, ref) {
|
|
12868
12877
|
const prefix = token.prefix?.text ?? "";
|
|
12869
12878
|
if (!ref) return `${prefix}#REF!`;
|
|
12870
12879
|
return `${prefix}${formatRefSpec(ref)}${token.spill ? "#" : ""}`;
|
|
12871
12880
|
}
|
|
12872
12881
|
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;
|
|
12873
|
-
|
|
12874
|
-
|
|
12875
|
-
|
|
12876
|
-
|
|
12877
|
-
|
|
12878
|
-
|
|
12879
|
-
const move = (c2) => {
|
|
12880
|
-
const row2 = spec2.kind === "cols" || c2.rowAbs ? c2.row : c2.row + dRow;
|
|
12881
|
-
const col = spec2.kind === "rows" || c2.colAbs ? c2.col : c2.col + dCol;
|
|
12882
|
-
if (row2 < 0 || row2 > MAX_ROW || col < 0 || col > MAX_COL) return void 0;
|
|
12883
|
-
return { ...c2, row: row2, col };
|
|
12884
|
-
};
|
|
12885
|
-
const start = move(spec2.start);
|
|
12886
|
-
const end = move(spec2.end);
|
|
12887
|
-
const next = start && end ? { kind: spec2.kind, start, end } : void 0;
|
|
12888
|
-
if (next && sameSpec(next, spec2)) continue;
|
|
12889
|
-
token.text = rewrite(token, next);
|
|
12890
|
-
}
|
|
12891
|
-
return joinTokens(tokens3);
|
|
12882
|
+
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);
|
|
12883
|
+
function prefixText(prefix) {
|
|
12884
|
+
const sheets = prefix.sheet2 !== void 0 ? `${prefix.sheet}:${prefix.sheet2}` : prefix.sheet;
|
|
12885
|
+
const book = prefix.book !== void 0 ? `[${prefix.book}]` : "";
|
|
12886
|
+
const quote2 = needsQuote(prefix.sheet) || prefix.sheet2 !== void 0 && needsQuote(prefix.sheet2);
|
|
12887
|
+
return quote2 ? `'${(book + sheets).replace(/'/g, "''")}'!` : `${book}${sheets}!`;
|
|
12892
12888
|
}
|
|
12893
|
-
|
|
12894
|
-
|
|
12895
|
-
|
|
12896
|
-
|
|
12897
|
-
|
|
12898
|
-
|
|
12899
|
-
|
|
12900
|
-
const na2 = a2 >= at2 ? a2 + count2 : a2;
|
|
12901
|
-
const nb2 = b >= at2 ? b + count2 : b;
|
|
12902
|
-
if (nb2 > max) return na2 > max ? void 0 : [na2, max];
|
|
12903
|
-
return [na2, nb2];
|
|
12904
|
-
}
|
|
12905
|
-
const n = -count2;
|
|
12906
|
-
const last = at2 + n - 1;
|
|
12907
|
-
if (a2 >= at2 && b <= last) return void 0;
|
|
12908
|
-
const na = a2 < at2 ? a2 : a2 <= last ? at2 : a2 - n;
|
|
12909
|
-
const nb = b < at2 ? b : b <= last ? at2 - 1 : b - n;
|
|
12910
|
-
return [na, nb];
|
|
12889
|
+
|
|
12890
|
+
// xlsx/formula/shift-formula.ts
|
|
12891
|
+
var templates = /* @__PURE__ */ new Map();
|
|
12892
|
+
var MAX_TEMPLATES = 2e5;
|
|
12893
|
+
function remember2(text2, template) {
|
|
12894
|
+
if (templates.size >= MAX_TEMPLATES) templates.clear();
|
|
12895
|
+
templates.set(text2, template);
|
|
12911
12896
|
}
|
|
12912
12897
|
function mergeSpacedAreas(tokens3) {
|
|
12913
12898
|
const out = [];
|
|
@@ -12934,63 +12919,145 @@ function mergeSpacedAreas(tokens3) {
|
|
|
12934
12919
|
}
|
|
12935
12920
|
return out;
|
|
12936
12921
|
}
|
|
12937
|
-
function
|
|
12938
|
-
|
|
12922
|
+
function templateOf(formula) {
|
|
12923
|
+
const cached3 = templates.get(formula);
|
|
12924
|
+
if (cached3 !== void 0) return cached3;
|
|
12939
12925
|
const raw2 = safeTokens(formula);
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
|
|
12947
|
-
|
|
12948
|
-
|
|
12949
|
-
|
|
12950
|
-
|
|
12951
|
-
|
|
12952
|
-
|
|
12953
|
-
|
|
12954
|
-
|
|
12955
|
-
|
|
12956
|
-
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
if (shifted2) {
|
|
12960
|
-
const [a2, b] = shifted2;
|
|
12961
|
-
const nlo = isRow ? { ...lo, row: a2 } : { ...lo, col: a2 };
|
|
12962
|
-
const nhi = isRow ? { ...hi, row: b } : { ...hi, col: b };
|
|
12963
|
-
next = { kind: ref.kind, start: startFirst ? nlo : nhi, end: startFirst ? nhi : nlo };
|
|
12964
|
-
if (ref.kind === "cell") next.end = next.start;
|
|
12926
|
+
let template = null;
|
|
12927
|
+
if (raw2) {
|
|
12928
|
+
template = [];
|
|
12929
|
+
let literal2 = "";
|
|
12930
|
+
for (const token of mergeSpacedAreas(raw2)) {
|
|
12931
|
+
if (token.kind !== "ref" && !(token.kind === "name" && token.prefix)) {
|
|
12932
|
+
literal2 += token.text;
|
|
12933
|
+
continue;
|
|
12934
|
+
}
|
|
12935
|
+
if (literal2) template.push(literal2);
|
|
12936
|
+
literal2 = "";
|
|
12937
|
+
const part = { kind: token.kind, text: token.text };
|
|
12938
|
+
if (token.prefix) {
|
|
12939
|
+
part.prefix = token.prefix;
|
|
12940
|
+
if (token.prefix.book === void 0) part.sheet = token.prefix.sheet.toLowerCase();
|
|
12941
|
+
}
|
|
12942
|
+
if (token.ref) part.ref = token.ref;
|
|
12943
|
+
if (token.spill) part.spill = true;
|
|
12944
|
+
template.push(part);
|
|
12965
12945
|
}
|
|
12966
|
-
if (
|
|
12967
|
-
token.text = rewrite(token, next);
|
|
12946
|
+
if (literal2) template.push(literal2);
|
|
12968
12947
|
}
|
|
12969
|
-
|
|
12948
|
+
remember2(formula, template);
|
|
12949
|
+
return template;
|
|
12970
12950
|
}
|
|
12971
|
-
|
|
12972
|
-
|
|
12973
|
-
|
|
12974
|
-
|
|
12975
|
-
|
|
12976
|
-
|
|
12951
|
+
function rewriteTemplate(formula, rewrite2) {
|
|
12952
|
+
const template = templateOf(formula);
|
|
12953
|
+
if (!template) return formula;
|
|
12954
|
+
let next;
|
|
12955
|
+
for (let i2 = 0; i2 < template.length; i2++) {
|
|
12956
|
+
const part = template[i2];
|
|
12957
|
+
if (typeof part === "string") continue;
|
|
12958
|
+
const changed = rewrite2(part);
|
|
12959
|
+
if (!changed) continue;
|
|
12960
|
+
next ??= template.slice();
|
|
12961
|
+
next[i2] = changed;
|
|
12962
|
+
}
|
|
12963
|
+
if (!next) return formula;
|
|
12964
|
+
const text2 = next.map((part) => typeof part === "string" ? part : part.text).join("");
|
|
12965
|
+
remember2(text2, next);
|
|
12966
|
+
return text2;
|
|
12967
|
+
}
|
|
12968
|
+
function shiftInterval(a2, b, at2, count2, max) {
|
|
12969
|
+
if (count2 > 0) {
|
|
12970
|
+
const na2 = a2 >= at2 ? a2 + count2 : a2;
|
|
12971
|
+
const nb2 = b >= at2 ? b + count2 : b;
|
|
12972
|
+
if (nb2 > max) return na2 > max ? void 0 : [na2, max];
|
|
12973
|
+
return [na2, nb2];
|
|
12974
|
+
}
|
|
12975
|
+
const n = -count2;
|
|
12976
|
+
const last = at2 + n - 1;
|
|
12977
|
+
if (a2 >= at2 && b <= last) return void 0;
|
|
12978
|
+
const na = a2 < at2 ? a2 : a2 <= last ? at2 : a2 - n;
|
|
12979
|
+
const nb = b < at2 ? b : b <= last ? at2 - 1 : b - n;
|
|
12980
|
+
return [na, nb];
|
|
12981
|
+
}
|
|
12982
|
+
function shiftRef(ref, spec2) {
|
|
12983
|
+
const isRow = spec2.axis === "row";
|
|
12984
|
+
if (isRow && ref.kind === "cols" || !isRow && ref.kind === "rows") return ref;
|
|
12985
|
+
const startFirst = isRow ? ref.start.row <= ref.end.row : ref.start.col <= ref.end.col;
|
|
12986
|
+
const lo = startFirst ? ref.start : ref.end;
|
|
12987
|
+
const hi = startFirst ? ref.end : ref.start;
|
|
12988
|
+
const shifted2 = shiftInterval(
|
|
12989
|
+
isRow ? lo.row : lo.col,
|
|
12990
|
+
isRow ? hi.row : hi.col,
|
|
12991
|
+
spec2.at,
|
|
12992
|
+
spec2.count,
|
|
12993
|
+
isRow ? MAX_ROW : MAX_COL
|
|
12994
|
+
);
|
|
12995
|
+
if (!shifted2) return void 0;
|
|
12996
|
+
const [a2, b] = shifted2;
|
|
12997
|
+
const nlo = isRow ? { ...lo, row: a2 } : { ...lo, col: a2 };
|
|
12998
|
+
const nhi = isRow ? { ...hi, row: b } : { ...hi, col: b };
|
|
12999
|
+
const next = {
|
|
13000
|
+
kind: ref.kind,
|
|
13001
|
+
start: startFirst ? nlo : nhi,
|
|
13002
|
+
end: startFirst ? nhi : nlo
|
|
13003
|
+
};
|
|
13004
|
+
if (ref.kind === "cell") next.end = next.start;
|
|
13005
|
+
return sameSpec(next, ref) ? ref : next;
|
|
13006
|
+
}
|
|
13007
|
+
function shiftFormula(formula, formulaSheet, spec2) {
|
|
13008
|
+
if (spec2.count === 0) return formula;
|
|
13009
|
+
const sheet = spec2.sheet.toLowerCase();
|
|
13010
|
+
const own = formulaSheet.toLowerCase() === sheet;
|
|
13011
|
+
return rewriteTemplate(formula, (part) => {
|
|
13012
|
+
if (part.kind !== "ref" || !part.ref || (part.prefix ? part.sheet !== sheet : !own))
|
|
13013
|
+
return void 0;
|
|
13014
|
+
const next = shiftRef(part.ref, spec2);
|
|
13015
|
+
if (next === part.ref) return void 0;
|
|
13016
|
+
const out = { kind: "ref", text: rewriteRef(part, next) };
|
|
13017
|
+
if (part.prefix) out.prefix = part.prefix;
|
|
13018
|
+
if (part.sheet !== void 0) out.sheet = part.sheet;
|
|
13019
|
+
if (next) out.ref = next;
|
|
13020
|
+
if (part.spill) out.spill = true;
|
|
13021
|
+
return out;
|
|
13022
|
+
});
|
|
12977
13023
|
}
|
|
12978
13024
|
function renameSheetInFormula(formula, oldName, newName) {
|
|
12979
|
-
const tokens3 = safeTokens(formula);
|
|
12980
|
-
if (!tokens3) return formula;
|
|
12981
13025
|
const lower2 = oldName.toLowerCase();
|
|
12982
|
-
|
|
12983
|
-
const prefix =
|
|
12984
|
-
if (!prefix ||
|
|
12985
|
-
const first3 =
|
|
13026
|
+
return rewriteTemplate(formula, (part) => {
|
|
13027
|
+
const prefix = part.prefix;
|
|
13028
|
+
if (!prefix || part.sheet === void 0) return void 0;
|
|
13029
|
+
const first3 = part.sheet === lower2;
|
|
12986
13030
|
const second = prefix.sheet2?.toLowerCase() === lower2;
|
|
12987
|
-
if (!first3 && !second)
|
|
13031
|
+
if (!first3 && !second) return void 0;
|
|
12988
13032
|
const renamed = { ...prefix, sheet: first3 ? newName : prefix.sheet };
|
|
12989
13033
|
if (prefix.sheet2 !== void 0) renamed.sheet2 = second ? newName : prefix.sheet2;
|
|
12990
13034
|
const text2 = prefixText(renamed);
|
|
12991
|
-
token.text = text2 + token.text.slice(prefix.text.length);
|
|
12992
13035
|
renamed.text = text2;
|
|
12993
|
-
|
|
13036
|
+
const out = { ...part, text: text2 + part.text.slice(prefix.text.length) };
|
|
13037
|
+
out.prefix = renamed;
|
|
13038
|
+
out.sheet = renamed.sheet.toLowerCase();
|
|
13039
|
+
return out;
|
|
13040
|
+
});
|
|
13041
|
+
}
|
|
13042
|
+
|
|
13043
|
+
// xlsx/formula/transform.ts
|
|
13044
|
+
function translateFormula(formula, dRow, dCol) {
|
|
13045
|
+
const tokens3 = safeTokens(formula);
|
|
13046
|
+
if (!tokens3) return formula;
|
|
13047
|
+
for (const token of tokens3) {
|
|
13048
|
+
if (token.kind !== "ref" || !token.ref) continue;
|
|
13049
|
+
const spec2 = token.ref;
|
|
13050
|
+
const move = (c2) => {
|
|
13051
|
+
const row2 = spec2.kind === "cols" || c2.rowAbs ? c2.row : c2.row + dRow;
|
|
13052
|
+
const col = spec2.kind === "rows" || c2.colAbs ? c2.col : c2.col + dCol;
|
|
13053
|
+
if (row2 < 0 || row2 > MAX_ROW || col < 0 || col > MAX_COL) return void 0;
|
|
13054
|
+
return { ...c2, row: row2, col };
|
|
13055
|
+
};
|
|
13056
|
+
const start = move(spec2.start);
|
|
13057
|
+
const end = move(spec2.end);
|
|
13058
|
+
const next = start && end ? { kind: spec2.kind, start, end } : void 0;
|
|
13059
|
+
if (next && sameSpec(next, spec2)) continue;
|
|
13060
|
+
token.text = rewriteRef(token, next);
|
|
12994
13061
|
}
|
|
12995
13062
|
return joinTokens(tokens3);
|
|
12996
13063
|
}
|
|
@@ -13060,14 +13127,14 @@ function fromStoredSyntax(formula) {
|
|
|
13060
13127
|
if (name !== "ANCHORARRAY" && name !== "SINGLE") continue;
|
|
13061
13128
|
const open = nextIndex(list, i2 + 1);
|
|
13062
13129
|
const arg = nextIndex(list, open + 1);
|
|
13063
|
-
const
|
|
13130
|
+
const close2 = nextIndex(list, arg + 1);
|
|
13064
13131
|
const target = list[arg];
|
|
13065
|
-
if (list[open]?.kind !== "open" || list[
|
|
13132
|
+
if (list[open]?.kind !== "open" || list[close2]?.kind !== "close" || !target) continue;
|
|
13066
13133
|
const single = target.kind === "ref" || target.kind === "name" || target.kind === "structured";
|
|
13067
13134
|
if (name === "ANCHORARRAY" && !(target.kind === "ref" && target.ref?.kind === "cell")) continue;
|
|
13068
13135
|
if (name === "SINGLE" && !single) continue;
|
|
13069
13136
|
const text2 = name === "ANCHORARRAY" ? `${target.text}#` : `@${target.text}`;
|
|
13070
|
-
for (let k = i2; k <=
|
|
13137
|
+
for (let k = i2; k <= close2; k++) list[k].text = "";
|
|
13071
13138
|
token.text = text2;
|
|
13072
13139
|
changed = true;
|
|
13073
13140
|
}
|
|
@@ -13079,7 +13146,7 @@ var FUTURE_FUNCTIONS = new Set(
|
|
|
13079
13146
|
"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(" ")
|
|
13080
13147
|
);
|
|
13081
13148
|
var WORKSHEET_PREFIXED = /* @__PURE__ */ new Set(["FILTER", "SORT"]);
|
|
13082
|
-
function
|
|
13149
|
+
function rewrite(formula, visit2) {
|
|
13083
13150
|
const out = [];
|
|
13084
13151
|
let i2 = 0;
|
|
13085
13152
|
while (i2 < formula.length) {
|
|
@@ -13122,7 +13189,7 @@ function rewrite2(formula, visit2) {
|
|
|
13122
13189
|
}
|
|
13123
13190
|
function stripFuturePrefixes(formula) {
|
|
13124
13191
|
if (!formula.includes("_xl")) return formula;
|
|
13125
|
-
const plain2 =
|
|
13192
|
+
const plain2 = rewrite(formula, (token, next, out) => {
|
|
13126
13193
|
if (!next.startsWith("(")) return false;
|
|
13127
13194
|
const stripped = token.replace(/^(_xlfn\.)?(_xlws\.)?/i, "");
|
|
13128
13195
|
if (stripped === token) return false;
|
|
@@ -13132,7 +13199,7 @@ function stripFuturePrefixes(formula) {
|
|
|
13132
13199
|
return fromStoredSyntax(plain2);
|
|
13133
13200
|
}
|
|
13134
13201
|
function addFuturePrefixes(formula) {
|
|
13135
|
-
return
|
|
13202
|
+
return rewrite(toStoredSyntax(formula), (token, next, out) => {
|
|
13136
13203
|
if (!next.startsWith("(")) return false;
|
|
13137
13204
|
const upper2 = token.toUpperCase();
|
|
13138
13205
|
if (!FUTURE_FUNCTIONS.has(upper2)) return false;
|
|
@@ -13785,13 +13852,13 @@ function dataBarLengths(rule2, node) {
|
|
|
13785
13852
|
maxLength: rule2.maxLength ?? numAttr(bar, "maxLength") ?? 90
|
|
13786
13853
|
};
|
|
13787
13854
|
}
|
|
13788
|
-
function rewriteConditionalExtension(rule2,
|
|
13855
|
+
function rewriteConditionalExtension(rule2, rewrite2) {
|
|
13789
13856
|
if (!rule2.extensionXml) return;
|
|
13790
13857
|
const doc = parseXml(rule2.extensionXml);
|
|
13791
13858
|
let changed = false;
|
|
13792
13859
|
for (const formula of descendants3(doc.documentElement, "f", XM)) {
|
|
13793
13860
|
const before = formula.textContent ?? "";
|
|
13794
|
-
const next =
|
|
13861
|
+
const next = rewrite2(before);
|
|
13795
13862
|
if (before !== next) {
|
|
13796
13863
|
formula.textContent = next;
|
|
13797
13864
|
changed = true;
|
|
@@ -14415,12 +14482,12 @@ function splitSheetData(xml) {
|
|
|
14415
14482
|
if (openEnd < 0) return void 0;
|
|
14416
14483
|
const attributes = xml.slice(open.index + tagName2.length + 1, openEnd);
|
|
14417
14484
|
if (attributes.trimEnd().endsWith("/") || attributes.includes("xmlns")) return void 0;
|
|
14418
|
-
const
|
|
14419
|
-
if (
|
|
14485
|
+
const close2 = xml.indexOf(`</${tagName2}`, openEnd);
|
|
14486
|
+
if (close2 < 0 || OPEN.test(xml.slice(openEnd))) return void 0;
|
|
14420
14487
|
const container = new LiteElement(tagName2, "sheetData", ns || null);
|
|
14421
|
-
const data = parseLiteFragment(xml.slice(openEnd + 1,
|
|
14488
|
+
const data = parseLiteFragment(xml.slice(openEnd + 1, close2), container, namespaces);
|
|
14422
14489
|
if (!data) return void 0;
|
|
14423
|
-
return { xml: xml.slice(0, openEnd + 1) + xml.slice(
|
|
14490
|
+
return { xml: xml.slice(0, openEnd + 1) + xml.slice(close2), sheetData: data.asElement() };
|
|
14424
14491
|
}
|
|
14425
14492
|
|
|
14426
14493
|
// xlsx/read/print-options.ts
|
|
@@ -14963,10 +15030,10 @@ function hls240ToRgb({ h: h2, l, s }) {
|
|
|
14963
15030
|
var parseHex = parseArgbHex;
|
|
14964
15031
|
var toHexColor = rgbToUpperHex;
|
|
14965
15032
|
function applyTint(hex, tint) {
|
|
14966
|
-
const
|
|
14967
|
-
if (!tint) return toHexColor(
|
|
15033
|
+
const rgb3 = parseHex(hex) ?? [0, 0, 0];
|
|
15034
|
+
if (!tint) return toHexColor(rgb3);
|
|
14968
15035
|
const t = Math.max(-1, Math.min(1, tint));
|
|
14969
|
-
const hls = rgbToHls240(...
|
|
15036
|
+
const hls = rgbToHls240(...rgb3);
|
|
14970
15037
|
const l = t < 0 ? Math.trunc(hls.l * (1 + t)) : Math.round(hls.l * (1 - t) + HLSMAX * t);
|
|
14971
15038
|
return toHexColor(hls240ToRgb({ ...hls, l: Math.max(0, Math.min(HLSMAX, l)) }));
|
|
14972
15039
|
}
|
|
@@ -17024,7 +17091,9 @@ var PREC_INTERSECT = 9;
|
|
|
17024
17091
|
var PREC_RANGE = 10;
|
|
17025
17092
|
var OPERAND_START = /* @__PURE__ */ new Set(["ref", "name", "func", "open", "structured"]);
|
|
17026
17093
|
function parseFormula(formula) {
|
|
17027
|
-
|
|
17094
|
+
return parseTokens(tokenize(formula));
|
|
17095
|
+
}
|
|
17096
|
+
function parseTokens(all2) {
|
|
17028
17097
|
const tokens3 = [];
|
|
17029
17098
|
const wsBefore = [];
|
|
17030
17099
|
let sawWs = false;
|
|
@@ -17365,6 +17434,222 @@ function localDateToSerial(date, date1904 = date1904Mode) {
|
|
|
17365
17434
|
return base + (utc - dayStart) / DAY_MS2;
|
|
17366
17435
|
}
|
|
17367
17436
|
|
|
17437
|
+
// xlsx/formula/area-index.ts
|
|
17438
|
+
var BUCKET_WIDTH = 64;
|
|
17439
|
+
var CHUNK_SHIFT = 6;
|
|
17440
|
+
var CHUNKS = 64;
|
|
17441
|
+
function push(map, key2, value) {
|
|
17442
|
+
const list = map.get(key2);
|
|
17443
|
+
if (list) list.push(value);
|
|
17444
|
+
else map.set(key2, [value]);
|
|
17445
|
+
}
|
|
17446
|
+
function inner(map, sheet) {
|
|
17447
|
+
let found = map.get(sheet);
|
|
17448
|
+
if (!found) map.set(sheet, found = /* @__PURE__ */ new Map());
|
|
17449
|
+
return found;
|
|
17450
|
+
}
|
|
17451
|
+
var AreaIndex = class {
|
|
17452
|
+
cells = /* @__PURE__ */ new Map();
|
|
17453
|
+
chunked = /* @__PURE__ */ new Map();
|
|
17454
|
+
tall = /* @__PURE__ */ new Map();
|
|
17455
|
+
wide = /* @__PURE__ */ new Map();
|
|
17456
|
+
add(area, node) {
|
|
17457
|
+
const { start, end } = area.range;
|
|
17458
|
+
if (start.row === end.row && end.col - start.col + 1 <= BUCKET_WIDTH) {
|
|
17459
|
+
const cells3 = inner(this.cells, area.sheet);
|
|
17460
|
+
for (let col = start.col; col <= end.col; col++) push(cells3, cellKey(start.row, col), node);
|
|
17461
|
+
return;
|
|
17462
|
+
}
|
|
17463
|
+
const entry3 = { range: area.range, node };
|
|
17464
|
+
if (end.col - start.col + 1 > BUCKET_WIDTH) {
|
|
17465
|
+
const list = this.wide.get(area.sheet);
|
|
17466
|
+
if (list) list.push(entry3);
|
|
17467
|
+
else this.wide.set(area.sheet, [entry3]);
|
|
17468
|
+
return;
|
|
17469
|
+
}
|
|
17470
|
+
const first3 = start.row >> CHUNK_SHIFT;
|
|
17471
|
+
const last = end.row >> CHUNK_SHIFT;
|
|
17472
|
+
if (last - first3 + 1 > CHUNKS) {
|
|
17473
|
+
const cols2 = inner(this.tall, area.sheet);
|
|
17474
|
+
for (let c2 = start.col; c2 <= end.col; c2++) push(cols2, c2, entry3);
|
|
17475
|
+
return;
|
|
17476
|
+
}
|
|
17477
|
+
const cols = inner(this.chunked, area.sheet);
|
|
17478
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
17479
|
+
let chunks = cols.get(c2);
|
|
17480
|
+
if (!chunks) cols.set(c2, chunks = /* @__PURE__ */ new Map());
|
|
17481
|
+
for (let k = first3; k <= last; k++) push(chunks, k, entry3);
|
|
17482
|
+
}
|
|
17483
|
+
}
|
|
17484
|
+
/** Items whose areas intersect `range` on `sheet` (each once). */
|
|
17485
|
+
dependents(sheet, range, out) {
|
|
17486
|
+
const found = out instanceof Set ? out : /* @__PURE__ */ new Set();
|
|
17487
|
+
this.collect(sheet, range, found);
|
|
17488
|
+
if (Array.isArray(out)) for (const node of found) out.push(node);
|
|
17489
|
+
}
|
|
17490
|
+
collect(sheet, range, out) {
|
|
17491
|
+
const { start, end } = range;
|
|
17492
|
+
const check3 = (list) => {
|
|
17493
|
+
if (list) {
|
|
17494
|
+
for (const entry3 of list) if (rangesIntersect(entry3.range, range)) out.add(entry3.node);
|
|
17495
|
+
}
|
|
17496
|
+
};
|
|
17497
|
+
const cells3 = this.cells.get(sheet);
|
|
17498
|
+
if (cells3) {
|
|
17499
|
+
const size = (end.row - start.row + 1) * (end.col - start.col + 1);
|
|
17500
|
+
if (size <= 4096) {
|
|
17501
|
+
for (let r = start.row; r <= end.row; r++) {
|
|
17502
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
17503
|
+
const list = cells3.get(cellKey(r, c2));
|
|
17504
|
+
if (list) for (const node of list) out.add(node);
|
|
17505
|
+
}
|
|
17506
|
+
}
|
|
17507
|
+
} else {
|
|
17508
|
+
for (const [key2, list] of cells3) {
|
|
17509
|
+
const { row: row2, col } = keyToAddress(key2);
|
|
17510
|
+
if (row2 >= start.row && row2 <= end.row && col >= start.col && col <= end.col)
|
|
17511
|
+
for (const node of list) out.add(node);
|
|
17512
|
+
}
|
|
17513
|
+
}
|
|
17514
|
+
}
|
|
17515
|
+
const columns = (map, visit2) => {
|
|
17516
|
+
if (!map) return;
|
|
17517
|
+
if (end.col - start.col + 1 <= map.size) {
|
|
17518
|
+
for (let c2 = start.col; c2 <= end.col; c2++) if (map.has(c2)) visit2(c2);
|
|
17519
|
+
} else for (const c2 of map.keys()) if (c2 >= start.col && c2 <= end.col) visit2(c2);
|
|
17520
|
+
};
|
|
17521
|
+
const chunked = this.chunked.get(sheet);
|
|
17522
|
+
const first3 = start.row >> CHUNK_SHIFT;
|
|
17523
|
+
const last = end.row >> CHUNK_SHIFT;
|
|
17524
|
+
columns(chunked, (c2) => {
|
|
17525
|
+
const chunks = chunked?.get(c2);
|
|
17526
|
+
if (last - first3 + 1 <= chunks.size) {
|
|
17527
|
+
for (let k = first3; k <= last; k++) check3(chunks.get(k));
|
|
17528
|
+
} else for (const [k, list] of chunks) if (k >= first3 && k <= last) check3(list);
|
|
17529
|
+
});
|
|
17530
|
+
const tall = this.tall.get(sheet);
|
|
17531
|
+
columns(tall, (c2) => check3(tall?.get(c2)));
|
|
17532
|
+
check3(this.wide.get(sheet));
|
|
17533
|
+
}
|
|
17534
|
+
};
|
|
17535
|
+
|
|
17536
|
+
// xlsx/formula/graph-index.ts
|
|
17537
|
+
var ColumnIndex = class {
|
|
17538
|
+
sheets = /* @__PURE__ */ new Map();
|
|
17539
|
+
constructor(nodes) {
|
|
17540
|
+
for (const node of nodes) {
|
|
17541
|
+
let cols = this.sheets.get(node.sheet);
|
|
17542
|
+
if (!cols) this.sheets.set(node.sheet, cols = /* @__PURE__ */ new Map());
|
|
17543
|
+
let list = cols.get(node.col);
|
|
17544
|
+
if (!list) cols.set(node.col, list = []);
|
|
17545
|
+
list.push(node);
|
|
17546
|
+
}
|
|
17547
|
+
for (const cols of this.sheets.values())
|
|
17548
|
+
for (const list of cols.values()) list.sort((a2, b) => a2.row - b.row);
|
|
17549
|
+
}
|
|
17550
|
+
nodesIn(area, out) {
|
|
17551
|
+
const cols = this.sheets.get(area.sheet);
|
|
17552
|
+
if (!cols) return;
|
|
17553
|
+
const { start, end } = area.range;
|
|
17554
|
+
const width = end.col - start.col + 1;
|
|
17555
|
+
const scan3 = (list) => {
|
|
17556
|
+
let lo = 0;
|
|
17557
|
+
let hi = list.length;
|
|
17558
|
+
while (lo < hi) {
|
|
17559
|
+
const mid = lo + hi >> 1;
|
|
17560
|
+
if (list[mid].row < start.row) lo = mid + 1;
|
|
17561
|
+
else hi = mid;
|
|
17562
|
+
}
|
|
17563
|
+
for (let i2 = lo; i2 < list.length; i2++) {
|
|
17564
|
+
const node = list[i2];
|
|
17565
|
+
if (node.row > end.row) break;
|
|
17566
|
+
out.push(node);
|
|
17567
|
+
}
|
|
17568
|
+
};
|
|
17569
|
+
if (width <= cols.size) {
|
|
17570
|
+
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
17571
|
+
const list = cols.get(c2);
|
|
17572
|
+
if (list) scan3(list);
|
|
17573
|
+
}
|
|
17574
|
+
} else {
|
|
17575
|
+
for (const [c2, list] of cols) if (c2 >= start.col && c2 <= end.col) scan3(list);
|
|
17576
|
+
}
|
|
17577
|
+
}
|
|
17578
|
+
};
|
|
17579
|
+
var ReverseIndex = class extends AreaIndex {
|
|
17580
|
+
constructor(nodes = []) {
|
|
17581
|
+
super();
|
|
17582
|
+
for (const node of nodes) this.addNode(node);
|
|
17583
|
+
}
|
|
17584
|
+
/** Indexes one more formula's precedents. */
|
|
17585
|
+
addNode(node) {
|
|
17586
|
+
for (const dep of node.deps) this.add(dep, node);
|
|
17587
|
+
for (const dep of node.dynamicDeps) this.add(dep, node);
|
|
17588
|
+
}
|
|
17589
|
+
};
|
|
17590
|
+
|
|
17591
|
+
// xlsx/formula/engine-prepare.ts
|
|
17592
|
+
var CHECK_EVERY = 32;
|
|
17593
|
+
var GraphPreparation = class {
|
|
17594
|
+
constructor(workbook, create) {
|
|
17595
|
+
this.workbook = workbook;
|
|
17596
|
+
this.create = create;
|
|
17597
|
+
}
|
|
17598
|
+
workbook;
|
|
17599
|
+
create;
|
|
17600
|
+
reverse = new ReverseIndex();
|
|
17601
|
+
formulas = { dynamic: [], unvalued: [] };
|
|
17602
|
+
sheet = 0;
|
|
17603
|
+
rows;
|
|
17604
|
+
row = 0;
|
|
17605
|
+
cells;
|
|
17606
|
+
finished = false;
|
|
17607
|
+
/**
|
|
17608
|
+
* Adds formulas to the graph until `timeRemaining` (milliseconds, as an idle deadline reports
|
|
17609
|
+
* them) reaches zero, or until every formula is in. Returns true when the graph is complete.
|
|
17610
|
+
*/
|
|
17611
|
+
run(timeRemaining) {
|
|
17612
|
+
let visited = 0;
|
|
17613
|
+
while (!this.finished) {
|
|
17614
|
+
const cells3 = this.cells ?? this.nextRow();
|
|
17615
|
+
if (!cells3) continue;
|
|
17616
|
+
const next = cells3.next();
|
|
17617
|
+
if (next.done) {
|
|
17618
|
+
this.cells = void 0;
|
|
17619
|
+
continue;
|
|
17620
|
+
}
|
|
17621
|
+
const [col, cell] = next.value;
|
|
17622
|
+
if (cell.formula) this.add(this.create(this.sheet, this.row, col, cell), cell);
|
|
17623
|
+
if (timeRemaining && ++visited % CHECK_EVERY === 0 && timeRemaining() <= 0) break;
|
|
17624
|
+
}
|
|
17625
|
+
return this.finished;
|
|
17626
|
+
}
|
|
17627
|
+
add(node, cell) {
|
|
17628
|
+
this.reverse.addNode(node);
|
|
17629
|
+
if (!node.legacy && !node.arrayRange) this.formulas.dynamic.push(node);
|
|
17630
|
+
if (cell.value === null && !node.keepCached) this.formulas.unvalued.push(node);
|
|
17631
|
+
}
|
|
17632
|
+
/** Moves to the next stored row (and sheet), or marks the walk finished. */
|
|
17633
|
+
nextRow() {
|
|
17634
|
+
for (; ; ) {
|
|
17635
|
+
const sheet = this.workbook.sheets[this.sheet];
|
|
17636
|
+
if (!sheet) {
|
|
17637
|
+
this.finished = true;
|
|
17638
|
+
return void 0;
|
|
17639
|
+
}
|
|
17640
|
+
this.rows ??= sheet.rows.entries();
|
|
17641
|
+
const next = this.rows.next();
|
|
17642
|
+
if (!next.done) {
|
|
17643
|
+
this.row = next.value[0];
|
|
17644
|
+
this.cells = next.value[1].entries();
|
|
17645
|
+
return this.cells;
|
|
17646
|
+
}
|
|
17647
|
+
this.rows = void 0;
|
|
17648
|
+
this.sheet++;
|
|
17649
|
+
}
|
|
17650
|
+
}
|
|
17651
|
+
};
|
|
17652
|
+
|
|
17368
17653
|
// xlsx/formula/text-number.ts
|
|
17369
17654
|
var MONTHS2 = [
|
|
17370
17655
|
"jan",
|
|
@@ -20499,8 +20784,10 @@ var FINANCIAL_FUNCTIONS = [
|
|
|
20499
20784
|
|
|
20500
20785
|
// xlsx/formula/references.ts
|
|
20501
20786
|
function sheetIndex(host, name) {
|
|
20787
|
+
const sheets = host.workbook.sheets;
|
|
20788
|
+
for (let i2 = 0; i2 < sheets.length; i2++) if (sheets[i2]?.name === name) return i2;
|
|
20502
20789
|
const lower2 = name.toLowerCase();
|
|
20503
|
-
return
|
|
20790
|
+
return sheets.findIndex((sheet) => sheet.name.toLowerCase() === lower2);
|
|
20504
20791
|
}
|
|
20505
20792
|
function prefixSheets(host, prefix, current) {
|
|
20506
20793
|
if (!prefix) return [current];
|
|
@@ -22114,9 +22401,9 @@ function readBlock(ctx, area, rows, cols) {
|
|
|
22114
22401
|
if (host.readBlock) return host.readBlock(area.sheet, range);
|
|
22115
22402
|
return Matrix.build(rows, cols, (r, c2) => ctx.readCell(area.sheet, row2 + r, col + c2));
|
|
22116
22403
|
}
|
|
22117
|
-
function shapedMatrices(ctx, values2,
|
|
22404
|
+
function shapedMatrices(ctx, values2, sameShape2) {
|
|
22118
22405
|
let { rows, cols } = shapeOf(values2[0] ?? null);
|
|
22119
|
-
if (
|
|
22406
|
+
if (sameShape2) {
|
|
22120
22407
|
for (const value of values2) {
|
|
22121
22408
|
const shape2 = shapeOf(value);
|
|
22122
22409
|
if (shape2.rows !== rows || shape2.cols !== cols) fail(ERR.VALUE);
|
|
@@ -22142,12 +22429,12 @@ function shapedMatrices(ctx, values2, sameShape) {
|
|
|
22142
22429
|
});
|
|
22143
22430
|
return { matrices, total: total2, block: rows * cols };
|
|
22144
22431
|
}
|
|
22145
|
-
function matchingCells(ctx, pairs, target,
|
|
22432
|
+
function matchingCells(ctx, pairs, target, sameShape2) {
|
|
22146
22433
|
const ranges = pairs.map((p) => p.range);
|
|
22147
22434
|
const { matrices, total: total2, block } = shapedMatrices(
|
|
22148
22435
|
ctx,
|
|
22149
22436
|
target === void 0 ? ranges : [...ranges, target],
|
|
22150
|
-
|
|
22437
|
+
sameShape2
|
|
22151
22438
|
);
|
|
22152
22439
|
const tests = pairs.map((p) => makeCriteria(scalar(p.criteria)));
|
|
22153
22440
|
const values2 = matrices[matrices.length - 1];
|
|
@@ -22186,7 +22473,7 @@ function indexedCandidates(pairs, matrices) {
|
|
|
22186
22473
|
}
|
|
22187
22474
|
return void 0;
|
|
22188
22475
|
}
|
|
22189
|
-
var matchingValues = (ctx, pairs, target,
|
|
22476
|
+
var matchingValues = (ctx, pairs, target, sameShape2) => matchingCells(ctx, pairs, target, sameShape2).values;
|
|
22190
22477
|
function criteriaPairs(args, from) {
|
|
22191
22478
|
if ((args.length - from) % 2 !== 0) fail(ERR.VALUE);
|
|
22192
22479
|
const pairs = [];
|
|
@@ -26080,7 +26367,7 @@ var REFERENCE_ARGUMENT = /* @__PURE__ */ new Set([
|
|
|
26080
26367
|
"AREAS",
|
|
26081
26368
|
"ISREF"
|
|
26082
26369
|
]);
|
|
26083
|
-
var
|
|
26370
|
+
var push2 = (c2, area) => {
|
|
26084
26371
|
(c2.dynamic > 0 ? c2.dynamicDeps : c2.deps).push(area);
|
|
26085
26372
|
};
|
|
26086
26373
|
function spans(areas) {
|
|
@@ -26106,7 +26393,7 @@ function visit(node, c2) {
|
|
|
26106
26393
|
if (!sheets) return;
|
|
26107
26394
|
const range = specRange(node.ref);
|
|
26108
26395
|
const target = node.spill ? { start: range.start, end: { ...range.start } } : range;
|
|
26109
|
-
for (const sheet of sheets)
|
|
26396
|
+
for (const sheet of sheets) push2(c2, { sheet, range: target });
|
|
26110
26397
|
return;
|
|
26111
26398
|
}
|
|
26112
26399
|
case "name": {
|
|
@@ -26180,7 +26467,7 @@ function visitBinary(node, c2) {
|
|
|
26180
26467
|
const list = c2.dynamic > 0 ? c2.dynamicDeps : c2.deps;
|
|
26181
26468
|
const l = list[list.length - 2];
|
|
26182
26469
|
const r = list[list.length - 1];
|
|
26183
|
-
if (l && r && l.sheet === r.sheet)
|
|
26470
|
+
if (l && r && l.sheet === r.sheet) push2(c2, spans([l, r])[0]);
|
|
26184
26471
|
continue;
|
|
26185
26472
|
}
|
|
26186
26473
|
const mentioned = [...c2.deps.slice(staticStart), ...c2.dynamicDeps.slice(dynamicStart)];
|
|
@@ -26196,7 +26483,7 @@ function addStructured(ref, c2) {
|
|
|
26196
26483
|
sheet: c2.sheet,
|
|
26197
26484
|
row: c2.row,
|
|
26198
26485
|
col: c2.col});
|
|
26199
|
-
if (value instanceof RefValue) for (const area of value.areas)
|
|
26486
|
+
if (value instanceof RefValue) for (const area of value.areas) push2(c2, area);
|
|
26200
26487
|
}
|
|
26201
26488
|
function analyze(ast, host, sheet, row2, col) {
|
|
26202
26489
|
const c2 = {
|
|
@@ -26220,155 +26507,191 @@ function analyze(ast, host, sheet, row2, col) {
|
|
|
26220
26507
|
};
|
|
26221
26508
|
}
|
|
26222
26509
|
|
|
26223
|
-
// xlsx/formula/
|
|
26224
|
-
var
|
|
26225
|
-
|
|
26226
|
-
|
|
26227
|
-
|
|
26228
|
-
|
|
26229
|
-
|
|
26230
|
-
|
|
26510
|
+
// xlsx/formula/formula-shape.ts
|
|
26511
|
+
var isDigit4 = (code) => code >= 48 && code <= 57;
|
|
26512
|
+
function formulaShape(formula) {
|
|
26513
|
+
const starts = [];
|
|
26514
|
+
const ends = [];
|
|
26515
|
+
let hash = 2166136261;
|
|
26516
|
+
for (let i2 = 0; i2 < formula.length; i2++) {
|
|
26517
|
+
let code = formula.charCodeAt(i2);
|
|
26518
|
+
if (isDigit4(code)) {
|
|
26519
|
+
let j = i2 + 1;
|
|
26520
|
+
while (j < formula.length && isDigit4(formula.charCodeAt(j))) j++;
|
|
26521
|
+
starts.push(i2);
|
|
26522
|
+
ends.push(j);
|
|
26523
|
+
i2 = j - 1;
|
|
26524
|
+
code = 0;
|
|
26525
|
+
}
|
|
26526
|
+
hash = Math.imul(hash ^ code, 16777619);
|
|
26527
|
+
}
|
|
26528
|
+
return { hash: hash >>> 0, starts, ends };
|
|
26231
26529
|
}
|
|
26232
|
-
function
|
|
26233
|
-
let
|
|
26234
|
-
|
|
26235
|
-
return
|
|
26530
|
+
function sameText(a2, from, b, at2, length) {
|
|
26531
|
+
for (let k = 0; k < length; k++)
|
|
26532
|
+
if (a2.charCodeAt(from + k) !== b.charCodeAt(at2 + k)) return false;
|
|
26533
|
+
return true;
|
|
26236
26534
|
}
|
|
26237
|
-
|
|
26238
|
-
|
|
26239
|
-
|
|
26240
|
-
|
|
26241
|
-
|
|
26242
|
-
|
|
26243
|
-
const
|
|
26244
|
-
|
|
26245
|
-
|
|
26246
|
-
|
|
26247
|
-
|
|
26535
|
+
function sameShape(a2, as, b, bs) {
|
|
26536
|
+
const runs = as.starts.length;
|
|
26537
|
+
if (runs !== bs.starts.length) return false;
|
|
26538
|
+
let fromA = 0;
|
|
26539
|
+
let fromB = 0;
|
|
26540
|
+
for (let i2 = 0; i2 <= runs; i2++) {
|
|
26541
|
+
const toA = i2 < runs ? as.starts[i2] : a2.length;
|
|
26542
|
+
const toB = i2 < runs ? bs.starts[i2] : b.length;
|
|
26543
|
+
if (toA - fromA !== toB - fromB || !sameText(a2, fromA, b, fromB, toA - fromA)) return false;
|
|
26544
|
+
fromA = as.ends[i2] ?? 0;
|
|
26545
|
+
fromB = bs.ends[i2] ?? 0;
|
|
26546
|
+
}
|
|
26547
|
+
return true;
|
|
26548
|
+
}
|
|
26549
|
+
function makeTemplate(formula, shape2) {
|
|
26550
|
+
let tokens3;
|
|
26551
|
+
let ast;
|
|
26552
|
+
try {
|
|
26553
|
+
tokens3 = tokenize(formula);
|
|
26554
|
+
ast = parseTokens(tokens3);
|
|
26555
|
+
} catch (e) {
|
|
26556
|
+
if (e instanceof RangeError) return new FormulaError(e.message, -1, "#VALUE!");
|
|
26557
|
+
if (e instanceof FormulaError) return e;
|
|
26558
|
+
throw e;
|
|
26559
|
+
}
|
|
26560
|
+
const { starts } = shape2;
|
|
26561
|
+
const slotted = starts.map(() => false);
|
|
26562
|
+
const refs = /* @__PURE__ */ new Map();
|
|
26563
|
+
let run2 = 0;
|
|
26564
|
+
for (const token of tokens3) {
|
|
26565
|
+
const end = token.start + token.text.length;
|
|
26566
|
+
const first3 = run2;
|
|
26567
|
+
while (run2 < starts.length && starts[run2] < end) run2++;
|
|
26568
|
+
const ref = token.kind === "ref" ? token.ref : void 0;
|
|
26569
|
+
if (!ref || ref.kind === "cols") continue;
|
|
26570
|
+
const count2 = ref.kind === "cell" ? 1 : 2;
|
|
26571
|
+
if (run2 - first3 < count2) continue;
|
|
26572
|
+
const at2 = run2 - count2;
|
|
26573
|
+
const indexes2 = count2 === 1 ? [at2] : [at2, at2 + 1];
|
|
26574
|
+
if (indexes2.some((i2) => formula.charCodeAt(starts[i2]) === 48)) continue;
|
|
26575
|
+
for (const i2 of indexes2) slotted[i2] = true;
|
|
26576
|
+
refs.set(ref, count2 === 1 ? { start: at2 } : { start: at2, end: at2 + 1 });
|
|
26577
|
+
}
|
|
26578
|
+
return { formula, shape: shape2, ast, slotted, refs };
|
|
26579
|
+
}
|
|
26580
|
+
function rowsFor(t, formula, shape2) {
|
|
26581
|
+
if (!sameShape(t.formula, t.shape, formula, shape2)) return void 0;
|
|
26582
|
+
const rows = [];
|
|
26583
|
+
for (let i2 = 0; i2 < shape2.starts.length; i2++) {
|
|
26584
|
+
const start = shape2.starts[i2];
|
|
26585
|
+
const length = shape2.ends[i2] - start;
|
|
26586
|
+
if (!t.slotted[i2]) {
|
|
26587
|
+
const own = t.shape.starts[i2];
|
|
26588
|
+
if (t.shape.ends[i2] - own !== length) return void 0;
|
|
26589
|
+
if (!sameText(t.formula, own, formula, start, length)) return void 0;
|
|
26590
|
+
rows.push(-1);
|
|
26591
|
+
continue;
|
|
26248
26592
|
}
|
|
26249
|
-
|
|
26250
|
-
|
|
26251
|
-
|
|
26252
|
-
|
|
26253
|
-
|
|
26254
|
-
|
|
26593
|
+
if (length > 7 || formula.charCodeAt(start) === 48) return void 0;
|
|
26594
|
+
let row2 = 0;
|
|
26595
|
+
for (let k = start; k < start + length; k++) row2 = row2 * 10 + formula.charCodeAt(k) - 48;
|
|
26596
|
+
if (row2 < 1 || row2 > MAX_ROW + 1) return void 0;
|
|
26597
|
+
rows.push(row2 - 1);
|
|
26598
|
+
}
|
|
26599
|
+
return rows;
|
|
26600
|
+
}
|
|
26601
|
+
function shiftSpec(spec2, slots, rows) {
|
|
26602
|
+
const startRow = rows[slots.start];
|
|
26603
|
+
const endRow = slots.end === void 0 ? startRow : rows[slots.end];
|
|
26604
|
+
if (startRow === spec2.start.row && endRow === spec2.end.row) return spec2;
|
|
26605
|
+
const { start: from, end: to } = spec2;
|
|
26606
|
+
const start = { row: startRow, col: from.col, rowAbs: from.rowAbs, colAbs: from.colAbs };
|
|
26607
|
+
if (slots.end === void 0) return { kind: spec2.kind, start, end: start };
|
|
26608
|
+
const end = { row: endRow, col: to.col, rowAbs: to.rowAbs, colAbs: to.colAbs };
|
|
26609
|
+
return { kind: spec2.kind, start, end };
|
|
26610
|
+
}
|
|
26611
|
+
function copyTree(node, t, rows) {
|
|
26612
|
+
switch (node.type) {
|
|
26613
|
+
case "ref": {
|
|
26614
|
+
const slots = node.ref ? t.refs.get(node.ref) : void 0;
|
|
26615
|
+
if (!slots || !node.ref) return node;
|
|
26616
|
+
const ref = shiftSpec(node.ref, slots, rows);
|
|
26617
|
+
if (ref === node.ref) return node;
|
|
26618
|
+
const copy2 = { type: "ref" };
|
|
26619
|
+
if (node.prefix) copy2.prefix = node.prefix;
|
|
26620
|
+
copy2.ref = ref;
|
|
26621
|
+
if (node.spill) copy2.spill = true;
|
|
26622
|
+
return copy2;
|
|
26255
26623
|
}
|
|
26256
|
-
|
|
26257
|
-
|
|
26258
|
-
|
|
26259
|
-
|
|
26260
|
-
|
|
26261
|
-
return;
|
|
26624
|
+
case "unary":
|
|
26625
|
+
case "percent": {
|
|
26626
|
+
const operand4 = copyTree(node.operand, t, rows);
|
|
26627
|
+
if (operand4 === node.operand) return node;
|
|
26628
|
+
return node.type === "unary" ? { type: "unary", op: node.op, operand: operand4 } : { type: "percent", operand: operand4 };
|
|
26262
26629
|
}
|
|
26263
|
-
|
|
26264
|
-
|
|
26265
|
-
|
|
26266
|
-
if (
|
|
26267
|
-
|
|
26630
|
+
case "binary": {
|
|
26631
|
+
const left2 = copyTree(node.left, t, rows);
|
|
26632
|
+
const right2 = copyTree(node.right, t, rows);
|
|
26633
|
+
if (left2 === node.left && right2 === node.right) return node;
|
|
26634
|
+
return { type: "binary", op: node.op, left: left2, right: right2 };
|
|
26268
26635
|
}
|
|
26269
|
-
|
|
26270
|
-
|
|
26271
|
-
|
|
26272
|
-
|
|
26273
|
-
this.collect(sheet, range, found);
|
|
26274
|
-
if (Array.isArray(out)) for (const node of found) out.push(node);
|
|
26275
|
-
}
|
|
26276
|
-
collect(sheet, range, out) {
|
|
26277
|
-
const { start, end } = range;
|
|
26278
|
-
const check3 = (list) => {
|
|
26279
|
-
if (list) {
|
|
26280
|
-
for (const entry3 of list) if (rangesIntersect(entry3.range, range)) out.add(entry3.node);
|
|
26281
|
-
}
|
|
26282
|
-
};
|
|
26283
|
-
const cells3 = this.cells.get(sheet);
|
|
26284
|
-
if (cells3) {
|
|
26285
|
-
const size = (end.row - start.row + 1) * (end.col - start.col + 1);
|
|
26286
|
-
if (size <= 4096) {
|
|
26287
|
-
for (let r = start.row; r <= end.row; r++) {
|
|
26288
|
-
for (let c2 = start.col; c2 <= end.col; c2++) {
|
|
26289
|
-
const list = cells3.get(cellKey(r, c2));
|
|
26290
|
-
if (list) for (const node of list) out.add(node);
|
|
26291
|
-
}
|
|
26292
|
-
}
|
|
26293
|
-
} else {
|
|
26294
|
-
for (const [key2, list] of cells3) {
|
|
26295
|
-
const { row: row2, col } = keyToAddress(key2);
|
|
26296
|
-
if (row2 >= start.row && row2 <= end.row && col >= start.col && col <= end.col)
|
|
26297
|
-
for (const node of list) out.add(node);
|
|
26298
|
-
}
|
|
26299
|
-
}
|
|
26636
|
+
case "call": {
|
|
26637
|
+
const args = copyAll(node.args, t, rows);
|
|
26638
|
+
if (args === node.args) return node;
|
|
26639
|
+
return { type: "call", name: node.name, rawName: node.rawName, args };
|
|
26300
26640
|
}
|
|
26301
|
-
|
|
26302
|
-
|
|
26303
|
-
|
|
26304
|
-
|
|
26305
|
-
|
|
26306
|
-
};
|
|
26307
|
-
const chunked = this.chunked.get(sheet);
|
|
26308
|
-
const first3 = start.row >> CHUNK_SHIFT;
|
|
26309
|
-
const last = end.row >> CHUNK_SHIFT;
|
|
26310
|
-
columns(chunked, (c2) => {
|
|
26311
|
-
const chunks = chunked?.get(c2);
|
|
26312
|
-
if (last - first3 + 1 <= chunks.size) {
|
|
26313
|
-
for (let k = first3; k <= last; k++) check3(chunks.get(k));
|
|
26314
|
-
} else for (const [k, list] of chunks) if (k >= first3 && k <= last) check3(list);
|
|
26315
|
-
});
|
|
26316
|
-
const tall = this.tall.get(sheet);
|
|
26317
|
-
columns(tall, (c2) => check3(tall?.get(c2)));
|
|
26318
|
-
check3(this.wide.get(sheet));
|
|
26319
|
-
}
|
|
26320
|
-
};
|
|
26321
|
-
|
|
26322
|
-
// xlsx/formula/graph-index.ts
|
|
26323
|
-
var ColumnIndex = class {
|
|
26324
|
-
sheets = /* @__PURE__ */ new Map();
|
|
26325
|
-
constructor(nodes) {
|
|
26326
|
-
for (const node of nodes) {
|
|
26327
|
-
let cols = this.sheets.get(node.sheet);
|
|
26328
|
-
if (!cols) this.sheets.set(node.sheet, cols = /* @__PURE__ */ new Map());
|
|
26329
|
-
let list = cols.get(node.col);
|
|
26330
|
-
if (!list) cols.set(node.col, list = []);
|
|
26331
|
-
list.push(node);
|
|
26641
|
+
case "invoke": {
|
|
26642
|
+
const callee = copyTree(node.callee, t, rows);
|
|
26643
|
+
const args = copyAll(node.args, t, rows);
|
|
26644
|
+
if (callee === node.callee && args === node.args) return node;
|
|
26645
|
+
return { type: "invoke", callee, args };
|
|
26332
26646
|
}
|
|
26333
|
-
|
|
26334
|
-
|
|
26647
|
+
default:
|
|
26648
|
+
return node;
|
|
26335
26649
|
}
|
|
26336
|
-
|
|
26337
|
-
|
|
26338
|
-
|
|
26339
|
-
|
|
26340
|
-
const
|
|
26341
|
-
const
|
|
26342
|
-
|
|
26343
|
-
|
|
26344
|
-
|
|
26345
|
-
|
|
26346
|
-
|
|
26347
|
-
|
|
26348
|
-
|
|
26349
|
-
|
|
26350
|
-
|
|
26351
|
-
|
|
26352
|
-
|
|
26353
|
-
|
|
26354
|
-
|
|
26355
|
-
|
|
26356
|
-
|
|
26357
|
-
|
|
26358
|
-
|
|
26359
|
-
|
|
26360
|
-
|
|
26361
|
-
|
|
26362
|
-
|
|
26650
|
+
}
|
|
26651
|
+
function copyAll(nodes, t, rows) {
|
|
26652
|
+
let out;
|
|
26653
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
26654
|
+
const node = nodes[i2];
|
|
26655
|
+
const copy2 = copyTree(node, t, rows);
|
|
26656
|
+
if (copy2 !== node && !out) out = nodes.slice(0, i2);
|
|
26657
|
+
out?.push(copy2);
|
|
26658
|
+
}
|
|
26659
|
+
return out ?? nodes;
|
|
26660
|
+
}
|
|
26661
|
+
function fromTemplate(t, formula, shape2) {
|
|
26662
|
+
const rows = rowsFor(t, formula, shape2);
|
|
26663
|
+
return rows ? copyTree(t.ast, t, rows) : void 0;
|
|
26664
|
+
}
|
|
26665
|
+
|
|
26666
|
+
// xlsx/formula/parse-cache.ts
|
|
26667
|
+
var MAX_TEMPLATE_LENGTH = 2048;
|
|
26668
|
+
var MAX_ENTRIES = 1e5;
|
|
26669
|
+
var MAX_TEMPLATES2 = 1e4;
|
|
26670
|
+
var NO_RUNS = { hash: 0, starts: [], ends: [] };
|
|
26671
|
+
var treeOf = (made) => "ast" in made ? made.ast : made;
|
|
26672
|
+
var ParseCache = class {
|
|
26673
|
+
byText = /* @__PURE__ */ new Map();
|
|
26674
|
+
templates = /* @__PURE__ */ new Map();
|
|
26675
|
+
parse(formula) {
|
|
26676
|
+
let ast = this.byText.get(formula);
|
|
26677
|
+
if (ast) return ast;
|
|
26678
|
+
ast = this.parseNew(formula);
|
|
26679
|
+
if (this.byText.size > MAX_ENTRIES) this.byText.clear();
|
|
26680
|
+
this.byText.set(formula, ast);
|
|
26681
|
+
return ast;
|
|
26363
26682
|
}
|
|
26364
|
-
|
|
26365
|
-
|
|
26366
|
-
|
|
26367
|
-
|
|
26368
|
-
|
|
26369
|
-
|
|
26370
|
-
|
|
26683
|
+
parseNew(formula) {
|
|
26684
|
+
if (formula.length > MAX_TEMPLATE_LENGTH) return treeOf(makeTemplate(formula, NO_RUNS));
|
|
26685
|
+
const shape2 = formulaShape(formula);
|
|
26686
|
+
const template = this.templates.get(shape2.hash);
|
|
26687
|
+
const reused = template && fromTemplate(template, formula, shape2);
|
|
26688
|
+
if (reused) return reused;
|
|
26689
|
+
const made = makeTemplate(formula, shape2);
|
|
26690
|
+
if (!template && "ast" in made) {
|
|
26691
|
+
if (this.templates.size > MAX_TEMPLATES2) this.templates.clear();
|
|
26692
|
+
this.templates.set(shape2.hash, made);
|
|
26371
26693
|
}
|
|
26694
|
+
return treeOf(made);
|
|
26372
26695
|
}
|
|
26373
26696
|
};
|
|
26374
26697
|
|
|
@@ -26508,7 +26831,7 @@ var EngineHost = class {
|
|
|
26508
26831
|
options;
|
|
26509
26832
|
nodes = /* @__PURE__ */ new Map();
|
|
26510
26833
|
footprints = /* @__PURE__ */ new Set();
|
|
26511
|
-
|
|
26834
|
+
parsed = new ParseCache();
|
|
26512
26835
|
boundsCache = /* @__PURE__ */ new Map();
|
|
26513
26836
|
inProgress = /* @__PURE__ */ new Set();
|
|
26514
26837
|
cycles = /* @__PURE__ */ new Set();
|
|
@@ -26532,6 +26855,8 @@ var EngineHost = class {
|
|
|
26532
26855
|
evaluations = 0;
|
|
26533
26856
|
built = false;
|
|
26534
26857
|
needsFull = false;
|
|
26858
|
+
/** No recalculation has run since the workbook was opened: stored values may stand. */
|
|
26859
|
+
fresh = true;
|
|
26535
26860
|
// ---- EvalHost ----
|
|
26536
26861
|
readCell(sheet, row2, col) {
|
|
26537
26862
|
const cell = this.workbook.sheets[sheet]?.rows.get(row2)?.get(col);
|
|
@@ -26620,19 +26945,7 @@ var EngineHost = class {
|
|
|
26620
26945
|
return this.workbook.sheets[sheet]?.rows.get(row2)?.get(col)?.formula;
|
|
26621
26946
|
}
|
|
26622
26947
|
parse(formula) {
|
|
26623
|
-
|
|
26624
|
-
if (!ast) {
|
|
26625
|
-
try {
|
|
26626
|
-
ast = parseFormula(formula);
|
|
26627
|
-
} catch (e) {
|
|
26628
|
-
if (e instanceof RangeError) ast = new FormulaError(e.message, -1, "#VALUE!");
|
|
26629
|
-
else if (!(e instanceof FormulaError)) throw e;
|
|
26630
|
-
else ast = e;
|
|
26631
|
-
}
|
|
26632
|
-
if (this.astCache.size > 1e5) this.astCache.clear();
|
|
26633
|
-
this.astCache.set(formula, ast);
|
|
26634
|
-
}
|
|
26635
|
-
return ast;
|
|
26948
|
+
return this.parsed.parse(formula);
|
|
26636
26949
|
}
|
|
26637
26950
|
now() {
|
|
26638
26951
|
return this.options.now ? this.options.now() : /* @__PURE__ */ new Date();
|
|
@@ -26641,20 +26954,6 @@ var EngineHost = class {
|
|
|
26641
26954
|
return this.options.random ? this.options.random() : Math.random();
|
|
26642
26955
|
}
|
|
26643
26956
|
// ---- graph ----
|
|
26644
|
-
build() {
|
|
26645
|
-
this.nodes.clear();
|
|
26646
|
-
this.footprints.clear();
|
|
26647
|
-
this.footprintIndex = void 0;
|
|
26648
|
-
this.workbook.sheets.forEach((sheet, s) => {
|
|
26649
|
-
for (const [row2, cells3] of sheet.rows) {
|
|
26650
|
-
for (const [col, cell] of cells3) {
|
|
26651
|
-
if (cell.formula) this.createNode(s, row2, col, cell, true);
|
|
26652
|
-
}
|
|
26653
|
-
}
|
|
26654
|
-
});
|
|
26655
|
-
this.built = true;
|
|
26656
|
-
this.graphChanged();
|
|
26657
|
-
}
|
|
26658
26957
|
createNode(sheet, row2, col, cell, initial) {
|
|
26659
26958
|
const formula = cell.formula ?? "";
|
|
26660
26959
|
const parsed = this.parse(formula);
|
|
@@ -26683,6 +26982,14 @@ var EngineHost = class {
|
|
|
26683
26982
|
map.set(cellKey(row2, col), node);
|
|
26684
26983
|
return node;
|
|
26685
26984
|
}
|
|
26985
|
+
/** Parses a node's text again after a structural edit rewrote it (see `FormulaNode.stale`). */
|
|
26986
|
+
refreshAst(node) {
|
|
26987
|
+
const parsed = this.parse(node.formula);
|
|
26988
|
+
delete node.stale;
|
|
26989
|
+
delete node.parseError;
|
|
26990
|
+
node.ast = parsed instanceof FormulaError ? void 0 : parsed;
|
|
26991
|
+
if (parsed instanceof FormulaError && parsed.code) node.parseError = err(parsed.code);
|
|
26992
|
+
}
|
|
26686
26993
|
removeNode(node, changed) {
|
|
26687
26994
|
const sheet = this.workbook.sheets[node.sheet];
|
|
26688
26995
|
if (node.spill && sheet) {
|
|
@@ -27113,6 +27420,7 @@ var EngineCore = class extends EngineHost {
|
|
|
27113
27420
|
return { host: this, sheet, row: row2, col, scope: void 0, depth: 0, root, legacy };
|
|
27114
27421
|
}
|
|
27115
27422
|
evaluateFormula(node) {
|
|
27423
|
+
if (node.stale) this.refreshAst(node);
|
|
27116
27424
|
if (!node.ast) return node.parseError ?? ERR.NAME;
|
|
27117
27425
|
const ast = node.ast;
|
|
27118
27426
|
const frame = this.frameFor(node.sheet, node.row, node.col, ast, node.legacy);
|
|
@@ -27130,20 +27438,363 @@ var EngineCore = class extends EngineHost {
|
|
|
27130
27438
|
}
|
|
27131
27439
|
};
|
|
27132
27440
|
|
|
27441
|
+
// xlsx/formula/shift-graph.ts
|
|
27442
|
+
var POSITIONAL = /* @__PURE__ */ new Set(["ROW", "COLUMN"]);
|
|
27443
|
+
var DESCRIPTIVE = /* @__PURE__ */ new Set(["FORMULATEXT", "CELL", "SHEET"]);
|
|
27444
|
+
var traitsCache = /* @__PURE__ */ new WeakMap();
|
|
27445
|
+
function astTraits(ast) {
|
|
27446
|
+
const cached3 = traitsCache.get(ast);
|
|
27447
|
+
if (cached3) return cached3;
|
|
27448
|
+
const sheets = /* @__PURE__ */ new Set();
|
|
27449
|
+
const traits = { complex: false, opaque: false, positional: false, descriptive: false, sheets };
|
|
27450
|
+
const stack2 = [ast];
|
|
27451
|
+
while (stack2.length) {
|
|
27452
|
+
const node = stack2.pop();
|
|
27453
|
+
switch (node.type) {
|
|
27454
|
+
case "ref":
|
|
27455
|
+
if (node.prefix) {
|
|
27456
|
+
sheets.add(node.prefix.sheet.toLowerCase());
|
|
27457
|
+
if (node.prefix.sheet2 !== void 0) {
|
|
27458
|
+
sheets.add(node.prefix.sheet2.toLowerCase());
|
|
27459
|
+
traits.complex = true;
|
|
27460
|
+
}
|
|
27461
|
+
}
|
|
27462
|
+
break;
|
|
27463
|
+
case "name":
|
|
27464
|
+
if (node.prefix) sheets.add(node.prefix.sheet.toLowerCase());
|
|
27465
|
+
traits.complex = true;
|
|
27466
|
+
break;
|
|
27467
|
+
case "structured":
|
|
27468
|
+
traits.complex = true;
|
|
27469
|
+
break;
|
|
27470
|
+
case "unary":
|
|
27471
|
+
case "percent":
|
|
27472
|
+
stack2.push(node.operand);
|
|
27473
|
+
break;
|
|
27474
|
+
case "binary":
|
|
27475
|
+
stack2.push(node.left, node.right);
|
|
27476
|
+
break;
|
|
27477
|
+
case "call":
|
|
27478
|
+
if (POSITIONAL.has(node.name)) traits.positional = true;
|
|
27479
|
+
if (DESCRIPTIVE.has(node.name)) traits.descriptive = true;
|
|
27480
|
+
if (!getFunction(node.name)) traits.complex = traits.opaque = true;
|
|
27481
|
+
stack2.push(...node.args);
|
|
27482
|
+
break;
|
|
27483
|
+
case "invoke":
|
|
27484
|
+
stack2.push(node.callee, ...node.args);
|
|
27485
|
+
break;
|
|
27486
|
+
}
|
|
27487
|
+
}
|
|
27488
|
+
traitsCache.set(ast, traits);
|
|
27489
|
+
return traits;
|
|
27490
|
+
}
|
|
27491
|
+
function intervalDelta(a2, b, shift2) {
|
|
27492
|
+
const { at: at2, count: count2 } = shift2;
|
|
27493
|
+
if (count2 > 0) {
|
|
27494
|
+
if (b < at2) return 0;
|
|
27495
|
+
if (a2 < at2) return void 0;
|
|
27496
|
+
return b + count2 > (shift2.axis === "row" ? MAX_ROW : MAX_COL) ? void 0 : count2;
|
|
27497
|
+
}
|
|
27498
|
+
const last = at2 - count2 - 1;
|
|
27499
|
+
if (b < at2) return 0;
|
|
27500
|
+
if (a2 > last) return count2;
|
|
27501
|
+
return void 0;
|
|
27502
|
+
}
|
|
27503
|
+
function areaDelta(area, sheet, shift2) {
|
|
27504
|
+
if (area.sheet !== sheet) return 0;
|
|
27505
|
+
const { start, end } = area.range;
|
|
27506
|
+
return shift2.axis === "row" ? intervalDelta(start.row, end.row, shift2) : intervalDelta(start.col, end.col, shift2);
|
|
27507
|
+
}
|
|
27508
|
+
function movedRange(range, axis, delta) {
|
|
27509
|
+
if (delta === 0) return range;
|
|
27510
|
+
return axis === "row" ? {
|
|
27511
|
+
start: { row: range.start.row + delta, col: range.start.col },
|
|
27512
|
+
end: { row: range.end.row + delta, col: range.end.col }
|
|
27513
|
+
} : {
|
|
27514
|
+
start: { row: range.start.row, col: range.start.col + delta },
|
|
27515
|
+
end: { row: range.end.row, col: range.end.col + delta }
|
|
27516
|
+
};
|
|
27517
|
+
}
|
|
27518
|
+
function reachesEdit(areas, sheet, shift2) {
|
|
27519
|
+
for (const area of areas) {
|
|
27520
|
+
if (area.sheet !== sheet) continue;
|
|
27521
|
+
if ((shift2.axis === "row" ? area.range.end.row : area.range.end.col) >= shift2.at) return true;
|
|
27522
|
+
}
|
|
27523
|
+
return false;
|
|
27524
|
+
}
|
|
27525
|
+
function intersectionMoves(area, delta, pos, nodeDelta, axis) {
|
|
27526
|
+
if (delta === nodeDelta) return false;
|
|
27527
|
+
const { start, end } = area.range;
|
|
27528
|
+
const a2 = axis === "row" ? start.row : start.col;
|
|
27529
|
+
const b = axis === "row" ? end.row : end.col;
|
|
27530
|
+
if (a2 === b) return false;
|
|
27531
|
+
return pos >= a2 && pos <= b || pos + nodeDelta >= a2 + delta && pos + nodeDelta <= b + delta;
|
|
27532
|
+
}
|
|
27533
|
+
|
|
27534
|
+
// xlsx/formula/engine-structure.ts
|
|
27535
|
+
var sameAreas = (a2, b) => a2.length === b.length && a2.every((x, i2) => {
|
|
27536
|
+
const y = b[i2];
|
|
27537
|
+
return x.sheet === y.sheet && sameRange(x.range, y.range);
|
|
27538
|
+
});
|
|
27539
|
+
var EngineStructure = class extends EngineCore {
|
|
27540
|
+
/** Formulas a structural edit left to recalculate (with their dependents) on the next pass. */
|
|
27541
|
+
structuralSeeds = /* @__PURE__ */ new Set();
|
|
27542
|
+
/** Whether the graph describes the workbook as it was before the edit just reported. */
|
|
27543
|
+
graphReady() {
|
|
27544
|
+
return this.built && !this.needsFull;
|
|
27545
|
+
}
|
|
27546
|
+
/** Parses a node's current text again and recomputes its precedents. */
|
|
27547
|
+
reanalyze(node) {
|
|
27548
|
+
const parsed = this.parse(node.formula);
|
|
27549
|
+
delete node.stale;
|
|
27550
|
+
delete node.parseError;
|
|
27551
|
+
if (parsed instanceof FormulaError) {
|
|
27552
|
+
node.ast = void 0;
|
|
27553
|
+
if (parsed.code) node.parseError = err(parsed.code);
|
|
27554
|
+
node.deps = [];
|
|
27555
|
+
node.dynamicDeps = [];
|
|
27556
|
+
return;
|
|
27557
|
+
}
|
|
27558
|
+
node.ast = parsed;
|
|
27559
|
+
const found = analyze(parsed, this, node.sheet, node.row, node.col);
|
|
27560
|
+
node.deps = found.deps;
|
|
27561
|
+
node.dynamicDeps = found.dynamicDeps;
|
|
27562
|
+
node.volatile = found.volatile;
|
|
27563
|
+
node.unsupported = found.unsupported;
|
|
27564
|
+
}
|
|
27565
|
+
/**
|
|
27566
|
+
* Moves the graph for rows or columns inserted or deleted on `sheet`, after the workbook was
|
|
27567
|
+
* changed (cells moved, formulas rewritten). Spills on the sheet, array formulas the edit cuts
|
|
27568
|
+
* and anything unexpected fall back to a rebuild on the next recalculation.
|
|
27569
|
+
*/
|
|
27570
|
+
shiftCells(sheet, shift2) {
|
|
27571
|
+
if (!this.graphReady() || !this.shiftable(sheet, shift2)) {
|
|
27572
|
+
this.invalidate();
|
|
27573
|
+
return;
|
|
27574
|
+
}
|
|
27575
|
+
const ws = this.workbook.sheets[sheet];
|
|
27576
|
+
const own = this.nodes.get(sheet);
|
|
27577
|
+
if (!ws) return;
|
|
27578
|
+
const moved = /* @__PURE__ */ new Map();
|
|
27579
|
+
if (own) {
|
|
27580
|
+
const next = /* @__PURE__ */ new Map();
|
|
27581
|
+
for (const node of own.values()) {
|
|
27582
|
+
const pos = shift2.axis === "row" ? node.row : node.col;
|
|
27583
|
+
const delta = intervalDelta(pos, pos, shift2);
|
|
27584
|
+
if (delta === void 0) {
|
|
27585
|
+
this.dropNode(node);
|
|
27586
|
+
continue;
|
|
27587
|
+
}
|
|
27588
|
+
if (delta !== 0) {
|
|
27589
|
+
moved.set(node, delta);
|
|
27590
|
+
if (shift2.axis === "row") node.row += delta;
|
|
27591
|
+
else node.col += delta;
|
|
27592
|
+
}
|
|
27593
|
+
next.set(cellKey(node.row, node.col), node);
|
|
27594
|
+
}
|
|
27595
|
+
this.nodes.set(sheet, next);
|
|
27596
|
+
}
|
|
27597
|
+
for (const map of this.nodes.values())
|
|
27598
|
+
for (const node of map.values()) {
|
|
27599
|
+
if (!this.shiftNode(node, sheet, shift2, moved.get(node) ?? 0)) {
|
|
27600
|
+
this.invalidate();
|
|
27601
|
+
return;
|
|
27602
|
+
}
|
|
27603
|
+
}
|
|
27604
|
+
this.boundsCache.clear();
|
|
27605
|
+
this.graphChanged();
|
|
27606
|
+
}
|
|
27607
|
+
/** No spill or stale spilled value on the sheet, and no array formula the edit cuts. */
|
|
27608
|
+
shiftable(sheet, shift2) {
|
|
27609
|
+
for (const node of this.footprints) {
|
|
27610
|
+
if (node.sheet !== sheet) continue;
|
|
27611
|
+
if (node.spill || node.blockedSpill) return false;
|
|
27612
|
+
if (node.arrayRange && areaDelta({ sheet, range: node.arrayRange }, sheet, shift2) === void 0)
|
|
27613
|
+
return false;
|
|
27614
|
+
}
|
|
27615
|
+
const ws = this.workbook.sheets[sheet];
|
|
27616
|
+
let spilled = false;
|
|
27617
|
+
ws?.rows.forEach((cells3) => {
|
|
27618
|
+
if (!spilled) cells3.forEach((cell) => spilled ||= isSpilledCell(cell));
|
|
27619
|
+
});
|
|
27620
|
+
return !spilled;
|
|
27621
|
+
}
|
|
27622
|
+
dropNode(node) {
|
|
27623
|
+
this.structuralSeeds.delete(node);
|
|
27624
|
+
this.cycles.delete(node);
|
|
27625
|
+
this.footprints.delete(node);
|
|
27626
|
+
}
|
|
27627
|
+
/** Updates one formula for the edit; false when the graph cannot follow it. */
|
|
27628
|
+
shiftNode(node, sheet, shift2, nodeDelta) {
|
|
27629
|
+
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
27630
|
+
if (cell?.formula === void 0) return false;
|
|
27631
|
+
if (node.arrayRange) {
|
|
27632
|
+
const delta = areaDelta({ sheet: node.sheet, range: node.arrayRange }, sheet, shift2);
|
|
27633
|
+
if (delta === void 0) return false;
|
|
27634
|
+
node.arrayRange = movedRange(node.arrayRange, shift2.axis, delta);
|
|
27635
|
+
if (!cell.arrayRange || !sameRange(node.arrayRange, normalizeRange(cell.arrayRange)))
|
|
27636
|
+
return false;
|
|
27637
|
+
}
|
|
27638
|
+
const changed = cell.formula !== node.formula;
|
|
27639
|
+
const traits = node.ast && astTraits(node.ast);
|
|
27640
|
+
const reached = reachesEdit(node.deps, sheet, shift2) || reachesEdit(node.dynamicDeps, sheet, shift2);
|
|
27641
|
+
if (!changed && !reached && nodeDelta === 0 && !traits?.descriptive && !traits?.opaque)
|
|
27642
|
+
return true;
|
|
27643
|
+
if (traits?.complex) {
|
|
27644
|
+
node.formula = cell.formula;
|
|
27645
|
+
this.reanalyze(node);
|
|
27646
|
+
this.structuralSeeds.add(node);
|
|
27647
|
+
return true;
|
|
27648
|
+
}
|
|
27649
|
+
const pos = shift2.axis === "row" ? node.row - nodeDelta : node.col - nodeDelta;
|
|
27650
|
+
const moves = { seed: !!traits?.descriptive, moved: false, cut: false };
|
|
27651
|
+
const deps = this.moveAreas(node.deps, sheet, shift2, pos, nodeDelta, moves);
|
|
27652
|
+
const dynamicDeps = this.moveAreas(node.dynamicDeps, sheet, shift2, pos, nodeDelta, moves);
|
|
27653
|
+
const { cut, moved: anyMoved } = moves;
|
|
27654
|
+
let seed = moves.seed;
|
|
27655
|
+
if (cut || changed !== anyMoved) {
|
|
27656
|
+
node.formula = cell.formula;
|
|
27657
|
+
this.reanalyze(node);
|
|
27658
|
+
this.structuralSeeds.add(node);
|
|
27659
|
+
return true;
|
|
27660
|
+
}
|
|
27661
|
+
if (traits?.positional && (anyMoved || nodeDelta !== 0)) seed = true;
|
|
27662
|
+
node.deps = deps;
|
|
27663
|
+
node.dynamicDeps = dynamicDeps;
|
|
27664
|
+
if (changed) {
|
|
27665
|
+
node.formula = cell.formula;
|
|
27666
|
+
node.stale = true;
|
|
27667
|
+
}
|
|
27668
|
+
if (seed) this.structuralSeeds.add(node);
|
|
27669
|
+
return true;
|
|
27670
|
+
}
|
|
27671
|
+
/**
|
|
27672
|
+
* Areas moved for the edit (the same list when none moves). Records in `moves` whether one
|
|
27673
|
+
* moved, one was cut (deleted, widened, pushed off the grid) and whether implicit intersection
|
|
27674
|
+
* with one can now pick another cell.
|
|
27675
|
+
*/
|
|
27676
|
+
moveAreas(list, sheet, shift2, pos, nodeDelta, moves) {
|
|
27677
|
+
let out;
|
|
27678
|
+
for (let i2 = 0; i2 < list.length; i2++) {
|
|
27679
|
+
const area = list[i2];
|
|
27680
|
+
const delta = areaDelta(area, sheet, shift2);
|
|
27681
|
+
if (delta === void 0) {
|
|
27682
|
+
moves.cut = true;
|
|
27683
|
+
continue;
|
|
27684
|
+
}
|
|
27685
|
+
if (intersectionMoves(area, delta, pos, nodeDelta, shift2.axis)) moves.seed = true;
|
|
27686
|
+
if (delta === 0) continue;
|
|
27687
|
+
moves.moved = true;
|
|
27688
|
+
out ??= list.slice();
|
|
27689
|
+
out[i2] = { sheet: area.sheet, range: movedRange(area.range, shift2.axis, delta) };
|
|
27690
|
+
}
|
|
27691
|
+
return out ?? list;
|
|
27692
|
+
}
|
|
27693
|
+
/**
|
|
27694
|
+
* Follows a sheet rename (`from` to `to`, formulas already rewritten): precedents are kept by
|
|
27695
|
+
* sheet index, so only rewritten formulas need their text parsed again, and only formulas that
|
|
27696
|
+
* name the new sheet without having been rewritten (previously unresolved), describe sheets
|
|
27697
|
+
* (CELL, SHEET, FORMULATEXT) or read defined names whose areas changed are recalculated.
|
|
27698
|
+
*/
|
|
27699
|
+
renameSheet(from, to) {
|
|
27700
|
+
if (!this.graphReady()) {
|
|
27701
|
+
this.invalidate();
|
|
27702
|
+
return;
|
|
27703
|
+
}
|
|
27704
|
+
const target = to.toLowerCase();
|
|
27705
|
+
let depsChanged = false;
|
|
27706
|
+
for (const map of this.nodes.values())
|
|
27707
|
+
for (const node of map.values()) {
|
|
27708
|
+
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
27709
|
+
if (cell?.formula === void 0) {
|
|
27710
|
+
this.invalidate();
|
|
27711
|
+
return;
|
|
27712
|
+
}
|
|
27713
|
+
const changed = cell.formula !== node.formula;
|
|
27714
|
+
const traits = node.ast && astTraits(node.ast);
|
|
27715
|
+
node.formula = cell.formula;
|
|
27716
|
+
if (traits?.complex || !changed && traits?.sheets.has(target)) {
|
|
27717
|
+
const deps = node.deps;
|
|
27718
|
+
const dynamicDeps = node.dynamicDeps;
|
|
27719
|
+
this.reanalyze(node);
|
|
27720
|
+
const same5 = sameAreas(deps, node.deps) && sameAreas(dynamicDeps, node.dynamicDeps);
|
|
27721
|
+
if (!same5) depsChanged = true;
|
|
27722
|
+
if (!same5 || !traits?.complex) this.structuralSeeds.add(node);
|
|
27723
|
+
} else if (changed) node.stale = true;
|
|
27724
|
+
if (traits?.descriptive || traits?.opaque) this.structuralSeeds.add(node);
|
|
27725
|
+
}
|
|
27726
|
+
if (depsChanged) this.graphChanged();
|
|
27727
|
+
}
|
|
27728
|
+
/** Takes the formulas queued by structural edits. */
|
|
27729
|
+
takeStructuralSeeds(into) {
|
|
27730
|
+
for (const node of this.structuralSeeds)
|
|
27731
|
+
if (this.nodes.get(node.sheet)?.get(cellKey(node.row, node.col)) === node) into.add(node);
|
|
27732
|
+
this.structuralSeeds.clear();
|
|
27733
|
+
}
|
|
27734
|
+
};
|
|
27735
|
+
|
|
27133
27736
|
// xlsx/formula/engine.ts
|
|
27134
|
-
var Engine = class extends
|
|
27737
|
+
var Engine = class extends EngineStructure {
|
|
27738
|
+
preparation;
|
|
27739
|
+
/** The prepared formulas the first recalculation checks (see `trustsStoredValues`). */
|
|
27740
|
+
prepared;
|
|
27741
|
+
// ---- the graph ----
|
|
27742
|
+
prepare(timeRemaining) {
|
|
27743
|
+
if (this.built || this.needsFull) return true;
|
|
27744
|
+
this.preparation ??= this.startPreparation();
|
|
27745
|
+
if (!this.preparation.run(timeRemaining)) return false;
|
|
27746
|
+
this.finishPreparation(this.preparation);
|
|
27747
|
+
return true;
|
|
27748
|
+
}
|
|
27749
|
+
discardPreparation() {
|
|
27750
|
+
if (!this.fresh || this.needsFull) return;
|
|
27751
|
+
this.preparation = void 0;
|
|
27752
|
+
this.prepared = void 0;
|
|
27753
|
+
this.structuralSeeds.clear();
|
|
27754
|
+
this.nodes.clear();
|
|
27755
|
+
this.footprints.clear();
|
|
27756
|
+
this.graphChanged();
|
|
27757
|
+
this.built = false;
|
|
27758
|
+
}
|
|
27759
|
+
/** Completes the graph, continuing a preparation that is under way. */
|
|
27760
|
+
build() {
|
|
27761
|
+
const preparation = this.preparation ?? this.startPreparation();
|
|
27762
|
+
preparation.run();
|
|
27763
|
+
this.finishPreparation(preparation);
|
|
27764
|
+
}
|
|
27765
|
+
startPreparation() {
|
|
27766
|
+
this.nodes.clear();
|
|
27767
|
+
this.footprints.clear();
|
|
27768
|
+
this.footprintIndex = void 0;
|
|
27769
|
+
this.prepared = void 0;
|
|
27770
|
+
return new GraphPreparation(
|
|
27771
|
+
this.workbook,
|
|
27772
|
+
(s, row2, col, cell) => this.createNode(s, row2, col, cell, true)
|
|
27773
|
+
);
|
|
27774
|
+
}
|
|
27775
|
+
finishPreparation(preparation) {
|
|
27776
|
+
this.preparation = void 0;
|
|
27777
|
+
this.built = true;
|
|
27778
|
+
this.graphChanged();
|
|
27779
|
+
this.reverseIndex = preparation.reverse;
|
|
27780
|
+
this.prepared = preparation.formulas;
|
|
27781
|
+
}
|
|
27135
27782
|
// ---- recalculation ----
|
|
27136
27783
|
recalculateAll() {
|
|
27784
|
+
this.fresh = false;
|
|
27785
|
+
this.prepared = void 0;
|
|
27137
27786
|
if (this.needsFull) this.releaseAllSpills();
|
|
27138
27787
|
if (!this.built || this.needsFull) this.build();
|
|
27139
27788
|
this.needsFull = false;
|
|
27789
|
+
this.structuralSeeds.clear();
|
|
27140
27790
|
this.cycles = /* @__PURE__ */ new Set();
|
|
27141
27791
|
this.run(new Set(this.allNodes()), true);
|
|
27142
27792
|
}
|
|
27143
27793
|
recalculateFrom(changes) {
|
|
27144
27794
|
const seeds = /* @__PURE__ */ new Set();
|
|
27145
|
-
if (
|
|
27146
|
-
this.
|
|
27795
|
+
if (this.fresh && !this.needsFull) {
|
|
27796
|
+
this.fresh = false;
|
|
27797
|
+
if (!this.built) this.build();
|
|
27147
27798
|
if (!this.trustsStoredValues(changes, seeds)) {
|
|
27148
27799
|
this.recalculateAll();
|
|
27149
27800
|
return;
|
|
@@ -27187,6 +27838,7 @@ var Engine = class extends EngineCore {
|
|
|
27187
27838
|
}
|
|
27188
27839
|
}
|
|
27189
27840
|
if (structural) this.graphChanged();
|
|
27841
|
+
this.takeStructuralSeeds(seeds);
|
|
27190
27842
|
const reverse2 = this.reverse();
|
|
27191
27843
|
for (const area of changed) reverse2.dependents(area.sheet, area.range, seeds);
|
|
27192
27844
|
for (const node of this.allNodes()) if (node.volatile) seeds.add(node);
|
|
@@ -27198,13 +27850,18 @@ var Engine = class extends EngineCore {
|
|
|
27198
27850
|
* without a value into `missing`.
|
|
27199
27851
|
*/
|
|
27200
27852
|
trustsStoredValues(changes, missing) {
|
|
27853
|
+
const prepared = this.prepared;
|
|
27854
|
+
this.prepared = void 0;
|
|
27855
|
+
if (!prepared) return false;
|
|
27201
27856
|
const changed = new Set(changes.map((c2) => `${c2.sheet}:${cellKey(c2.row, c2.col)}`));
|
|
27202
|
-
|
|
27203
|
-
|
|
27204
|
-
if (
|
|
27857
|
+
const current = (node) => this.nodes.get(node.sheet)?.get(cellKey(node.row, node.col)) === node;
|
|
27858
|
+
for (const node of prepared.dynamic) {
|
|
27859
|
+
if (current(node) && !changed.has(`${node.sheet}:${cellKey(node.row, node.col)}`))
|
|
27205
27860
|
return false;
|
|
27861
|
+
}
|
|
27862
|
+
for (const node of prepared.unvalued) {
|
|
27206
27863
|
const cell = this.workbook.sheets[node.sheet]?.rows.get(node.row)?.get(node.col);
|
|
27207
|
-
if (cell && cell.value === null
|
|
27864
|
+
if (current(node) && cell && cell.value === null) missing.add(node);
|
|
27208
27865
|
}
|
|
27209
27866
|
return true;
|
|
27210
27867
|
}
|
|
@@ -27218,7 +27875,10 @@ var Engine = class extends EngineCore {
|
|
|
27218
27875
|
return !!anchor?.spill && rangeHas(anchor.spill, row2, col);
|
|
27219
27876
|
}
|
|
27220
27877
|
invalidate() {
|
|
27878
|
+
this.structuralSeeds.clear();
|
|
27221
27879
|
this.releaseAllSpills();
|
|
27880
|
+
this.preparation = void 0;
|
|
27881
|
+
this.prepared = void 0;
|
|
27222
27882
|
this.nodes.clear();
|
|
27223
27883
|
this.footprints.clear();
|
|
27224
27884
|
this.graphChanged();
|
|
@@ -27242,8 +27902,8 @@ var Engine = class extends EngineCore {
|
|
|
27242
27902
|
evaluate(formula, at2) {
|
|
27243
27903
|
const value = this.evaluateAdHoc(formula, at2);
|
|
27244
27904
|
const frame = this.frameFor(at2.sheet, at2.row, at2.col, void 0);
|
|
27245
|
-
const
|
|
27246
|
-
return typeof
|
|
27905
|
+
const scalar4 = implicitIntersection(value, frame);
|
|
27906
|
+
return typeof scalar4 === "number" && !Number.isFinite(scalar4) ? ERR.NUM : scalar4;
|
|
27247
27907
|
}
|
|
27248
27908
|
evaluateArray(formula, at2) {
|
|
27249
27909
|
const value = this.evaluateAdHoc(formula, at2);
|
|
@@ -27707,7 +28367,7 @@ var attrPattern = (name) => new RegExp(`(\\s${name}\\s*=\\s*)(["'])(.*?)\\2`);
|
|
|
27707
28367
|
function patchWorksheetSource(xml, edits) {
|
|
27708
28368
|
const match2 = WORKSHEET_SOURCE.exec(xml);
|
|
27709
28369
|
if (!match2) return xml;
|
|
27710
|
-
const [whole, tag, attrs2 = "",
|
|
28370
|
+
const [whole, tag, attrs2 = "", close2] = match2;
|
|
27711
28371
|
if (/\sr:id\s*=/.test(attrs2)) return xml;
|
|
27712
28372
|
const sheetMatch = attrPattern("sheet").exec(attrs2);
|
|
27713
28373
|
const refMatch = attrPattern("ref").exec(attrs2);
|
|
@@ -27731,7 +28391,7 @@ function patchWorksheetSource(xml, edits) {
|
|
|
27731
28391
|
nextAttrs = nextAttrs.replace(attrPattern("sheet"), (_m, lead, q) => {
|
|
27732
28392
|
return `${lead}${q}${escapeXmlAttr(nextSheet)}${q}`;
|
|
27733
28393
|
});
|
|
27734
|
-
return xml.replace(whole, `<${tag}${nextAttrs}${
|
|
28394
|
+
return xml.replace(whole, `<${tag}${nextAttrs}${close2}>`);
|
|
27735
28395
|
}
|
|
27736
28396
|
function rootName(xml) {
|
|
27737
28397
|
const match2 = /<(?![?!])(?:[A-Za-z][\w.-]*:)?([A-Za-z][\w.-]*)/.exec(xml);
|
|
@@ -27925,7 +28585,7 @@ function writeMetadataPart(writer, rels, bookPart, plan, dynamicArraysUsed, sour
|
|
|
27925
28585
|
}
|
|
27926
28586
|
|
|
27927
28587
|
// xlsx/write/style-xml.ts
|
|
27928
|
-
var argb = (
|
|
28588
|
+
var argb = (rgb3) => (rgb3.length === 6 ? `FF${rgb3}` : rgb3).toUpperCase();
|
|
27929
28589
|
function colorXml(color2, name = "color") {
|
|
27930
28590
|
if (!color2) return "";
|
|
27931
28591
|
if (color2.rgb) return el3(name, { rgb: argb(color2.rgb), tint: color2.tint });
|
|
@@ -30149,13 +30809,13 @@ function linearTrend(values2) {
|
|
|
30149
30809
|
const slope = den ? num3 / den : 0;
|
|
30150
30810
|
return (k) => Number((meanY + slope * (k - meanX)).toPrecision(15));
|
|
30151
30811
|
}
|
|
30152
|
-
var
|
|
30812
|
+
var isDigit5 = (ch) => ch !== void 0 && ch >= "0" && ch <= "9";
|
|
30153
30813
|
function matchTextNumber(text2) {
|
|
30154
30814
|
let end = text2.length;
|
|
30155
|
-
while (end > 0 && !
|
|
30815
|
+
while (end > 0 && !isDigit5(text2[end - 1])) end--;
|
|
30156
30816
|
if (end === 0) return null;
|
|
30157
30817
|
let start = end;
|
|
30158
|
-
while (start > 0 &&
|
|
30818
|
+
while (start > 0 && isDigit5(text2[start - 1])) start--;
|
|
30159
30819
|
return [text2, text2.slice(0, start), text2.slice(start, end), text2.slice(end)];
|
|
30160
30820
|
}
|
|
30161
30821
|
var QUARTER = /^(q|qtr|quarter)(\s?)([1-4])$/i;
|
|
@@ -30338,10 +30998,10 @@ function removeValidationArea(rules, area) {
|
|
|
30338
30998
|
}
|
|
30339
30999
|
|
|
30340
31000
|
// xlsx/edit/conditional-formulas.ts
|
|
30341
|
-
function rewriteConditionalRule(rule2,
|
|
31001
|
+
function rewriteConditionalRule(rule2, rewrite2) {
|
|
30342
31002
|
const safe2 = (formula) => {
|
|
30343
31003
|
try {
|
|
30344
|
-
return
|
|
31004
|
+
return rewrite2(formula);
|
|
30345
31005
|
} catch {
|
|
30346
31006
|
return formula;
|
|
30347
31007
|
}
|
|
@@ -30860,7 +31520,7 @@ function shiftPreservedXml(sheet, shift2, moveRange, banded) {
|
|
|
30860
31520
|
(xml) => xml.includes("sqref")
|
|
30861
31521
|
);
|
|
30862
31522
|
}
|
|
30863
|
-
function rewritePreservedFormulas(sheet,
|
|
31523
|
+
function rewritePreservedFormulas(sheet, rewrite2) {
|
|
30864
31524
|
editEntries(
|
|
30865
31525
|
sheet,
|
|
30866
31526
|
"extLst",
|
|
@@ -30870,7 +31530,7 @@ function rewritePreservedFormulas(sheet, rewrite3) {
|
|
|
30870
31530
|
const text2 = f6.textContent ?? "";
|
|
30871
31531
|
let next = text2;
|
|
30872
31532
|
try {
|
|
30873
|
-
next =
|
|
31533
|
+
next = rewrite2(text2, sheet.name);
|
|
30874
31534
|
} catch {
|
|
30875
31535
|
next = text2;
|
|
30876
31536
|
}
|
|
@@ -30885,46 +31545,46 @@ function rewritePreservedFormulas(sheet, rewrite3) {
|
|
|
30885
31545
|
}
|
|
30886
31546
|
|
|
30887
31547
|
// xlsx/edit/shift-formulas.ts
|
|
30888
|
-
function safe(
|
|
31548
|
+
function safe(rewrite2, formula, formulaSheet) {
|
|
30889
31549
|
try {
|
|
30890
|
-
return
|
|
31550
|
+
return rewrite2(formula, formulaSheet);
|
|
30891
31551
|
} catch {
|
|
30892
31552
|
return formula;
|
|
30893
31553
|
}
|
|
30894
31554
|
}
|
|
30895
|
-
function rewriteFormulas(workbook,
|
|
30896
|
-
for (const sheet of workbook.sheets) rewriteSheetFormulas(sheet,
|
|
31555
|
+
function rewriteFormulas(workbook, rewrite2) {
|
|
31556
|
+
for (const sheet of workbook.sheets) rewriteSheetFormulas(sheet, rewrite2);
|
|
30897
31557
|
for (const definedName of workbook.definedNames) {
|
|
30898
31558
|
const local = definedName.localSheet === void 0 ? void 0 : workbook.sheets[definedName.localSheet];
|
|
30899
|
-
definedName.formula = safe(
|
|
31559
|
+
definedName.formula = safe(rewrite2, definedName.formula, local?.name ?? "");
|
|
30900
31560
|
}
|
|
30901
31561
|
}
|
|
30902
|
-
function rewriteSheetFormulas(sheet,
|
|
30903
|
-
rewritePreservedFormulas(sheet,
|
|
31562
|
+
function rewriteSheetFormulas(sheet, rewrite2) {
|
|
31563
|
+
rewritePreservedFormulas(sheet, rewrite2);
|
|
30904
31564
|
{
|
|
30905
31565
|
const name = sheet.name;
|
|
30906
31566
|
for (const table2 of sheet.tables)
|
|
30907
31567
|
for (const column of table2.columns)
|
|
30908
31568
|
if (column.calculatedColumnFormula !== void 0)
|
|
30909
|
-
column.calculatedColumnFormula = safe(
|
|
31569
|
+
column.calculatedColumnFormula = safe(rewrite2, column.calculatedColumnFormula, name);
|
|
30910
31570
|
for (const cells3 of sheet.rows.values())
|
|
30911
31571
|
for (const cell of cells3.values())
|
|
30912
|
-
if (cell.formula !== void 0) cell.formula = safe(
|
|
31572
|
+
if (cell.formula !== void 0) cell.formula = safe(rewrite2, cell.formula, name);
|
|
30913
31573
|
for (const cf of sheet.conditionalFormats)
|
|
30914
|
-
for (const rule2 of cf.rules) rewriteConditionalRule(rule2, (f6) =>
|
|
31574
|
+
for (const rule2 of cf.rules) rewriteConditionalRule(rule2, (f6) => rewrite2(f6, name));
|
|
30915
31575
|
for (const dv of sheet.dataValidations) {
|
|
30916
|
-
if (dv.formula1 !== void 0) dv.formula1 = safe(
|
|
30917
|
-
if (dv.formula2 !== void 0) dv.formula2 = safe(
|
|
31576
|
+
if (dv.formula1 !== void 0) dv.formula1 = safe(rewrite2, dv.formula1, name);
|
|
31577
|
+
if (dv.formula2 !== void 0) dv.formula2 = safe(rewrite2, dv.formula2, name);
|
|
30918
31578
|
}
|
|
30919
31579
|
for (const link of sheet.hyperlinks)
|
|
30920
31580
|
if (link.location && /![A-Za-z$]/.test(link.location))
|
|
30921
|
-
link.location = safe(
|
|
31581
|
+
link.location = safe(rewrite2, link.location, name);
|
|
30922
31582
|
for (const drawing of sheet.drawings) {
|
|
30923
31583
|
if (drawing.kind !== "chart") continue;
|
|
30924
31584
|
for (const series of drawing.series) {
|
|
30925
|
-
if (series.nameRef) series.nameRef = safe(
|
|
30926
|
-
if (series.categoriesRef) series.categoriesRef = safe(
|
|
30927
|
-
if (series.valuesRef) series.valuesRef = safe(
|
|
31585
|
+
if (series.nameRef) series.nameRef = safe(rewrite2, series.nameRef, name);
|
|
31586
|
+
if (series.categoriesRef) series.categoriesRef = safe(rewrite2, series.categoriesRef, name);
|
|
31587
|
+
if (series.valuesRef) series.valuesRef = safe(rewrite2, series.valuesRef, name);
|
|
30928
31588
|
}
|
|
30929
31589
|
}
|
|
30930
31590
|
}
|
|
@@ -31111,7 +31771,7 @@ function shiftAxis(ctx, s, axis, at2, count2, insert) {
|
|
|
31111
31771
|
applyAxisShift(ctx, sheet, shift2);
|
|
31112
31772
|
if (insert) inheritFormats(sheet, axis, at2, count2);
|
|
31113
31773
|
},
|
|
31114
|
-
{ sheet: s, structural: true }
|
|
31774
|
+
{ sheet: s, structural: true, calc: { kind: "shift", sheet: s, shift: shift2 } }
|
|
31115
31775
|
);
|
|
31116
31776
|
}
|
|
31117
31777
|
var insertRows = (ctx, s, at2, count2) => shiftAxis(ctx, s, "row", at2, count2, true);
|
|
@@ -31330,10 +31990,10 @@ function parseCssColor(text2) {
|
|
|
31330
31990
|
return {
|
|
31331
31991
|
rgb: (hex.length === 3 ? [...hex].map((ch) => ch + ch).join("") : hex).toUpperCase()
|
|
31332
31992
|
};
|
|
31333
|
-
const
|
|
31334
|
-
if (
|
|
31993
|
+
const rgb3 = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(value);
|
|
31994
|
+
if (rgb3)
|
|
31335
31995
|
return {
|
|
31336
|
-
rgb:
|
|
31996
|
+
rgb: rgb3.slice(1, 4).map((n) => Math.min(255, Number(n)).toString(16).padStart(2, "0")).join("").toUpperCase()
|
|
31337
31997
|
};
|
|
31338
31998
|
const named3 = NAMED_COLORS2[value];
|
|
31339
31999
|
return named3 ? { rgb: named3 } : void 0;
|
|
@@ -31418,10 +32078,10 @@ function removeComments(text2) {
|
|
|
31418
32078
|
let from = 0;
|
|
31419
32079
|
for (; ; ) {
|
|
31420
32080
|
const open = text2.indexOf("<!--", from);
|
|
31421
|
-
const
|
|
31422
|
-
if (
|
|
32081
|
+
const close2 = open < 0 ? -1 : text2.indexOf("-->", open + 4);
|
|
32082
|
+
if (close2 < 0) return out + text2.slice(from);
|
|
31423
32083
|
out += text2.slice(from, open);
|
|
31424
|
-
from =
|
|
32084
|
+
from = close2 + 3;
|
|
31425
32085
|
}
|
|
31426
32086
|
}
|
|
31427
32087
|
function removeTags(text2) {
|
|
@@ -31559,12 +32219,12 @@ function parseTsv(text2) {
|
|
|
31559
32219
|
while (i2 < body.length) {
|
|
31560
32220
|
const ch = body[i2] ?? "";
|
|
31561
32221
|
if (atFieldStart && ch === '"') {
|
|
31562
|
-
const
|
|
31563
|
-
if (
|
|
31564
|
-
const next = body[
|
|
32222
|
+
const close2 = findClosingQuote(body, i2 + 1);
|
|
32223
|
+
if (close2 >= 0) {
|
|
32224
|
+
const next = body[close2 + 1];
|
|
31565
32225
|
if (next === void 0 || next === " " || next === "\n") {
|
|
31566
|
-
field = body.slice(i2 + 1,
|
|
31567
|
-
i2 =
|
|
32226
|
+
field = body.slice(i2 + 1, close2).replace(/""/g, '"');
|
|
32227
|
+
i2 = close2 + 1;
|
|
31568
32228
|
atFieldStart = false;
|
|
31569
32229
|
continue;
|
|
31570
32230
|
}
|
|
@@ -32925,6 +33585,14 @@ function setCalcMode(ctx, mode) {
|
|
|
32925
33585
|
|
|
32926
33586
|
// xlsx/edit/session-calc.ts
|
|
32927
33587
|
var isStructural = (step) => step.structural || step.entries.some((entry3) => entry3.before.kind !== "cells");
|
|
33588
|
+
function hintFor(step, mode) {
|
|
33589
|
+
const hint = step.calc;
|
|
33590
|
+
if (!hint) return void 0;
|
|
33591
|
+
if (hint.kind === "rename")
|
|
33592
|
+
return mode === "undo" ? { kind: "rename", from: hint.to, to: hint.from } : hint;
|
|
33593
|
+
return mode === "undo" ? void 0 : hint;
|
|
33594
|
+
}
|
|
33595
|
+
var settingsOf = (workbook) => `${workbook.iterate ? `${workbook.iterate.count}:${workbook.iterate.delta}` : ""}|${workbook.date1904}`;
|
|
32928
33596
|
var SessionCalculator = class {
|
|
32929
33597
|
constructor(workbook, calc, enabled2) {
|
|
32930
33598
|
this.workbook = workbook;
|
|
@@ -32934,43 +33602,113 @@ var SessionCalculator = class {
|
|
|
32934
33602
|
workbook;
|
|
32935
33603
|
calc;
|
|
32936
33604
|
enabled;
|
|
32937
|
-
/** Structural edits
|
|
33605
|
+
/** Structural edits the engine could not follow leave the dependency graph stale (manual mode). */
|
|
32938
33606
|
staleGraph = false;
|
|
33607
|
+
/** Cells changed in manual mode since the last calculation. */
|
|
33608
|
+
dirty = [];
|
|
33609
|
+
/** The settings at the last calculation; undefined before the first. */
|
|
33610
|
+
calculated;
|
|
32939
33611
|
/** Recalculates after an applied, undone or redone step (failures become warnings). */
|
|
32940
|
-
afterStep(step) {
|
|
32941
|
-
if (!this.enabled)
|
|
33612
|
+
afterStep(step, mode = "apply") {
|
|
33613
|
+
if (!this.enabled) {
|
|
33614
|
+
this.calc.discardPreparation();
|
|
33615
|
+
return;
|
|
33616
|
+
}
|
|
33617
|
+
const structural = isStructural(step);
|
|
33618
|
+
const hint = structural ? hintFor(step, mode) : void 0;
|
|
32942
33619
|
if (calcModeOf(this.workbook) === "manual") {
|
|
32943
|
-
if (
|
|
33620
|
+
if (hint && !this.staleGraph && !this.dirty.length) {
|
|
33621
|
+
this.guard(() => this.follow(hint));
|
|
33622
|
+
return;
|
|
33623
|
+
}
|
|
33624
|
+
this.calc.discardPreparation();
|
|
33625
|
+
if (structural) this.staleGraph = true;
|
|
33626
|
+
else this.dirty.push(...touchedCells(step));
|
|
32944
33627
|
return;
|
|
32945
33628
|
}
|
|
32946
|
-
|
|
33629
|
+
if (hint && !this.staleGraph) {
|
|
33630
|
+
this.guard(() => {
|
|
33631
|
+
this.follow(hint);
|
|
33632
|
+
this.calc.recalculateFrom(touchedCells(step));
|
|
33633
|
+
this.calculated = settingsOf(this.workbook);
|
|
33634
|
+
});
|
|
33635
|
+
return;
|
|
33636
|
+
}
|
|
33637
|
+
this.recalc(structural, () => touchedCells(step));
|
|
32947
33638
|
}
|
|
32948
33639
|
/** Recalculates after a change applied outside the history (a collaborator's edit). */
|
|
32949
33640
|
afterExternal(structural, cells3) {
|
|
32950
|
-
if (!this.enabled)
|
|
32951
|
-
|
|
33641
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual") {
|
|
33642
|
+
this.calc.discardPreparation();
|
|
33643
|
+
if (!this.enabled) return;
|
|
32952
33644
|
if (structural) this.staleGraph = true;
|
|
33645
|
+
else this.dirty.push(...cells3);
|
|
32953
33646
|
return;
|
|
32954
33647
|
}
|
|
32955
33648
|
this.recalc(structural, () => cells3);
|
|
32956
33649
|
}
|
|
32957
|
-
|
|
33650
|
+
follow(hint) {
|
|
33651
|
+
if (hint.kind === "shift") this.calc.shiftCells(hint.sheet, hint.shift);
|
|
33652
|
+
else this.calc.renameSheet(hint.from, hint.to);
|
|
33653
|
+
}
|
|
33654
|
+
guard(run2) {
|
|
32958
33655
|
try {
|
|
33656
|
+
run2();
|
|
33657
|
+
} catch (error) {
|
|
33658
|
+
const message = `Recalculation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
33659
|
+
if (!this.workbook.warnings.includes(message)) this.workbook.warnings.push(message);
|
|
33660
|
+
}
|
|
33661
|
+
}
|
|
33662
|
+
/** Builds the dependency graph ahead of the first edit (see `EditSession.prepareCalculation`). */
|
|
33663
|
+
prepare(timeRemaining) {
|
|
33664
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual" || this.staleGraph) return true;
|
|
33665
|
+
try {
|
|
33666
|
+
return this.calc.prepare(timeRemaining);
|
|
33667
|
+
} catch {
|
|
33668
|
+
this.calc.discardPreparation();
|
|
33669
|
+
return true;
|
|
33670
|
+
}
|
|
33671
|
+
}
|
|
33672
|
+
/**
|
|
33673
|
+
* Before a structural edit the graph can follow in place: finishes a graph being prepared (or
|
|
33674
|
+
* builds it) while it still matches the workbook, so the edit moves it instead of rebuilding.
|
|
33675
|
+
*/
|
|
33676
|
+
beforeStructural() {
|
|
33677
|
+
if (!this.enabled || calcModeOf(this.workbook) === "manual" || this.staleGraph) return;
|
|
33678
|
+
this.prepare();
|
|
33679
|
+
}
|
|
33680
|
+
recalc(structural, cells3) {
|
|
33681
|
+
this.guard(() => {
|
|
32959
33682
|
if (this.staleGraph || structural) this.full();
|
|
32960
33683
|
else {
|
|
32961
33684
|
const changed = cells3();
|
|
32962
33685
|
if (changed.length) this.calc.recalculateFrom(changed);
|
|
33686
|
+
this.calculated = settingsOf(this.workbook);
|
|
32963
33687
|
}
|
|
32964
|
-
}
|
|
32965
|
-
const message = `Recalculation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
32966
|
-
if (!this.workbook.warnings.includes(message)) this.workbook.warnings.push(message);
|
|
32967
|
-
}
|
|
33688
|
+
});
|
|
32968
33689
|
}
|
|
32969
|
-
/** Rebuilds the dependency graph and recalculates every formula (F9). */
|
|
33690
|
+
/** Rebuilds the dependency graph and recalculates every formula (Ctrl+Alt+F9). */
|
|
32970
33691
|
full() {
|
|
32971
33692
|
this.staleGraph = false;
|
|
33693
|
+
this.dirty = [];
|
|
32972
33694
|
this.calc.invalidate();
|
|
32973
33695
|
this.calc.recalculateAll();
|
|
33696
|
+
this.calculated = settingsOf(this.workbook);
|
|
33697
|
+
}
|
|
33698
|
+
/**
|
|
33699
|
+
* Calculate Now (F9): the cells changed since the last calculation, the formulas structural
|
|
33700
|
+
* edits queued, their dependents and the volatile functions. Everything when `full`, before
|
|
33701
|
+
* the session's first calculation, after the iteration settings changed or while the graph
|
|
33702
|
+
* is stale.
|
|
33703
|
+
*/
|
|
33704
|
+
now(full) {
|
|
33705
|
+
if (full || this.staleGraph || this.calculated !== settingsOf(this.workbook)) {
|
|
33706
|
+
this.full();
|
|
33707
|
+
return;
|
|
33708
|
+
}
|
|
33709
|
+
const changed = this.dirty;
|
|
33710
|
+
this.dirty = [];
|
|
33711
|
+
this.calc.recalculateFrom(changed);
|
|
32974
33712
|
}
|
|
32975
33713
|
/**
|
|
32976
33714
|
* Recalculates one sheet's formulas and their dependents (Shift+F9); after structural edits
|
|
@@ -36774,12 +37512,12 @@ function renameSheet(ctx, index2, name) {
|
|
|
36774
37512
|
ctx.run(
|
|
36775
37513
|
"Rename sheet",
|
|
36776
37514
|
"sheets",
|
|
36777
|
-
[{ kind: "
|
|
37515
|
+
[{ kind: "refs" }],
|
|
36778
37516
|
() => {
|
|
36779
37517
|
rewriteFormulas(workbook, (formula) => renameSheetInFormula(formula, old, name));
|
|
36780
37518
|
sheet.name = name;
|
|
36781
37519
|
},
|
|
36782
|
-
{ sheet: index2, structural: true }
|
|
37520
|
+
{ sheet: index2, structural: true, calc: { kind: "rename", from: old, to: name } }
|
|
36783
37521
|
);
|
|
36784
37522
|
}
|
|
36785
37523
|
function moveSheet(ctx, from, to) {
|
|
@@ -37155,13 +37893,12 @@ function createEditSession(workbook, options = {}) {
|
|
|
37155
37893
|
for (const listener of [...listeners]) listener(change);
|
|
37156
37894
|
};
|
|
37157
37895
|
const calculator = new SessionCalculator(workbook, calc, autoRecalc);
|
|
37158
|
-
const recalc = (step) => calculator.afterStep(step);
|
|
37159
|
-
const begin = (label2, kind, info) =>
|
|
37160
|
-
step
|
|
37161
|
-
|
|
37162
|
-
sheet: info.sheet,
|
|
37163
|
-
|
|
37164
|
-
});
|
|
37896
|
+
const recalc = (step, mode = "apply") => calculator.afterStep(step, mode);
|
|
37897
|
+
const begin = (label2, kind, info) => {
|
|
37898
|
+
const step = { label: label2, entries: [], structural: info.structural ?? false };
|
|
37899
|
+
if (info.calc) step.calc = info.calc;
|
|
37900
|
+
return { step, kind, sheet: info.sheet, ranges: [...info.ranges ?? []] };
|
|
37901
|
+
};
|
|
37165
37902
|
const finish = (current) => {
|
|
37166
37903
|
if (!current.step.entries.length) return;
|
|
37167
37904
|
history.push(current.step);
|
|
@@ -37186,10 +37923,12 @@ function createEditSession(workbook, options = {}) {
|
|
|
37186
37923
|
const outer = !open;
|
|
37187
37924
|
const current = open ?? begin(label2, kind, info);
|
|
37188
37925
|
if (!outer) {
|
|
37926
|
+
delete current.step.calc;
|
|
37189
37927
|
if (info.structural) current.step.structural = true;
|
|
37190
37928
|
if (current.sheet === void 0 && info.sheet !== void 0) current.sheet = info.sheet;
|
|
37191
37929
|
current.ranges.push(...info.ranges ?? []);
|
|
37192
37930
|
}
|
|
37931
|
+
if (outer && info.calc) calculator.beforeStructural();
|
|
37193
37932
|
open = current;
|
|
37194
37933
|
const mark = current.step.entries.length;
|
|
37195
37934
|
const befores = scopes.map((scope) => captureScope(workbook, scope));
|
|
@@ -37237,7 +37976,7 @@ function createEditSession(workbook, options = {}) {
|
|
|
37237
37976
|
if (open) throw new Error(`Cannot ${kind} inside a batch`);
|
|
37238
37977
|
const step = kind === "undo" ? history.undo(workbook) : history.redo(workbook);
|
|
37239
37978
|
if (!step) return false;
|
|
37240
|
-
recalc(step);
|
|
37979
|
+
recalc(step, kind);
|
|
37241
37980
|
emit({ kind, label: step.label, structural: step.structural });
|
|
37242
37981
|
return true;
|
|
37243
37982
|
};
|
|
@@ -37316,10 +38055,11 @@ function createEditSession(workbook, options = {}) {
|
|
|
37316
38055
|
setDocumentProperties: (patch) => setDocumentProperties(ctx, patch),
|
|
37317
38056
|
setAutoRecalc: (enabled2) => setCalcMode(ctx, enabled2 ? "auto" : "manual"),
|
|
37318
38057
|
autoRecalc: () => autoRecalc && calcModeOf(workbook) === "auto",
|
|
37319
|
-
calculateNow() {
|
|
37320
|
-
calculator.full
|
|
38058
|
+
calculateNow(options2) {
|
|
38059
|
+
calculator.now(options2?.full ?? false);
|
|
37321
38060
|
emit({ kind: "cells", label: "Calculate now", structural: false });
|
|
37322
38061
|
},
|
|
38062
|
+
prepareCalculation: (opts) => calculator.prepare(opts?.timeRemaining),
|
|
37323
38063
|
calculateSheet(s) {
|
|
37324
38064
|
calculator.sheet(s);
|
|
37325
38065
|
emit({ kind: "cells", label: "Calculate sheet", sheet: s, structural: false });
|
|
@@ -40444,20 +41184,20 @@ function drawingPaint(node, colors, placeholder, depth = 0) {
|
|
|
40444
41184
|
(transform7) => !SUPPORTED_TRANSFORMS.has(transform7.name) || (integer3(transform7.value) ?? 100001) > 1e5
|
|
40445
41185
|
))
|
|
40446
41186
|
return void 0;
|
|
40447
|
-
let
|
|
41187
|
+
let rgb3;
|
|
40448
41188
|
let inherited;
|
|
40449
|
-
if (color2.kind === "srgb")
|
|
40450
|
-
else if (color2.kind === "system")
|
|
41189
|
+
if (color2.kind === "srgb") rgb3 = color2.value;
|
|
41190
|
+
else if (color2.kind === "system") rgb3 = color2.fallback;
|
|
40451
41191
|
else if (color2.kind === "scheme") {
|
|
40452
|
-
if (color2.value === "phClr")
|
|
41192
|
+
if (color2.value === "phClr") rgb3 = placeholder;
|
|
40453
41193
|
else {
|
|
40454
41194
|
inherited = drawingPaint(colors.get(color2.value), colors, placeholder, depth + 1);
|
|
40455
|
-
|
|
41195
|
+
rgb3 = inherited?.color;
|
|
40456
41196
|
}
|
|
40457
41197
|
}
|
|
40458
|
-
if (!
|
|
41198
|
+
if (!rgb3 || !/^#?[\da-f]{6}$/i.test(rgb3)) return void 0;
|
|
40459
41199
|
const resolved = resolveDrawingColor(
|
|
40460
|
-
{ kind: "srgb", value:
|
|
41200
|
+
{ kind: "srgb", value: rgb3.replace(/^#/, ""), transforms },
|
|
40461
41201
|
void 0,
|
|
40462
41202
|
{ }
|
|
40463
41203
|
);
|
|
@@ -41255,13 +41995,7 @@ function lineCap(cells3, resources, report) {
|
|
|
41255
41995
|
}
|
|
41256
41996
|
const value = number(cells3, "LineCap", NaN, report);
|
|
41257
41997
|
if (value === 0) return "round";
|
|
41258
|
-
if (value === 1 || value === 2)
|
|
41259
|
-
report(
|
|
41260
|
-
"inferred-line-cap",
|
|
41261
|
-
"Legacy square/extended cap geometry uses an inferred compatibility mapping."
|
|
41262
|
-
);
|
|
41263
|
-
return value === 1 ? "butt" : "square";
|
|
41264
|
-
}
|
|
41998
|
+
if (value === 1 || value === 2) return value === 1 ? "butt" : "square";
|
|
41265
41999
|
if (Number.isFinite(value))
|
|
41266
42000
|
report("invalid-line-cap", "The cached line cap is outside the supported enumeration.");
|
|
41267
42001
|
return void 0;
|
|
@@ -41269,13 +42003,12 @@ function lineCap(cells3, resources, report) {
|
|
|
41269
42003
|
|
|
41270
42004
|
// visio/line-pattern.ts
|
|
41271
42005
|
function builtinDash(pattern) {
|
|
41272
|
-
if (pattern === 23) return [2,
|
|
42006
|
+
if (pattern === 23) return [2, 1];
|
|
41273
42007
|
const band = Math.floor((pattern - 2) / 7);
|
|
41274
42008
|
const motif = (pattern - 2) % 7;
|
|
41275
|
-
const dash = [
|
|
41276
|
-
const gap = [
|
|
41277
|
-
const long = [
|
|
41278
|
-
const longGap = [2, 2, 5][band];
|
|
42009
|
+
const dash = [8, 4, 16][band];
|
|
42010
|
+
const gap = [4, 2, 8][band];
|
|
42011
|
+
const long = [20, 10, 40][band];
|
|
41279
42012
|
const lengths = [
|
|
41280
42013
|
[dash],
|
|
41281
42014
|
[1],
|
|
@@ -41285,9 +42018,9 @@ function builtinDash(pattern) {
|
|
|
41285
42018
|
[long, dash],
|
|
41286
42019
|
[long, dash, dash]
|
|
41287
42020
|
][motif];
|
|
41288
|
-
return lengths.flatMap((length) => [length,
|
|
42021
|
+
return lengths.flatMap((length) => [length, gap]);
|
|
41289
42022
|
}
|
|
41290
|
-
function linePattern(cells3, report) {
|
|
42023
|
+
function linePattern(cells3, report, cap = "round") {
|
|
41291
42024
|
const raw2 = cells3.get("LinePattern")?.value;
|
|
41292
42025
|
if (raw2 === "Themed") {
|
|
41293
42026
|
report(
|
|
@@ -41302,11 +42035,14 @@ function linePattern(cells3, report) {
|
|
|
41302
42035
|
}
|
|
41303
42036
|
const pattern = number(cells3, "LinePattern", 1, report);
|
|
41304
42037
|
if (Number.isInteger(pattern) && pattern >= 2 && pattern <= 23) {
|
|
41305
|
-
|
|
41306
|
-
"
|
|
41307
|
-
"Built-in line-pattern spacing uses inferred stroke-width ratios, not verified native spacing."
|
|
42038
|
+
const lineDash = builtinDash(pattern).map(
|
|
42039
|
+
(value, index2) => cap === "butt" ? value : value + (index2 % 2 ? 1 : -1)
|
|
41308
42040
|
);
|
|
41309
|
-
return {
|
|
42041
|
+
return {
|
|
42042
|
+
linePattern: pattern,
|
|
42043
|
+
lineDash,
|
|
42044
|
+
...cap === "square" && lineDash.includes(0) ? { lineDashDotLength: 0.01 / 72 } : {}
|
|
42045
|
+
};
|
|
41310
42046
|
}
|
|
41311
42047
|
if (pattern === 254)
|
|
41312
42048
|
report(
|
|
@@ -41323,6 +42059,25 @@ function linePattern(cells3, report) {
|
|
|
41323
42059
|
return { linePattern: pattern };
|
|
41324
42060
|
}
|
|
41325
42061
|
|
|
42062
|
+
// visio/source-paint.ts
|
|
42063
|
+
function sourcePaint(cells3, resolveColor2) {
|
|
42064
|
+
const opacity2 = (name) => {
|
|
42065
|
+
if (cells3.get(name)?.error) return void 0;
|
|
42066
|
+
const cached3 = number(cells3, name, cells3.has(name) ? NaN : 0);
|
|
42067
|
+
return Number.isFinite(cached3) && cached3 >= 0 && cached3 <= 1 ? 1 - cached3 : void 0;
|
|
42068
|
+
};
|
|
42069
|
+
const foregroundOpacity = opacity2("FillForegndTrans"), backgroundOpacity = opacity2("FillBkgndTrans"), lineColorOpacity = opacity2("LineColorTrans");
|
|
42070
|
+
const pattern = cells3.get("FillPattern")?.error ? NaN : number(cells3, "FillPattern", cells3.has("FillPattern") ? NaN : 1);
|
|
42071
|
+
const backgroundColor = cells3.get("FillBkgnd")?.error ? "" : resolveColor2("FillBkgnd", cells3.has("FillBkgnd") ? "" : "#ffffff");
|
|
42072
|
+
return {
|
|
42073
|
+
...Number.isInteger(pattern) && pattern >= 0 && pattern <= 65535 ? { fillPatternIndex: pattern } : {},
|
|
42074
|
+
...foregroundOpacity === void 0 ? {} : { fillForegroundOpacity: foregroundOpacity },
|
|
42075
|
+
...backgroundColor ? { fillBackgroundColor: backgroundColor } : {},
|
|
42076
|
+
...backgroundOpacity === void 0 ? {} : { fillBackgroundOpacity: backgroundOpacity },
|
|
42077
|
+
...lineColorOpacity === void 0 ? {} : { lineColorOpacity }
|
|
42078
|
+
};
|
|
42079
|
+
}
|
|
42080
|
+
|
|
41326
42081
|
// visio/text-background.ts
|
|
41327
42082
|
function textBackground(cells3, resources, report) {
|
|
41328
42083
|
const raw2 = cells3.get("TextBkgnd")?.value;
|
|
@@ -41403,6 +42158,15 @@ function textParagraphs(text2, markers, sheet, fontFamily, fontSize, resources,
|
|
|
41403
42158
|
return paragraphs;
|
|
41404
42159
|
}
|
|
41405
42160
|
|
|
42161
|
+
// visio/plain-text.ts
|
|
42162
|
+
function encodeVisioPlainText(text2) {
|
|
42163
|
+
return text2 ? `${text2}
|
|
42164
|
+
` : "";
|
|
42165
|
+
}
|
|
42166
|
+
function decodeVisioPlainText(text2) {
|
|
42167
|
+
return text2.endsWith("\n") ? text2.slice(0, -1) : text2;
|
|
42168
|
+
}
|
|
42169
|
+
|
|
41406
42170
|
// visio/nurbs-flatten.ts
|
|
41407
42171
|
var CURVE_TOLERANCE = 1e-4;
|
|
41408
42172
|
var MAX_WORK = 2e6;
|
|
@@ -42123,11 +42887,13 @@ function shapeStyle(sheet, resources, report, width = number(sheet.cells, "Width
|
|
|
42123
42887
|
fill: pattern === 0 ? "none" : color(cells3, "FillForegnd", "#ffffff", resources, report, cells3, !!fillGradient),
|
|
42124
42888
|
...fillGradient ? { fillGradient } : {},
|
|
42125
42889
|
...fillPattern ? { fillPattern } : {},
|
|
42890
|
+
...sourcePaint(cells3, (name, fallback) => color(cells3, name, fallback, resources, () => {
|
|
42891
|
+
})),
|
|
42126
42892
|
lineColor: color(cells3, "LineColor", "#000000", resources, report),
|
|
42127
42893
|
...lineGradient ? { lineGradient } : {},
|
|
42128
42894
|
lineWidth: themeLineWeight(cells3, resources, report) ?? Math.max(0, number(cells3, "LineWeight", 0.01, report)),
|
|
42129
42895
|
...cap === void 0 ? {} : { lineCap: cap },
|
|
42130
|
-
...themeSolidLinePattern(cells3, resources) ?? linePattern(cells3, report),
|
|
42896
|
+
...themeSolidLinePattern(cells3, resources) ?? linePattern(cells3, report, cap),
|
|
42131
42897
|
// Saved and legacy stop transparencies already supply the fill opacity.
|
|
42132
42898
|
fillOpacity: savedGradient || legacyGradient || fillPattern ? 1 : opacity(number(cells3, "FillForegndTrans", 0, report)),
|
|
42133
42899
|
lineOpacity: lineGradient ? 1 : opacity(number(cells3, "LineColorTrans", 0, report)),
|
|
@@ -42151,7 +42917,8 @@ function runStyle(cells3, resources, report, themeCells) {
|
|
|
42151
42917
|
...transparency > 0 ? { opacity: 1 - Math.round(transparency * 255) / 255 } : {},
|
|
42152
42918
|
bold: !!(bits & 1),
|
|
42153
42919
|
italic: !!(bits & 2),
|
|
42154
|
-
underline: !!(bits & 4)
|
|
42920
|
+
underline: !!(bits & 4),
|
|
42921
|
+
strikethrough: number(cells3, "Strikethru", 0, report) !== 0
|
|
42155
42922
|
};
|
|
42156
42923
|
}
|
|
42157
42924
|
function shapeText(sheet, node, width, height, resources, report, consume, consumeParagraph) {
|
|
@@ -42161,8 +42928,9 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
|
|
|
42161
42928
|
let currentCells = defaultCells;
|
|
42162
42929
|
const runs = [];
|
|
42163
42930
|
const paragraphMarkers = [];
|
|
42164
|
-
let textOffset = 0;
|
|
42165
|
-
const append = (text2) => {
|
|
42931
|
+
let textOffset = 0, terminalDirectText = false;
|
|
42932
|
+
const append = (text2, direct = false) => {
|
|
42933
|
+
terminalDirectText = direct;
|
|
42166
42934
|
if (text2) {
|
|
42167
42935
|
consume(text2.length);
|
|
42168
42936
|
runs.push({ text: text2, ...runStyle(currentCells, resources, report, cells3) });
|
|
@@ -42171,8 +42939,9 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
|
|
|
42171
42939
|
};
|
|
42172
42940
|
if (node && !number(cells3, "HideText", 0, report)) {
|
|
42173
42941
|
for (const part of Array.from(node.childNodes)) {
|
|
42174
|
-
if (part.nodeType === 3 || part.nodeType === 4)
|
|
42175
|
-
|
|
42942
|
+
if (part.nodeType === 3 || part.nodeType === 4) {
|
|
42943
|
+
if (part.nodeValue) append(part.nodeValue, true);
|
|
42944
|
+
} else if (part.nodeType === 1) {
|
|
42176
42945
|
const element2 = part;
|
|
42177
42946
|
if (element2.localName === "cp")
|
|
42178
42947
|
currentCells = characters.get(element2.getAttribute("IX") ?? "0") ?? defaultCells;
|
|
@@ -42193,10 +42962,10 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
|
|
|
42193
42962
|
const alignment = number(paragraph2, "HorzAlign", 1, report);
|
|
42194
42963
|
const textWidth = Math.max(0, number(cells3, "TxtWidth", width, report)), textHeight = Math.max(0, number(cells3, "TxtHeight", height, report));
|
|
42195
42964
|
const vertical = number(cells3, "VerticalAlign", 1, report);
|
|
42196
|
-
const
|
|
42965
|
+
const storedText = runs.map((r) => r.text).join("");
|
|
42197
42966
|
const defaultRun = runStyle(defaultCells, resources, report, cells3);
|
|
42198
42967
|
const paragraphs = textParagraphs(
|
|
42199
|
-
|
|
42968
|
+
storedText,
|
|
42200
42969
|
paragraphMarkers,
|
|
42201
42970
|
sheet,
|
|
42202
42971
|
defaultRun.fontFamily,
|
|
@@ -42206,13 +42975,16 @@ function shapeText(sheet, node, width, height, resources, report, consume, consu
|
|
|
42206
42975
|
runs,
|
|
42207
42976
|
consumeParagraph
|
|
42208
42977
|
);
|
|
42978
|
+
const lastRun = runs.at(-1);
|
|
42979
|
+
if (terminalDirectText && lastRun) lastRun.text = decodeVisioPlainText(lastRun.text);
|
|
42980
|
+
const plainText = runs.map((run2) => run2.text).join("");
|
|
42209
42981
|
return {
|
|
42210
42982
|
plainText,
|
|
42211
42983
|
...textBackground(cells3, resources, report),
|
|
42212
42984
|
paragraphs,
|
|
42213
42985
|
runs,
|
|
42214
42986
|
...runStyle(defaultCells, resources, report, cells3),
|
|
42215
|
-
horizontalAlign: alignment === 1 ? "center" : alignment === 2 ? "right" : "left",
|
|
42987
|
+
horizontalAlign: alignment === 1 ? "center" : alignment === 2 ? "right" : alignment === 3 ? "justify" : "left",
|
|
42216
42988
|
verticalAlign: vertical === 0 ? "top" : vertical === 2 ? "bottom" : "middle",
|
|
42217
42989
|
width: textWidth,
|
|
42218
42990
|
height: textHeight,
|
|
@@ -42653,6 +43425,7 @@ var LINE_PROPERTIES = [
|
|
|
42653
43425
|
"LineCap",
|
|
42654
43426
|
"LinePattern",
|
|
42655
43427
|
"LineColorTrans",
|
|
43428
|
+
"LineGradientEnabled",
|
|
42656
43429
|
"BeginArrow",
|
|
42657
43430
|
"EndArrow",
|
|
42658
43431
|
"BeginArrowSize",
|
|
@@ -43224,12 +43997,26 @@ async function parseVsdx(input, options = {}) {
|
|
|
43224
43997
|
};
|
|
43225
43998
|
for (const color2 of children3(child5(documentRoot, "Colors"), "ColorEntry"))
|
|
43226
43999
|
resources.colors.set(attribute3(color2, "IX") ?? "", attribute3(color2, "RGB") ?? "");
|
|
43227
|
-
children3(child5(documentRoot, "FaceNames"), "FaceName")
|
|
43228
|
-
|
|
44000
|
+
const faceNames = children3(child5(documentRoot, "FaceNames"), "FaceName");
|
|
44001
|
+
if (faceNames.length > 1e4)
|
|
44002
|
+
throw new VisioPackageError(
|
|
44003
|
+
"METADATA_LIMIT",
|
|
44004
|
+
"Document font count exceeds its metadata limit."
|
|
44005
|
+
);
|
|
44006
|
+
let fontCharacters = 0;
|
|
44007
|
+
faceNames.forEach((font2, index2) => {
|
|
44008
|
+
checkTime();
|
|
44009
|
+
fontCharacters += (attribute3(font2, "Name") ?? attribute3(font2, "NameU") ?? "Arial").length;
|
|
44010
|
+
if (fontCharacters > 1e6)
|
|
44011
|
+
throw new VisioPackageError(
|
|
44012
|
+
"METADATA_LIMIT",
|
|
44013
|
+
"Document fonts exceed aggregate metadata limits."
|
|
44014
|
+
);
|
|
44015
|
+
resources.fonts.set(
|
|
43229
44016
|
metadata(attribute3(font2, "ID") ?? String(index2), 256, "Font ID"),
|
|
43230
44017
|
metadata(attribute3(font2, "Name") ?? attribute3(font2, "NameU") ?? "Arial", 1024, "Font name")
|
|
43231
|
-
)
|
|
43232
|
-
);
|
|
44018
|
+
);
|
|
44019
|
+
});
|
|
43233
44020
|
const styles = /* @__PURE__ */ new Map();
|
|
43234
44021
|
for (const style2 of children3(child5(documentRoot, "StyleSheets"), "StyleSheet"))
|
|
43235
44022
|
styles.set(metadata(attribute3(style2, "ID") ?? "", 256, "Style ID"), {
|
|
@@ -43396,7 +44183,12 @@ async function parseVsdx(input, options = {}) {
|
|
|
43396
44183
|
"ShapeSheet formulas, automatic connector routing, and external data are not evaluated; saved cached values and supported theme records are used.",
|
|
43397
44184
|
{ severity: "info" }
|
|
43398
44185
|
);
|
|
43399
|
-
return {
|
|
44186
|
+
return {
|
|
44187
|
+
format: "vsdx",
|
|
44188
|
+
pages,
|
|
44189
|
+
diagnostics: diagnosticState.finish(),
|
|
44190
|
+
fontFamilies: [...new Set(resources.fonts.values())]
|
|
44191
|
+
};
|
|
43400
44192
|
}
|
|
43401
44193
|
|
|
43402
44194
|
// automation/visio.ts
|
|
@@ -43551,203 +44343,12 @@ function writeEditedPackage(parts, maxBytes, deadline, check3) {
|
|
|
43551
44343
|
});
|
|
43552
44344
|
}
|
|
43553
44345
|
|
|
43554
|
-
// visio/
|
|
43555
|
-
function
|
|
43556
|
-
|
|
43557
|
-
const containers = children3(parent, "Shapes");
|
|
43558
|
-
if (containers.length > 1)
|
|
43559
|
-
fail2("INVALID_SHAPE_ID", "Duplicate Shapes containers are ambiguous.");
|
|
43560
|
-
return children3(containers[0], "Shape");
|
|
43561
|
-
};
|
|
43562
|
-
const shapes = /* @__PURE__ */ new Map();
|
|
43563
|
-
const pending2 = shapeChildren(root).map((node2) => ({
|
|
43564
|
-
node: node2,
|
|
43565
|
-
inherited: false,
|
|
43566
|
-
deleted: false
|
|
43567
|
-
}));
|
|
43568
|
-
while (pending2.length) {
|
|
43569
|
-
check3();
|
|
43570
|
-
const item = pending2.pop();
|
|
43571
|
-
const id = attribute3(item.node, "ID");
|
|
43572
|
-
if (!id || shapes.has(id))
|
|
43573
|
-
fail2("INVALID_SHAPE_ID", "Local shape IDs must be present and unique.");
|
|
43574
|
-
const inherited = item.inherited || item.node.hasAttribute("Master") || item.node.hasAttribute("MasterShape");
|
|
43575
|
-
const deleted = item.deleted || ["1", "true"].includes(attribute3(item.node, "Del") ?? "");
|
|
43576
|
-
shapes.set(id, { node: item.node, inherited, deleted });
|
|
43577
|
-
for (const node2 of shapeChildren(item.node)) pending2.push({ node: node2, inherited, deleted });
|
|
43578
|
-
}
|
|
43579
|
-
const target = shapes.get(shapeId);
|
|
43580
|
-
if (!target) fail2("EDIT_TARGET_NOT_FOUND", "Local shape does not exist.");
|
|
43581
|
-
if (target.inherited || target.deleted)
|
|
43582
|
-
fail2("UNSUPPORTED_TEXT_EDIT", "Master-linked or deleted shapes cannot be edited.");
|
|
43583
|
-
const texts = children3(target.node, "Text");
|
|
43584
|
-
if (texts.length !== 1)
|
|
43585
|
-
fail2("UNSUPPORTED_TEXT_EDIT", "Editing requires one existing local Text element.");
|
|
43586
|
-
const node = texts[0];
|
|
43587
|
-
if (Array.from(node.childNodes).some((item) => item.nodeType !== 3 && item.nodeType !== 4))
|
|
43588
|
-
fail2("UNSUPPORTED_TEXT_EDIT", "Rich text, fields and unknown text markup cannot be edited.");
|
|
43589
|
-
if (children3(target.node, "Section").some((section) => attribute3(section, "N") === "Field"))
|
|
43590
|
-
fail2("UNSUPPORTED_TEXT_EDIT", "Shapes with text fields cannot be edited.");
|
|
43591
|
-
if (node.textContent === text2) return false;
|
|
43592
|
-
while (node.firstChild) node.removeChild(node.firstChild);
|
|
43593
|
-
node.appendChild(node.ownerDocument.createTextNode(text2));
|
|
43594
|
-
return true;
|
|
43595
|
-
}
|
|
43596
|
-
function serializeEditedXml(root, limits, check3) {
|
|
43597
|
-
check3();
|
|
43598
|
-
const pending2 = [root.ownerDocument];
|
|
43599
|
-
while (pending2.length) {
|
|
43600
|
-
check3();
|
|
43601
|
-
const node = pending2.pop();
|
|
43602
|
-
if ((node.nodeType === 3 || node.nodeType === 4) && node.nodeValue?.includes("\r"))
|
|
43603
|
-
fail2("UNSUPPORTED_XML_EDIT", "Carriage-return text cannot be preserved by this writer.");
|
|
43604
|
-
if (node.nodeType === 1) {
|
|
43605
|
-
for (const attr3 of Array.from(node.attributes))
|
|
43606
|
-
if (/[\t\r\n]/.test(attr3.value))
|
|
43607
|
-
fail2("UNSUPPORTED_XML_EDIT", "Attribute whitespace cannot be preserved by this writer.");
|
|
43608
|
-
}
|
|
43609
|
-
for (const child6 of Array.from(node.childNodes)) pending2.push(child6);
|
|
43610
|
-
}
|
|
43611
|
-
let xml = buildXml(root.ownerDocument);
|
|
43612
|
-
xml = xml.replace(
|
|
43613
|
-
/^<\?xml\s[^?]*\?>/,
|
|
43614
|
-
(declaration) => declaration.replace(/encoding\s*=\s*(['"])[^'"]*\1/, 'encoding="UTF-8"')
|
|
43615
|
-
);
|
|
43616
|
-
const nodes = inspectXml(xml, limits, check3);
|
|
43617
|
-
inspectNamespaces(root, check3);
|
|
43618
|
-
const bytes = new TextEncoder().encode(xml);
|
|
43619
|
-
if (bytes.length > limits.maxEntryBytes)
|
|
43620
|
-
fail2("LIMIT_ENTRY", "Edited XML part exceeds byte limit.");
|
|
43621
|
-
return { bytes, nodes };
|
|
43622
|
-
}
|
|
43623
|
-
|
|
43624
|
-
// visio/edit-commands.ts
|
|
43625
|
-
var isVisioPageEdit = (edit) => edit.type === "insert-page" || edit.type === "reorder-page" || edit.type === "rename-page" || edit.type === "delete-page";
|
|
43626
|
-
function geometryChangedCells(edit) {
|
|
43627
|
-
if (edit.type === "create-line")
|
|
43628
|
-
return [
|
|
43629
|
-
"BeginX",
|
|
43630
|
-
"BeginY",
|
|
43631
|
-
"EndX",
|
|
43632
|
-
"EndY",
|
|
43633
|
-
"PinX",
|
|
43634
|
-
"PinY",
|
|
43635
|
-
"Width",
|
|
43636
|
-
"Height",
|
|
43637
|
-
"Angle",
|
|
43638
|
-
"LocPinX",
|
|
43639
|
-
"LocPinY"
|
|
43640
|
-
];
|
|
43641
|
-
if (edit.type === "delete-shape") return [];
|
|
43642
|
-
if (edit.type === "move-line-endpoint") {
|
|
43643
|
-
const prefix = edit.endpoint === "begin" ? "Begin" : "End";
|
|
43644
|
-
return [`${prefix}X`, `${prefix}Y`];
|
|
43645
|
-
}
|
|
43646
|
-
if (edit.type === "move-shape") return ["PinX", "PinY"];
|
|
43647
|
-
if (edit.type === "resize-shape") return ["Width", "Height"];
|
|
43648
|
-
if (edit.type === "rotate-shape") return ["Angle"];
|
|
43649
|
-
if (edit.type === "flip-shape") return ["Angle", edit.axis === "horizontal" ? "FlipX" : "FlipY"];
|
|
43650
|
-
return ["PinX", "PinY", "Width", "Height"];
|
|
44346
|
+
// visio/cell-formula.ts
|
|
44347
|
+
function executableCellFormula(source2) {
|
|
44348
|
+
return !source2 || source2 === "No Formula" || source2 === "Inh" ? void 0 : source2;
|
|
43651
44349
|
}
|
|
43652
|
-
function
|
|
43653
|
-
|
|
43654
|
-
fail2("LIMIT_EDITS", "Edit command count exceeds limit.");
|
|
43655
|
-
let textLength = 0;
|
|
43656
|
-
const text2 = (value) => {
|
|
43657
|
-
if (typeof value !== "string") fail2("INVALID_EDIT", "Edit text must be a string.");
|
|
43658
|
-
textLength += value.length;
|
|
43659
|
-
if (textLength > maxText) fail2("LIMIT_EDIT_TEXT", "Replacement text exceeds aggregate limit.");
|
|
43660
|
-
if (/[\u0000-\u0008\u000b\u000c\u000d\u000e-\u001f\ufffe\uffff]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/u.test(
|
|
43661
|
-
value
|
|
43662
|
-
))
|
|
43663
|
-
fail2("INVALID_EDIT_TEXT", "Replacement text contains invalid XML characters.");
|
|
43664
|
-
return value;
|
|
43665
|
-
};
|
|
43666
|
-
const numeric5 = (value, dimension2 = false, allowZero = false) => {
|
|
43667
|
-
if (typeof value !== "number" || !Number.isFinite(value) || Math.abs(value) > 1e6 || dimension2 && (value < 0 || !allowZero && value === 0))
|
|
43668
|
-
fail2(
|
|
43669
|
-
"INVALID_EDIT",
|
|
43670
|
-
"Geometry requires finite drawing inches within limits and positive dimensions."
|
|
43671
|
-
);
|
|
43672
|
-
return value;
|
|
43673
|
-
};
|
|
43674
|
-
return Array.from(edits, (edit) => {
|
|
43675
|
-
if (!edit || typeof edit.pageId !== "string" || !edit.pageId || edit.pageId.length > 256)
|
|
43676
|
-
fail2("INVALID_EDIT", "Invalid edit target.");
|
|
43677
|
-
if (edit.type === "delete-page") return { type: edit.type, pageId: edit.pageId };
|
|
43678
|
-
if (edit.type === "reorder-page") {
|
|
43679
|
-
if (!Number.isSafeInteger(edit.index) || edit.index < 0 || edit.index > 1e6)
|
|
43680
|
-
fail2("INVALID_EDIT", "Page order requires a bounded zero-based integer index.");
|
|
43681
|
-
return { type: edit.type, pageId: edit.pageId, index: edit.index };
|
|
43682
|
-
}
|
|
43683
|
-
if (edit.type === "insert-page") {
|
|
43684
|
-
const name = text2(edit.name);
|
|
43685
|
-
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))
|
|
43686
|
-
fail2("INVALID_EDIT", "Invalid new page ID, name or insertion target.");
|
|
43687
|
-
return { type: edit.type, pageId: edit.pageId, afterPageId: edit.afterPageId, name };
|
|
43688
|
-
}
|
|
43689
|
-
if (edit.type === "rename-page") {
|
|
43690
|
-
const name = text2(edit.name);
|
|
43691
|
-
if (!name.trim() || name.length > 255 || /[\t\n]/.test(name))
|
|
43692
|
-
fail2("INVALID_EDIT", "Invalid page name.");
|
|
43693
|
-
return { type: edit.type, pageId: edit.pageId, name };
|
|
43694
|
-
}
|
|
43695
|
-
if (typeof edit.shapeId !== "string" || !edit.shapeId || edit.shapeId.length > 256)
|
|
43696
|
-
fail2("INVALID_EDIT", "Invalid edit shape target.");
|
|
43697
|
-
const target = { pageId: edit.pageId, shapeId: edit.shapeId };
|
|
43698
|
-
if (edit.type === "replace-plain-text")
|
|
43699
|
-
return { ...target, type: edit.type, text: text2(edit.text) };
|
|
43700
|
-
if (!/^[1-9]\d{0,9}$/.test(edit.shapeId) || Number(edit.shapeId) > 4294967295)
|
|
43701
|
-
fail2("INVALID_EDIT", "Geometry shape IDs must be canonical positive unsigned integers.");
|
|
43702
|
-
switch (edit.type) {
|
|
43703
|
-
case "create-line": {
|
|
43704
|
-
const beginX = numeric5(edit.beginX), beginY = numeric5(edit.beginY);
|
|
43705
|
-
const endX = numeric5(edit.endX), endY = numeric5(edit.endY);
|
|
43706
|
-
numeric5(Math.hypot(endX - beginX, endY - beginY), true);
|
|
43707
|
-
return { ...target, type: edit.type, beginX, beginY, endX, endY };
|
|
43708
|
-
}
|
|
43709
|
-
case "create-rectangle":
|
|
43710
|
-
case "create-ellipse":
|
|
43711
|
-
return {
|
|
43712
|
-
...target,
|
|
43713
|
-
type: edit.type,
|
|
43714
|
-
x: numeric5(edit.x),
|
|
43715
|
-
y: numeric5(edit.y),
|
|
43716
|
-
width: numeric5(edit.width, true),
|
|
43717
|
-
height: numeric5(edit.height, true),
|
|
43718
|
-
...edit.text === void 0 ? {} : { text: text2(edit.text) }
|
|
43719
|
-
};
|
|
43720
|
-
case "rotate-shape":
|
|
43721
|
-
return { ...target, type: edit.type, angle: numeric5(edit.angle) };
|
|
43722
|
-
case "flip-shape":
|
|
43723
|
-
if (edit.axis !== "horizontal" && edit.axis !== "vertical")
|
|
43724
|
-
fail2("INVALID_EDIT", "Invalid flip axis.");
|
|
43725
|
-
return { ...target, type: edit.type, axis: edit.axis };
|
|
43726
|
-
case "move-shape":
|
|
43727
|
-
return { ...target, type: edit.type, x: numeric5(edit.x), y: numeric5(edit.y) };
|
|
43728
|
-
case "move-line-endpoint":
|
|
43729
|
-
if (edit.endpoint !== "begin" && edit.endpoint !== "end")
|
|
43730
|
-
fail2("INVALID_EDIT", "A line endpoint must be begin or end.");
|
|
43731
|
-
return {
|
|
43732
|
-
...target,
|
|
43733
|
-
type: edit.type,
|
|
43734
|
-
endpoint: edit.endpoint,
|
|
43735
|
-
x: numeric5(edit.x),
|
|
43736
|
-
y: numeric5(edit.y)
|
|
43737
|
-
};
|
|
43738
|
-
case "resize-shape":
|
|
43739
|
-
return {
|
|
43740
|
-
...target,
|
|
43741
|
-
type: edit.type,
|
|
43742
|
-
width: numeric5(edit.width, true),
|
|
43743
|
-
height: numeric5(edit.height, true, true)
|
|
43744
|
-
};
|
|
43745
|
-
case "delete-shape":
|
|
43746
|
-
return { ...target, type: edit.type };
|
|
43747
|
-
default:
|
|
43748
|
-
return fail2("INVALID_EDIT", "Unsupported edit command.");
|
|
43749
|
-
}
|
|
43750
|
-
});
|
|
44350
|
+
function inertDoubleClickFormula(cell, source2) {
|
|
44351
|
+
return cell === "EventDblClick" && /^\s*=?\s*(OPENTEXTWIN|DEFAULTEVENT)\(\s*\)\s*$/i.test(source2);
|
|
43751
44352
|
}
|
|
43752
44353
|
|
|
43753
44354
|
// visio/formula-theme.ts
|
|
@@ -43833,11 +44434,11 @@ function evaluateNumericFormulaFunction(name, args) {
|
|
|
43833
44434
|
if (args.length < min || args.length > max)
|
|
43834
44435
|
return formulaFailure("arity", `Invalid ${name} argument count`);
|
|
43835
44436
|
};
|
|
43836
|
-
const
|
|
44437
|
+
const scalar4 = (value) => ({ value, unit: "scalar" });
|
|
43837
44438
|
if (name === "AND" || name === "OR" || name === "NOT") {
|
|
43838
44439
|
arity(1, name === "NOT" ? 1 : 1024);
|
|
43839
44440
|
const values2 = args.map((arg) => finiteFormulaValue(arg).value !== 0);
|
|
43840
|
-
return
|
|
44441
|
+
return scalar4(
|
|
43841
44442
|
Number(
|
|
43842
44443
|
name === "AND" ? values2.every(Boolean) : name === "OR" ? values2.some(Boolean) : !values2[0]
|
|
43843
44444
|
)
|
|
@@ -43851,7 +44452,7 @@ function evaluateNumericFormulaFunction(name, args) {
|
|
|
43851
44452
|
return formulaFailure("value", `${name} requires an integer from 0 to 65535`);
|
|
43852
44453
|
return arg.value;
|
|
43853
44454
|
});
|
|
43854
|
-
return
|
|
44455
|
+
return scalar4(
|
|
43855
44456
|
name === "BITAND" ? values2[0] & values2[1] : name === "BITOR" ? values2[0] | values2[1] : values2[0] ^ values2[1]
|
|
43856
44457
|
);
|
|
43857
44458
|
}
|
|
@@ -44280,6 +44881,115 @@ function parseVisioFormula(source2, limits = {}) {
|
|
|
44280
44881
|
return ast;
|
|
44281
44882
|
}
|
|
44282
44883
|
|
|
44884
|
+
// visio/edit-formatting-rows.ts
|
|
44885
|
+
var delegatedSources = /* @__PURE__ */ new WeakMap();
|
|
44886
|
+
function delegatedFormattingCell(cell) {
|
|
44887
|
+
const seen = /* @__PURE__ */ new Set();
|
|
44888
|
+
while (cell && attribute3(cell, "F") === "Inh") {
|
|
44889
|
+
const ancestor = delegatedSources.get(cell);
|
|
44890
|
+
if (!ancestor || seen.has(cell) || seen.size >= 64 || cell.hasAttribute("E"))
|
|
44891
|
+
fail2("EDIT_PROTECTED_CELL", "Inherited formatting has no proven source.");
|
|
44892
|
+
seen.add(cell);
|
|
44893
|
+
const current = attribute3(cell, "V"), previous = attribute3(ancestor, "V");
|
|
44894
|
+
if (current !== previous || attribute3(cell, "U") !== attribute3(ancestor, "U")) {
|
|
44895
|
+
let agrees = false;
|
|
44896
|
+
try {
|
|
44897
|
+
const a2 = visioFormulaCachedValue(current ?? "", attribute3(cell, "U"));
|
|
44898
|
+
const b = visioFormulaCachedValue(previous ?? "", attribute3(ancestor, "U"));
|
|
44899
|
+
agrees = a2.value === b.value && a2.unit === b.unit;
|
|
44900
|
+
} catch {
|
|
44901
|
+
}
|
|
44902
|
+
if (!agrees)
|
|
44903
|
+
fail2(
|
|
44904
|
+
"EDIT_PROTECTED_CELL",
|
|
44905
|
+
"Inherited formatting cache is stale or has incompatible units."
|
|
44906
|
+
);
|
|
44907
|
+
}
|
|
44908
|
+
cell = ancestor;
|
|
44909
|
+
}
|
|
44910
|
+
return cell;
|
|
44911
|
+
}
|
|
44912
|
+
function formattingIndex(value) {
|
|
44913
|
+
if (value === void 0 || !/^(0|[1-9]\d{0,9})$/.test(value) || Number(value) > 4294967295)
|
|
44914
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting requires canonical unsigned row indices.");
|
|
44915
|
+
return value;
|
|
44916
|
+
}
|
|
44917
|
+
function formattingRows(sheet, sectionName) {
|
|
44918
|
+
const sections = children3(sheet, "Section").filter((section2) => {
|
|
44919
|
+
const name = attribute3(section2, "N");
|
|
44920
|
+
if (name?.toLowerCase() === sectionName.toLowerCase() && name !== sectionName)
|
|
44921
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Noncanonical formatting section names are unsupported.");
|
|
44922
|
+
return name === sectionName;
|
|
44923
|
+
});
|
|
44924
|
+
if (sections.length > 1) fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting section is ambiguous.");
|
|
44925
|
+
const section = sections[0];
|
|
44926
|
+
const result2 = /* @__PURE__ */ new Map();
|
|
44927
|
+
if (!section) return result2;
|
|
44928
|
+
if (section.hasAttribute("Del") || (attribute3(section, "IX") ?? "0") !== "0")
|
|
44929
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting requires one live section with index zero.");
|
|
44930
|
+
for (const row2 of children3(section, "Row")) {
|
|
44931
|
+
const index2 = formattingIndex(attribute3(row2, "IX") ?? "0");
|
|
44932
|
+
if (row2.hasAttribute("Del") || row2.hasAttribute("N") || row2.hasAttribute("T") || result2.has(index2))
|
|
44933
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting requires unique live indexed rows.");
|
|
44934
|
+
result2.set(index2, row2);
|
|
44935
|
+
if (result2.size > 1e4) fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting row limit exceeded.");
|
|
44936
|
+
}
|
|
44937
|
+
return result2;
|
|
44938
|
+
}
|
|
44939
|
+
function formattingRow(sheet, sectionName, index2 = "0") {
|
|
44940
|
+
return formattingRows(sheet, sectionName).get(index2);
|
|
44941
|
+
}
|
|
44942
|
+
function mergeFormattingRows(base, sheet, sectionName, cells3) {
|
|
44943
|
+
const result2 = new Map(base);
|
|
44944
|
+
for (const [index2, row2] of formattingRows(sheet, sectionName)) {
|
|
44945
|
+
const merged = new Map(base.get(index2) ?? base.get("0"));
|
|
44946
|
+
for (const [name, cell] of cells3(row2)) {
|
|
44947
|
+
if (attribute3(cell, "F") === "Inh" && !cell.hasAttribute("V") && !cell.hasAttribute("E"))
|
|
44948
|
+
continue;
|
|
44949
|
+
const ancestor = merged.get(name);
|
|
44950
|
+
const inheritedUnit = attribute3(ancestor, "U");
|
|
44951
|
+
let effective = cell;
|
|
44952
|
+
if (!cell.hasAttribute("U") && inheritedUnit !== void 0) {
|
|
44953
|
+
effective = cell.cloneNode(true);
|
|
44954
|
+
effective.setAttribute("U", inheritedUnit);
|
|
44955
|
+
}
|
|
44956
|
+
if (attribute3(cell, "F") === "Inh") delegatedSources.set(effective, ancestor);
|
|
44957
|
+
merged.set(name, effective);
|
|
44958
|
+
}
|
|
44959
|
+
result2.set(index2, merged);
|
|
44960
|
+
if (result2.size > 1e4) fail2("UNSUPPORTED_FORMAT_EDIT", "Formatting row limit exceeded.");
|
|
44961
|
+
}
|
|
44962
|
+
return result2;
|
|
44963
|
+
}
|
|
44964
|
+
function assertFormattingText(shape2, characters, paragraphs) {
|
|
44965
|
+
const texts = children3(shape2, "Text");
|
|
44966
|
+
if (texts.length !== 1)
|
|
44967
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Text formatting requires one existing local Text.");
|
|
44968
|
+
let fields;
|
|
44969
|
+
for (const part of Array.from(texts[0].childNodes)) {
|
|
44970
|
+
if (part.nodeType === 3 || part.nodeType === 4) continue;
|
|
44971
|
+
const marker4 = part;
|
|
44972
|
+
if (part.nodeType !== 1 || marker4.namespaceURI !== shape2.namespaceURI || !["cp", "pp", "tp", "fld"].includes(marker4.localName))
|
|
44973
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Unknown text markup cannot be formatted.");
|
|
44974
|
+
const index2 = formattingIndex(attribute3(marker4, "IX"));
|
|
44975
|
+
if (marker4.localName === "fld") {
|
|
44976
|
+
fields ??= formattingRows(shape2, "Field");
|
|
44977
|
+
if (!fields.has(index2) || Array.from(marker4.childNodes).some((node) => ![3, 4].includes(node.nodeType)))
|
|
44978
|
+
fail2(
|
|
44979
|
+
"UNSUPPORTED_FORMAT_EDIT",
|
|
44980
|
+
"Text fields require a live local field row and plain cached text."
|
|
44981
|
+
);
|
|
44982
|
+
continue;
|
|
44983
|
+
}
|
|
44984
|
+
const rows = marker4.localName === "cp" ? characters : marker4.localName === "pp" ? paragraphs : void 0;
|
|
44985
|
+
if (marker4.childNodes.length || index2 !== "0" && rows && !rows.has(index2))
|
|
44986
|
+
fail2(
|
|
44987
|
+
"UNSUPPORTED_FORMAT_EDIT",
|
|
44988
|
+
"Formatting markers require existing rows and no nested markup."
|
|
44989
|
+
);
|
|
44990
|
+
}
|
|
44991
|
+
}
|
|
44992
|
+
|
|
44283
44993
|
// visio/edit-geometry-cells.ts
|
|
44284
44994
|
var cells = (shape2) => new Map(children3(shape2, "Cell").map((node) => [attribute3(node, "N") ?? "", node]));
|
|
44285
44995
|
function numeric4(node, fallback) {
|
|
@@ -44352,14 +45062,6 @@ function assertEllipseResizeRow(shape2, row2) {
|
|
|
44352
45062
|
}
|
|
44353
45063
|
}
|
|
44354
45064
|
|
|
44355
|
-
// visio/cell-formula.ts
|
|
44356
|
-
function executableCellFormula(source2) {
|
|
44357
|
-
return !source2 || source2 === "No Formula" || source2 === "Inh" ? void 0 : source2;
|
|
44358
|
-
}
|
|
44359
|
-
function inertDoubleClickFormula(cell, source2) {
|
|
44360
|
-
return cell === "EventDblClick" && /^\s*=?\s*(OPENTEXTWIN|DEFAULTEVENT)\(\s*\)\s*$/i.test(source2);
|
|
44361
|
-
}
|
|
44362
|
-
|
|
44363
45065
|
// visio/edit-recalculate-index.ts
|
|
44364
45066
|
var key = (cell) => JSON.stringify([cell.pageId, cell.shapeId, cell.cell.toLowerCase()]);
|
|
44365
45067
|
function bound(value, fallback) {
|
|
@@ -44611,26 +45313,27 @@ function recalculateVisioCells(roots, changed, options = {}) {
|
|
|
44611
45313
|
}
|
|
44612
45314
|
return [...pages];
|
|
44613
45315
|
}
|
|
44614
|
-
function
|
|
45316
|
+
function assertVisioShapesUnreferenced(roots, removed, options = {}) {
|
|
44615
45317
|
const cells3 = indexCells(roots, options);
|
|
44616
45318
|
for (const cell of cells3.values()) {
|
|
44617
|
-
|
|
45319
|
+
options.check?.();
|
|
45320
|
+
if (removed.get(cell.pageId)?.has(cell.shapeId)) continue;
|
|
44618
45321
|
if (cell.dependencies.some((id) => {
|
|
44619
45322
|
const parts = JSON.parse(id);
|
|
44620
|
-
return parts[0]
|
|
45323
|
+
return removed.get(parts[0])?.has(parts[1]) ?? false;
|
|
44621
45324
|
}))
|
|
44622
45325
|
fail2("EDIT_REFERENCED_DELETE", "Shape is referenced by a ShapeSheet formula.");
|
|
44623
45326
|
}
|
|
44624
|
-
const
|
|
44625
|
-
|
|
44626
|
-
for (const connections2 of children3(root, "Connects"))
|
|
45327
|
+
for (const [pageId, ids] of removed)
|
|
45328
|
+
for (const connections2 of children3(roots.get(pageId), "Connects"))
|
|
44627
45329
|
for (const connection of children3(connections2, "Connect")) {
|
|
44628
|
-
|
|
45330
|
+
options.check?.();
|
|
45331
|
+
if (["FromSheet", "ToSheet"].some((name) => ids.has(attribute3(connection, name) ?? "")))
|
|
44629
45332
|
fail2("EDIT_REFERENCED_DELETE", "Shape participates in a Connect record.");
|
|
44630
45333
|
}
|
|
44631
45334
|
}
|
|
44632
|
-
function
|
|
44633
|
-
|
|
45335
|
+
function assertVisioShapeUnreferenced(roots, pageId, shapeId, options = {}) {
|
|
45336
|
+
assertVisioShapesUnreferenced(roots, /* @__PURE__ */ new Map([[pageId, /* @__PURE__ */ new Set([shapeId])]]), options);
|
|
44634
45337
|
}
|
|
44635
45338
|
function createVisioDependencyQuery(roots, options = {}) {
|
|
44636
45339
|
const cells3 = indexCells(roots, options);
|
|
@@ -44823,6 +45526,7 @@ function protectedShape(shape2, document, masterMovePins = /* @__PURE__ */ new S
|
|
|
44823
45526
|
}
|
|
44824
45527
|
function resizeGeometry(shape2, roots, edit, check3, lineEditShapes = /* @__PURE__ */ new Set()) {
|
|
44825
45528
|
const sections = children3(shape2, "Section").filter((node) => attribute3(node, "N") === "Geometry");
|
|
45529
|
+
let depends;
|
|
44826
45530
|
if (!sections.length)
|
|
44827
45531
|
fail2("UNSUPPORTED_GEOMETRY_EDIT", "Resizing requires explicit supported local geometry.");
|
|
44828
45532
|
for (const section of sections) {
|
|
@@ -44852,15 +45556,14 @@ function resizeGeometry(shape2, roots, edit, check3, lineEditShapes = /* @__PURE
|
|
|
44852
45556
|
const analysis = analyzeVisioFormula(formula);
|
|
44853
45557
|
if (!analysis.references.length && numeric4(node) === 0) continue;
|
|
44854
45558
|
const cell = `Geometry${Number(attribute3(section, "IX") ?? "0") + 1}.${attribute3(node, "N")}${attribute3(row2, "IX")}`;
|
|
44855
|
-
|
|
44856
|
-
|
|
45559
|
+
depends ??= createVisioDependencyQuery(roots, { check: check3, lineEditShapes });
|
|
45560
|
+
if (!depends(
|
|
44857
45561
|
{ pageId: edit.pageId, shapeId: edit.shapeId, cell },
|
|
44858
45562
|
["Width", "Height"].map((cell2) => ({
|
|
44859
45563
|
pageId: edit.pageId,
|
|
44860
45564
|
shapeId: edit.shapeId,
|
|
44861
45565
|
cell: cell2
|
|
44862
|
-
}))
|
|
44863
|
-
{ check: check3, lineEditShapes }
|
|
45566
|
+
}))
|
|
44864
45567
|
))
|
|
44865
45568
|
fail2(
|
|
44866
45569
|
"UNSUPPORTED_GEOMETRY_EDIT",
|
|
@@ -44878,6 +45581,704 @@ function assertLengthTransformCells(local) {
|
|
|
44878
45581
|
}
|
|
44879
45582
|
}
|
|
44880
45583
|
|
|
45584
|
+
// visio/edit-formatting-cell-admission.ts
|
|
45585
|
+
function assertEditableFormattingCell(cell) {
|
|
45586
|
+
const source2 = executableCellFormula(attribute3(cell, "F"));
|
|
45587
|
+
const ast = source2 ? parseVisioFormula(source2) : void 0;
|
|
45588
|
+
const themeLiteral = (node) => {
|
|
45589
|
+
if (node.kind === "string" || node.kind === "number") return true;
|
|
45590
|
+
if (node.kind !== "call" || !node.args.every(themeLiteral)) return false;
|
|
45591
|
+
if (node.name === "THEMEGUARD") return node.args.length <= 1;
|
|
45592
|
+
if (node.name === "THEME")
|
|
45593
|
+
return node.args.length === 0 || node.args.length === 1 && node.args[0]?.kind === "string";
|
|
45594
|
+
if (node.name !== "THEMEVAL" || node.args.length > 2) return false;
|
|
45595
|
+
const selector = node.args[0];
|
|
45596
|
+
return !selector || selector.kind === "string" || selector.kind === "number" && selector.unit === "scalar" && Number.isInteger(selector.value) && selector.value >= 1 && selector.value <= 8;
|
|
45597
|
+
};
|
|
45598
|
+
if (ast?.kind === "call" && (ast.name === "FONT" && ast.args.length === 1 && ast.args[0]?.kind === "string" || ast.name === "RGB" && ast.args.length === 3 && ast.args.every(
|
|
45599
|
+
(arg) => arg.kind === "number" && arg.unit === "scalar" && Number.isInteger(arg.value) && arg.value >= 0 && arg.value <= 255
|
|
45600
|
+
) || ["THEMEVAL", "THEME", "THEMEGUARD"].includes(ast.name) && themeLiteral(ast))) {
|
|
45601
|
+
if (cell?.hasAttribute("E"))
|
|
45602
|
+
fail2("EDIT_PROTECTED_CELL", "Cannot overwrite an error formatting cell.");
|
|
45603
|
+
return;
|
|
45604
|
+
}
|
|
45605
|
+
editableCell(cell);
|
|
45606
|
+
if (source2 && cell) {
|
|
45607
|
+
const actual = evaluateVisioFormula(
|
|
45608
|
+
source2,
|
|
45609
|
+
() => fail2("EDIT_PROTECTED_CELL", "Formatting dependencies cannot be overwritten.")
|
|
45610
|
+
);
|
|
45611
|
+
const cache3 = visioFormulaCachedValue(attribute3(cell, "V") ?? "", attribute3(cell, "U"));
|
|
45612
|
+
if (actual.value !== cache3.value || actual.unit !== cache3.unit && !(cache3.unit === "scalar" && actual.unit === "length" && !cell.hasAttribute("U")))
|
|
45613
|
+
fail2("EDIT_PROTECTED_CELL", "Formatting formula cache is stale or has incompatible units.");
|
|
45614
|
+
}
|
|
45615
|
+
}
|
|
45616
|
+
|
|
45617
|
+
// visio/edit-style-admission.ts
|
|
45618
|
+
function uniqueFormattingCells(sheet) {
|
|
45619
|
+
const result2 = /* @__PURE__ */ new Map();
|
|
45620
|
+
const seen = /* @__PURE__ */ new Set();
|
|
45621
|
+
for (const cell of children3(sheet, "Cell")) {
|
|
45622
|
+
const name = attribute3(cell, "N");
|
|
45623
|
+
if (!name || seen.has(name.toLowerCase()))
|
|
45624
|
+
fail2("EDIT_AMBIGUOUS_CELL", "Formatting requires unique named cells.");
|
|
45625
|
+
result2.set(name, cell);
|
|
45626
|
+
seen.add(name.toLowerCase());
|
|
45627
|
+
}
|
|
45628
|
+
return result2;
|
|
45629
|
+
}
|
|
45630
|
+
function formattingCell(sheet, name) {
|
|
45631
|
+
const cells3 = uniqueFormattingCells(sheet);
|
|
45632
|
+
if (!cells3.has(name) && [...cells3.keys()].some((key2) => key2.toLowerCase() === name.toLowerCase()))
|
|
45633
|
+
fail2("EDIT_AMBIGUOUS_CELL", "Noncanonical formatting cell names cannot be overridden.");
|
|
45634
|
+
return cells3.get(name);
|
|
45635
|
+
}
|
|
45636
|
+
function namedCell(sheet, name) {
|
|
45637
|
+
const [section, index2, cell] = name.split(".");
|
|
45638
|
+
if (!cell) return formattingCell(sheet, name);
|
|
45639
|
+
const row2 = formattingRow(sheet, section, index2);
|
|
45640
|
+
return row2 ? formattingCell(row2, cell) : void 0;
|
|
45641
|
+
}
|
|
45642
|
+
function categoryEnabled(style2, category) {
|
|
45643
|
+
const name = category === "TextStyle" ? "EnableTextProps" : category === "FillStyle" ? "EnableFillProps" : "EnableLineProps";
|
|
45644
|
+
const cell = formattingCell(style2, name);
|
|
45645
|
+
if (!cell) return true;
|
|
45646
|
+
if (cell.hasAttribute("E") || attribute3(cell, "F") === "Inh")
|
|
45647
|
+
fail2("EDIT_PROTECTED_CELL", "Style category enable state cannot be proven.");
|
|
45648
|
+
const cache3 = visioFormulaCachedValue(attribute3(cell, "V") ?? "", attribute3(cell, "U"));
|
|
45649
|
+
if (cache3.unit !== "scalar" || ![0, 1].includes(cache3.value))
|
|
45650
|
+
fail2("EDIT_PROTECTED_CELL", "Style category enable state must be a scalar boolean.");
|
|
45651
|
+
const source2 = executableCellFormula(attribute3(cell, "F"));
|
|
45652
|
+
if (source2) {
|
|
45653
|
+
const analysis = analyzeVisioFormula(source2);
|
|
45654
|
+
if (analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length)
|
|
45655
|
+
fail2("EDIT_PROTECTED_CELL", "Style category enable formula cannot be resolved safely.");
|
|
45656
|
+
const result2 = evaluateVisioFormula(
|
|
45657
|
+
source2,
|
|
45658
|
+
() => fail2("EDIT_PROTECTED_CELL", "Style category enable dependencies are unsupported.")
|
|
45659
|
+
);
|
|
45660
|
+
if (result2.unit !== "scalar" || result2.value !== cache3.value)
|
|
45661
|
+
fail2("EDIT_PROTECTED_CELL", "Style category enable formula cache is stale.");
|
|
45662
|
+
}
|
|
45663
|
+
return cache3.value !== 0;
|
|
45664
|
+
}
|
|
45665
|
+
function formattingStyles(shape2, document, category, gate) {
|
|
45666
|
+
const styles = /* @__PURE__ */ new Map();
|
|
45667
|
+
for (const container of children3(document, "StyleSheets"))
|
|
45668
|
+
for (const style2 of children3(container, "StyleSheet")) {
|
|
45669
|
+
const id2 = attribute3(style2, "ID");
|
|
45670
|
+
if (!id2 || styles.has(id2)) fail2("EDIT_PROTECTED_CELL", "Ambiguous formatting style IDs.");
|
|
45671
|
+
styles.set(id2, style2);
|
|
45672
|
+
}
|
|
45673
|
+
const sheets = children3(document, "DocumentSheet");
|
|
45674
|
+
if (sheets.length > 1) fail2("EDIT_PROTECTED_CELL", "Ambiguous document formatting defaults.");
|
|
45675
|
+
let id = attribute3(shape2, category) ?? attribute3(sheets[0], category) ?? (styles.has("0") ? "0" : void 0);
|
|
45676
|
+
const seen = /* @__PURE__ */ new Set();
|
|
45677
|
+
const result2 = [];
|
|
45678
|
+
while (id !== void 0) {
|
|
45679
|
+
if (seen.has(id) || seen.size >= 64)
|
|
45680
|
+
fail2("EDIT_PROTECTED_CELL", "Formatting style ancestry is cyclic or too deep.");
|
|
45681
|
+
seen.add(id);
|
|
45682
|
+
const style2 = styles.get(id);
|
|
45683
|
+
if (!style2) fail2("EDIT_PROTECTED_CELL", "Formatting style ancestry cannot be resolved.");
|
|
45684
|
+
if (gate && !categoryEnabled(style2, category)) break;
|
|
45685
|
+
result2.push(style2);
|
|
45686
|
+
const parent = attribute3(style2, category);
|
|
45687
|
+
id = parent !== id ? parent : void 0;
|
|
45688
|
+
}
|
|
45689
|
+
return result2;
|
|
45690
|
+
}
|
|
45691
|
+
function effectiveFormattingRows(shape2, document, section) {
|
|
45692
|
+
let result2 = /* @__PURE__ */ new Map();
|
|
45693
|
+
for (const style2 of formattingStyles(shape2, document, "TextStyle", true).reverse())
|
|
45694
|
+
result2 = mergeFormattingRows(result2, style2, section, uniqueFormattingCells);
|
|
45695
|
+
return mergeFormattingRows(result2, shape2, section, uniqueFormattingCells);
|
|
45696
|
+
}
|
|
45697
|
+
function formattingRowContext(shape2, document, section) {
|
|
45698
|
+
return {
|
|
45699
|
+
source: effectiveFormattingRows(shape2, document, section),
|
|
45700
|
+
local: formattingRows(shape2, section)
|
|
45701
|
+
};
|
|
45702
|
+
}
|
|
45703
|
+
function effectiveShapeCell(shape2, document, name, category, rows) {
|
|
45704
|
+
const [section, index2, cellName] = name.split(".");
|
|
45705
|
+
const localRow = rows?.local.get(index2);
|
|
45706
|
+
const local = rows ? localRow ? formattingCell(localRow, cellName) : void 0 : namedCell(shape2, name);
|
|
45707
|
+
const delegatedLocal = local && attribute3(local, "F") === "Inh";
|
|
45708
|
+
if (delegatedLocal && !(category === "TextStyle" && cellName && ["Character", "Paragraph"].includes(section)))
|
|
45709
|
+
fail2("EDIT_PROTECTED_CELL", "Inherited formatting cells cannot be overwritten.");
|
|
45710
|
+
if (local && !cellName) return local;
|
|
45711
|
+
if (cellName) {
|
|
45712
|
+
const sources = rows?.source ?? effectiveFormattingRows(shape2, document, section);
|
|
45713
|
+
const cells3 = sources.get(index2) ?? sources.get("0");
|
|
45714
|
+
if (cells3 && !cells3.has(cellName) && [...cells3.keys()].some((key2) => key2.toLowerCase() === cellName.toLowerCase()))
|
|
45715
|
+
fail2("EDIT_AMBIGUOUS_CELL", "Noncanonical formatting cell names cannot be overridden.");
|
|
45716
|
+
const effective = delegatedFormattingCell(cells3?.get(cellName));
|
|
45717
|
+
if (delegatedLocal) {
|
|
45718
|
+
if (!effective)
|
|
45719
|
+
fail2(
|
|
45720
|
+
"EDIT_PROTECTED_CELL",
|
|
45721
|
+
"Inherited formatting cannot be overwritten without a proven ancestor."
|
|
45722
|
+
);
|
|
45723
|
+
if (!local.hasAttribute("V") && local.hasAttribute("U") && visioFormulaCachedValue("0", attribute3(local, "U")).unit !== visioFormulaCachedValue("0", attribute3(effective, "U")).unit)
|
|
45724
|
+
fail2("EDIT_PROTECTED_CELL", "Inherited formatting has incompatible local units.");
|
|
45725
|
+
}
|
|
45726
|
+
return effective;
|
|
45727
|
+
}
|
|
45728
|
+
for (const style2 of formattingStyles(
|
|
45729
|
+
shape2,
|
|
45730
|
+
document,
|
|
45731
|
+
category,
|
|
45732
|
+
!/^(Lock|LayerMember$|DisplayLevel$)/.test(name)
|
|
45733
|
+
)) {
|
|
45734
|
+
const cell = namedCell(style2, name);
|
|
45735
|
+
if (cell && attribute3(cell, "F") !== "Inh") return cell;
|
|
45736
|
+
if (cell && (!attribute3(style2, category) || attribute3(style2, category) === attribute3(style2, "ID")))
|
|
45737
|
+
fail2("EDIT_PROTECTED_CELL", "Delegated formatting has no explicit ancestor.");
|
|
45738
|
+
}
|
|
45739
|
+
return void 0;
|
|
45740
|
+
}
|
|
45741
|
+
function assertShapeLocks(shape2, document, locks2) {
|
|
45742
|
+
const inheritedShape = shape2.cloneNode(true);
|
|
45743
|
+
for (const cell of children3(inheritedShape, "Cell"))
|
|
45744
|
+
if (locks2.includes(attribute3(cell, "N") ?? "")) inheritedShape.removeChild(cell);
|
|
45745
|
+
for (const lock of locks2)
|
|
45746
|
+
for (const [target, category] of [
|
|
45747
|
+
[shape2, "LineStyle"],
|
|
45748
|
+
[inheritedShape, "LineStyle"],
|
|
45749
|
+
[inheritedShape, "FillStyle"],
|
|
45750
|
+
[inheritedShape, "TextStyle"]
|
|
45751
|
+
]) {
|
|
45752
|
+
const cell = effectiveShapeCell(target, document, lock, category);
|
|
45753
|
+
if (!cell) continue;
|
|
45754
|
+
if (cell.hasAttribute("E"))
|
|
45755
|
+
fail2("EDIT_PROTECTED_CELL", "Formatting protection has an error.");
|
|
45756
|
+
const cached3 = visioFormulaCachedValue(attribute3(cell, "V") ?? "", attribute3(cell, "U"));
|
|
45757
|
+
if (cached3.unit !== "scalar" || cached3.value !== 0)
|
|
45758
|
+
fail2("EDIT_PROTECTED_CELL", "Formatting protection is active or invalid.");
|
|
45759
|
+
const formula = executableCellFormula(attribute3(cell, "F"));
|
|
45760
|
+
if (!formula) continue;
|
|
45761
|
+
const analysis = analyzeVisioFormula(formula);
|
|
45762
|
+
if (analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length)
|
|
45763
|
+
fail2("EDIT_PROTECTED_CELL", "Formatting protection formula cannot be proven safe.");
|
|
45764
|
+
const value = evaluateVisioFormula(
|
|
45765
|
+
formula,
|
|
45766
|
+
() => fail2("EDIT_PROTECTED_CELL", "Formatting lock dependency is unsupported.")
|
|
45767
|
+
);
|
|
45768
|
+
if (value.unit !== "scalar" || value.value !== cached3.value)
|
|
45769
|
+
fail2("EDIT_PROTECTED_CELL", "Formatting protection cache is stale.");
|
|
45770
|
+
}
|
|
45771
|
+
}
|
|
45772
|
+
function assertUnlayeredShape(shape2, document) {
|
|
45773
|
+
for (const category of ["LineStyle", "FillStyle", "TextStyle"]) {
|
|
45774
|
+
const cell = effectiveShapeCell(shape2, document, "LayerMember", category);
|
|
45775
|
+
if (!cell) continue;
|
|
45776
|
+
if (attribute3(cell, "V") !== "" || cell.hasAttribute("E") || executableCellFormula(attribute3(cell, "F")))
|
|
45777
|
+
fail2(
|
|
45778
|
+
"UNSUPPORTED_FORMAT_EDIT",
|
|
45779
|
+
"Layered or unresolved layer membership is not yet supported."
|
|
45780
|
+
);
|
|
45781
|
+
}
|
|
45782
|
+
}
|
|
45783
|
+
|
|
45784
|
+
// visio/edit-text.ts
|
|
45785
|
+
async function replacePlainText(root, document, shapeId, text2, check3, assertDependencies) {
|
|
45786
|
+
const shapeChildren = (parent) => {
|
|
45787
|
+
const containers = children3(parent, "Shapes");
|
|
45788
|
+
if (containers.length > 1)
|
|
45789
|
+
fail2("INVALID_SHAPE_ID", "Duplicate Shapes containers are ambiguous.");
|
|
45790
|
+
return children3(containers[0], "Shape");
|
|
45791
|
+
};
|
|
45792
|
+
const shapes = /* @__PURE__ */ new Map();
|
|
45793
|
+
const pending2 = shapeChildren(root).map((node2) => ({
|
|
45794
|
+
node: node2,
|
|
45795
|
+
inherited: false,
|
|
45796
|
+
deleted: false
|
|
45797
|
+
}));
|
|
45798
|
+
while (pending2.length) {
|
|
45799
|
+
check3();
|
|
45800
|
+
const item = pending2.pop();
|
|
45801
|
+
const id = attribute3(item.node, "ID");
|
|
45802
|
+
if (!id || shapes.has(id))
|
|
45803
|
+
fail2("INVALID_SHAPE_ID", "Local shape IDs must be present and unique.");
|
|
45804
|
+
const inherited = item.inherited || item.node.hasAttribute("Master") || item.node.hasAttribute("MasterShape");
|
|
45805
|
+
const deleted = item.deleted || ["1", "true"].includes(attribute3(item.node, "Del") ?? "");
|
|
45806
|
+
shapes.set(id, { node: item.node, inherited, deleted });
|
|
45807
|
+
for (const node2 of shapeChildren(item.node)) pending2.push({ node: node2, inherited, deleted });
|
|
45808
|
+
}
|
|
45809
|
+
const target = shapes.get(shapeId);
|
|
45810
|
+
if (!target) fail2("EDIT_TARGET_NOT_FOUND", "Local shape does not exist.");
|
|
45811
|
+
if (target.inherited || target.deleted)
|
|
45812
|
+
fail2("UNSUPPORTED_TEXT_EDIT", "Master-linked or deleted shapes cannot be edited.");
|
|
45813
|
+
assertShapeLocks(target.node, document, ["LockTextEdit"]);
|
|
45814
|
+
const texts = children3(target.node, "Text");
|
|
45815
|
+
if (texts.length !== 1)
|
|
45816
|
+
fail2("UNSUPPORTED_TEXT_EDIT", "Editing requires one existing local Text element.");
|
|
45817
|
+
const node = texts[0];
|
|
45818
|
+
if (Array.from(node.childNodes).some((item) => item.nodeType !== 3 && item.nodeType !== 4))
|
|
45819
|
+
fail2("UNSUPPORTED_TEXT_EDIT", "Rich text, fields and unknown text markup cannot be edited.");
|
|
45820
|
+
if (children3(target.node, "Section").some((section) => attribute3(section, "N") === "Field"))
|
|
45821
|
+
fail2("UNSUPPORTED_TEXT_EDIT", "Shapes with text fields cannot be edited.");
|
|
45822
|
+
if (decodeVisioPlainText(node.textContent ?? "") === text2) return false;
|
|
45823
|
+
await assertDependencies(target.node, node);
|
|
45824
|
+
check3();
|
|
45825
|
+
while (node.firstChild) node.removeChild(node.firstChild);
|
|
45826
|
+
node.appendChild(node.ownerDocument.createTextNode(encodeVisioPlainText(text2)));
|
|
45827
|
+
return true;
|
|
45828
|
+
}
|
|
45829
|
+
function serializeEditedXml(root, limits, check3) {
|
|
45830
|
+
check3();
|
|
45831
|
+
const pending2 = [root.ownerDocument];
|
|
45832
|
+
while (pending2.length) {
|
|
45833
|
+
check3();
|
|
45834
|
+
const node = pending2.pop();
|
|
45835
|
+
if ((node.nodeType === 3 || node.nodeType === 4) && node.nodeValue?.includes("\r"))
|
|
45836
|
+
fail2("UNSUPPORTED_XML_EDIT", "Carriage-return text cannot be preserved by this writer.");
|
|
45837
|
+
if (node.nodeType === 1) {
|
|
45838
|
+
for (const attr3 of Array.from(node.attributes))
|
|
45839
|
+
if (/[\t\r\n]/.test(attr3.value))
|
|
45840
|
+
fail2("UNSUPPORTED_XML_EDIT", "Attribute whitespace cannot be preserved by this writer.");
|
|
45841
|
+
}
|
|
45842
|
+
for (const child6 of Array.from(node.childNodes)) pending2.push(child6);
|
|
45843
|
+
}
|
|
45844
|
+
let xml = buildXml(root.ownerDocument);
|
|
45845
|
+
xml = xml.replace(
|
|
45846
|
+
/^<\?xml\s[^?]*\?>/,
|
|
45847
|
+
(declaration) => declaration.replace(/encoding\s*=\s*(['"])[^'"]*\1/, 'encoding="UTF-8"')
|
|
45848
|
+
);
|
|
45849
|
+
const nodes = inspectXml(xml, limits, check3);
|
|
45850
|
+
inspectNamespaces(root, check3);
|
|
45851
|
+
const bytes = new TextEncoder().encode(xml);
|
|
45852
|
+
if (bytes.length > limits.maxEntryBytes)
|
|
45853
|
+
fail2("LIMIT_ENTRY", "Edited XML part exceeds byte limit.");
|
|
45854
|
+
return { bytes, nodes };
|
|
45855
|
+
}
|
|
45856
|
+
|
|
45857
|
+
// visio/edit-formatting-scope.ts
|
|
45858
|
+
async function assertFormattingDependencies(pkg, pagePaths, roots, pageId, shape2, changed, check3) {
|
|
45859
|
+
indexCells(roots, { check: check3 });
|
|
45860
|
+
const shapeId = attribute3(shape2, "ID");
|
|
45861
|
+
const changedNames = new Set([...changed.keys()].map((name) => name.toLowerCase()));
|
|
45862
|
+
const canonical = (name) => name.toLowerCase().replace(/^char\.([a-z]+)$/, "character.0.$1").replace(/^para\.([a-z]+)$/, "paragraph.0.$1");
|
|
45863
|
+
const replaced = new Set(changed.values());
|
|
45864
|
+
const inspect2 = (root, sourcePageId) => {
|
|
45865
|
+
for (const node of [root, ...Array.from(root.getElementsByTagName("*"))]) {
|
|
45866
|
+
check3();
|
|
45867
|
+
if (![VISIO_NS, VISIO_LEGACY_NS].includes(node.namespaceURI ?? "") || replaced.has(node))
|
|
45868
|
+
continue;
|
|
45869
|
+
const source2 = executableCellFormula(attribute3(node, "F"));
|
|
45870
|
+
if (!source2 || inertDoubleClickFormula(attribute3(node, "N") ?? "", source2)) continue;
|
|
45871
|
+
let localShapeId;
|
|
45872
|
+
let parent = node;
|
|
45873
|
+
while (parent?.nodeType === 1) {
|
|
45874
|
+
if (parent.localName === "Shape") {
|
|
45875
|
+
localShapeId = attribute3(parent, "ID");
|
|
45876
|
+
break;
|
|
45877
|
+
}
|
|
45878
|
+
parent = parent.parentNode;
|
|
45879
|
+
}
|
|
45880
|
+
const analysis = analyzeVisioFormula(source2);
|
|
45881
|
+
if (analysis.dynamic || analysis.references.some(
|
|
45882
|
+
(ref) => changedNames.has(canonical(ref.cell)) && (sourcePageId === void 0 || sourcePageId === pageId) && (ref.shapeId === shapeId || ref.shapeId === void 0 && (localShapeId === shapeId || sourcePageId === void 0))
|
|
45883
|
+
))
|
|
45884
|
+
fail2(
|
|
45885
|
+
"EDIT_UNSUPPORTED_FORMAT_DEPENDENCY",
|
|
45886
|
+
"Formatting has affected or unknown formula dependencies; dependent caches cannot be recalculated safely."
|
|
45887
|
+
);
|
|
45888
|
+
}
|
|
45889
|
+
};
|
|
45890
|
+
for (const [id, root] of roots) inspect2(root, id);
|
|
45891
|
+
for (const path2 of pkg.paths()) {
|
|
45892
|
+
if (!/^visio\/.*\.xml$/i.test(path2) || pagePaths.has(path2)) continue;
|
|
45893
|
+
inspect2(await pkg.readXml(path2));
|
|
45894
|
+
}
|
|
45895
|
+
}
|
|
45896
|
+
|
|
45897
|
+
// visio/edit-text-scope.ts
|
|
45898
|
+
function replaceScopedPlainText(pkg, pagePaths, roots, document, edit, check3) {
|
|
45899
|
+
return replacePlainText(
|
|
45900
|
+
roots.get(edit.pageId),
|
|
45901
|
+
document,
|
|
45902
|
+
edit.shapeId,
|
|
45903
|
+
edit.text,
|
|
45904
|
+
check3,
|
|
45905
|
+
(shape2, text2) => assertFormattingDependencies(
|
|
45906
|
+
pkg,
|
|
45907
|
+
pagePaths,
|
|
45908
|
+
roots,
|
|
45909
|
+
edit.pageId,
|
|
45910
|
+
shape2,
|
|
45911
|
+
/* @__PURE__ */ new Map([["TheText", text2]]),
|
|
45912
|
+
check3
|
|
45913
|
+
)
|
|
45914
|
+
);
|
|
45915
|
+
}
|
|
45916
|
+
|
|
45917
|
+
// visio/resize-anchor.ts
|
|
45918
|
+
function snapshotResizeAnchor(value) {
|
|
45919
|
+
if (value === void 0) return void 0;
|
|
45920
|
+
if (!value || typeof value !== "object") fail2("INVALID_EDIT", "Invalid resize anchor.");
|
|
45921
|
+
const { x, y } = value;
|
|
45922
|
+
if (![0, 0.5, 1].includes(x) || ![0, 0.5, 1].includes(y))
|
|
45923
|
+
fail2("INVALID_EDIT", "Resize anchor coordinates must be 0, 0.5 or 1.");
|
|
45924
|
+
return { x, y };
|
|
45925
|
+
}
|
|
45926
|
+
function visioAnchoredResizeGeometry(current, size, anchor) {
|
|
45927
|
+
const [a2, b, c2, d, e, f6] = current.transform;
|
|
45928
|
+
const determinant = a2 * d - b * c2;
|
|
45929
|
+
if (![0, 0.5, 1].includes(anchor.x) || ![0, 0.5, 1].includes(anchor.y) || ![
|
|
45930
|
+
current.width,
|
|
45931
|
+
current.height,
|
|
45932
|
+
current.pinX,
|
|
45933
|
+
current.pinY,
|
|
45934
|
+
...current.transform,
|
|
45935
|
+
size.width,
|
|
45936
|
+
size.height,
|
|
45937
|
+
anchor.x,
|
|
45938
|
+
anchor.y
|
|
45939
|
+
].every(Number.isFinite) || !(current.width > 0 && current.height > 0 && size.width > 0 && size.height > 0) || Math.abs(Math.abs(determinant) - 1) > 1e-8 || Math.abs(a2 * a2 + b * b - 1) > 1e-8 || Math.abs(c2 * c2 + d * d - 1) > 1e-8 || Math.abs(a2 * c2 + b * d) > 1e-8)
|
|
45940
|
+
return void 0;
|
|
45941
|
+
const offsetX = current.pinX - e, offsetY = current.pinY - f6;
|
|
45942
|
+
const oldX = (d * offsetX - c2 * offsetY) / determinant;
|
|
45943
|
+
const oldY = (-b * offsetX + a2 * offsetY) / determinant;
|
|
45944
|
+
const locPinX = oldX / current.width * size.width, locPinY = oldY / current.height * size.height;
|
|
45945
|
+
const deltaX = anchor.x * (current.width - size.width) - oldX + locPinX;
|
|
45946
|
+
const deltaY = anchor.y * (current.height - size.height) - oldY + locPinY;
|
|
45947
|
+
const pinX = current.pinX + a2 * deltaX + c2 * deltaY, pinY = current.pinY + b * deltaX + d * deltaY;
|
|
45948
|
+
const matrix3 = [
|
|
45949
|
+
a2,
|
|
45950
|
+
b,
|
|
45951
|
+
c2,
|
|
45952
|
+
d,
|
|
45953
|
+
pinX - a2 * locPinX - c2 * locPinY,
|
|
45954
|
+
pinY - b * locPinX - d * locPinY
|
|
45955
|
+
];
|
|
45956
|
+
return [pinX, pinY, locPinX, locPinY, ...matrix3].every(Number.isFinite) ? { pinX, pinY, locPinX, locPinY, transform: matrix3 } : void 0;
|
|
45957
|
+
}
|
|
45958
|
+
|
|
45959
|
+
// visio/edit-duplicate-commands.ts
|
|
45960
|
+
function snapshotDuplicateShapes(edit) {
|
|
45961
|
+
if (!Array.isArray(edit.copies) || !edit.copies.length || edit.copies.length > 1e3)
|
|
45962
|
+
fail2("INVALID_EDIT", "Duplication requires between one and 1000 shape mappings.");
|
|
45963
|
+
if ([edit.offsetX, edit.offsetY].some(
|
|
45964
|
+
(value) => typeof value !== "number" || !Number.isFinite(value) || Math.abs(value) > 1e6
|
|
45965
|
+
))
|
|
45966
|
+
fail2("INVALID_EDIT", "Duplication offsets require bounded finite drawing inches.");
|
|
45967
|
+
const sources = /* @__PURE__ */ new Set(), targets = /* @__PURE__ */ new Set();
|
|
45968
|
+
const id = (value) => {
|
|
45969
|
+
if (typeof value !== "string" || !/^(0|[1-9]\d{0,9})$/.test(value) || Number(value) > 4294967295)
|
|
45970
|
+
fail2("INVALID_EDIT", "Duplicate shape IDs require canonical unsigned integers.");
|
|
45971
|
+
return value;
|
|
45972
|
+
};
|
|
45973
|
+
const copies = edit.copies.map((copy2) => {
|
|
45974
|
+
if (!copy2 || typeof copy2 !== "object") fail2("INVALID_EDIT", "Invalid duplicate shape mapping.");
|
|
45975
|
+
const shapeId = id(copy2.shapeId), newShapeId = id(copy2.newShapeId);
|
|
45976
|
+
if (sources.has(shapeId) || targets.has(newShapeId))
|
|
45977
|
+
fail2("INVALID_EDIT", "Duplicate shape mappings must have unique sources and targets.");
|
|
45978
|
+
sources.add(shapeId);
|
|
45979
|
+
targets.add(newShapeId);
|
|
45980
|
+
return { shapeId, newShapeId };
|
|
45981
|
+
});
|
|
45982
|
+
return {
|
|
45983
|
+
type: edit.type,
|
|
45984
|
+
pageId: edit.pageId,
|
|
45985
|
+
copies,
|
|
45986
|
+
offsetX: edit.offsetX,
|
|
45987
|
+
offsetY: edit.offsetY
|
|
45988
|
+
};
|
|
45989
|
+
}
|
|
45990
|
+
|
|
45991
|
+
// visio/clipboard-types.ts
|
|
45992
|
+
var VISIO_CLIPBOARD_MAX_CHARS = 8 * 1024 * 1024;
|
|
45993
|
+
function clipboardId(value) {
|
|
45994
|
+
if (typeof value !== "string" || !/^(0|[1-9]\d{0,9})$/.test(value) || Number(value) > 4294967295)
|
|
45995
|
+
fail2("INVALID_CLIPBOARD", "Clipboard IDs require canonical unsigned integers.");
|
|
45996
|
+
return value;
|
|
45997
|
+
}
|
|
45998
|
+
function snapshotVisioClipboard(value) {
|
|
45999
|
+
if (!value || typeof value !== "object" || value.format !== "ooxml.visio-shapes" || value.version !== 1)
|
|
46000
|
+
fail2("INVALID_CLIPBOARD", "Unsupported Visio clipboard format or version.");
|
|
46001
|
+
const sourcePageId = clipboardId(value.sourcePageId), sourceDrawingScale = value.sourceDrawingScale;
|
|
46002
|
+
if (!Number.isFinite(sourceDrawingScale) || sourceDrawingScale <= 0 || sourceDrawingScale > 1e6)
|
|
46003
|
+
fail2("INVALID_CLIPBOARD", "Invalid clipboard drawing ratio.");
|
|
46004
|
+
let characters = 0;
|
|
46005
|
+
const text2 = (input) => {
|
|
46006
|
+
if (typeof input !== "string" || (characters += input.length) > VISIO_CLIPBOARD_MAX_CHARS)
|
|
46007
|
+
fail2("LIMIT_CLIPBOARD", "Clipboard XML exceeds bounded text limits.");
|
|
46008
|
+
if (/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/.test(input))
|
|
46009
|
+
fail2("INVALID_CLIPBOARD", "Clipboard XML must contain well-formed Unicode.");
|
|
46010
|
+
return input;
|
|
46011
|
+
};
|
|
46012
|
+
const list = (input, max) => {
|
|
46013
|
+
if (!Array.isArray(input) || !input.length || input.length > max)
|
|
46014
|
+
fail2("INVALID_CLIPBOARD", "Invalid clipboard array length.");
|
|
46015
|
+
return input;
|
|
46016
|
+
};
|
|
46017
|
+
const selectionIds = list(value.selectionIds, 1e3).map(clipboardId);
|
|
46018
|
+
const shapes = list(value.shapes, 1e3).map((shape2) => {
|
|
46019
|
+
if (!shape2 || typeof shape2 !== "object") fail2("INVALID_CLIPBOARD", "Invalid captured shape.");
|
|
46020
|
+
return { shapeId: clipboardId(shape2.shapeId), xml: text2(shape2.xml) };
|
|
46021
|
+
});
|
|
46022
|
+
const resources = list(value.resources, 64).map((resource) => {
|
|
46023
|
+
const path2 = resource?.path;
|
|
46024
|
+
if (!resource || typeof resource !== "object" || typeof path2 !== "string" || path2.length > 1024 || !/^visio\/(?:document\.xml|_rels\/document\.xml\.rels|theme\/[^/]+\.(?:xml|rels)|theme\/_rels\/[^/]+\.rels)$/.test(
|
|
46025
|
+
path2
|
|
46026
|
+
))
|
|
46027
|
+
fail2("INVALID_CLIPBOARD", "Invalid clipboard resource path.");
|
|
46028
|
+
return { path: text2(safePath(path2)), xml: text2(resource.xml) };
|
|
46029
|
+
});
|
|
46030
|
+
if (new Set(selectionIds).size !== selectionIds.length || new Set(shapes.map((shape2) => shape2.shapeId)).size !== shapes.length || selectionIds.length !== shapes.length || selectionIds.some((id) => !shapes.some((shape2) => shape2.shapeId === id)) || new Set(resources.map((resource) => resource.path)).size !== resources.length)
|
|
46031
|
+
fail2("INVALID_CLIPBOARD", "Clipboard mappings and resources must be unique and complete.");
|
|
46032
|
+
return {
|
|
46033
|
+
format: "ooxml.visio-shapes",
|
|
46034
|
+
version: 1,
|
|
46035
|
+
sourcePageId,
|
|
46036
|
+
sourceDrawingScale,
|
|
46037
|
+
selectionIds,
|
|
46038
|
+
shapes,
|
|
46039
|
+
resources: resources.sort((a2, b) => a2.path.localeCompare(b.path)),
|
|
46040
|
+
pageContext: text2(value.pageContext)
|
|
46041
|
+
};
|
|
46042
|
+
}
|
|
46043
|
+
|
|
46044
|
+
// visio/edit-paste-commands.ts
|
|
46045
|
+
function snapshotPasteShapes(edit) {
|
|
46046
|
+
const clipboard = snapshotVisioClipboard(edit.clipboard);
|
|
46047
|
+
const copies = snapshotDuplicateShapes({
|
|
46048
|
+
type: "duplicate-shapes",
|
|
46049
|
+
pageId: edit.pageId,
|
|
46050
|
+
copies: edit.copies,
|
|
46051
|
+
offsetX: edit.offsetX,
|
|
46052
|
+
offsetY: edit.offsetY
|
|
46053
|
+
});
|
|
46054
|
+
if (copies.copies.length !== clipboard.shapes.length || copies.copies.some((copy2) => !clipboard.selectionIds.includes(copy2.shapeId)))
|
|
46055
|
+
fail2("INVALID_CLIPBOARD", "Paste mappings must cover every captured shape exactly once.");
|
|
46056
|
+
return {
|
|
46057
|
+
type: "paste-shapes",
|
|
46058
|
+
pageId: copies.pageId,
|
|
46059
|
+
copies: copies.copies,
|
|
46060
|
+
offsetX: copies.offsetX,
|
|
46061
|
+
offsetY: copies.offsetY,
|
|
46062
|
+
clipboard
|
|
46063
|
+
};
|
|
46064
|
+
}
|
|
46065
|
+
|
|
46066
|
+
// visio/edit-formatting-commands.ts
|
|
46067
|
+
var isVisioFormatEdit = (edit) => edit.type === "format-text" || edit.type === "format-shape";
|
|
46068
|
+
function snapshotFormatting(edit) {
|
|
46069
|
+
const result2 = { type: edit.type, pageId: edit.pageId, shapeId: edit.shapeId };
|
|
46070
|
+
const points = (value, minimum, maximum) => {
|
|
46071
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < minimum || value > maximum)
|
|
46072
|
+
fail2("INVALID_EDIT", "Formatting point size is outside supported limits.");
|
|
46073
|
+
return value;
|
|
46074
|
+
};
|
|
46075
|
+
const color2 = (value, allowNone = false) => {
|
|
46076
|
+
if (typeof value !== "string" || !(allowNone && value === "none") && !/^#[0-9a-f]{6}$/i.test(value))
|
|
46077
|
+
fail2("INVALID_EDIT", "Formatting colors require six hexadecimal digits.");
|
|
46078
|
+
return value.toLowerCase();
|
|
46079
|
+
};
|
|
46080
|
+
if (edit.type === "format-text" && result2.type === "format-text") {
|
|
46081
|
+
if (edit.fontSize !== void 0) result2.fontSize = points(edit.fontSize, 1, 1e3);
|
|
46082
|
+
if (edit.fontColor !== void 0) result2.fontColor = color2(edit.fontColor);
|
|
46083
|
+
if (edit.indentLeft !== void 0) result2.indentLeft = points(edit.indentLeft, 0, 7200);
|
|
46084
|
+
if (edit.fontFamily !== void 0) {
|
|
46085
|
+
if (typeof edit.fontFamily !== "string" || !edit.fontFamily.trim() || edit.fontFamily.length > 256 || /[\u0000-\u001f\u007f]/.test(edit.fontFamily))
|
|
46086
|
+
fail2("INVALID_EDIT", "Invalid font family.");
|
|
46087
|
+
result2.fontFamily = edit.fontFamily;
|
|
46088
|
+
}
|
|
46089
|
+
for (const name of ["bold", "italic", "underline", "strikethrough", "bullets"]) {
|
|
46090
|
+
if (edit[name] === void 0) continue;
|
|
46091
|
+
if (typeof edit[name] !== "boolean") fail2("INVALID_EDIT", "Text styles require booleans.");
|
|
46092
|
+
result2[name] = edit[name];
|
|
46093
|
+
}
|
|
46094
|
+
if (edit.horizontalAlign !== void 0) {
|
|
46095
|
+
if (!["left", "center", "right", "justify"].includes(edit.horizontalAlign))
|
|
46096
|
+
fail2("INVALID_EDIT", "Invalid horizontal alignment.");
|
|
46097
|
+
result2.horizontalAlign = edit.horizontalAlign;
|
|
46098
|
+
}
|
|
46099
|
+
if (edit.verticalAlign !== void 0) {
|
|
46100
|
+
if (!["top", "middle", "bottom"].includes(edit.verticalAlign))
|
|
46101
|
+
fail2("INVALID_EDIT", "Invalid vertical alignment.");
|
|
46102
|
+
result2.verticalAlign = edit.verticalAlign;
|
|
46103
|
+
}
|
|
46104
|
+
} else if (edit.type === "format-shape" && result2.type === "format-shape") {
|
|
46105
|
+
if (edit.fillColor !== void 0) result2.fillColor = color2(edit.fillColor, true);
|
|
46106
|
+
if (edit.lineColor !== void 0) result2.lineColor = color2(edit.lineColor);
|
|
46107
|
+
if (edit.lineWeight !== void 0) result2.lineWeight = points(edit.lineWeight, 0, 100);
|
|
46108
|
+
for (const [name, maximum] of [
|
|
46109
|
+
["linePattern", 23],
|
|
46110
|
+
["fillPattern", 24]
|
|
46111
|
+
]) {
|
|
46112
|
+
if (edit[name] === void 0) continue;
|
|
46113
|
+
const value = points(edit[name], 0, maximum);
|
|
46114
|
+
if (!Number.isInteger(value)) fail2("INVALID_EDIT", "Paint patterns require integers.");
|
|
46115
|
+
result2[name] = value;
|
|
46116
|
+
}
|
|
46117
|
+
for (const name of ["lineTransparency", "fillTransparency"])
|
|
46118
|
+
if (edit[name] !== void 0) result2[name] = Math.round(points(edit[name], 0, 100) * 2) / 2;
|
|
46119
|
+
if (edit.fillBackgroundColor !== void 0)
|
|
46120
|
+
result2.fillBackgroundColor = color2(edit.fillBackgroundColor);
|
|
46121
|
+
if (result2.fillColor === "none" && result2.fillPattern !== void 0 && result2.fillPattern !== 0)
|
|
46122
|
+
fail2("INVALID_EDIT", "No fill conflicts with a visible fill pattern.");
|
|
46123
|
+
}
|
|
46124
|
+
if (Object.keys(result2).length === 3)
|
|
46125
|
+
fail2("INVALID_EDIT", "Formatting requires at least one property.");
|
|
46126
|
+
return result2;
|
|
46127
|
+
}
|
|
46128
|
+
|
|
46129
|
+
// visio/edit-commands.ts
|
|
46130
|
+
var isVisioPageEdit = (edit) => edit.type === "insert-page" || edit.type === "reorder-page" || edit.type === "rename-page" || edit.type === "delete-page";
|
|
46131
|
+
function geometryChangedCells(edit) {
|
|
46132
|
+
if (edit.type === "create-line")
|
|
46133
|
+
return [
|
|
46134
|
+
"BeginX",
|
|
46135
|
+
"BeginY",
|
|
46136
|
+
"EndX",
|
|
46137
|
+
"EndY",
|
|
46138
|
+
"PinX",
|
|
46139
|
+
"PinY",
|
|
46140
|
+
"Width",
|
|
46141
|
+
"Height",
|
|
46142
|
+
"Angle",
|
|
46143
|
+
"LocPinX",
|
|
46144
|
+
"LocPinY"
|
|
46145
|
+
];
|
|
46146
|
+
if (edit.type === "delete-shape") return [];
|
|
46147
|
+
if (edit.type === "create-text-box")
|
|
46148
|
+
return ["PinX", "PinY", "Width", "Height", "LinePattern", "FillPattern"];
|
|
46149
|
+
if (edit.type === "move-line-endpoint") {
|
|
46150
|
+
const prefix = edit.endpoint === "begin" ? "Begin" : "End";
|
|
46151
|
+
return [`${prefix}X`, `${prefix}Y`];
|
|
46152
|
+
}
|
|
46153
|
+
if (edit.type === "move-shape") return ["PinX", "PinY"];
|
|
46154
|
+
if (edit.type === "resize-shape")
|
|
46155
|
+
return edit.anchor ? ["Width", "Height", "PinX", "PinY", "LocPinX", "LocPinY"] : ["Width", "Height"];
|
|
46156
|
+
if (edit.type === "rotate-shape") return ["Angle"];
|
|
46157
|
+
if (edit.type === "flip-shape") return ["Angle", edit.axis === "horizontal" ? "FlipX" : "FlipY"];
|
|
46158
|
+
return ["PinX", "PinY", "Width", "Height"];
|
|
46159
|
+
}
|
|
46160
|
+
function snapshotVisioEdits(edits, maxEdits, maxText) {
|
|
46161
|
+
if (!Array.isArray(edits) || edits.length > maxEdits)
|
|
46162
|
+
fail2("LIMIT_EDITS", "Edit command count exceeds limit.");
|
|
46163
|
+
let textLength = 0;
|
|
46164
|
+
const text2 = (value) => {
|
|
46165
|
+
if (typeof value !== "string") fail2("INVALID_EDIT", "Edit text must be a string.");
|
|
46166
|
+
textLength += value.length;
|
|
46167
|
+
if (textLength > maxText) fail2("LIMIT_EDIT_TEXT", "Replacement text exceeds aggregate limit.");
|
|
46168
|
+
if (/[\u0000-\u0008\u000b\u000c\u000d\u000e-\u001f\ufffe\uffff]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/u.test(
|
|
46169
|
+
value
|
|
46170
|
+
))
|
|
46171
|
+
fail2("INVALID_EDIT_TEXT", "Replacement text contains invalid XML characters.");
|
|
46172
|
+
return value;
|
|
46173
|
+
};
|
|
46174
|
+
const numeric5 = (value, dimension2 = false, allowZero = false) => {
|
|
46175
|
+
if (typeof value !== "number" || !Number.isFinite(value) || Math.abs(value) > 1e6 || dimension2 && (value < 0 || !allowZero && value === 0))
|
|
46176
|
+
fail2(
|
|
46177
|
+
"INVALID_EDIT",
|
|
46178
|
+
"Geometry requires finite drawing inches within limits and positive dimensions."
|
|
46179
|
+
);
|
|
46180
|
+
return value;
|
|
46181
|
+
};
|
|
46182
|
+
return Array.from(edits, (edit) => {
|
|
46183
|
+
if (!edit || typeof edit.pageId !== "string" || !edit.pageId || edit.pageId.length > 256)
|
|
46184
|
+
fail2("INVALID_EDIT", "Invalid edit target.");
|
|
46185
|
+
if (edit.type === "duplicate-shapes") return snapshotDuplicateShapes(edit);
|
|
46186
|
+
if (edit.type === "paste-shapes") return snapshotPasteShapes(edit);
|
|
46187
|
+
if (edit.type === "delete-page") return { type: edit.type, pageId: edit.pageId };
|
|
46188
|
+
if (edit.type === "reorder-page") {
|
|
46189
|
+
if (!Number.isSafeInteger(edit.index) || edit.index < 0 || edit.index > 1e6)
|
|
46190
|
+
fail2("INVALID_EDIT", "Page order requires a bounded zero-based integer index.");
|
|
46191
|
+
return { type: edit.type, pageId: edit.pageId, index: edit.index };
|
|
46192
|
+
}
|
|
46193
|
+
if (edit.type === "insert-page") {
|
|
46194
|
+
const name = text2(edit.name);
|
|
46195
|
+
if (!/^(0|[1-9]\d{0,9})$/.test(edit.pageId) || Number(edit.pageId) > 4294967295 || typeof edit.afterPageId !== "string" || !edit.afterPageId || edit.afterPageId.length > 256 || !name.trim() || name.length > 256 || /[\t\n]/.test(name))
|
|
46196
|
+
fail2("INVALID_EDIT", "Invalid new page ID, name or insertion target.");
|
|
46197
|
+
return { type: edit.type, pageId: edit.pageId, afterPageId: edit.afterPageId, name };
|
|
46198
|
+
}
|
|
46199
|
+
if (edit.type === "rename-page") {
|
|
46200
|
+
const name = text2(edit.name);
|
|
46201
|
+
if (!name.trim() || name.length > 255 || /[\t\n]/.test(name))
|
|
46202
|
+
fail2("INVALID_EDIT", "Invalid page name.");
|
|
46203
|
+
return { type: edit.type, pageId: edit.pageId, name };
|
|
46204
|
+
}
|
|
46205
|
+
if (typeof edit.shapeId !== "string" || !edit.shapeId || edit.shapeId.length > 256)
|
|
46206
|
+
fail2("INVALID_EDIT", "Invalid edit shape target.");
|
|
46207
|
+
const target = { pageId: edit.pageId, shapeId: edit.shapeId };
|
|
46208
|
+
if (edit.type === "replace-plain-text")
|
|
46209
|
+
return { ...target, type: edit.type, text: text2(edit.text) };
|
|
46210
|
+
if (isVisioFormatEdit(edit)) return snapshotFormatting(edit);
|
|
46211
|
+
if (edit.type === "reorder-shape") {
|
|
46212
|
+
if (!["front", "back", "forward", "backward"].includes(edit.order))
|
|
46213
|
+
fail2("INVALID_EDIT", "Invalid shape order.");
|
|
46214
|
+
return { ...target, type: edit.type, order: edit.order };
|
|
46215
|
+
}
|
|
46216
|
+
if (!/^[1-9]\d{0,9}$/.test(edit.shapeId) || Number(edit.shapeId) > 4294967295)
|
|
46217
|
+
fail2("INVALID_EDIT", "Geometry shape IDs must be canonical positive unsigned integers.");
|
|
46218
|
+
switch (edit.type) {
|
|
46219
|
+
case "create-text-box":
|
|
46220
|
+
return {
|
|
46221
|
+
...target,
|
|
46222
|
+
type: edit.type,
|
|
46223
|
+
x: numeric5(edit.x),
|
|
46224
|
+
y: numeric5(edit.y),
|
|
46225
|
+
width: numeric5(edit.width, true),
|
|
46226
|
+
height: numeric5(edit.height, true),
|
|
46227
|
+
text: text2(edit.text)
|
|
46228
|
+
};
|
|
46229
|
+
case "create-line": {
|
|
46230
|
+
const beginX = numeric5(edit.beginX), beginY = numeric5(edit.beginY);
|
|
46231
|
+
const endX = numeric5(edit.endX), endY = numeric5(edit.endY);
|
|
46232
|
+
numeric5(Math.hypot(endX - beginX, endY - beginY), true);
|
|
46233
|
+
return { ...target, type: edit.type, beginX, beginY, endX, endY };
|
|
46234
|
+
}
|
|
46235
|
+
case "create-rectangle":
|
|
46236
|
+
case "create-ellipse":
|
|
46237
|
+
return {
|
|
46238
|
+
...target,
|
|
46239
|
+
type: edit.type,
|
|
46240
|
+
x: numeric5(edit.x),
|
|
46241
|
+
y: numeric5(edit.y),
|
|
46242
|
+
width: numeric5(edit.width, true),
|
|
46243
|
+
height: numeric5(edit.height, true),
|
|
46244
|
+
...edit.text === void 0 ? {} : { text: text2(edit.text) }
|
|
46245
|
+
};
|
|
46246
|
+
case "rotate-shape":
|
|
46247
|
+
return { ...target, type: edit.type, angle: numeric5(edit.angle) };
|
|
46248
|
+
case "flip-shape":
|
|
46249
|
+
if (edit.axis !== "horizontal" && edit.axis !== "vertical")
|
|
46250
|
+
fail2("INVALID_EDIT", "Invalid flip axis.");
|
|
46251
|
+
return { ...target, type: edit.type, axis: edit.axis };
|
|
46252
|
+
case "move-shape":
|
|
46253
|
+
return { ...target, type: edit.type, x: numeric5(edit.x), y: numeric5(edit.y) };
|
|
46254
|
+
case "move-line-endpoint":
|
|
46255
|
+
if (edit.endpoint !== "begin" && edit.endpoint !== "end")
|
|
46256
|
+
fail2("INVALID_EDIT", "A line endpoint must be begin or end.");
|
|
46257
|
+
return {
|
|
46258
|
+
...target,
|
|
46259
|
+
type: edit.type,
|
|
46260
|
+
endpoint: edit.endpoint,
|
|
46261
|
+
x: numeric5(edit.x),
|
|
46262
|
+
y: numeric5(edit.y)
|
|
46263
|
+
};
|
|
46264
|
+
case "resize-shape": {
|
|
46265
|
+
const anchor = snapshotResizeAnchor(edit.anchor);
|
|
46266
|
+
return {
|
|
46267
|
+
...target,
|
|
46268
|
+
type: edit.type,
|
|
46269
|
+
width: numeric5(edit.width, true),
|
|
46270
|
+
height: numeric5(edit.height, true, true),
|
|
46271
|
+
...anchor === void 0 ? {} : { anchor }
|
|
46272
|
+
};
|
|
46273
|
+
}
|
|
46274
|
+
case "delete-shape":
|
|
46275
|
+
return { ...target, type: edit.type };
|
|
46276
|
+
default:
|
|
46277
|
+
return fail2("INVALID_EDIT", "Unsupported edit command.");
|
|
46278
|
+
}
|
|
46279
|
+
});
|
|
46280
|
+
}
|
|
46281
|
+
|
|
44881
46282
|
// visio/edit-group-rotation.ts
|
|
44882
46283
|
function proveLocalGroupRotation(root, edit, check3) {
|
|
44883
46284
|
const groups = /* @__PURE__ */ new Set(), angleCells = /* @__PURE__ */ new Set();
|
|
@@ -44942,6 +46343,238 @@ function proveLocalGroupRotation(root, edit, check3) {
|
|
|
44942
46343
|
return { groups, angleCells };
|
|
44943
46344
|
}
|
|
44944
46345
|
|
|
46346
|
+
// visio/edit-resize-anchor.ts
|
|
46347
|
+
var close = (a2, b) => Math.abs(a2 - b) <= 1e-10 * Math.max(1, Math.abs(a2), Math.abs(b));
|
|
46348
|
+
function closure(graph, changed, check3) {
|
|
46349
|
+
const reverse2 = /* @__PURE__ */ new Map();
|
|
46350
|
+
for (const [id, item] of graph) {
|
|
46351
|
+
check3();
|
|
46352
|
+
for (const dependency of item.dependencies) {
|
|
46353
|
+
const list = reverse2.get(dependency) ?? [];
|
|
46354
|
+
list.push(id);
|
|
46355
|
+
reverse2.set(dependency, list);
|
|
46356
|
+
}
|
|
46357
|
+
}
|
|
46358
|
+
const affected = new Set(changed), pending2 = [...changed];
|
|
46359
|
+
for (let index2 = 0; index2 < pending2.length; index2++) {
|
|
46360
|
+
check3();
|
|
46361
|
+
for (const id of reverse2.get(pending2[index2]) ?? [])
|
|
46362
|
+
if (!affected.has(id)) {
|
|
46363
|
+
affected.add(id);
|
|
46364
|
+
pending2.push(id);
|
|
46365
|
+
}
|
|
46366
|
+
if (affected.size > 1e4)
|
|
46367
|
+
fail2("LIMIT_FORMULA_AFFECTED", "Affected ShapeSheet cell limit exceeded.");
|
|
46368
|
+
}
|
|
46369
|
+
return affected;
|
|
46370
|
+
}
|
|
46371
|
+
function resizeVisioShapeAtAnchor(roots, document, edit, check3) {
|
|
46372
|
+
check3();
|
|
46373
|
+
const root = roots.get(edit.pageId);
|
|
46374
|
+
if (!root) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
|
|
46375
|
+
const shape2 = admitted(root, edit.shapeId);
|
|
46376
|
+
const local = cells(shape2);
|
|
46377
|
+
const canonical = [
|
|
46378
|
+
"Width",
|
|
46379
|
+
"Height",
|
|
46380
|
+
"PinX",
|
|
46381
|
+
"PinY",
|
|
46382
|
+
"LocPinX",
|
|
46383
|
+
"LocPinY",
|
|
46384
|
+
"Angle",
|
|
46385
|
+
"FlipX",
|
|
46386
|
+
"FlipY",
|
|
46387
|
+
"LockMoveX",
|
|
46388
|
+
"LockMoveY",
|
|
46389
|
+
"LockWidth",
|
|
46390
|
+
"LockHeight",
|
|
46391
|
+
"LockAspect",
|
|
46392
|
+
"LockDelete"
|
|
46393
|
+
];
|
|
46394
|
+
for (const name of local.keys())
|
|
46395
|
+
if (canonical.some(
|
|
46396
|
+
(expected) => expected.toLowerCase() === name.toLowerCase() && expected !== name
|
|
46397
|
+
))
|
|
46398
|
+
fail2(
|
|
46399
|
+
"EDIT_AMBIGUOUS_CELL",
|
|
46400
|
+
"Noncanonical transform and protection cell names are unsupported."
|
|
46401
|
+
);
|
|
46402
|
+
if (!edit.anchor || isLineSheet(cells(shape2)) || edit.height <= 0)
|
|
46403
|
+
fail2("UNSUPPORTED_GEOMETRY_EDIT", "Anchored resizing requires an ordinary local 2D shape.");
|
|
46404
|
+
if (Array.from(shape2.getElementsByTagName("*")).some(
|
|
46405
|
+
(node) => node.localName === "Shape" && [VISIO_NS, VISIO_LEGACY_NS].includes(node.namespaceURI ?? "")
|
|
46406
|
+
))
|
|
46407
|
+
fail2("UNSUPPORTED_GEOMETRY_EDIT", "Nested shape identities cannot be resized as a local leaf.");
|
|
46408
|
+
protectedShape(shape2, document);
|
|
46409
|
+
assertUnlayeredShape(shape2, document);
|
|
46410
|
+
for (const container of children3(root, "Connects"))
|
|
46411
|
+
for (const connection of children3(container, "Connect"))
|
|
46412
|
+
if (["FromSheet", "ToSheet"].some((name) => attribute3(connection, name) === edit.shapeId))
|
|
46413
|
+
fail2("UNSUPPORTED_GEOMETRY_EDIT", "Glued shapes require routing outside this subset.");
|
|
46414
|
+
const graph = indexCells(roots, { check: check3 });
|
|
46415
|
+
const id = (cell) => key({ pageId: edit.pageId, shapeId: edit.shapeId, cell });
|
|
46416
|
+
const source2 = createVisioCellEvaluator(graph, { check: check3 }, true);
|
|
46417
|
+
const read = (name, fallback) => graph.has(id(name)) ? source2(id(name)).value : numeric4(local.get(name), fallback);
|
|
46418
|
+
const width = read("Width"), height = read("Height");
|
|
46419
|
+
const pinX = read("PinX", width / 2), pinY = read("PinY", height / 2);
|
|
46420
|
+
const locX = read("LocPinX", width / 2), locY = read("LocPinY", height / 2);
|
|
46421
|
+
const angle = read("Angle", 0), flipX = read("FlipX", 0), flipY = read("FlipY", 0);
|
|
46422
|
+
for (const name of ["Angle", "FlipX", "FlipY"]) {
|
|
46423
|
+
const unit = attribute3(local.get(name), "U");
|
|
46424
|
+
if (unit && visioFormulaCachedValue("0", unit).unit !== (name === "Angle" ? "angle" : "scalar"))
|
|
46425
|
+
fail2("EDIT_FORMULA_UNIT", "Rotation and flip cells require their declared dimensions.");
|
|
46426
|
+
}
|
|
46427
|
+
if (![0, 1].includes(flipX) || ![0, 1].includes(flipY))
|
|
46428
|
+
fail2("EDIT_FORMULA_UNIT", "Flip cells must be scalar booleans.");
|
|
46429
|
+
if (width === edit.width && height === edit.height) return [];
|
|
46430
|
+
resizeGeometry(shape2, roots, edit, check3);
|
|
46431
|
+
if (numeric4(local.get("LockAspect"), 0) !== 0 && !close(edit.width / width, edit.height / height))
|
|
46432
|
+
fail2("EDIT_PROTECTED_CELL", "LockAspect prevents changing the aspect ratio.");
|
|
46433
|
+
const geometry = visioAnchoredResizeGeometry(
|
|
46434
|
+
{
|
|
46435
|
+
width,
|
|
46436
|
+
height,
|
|
46437
|
+
pinX,
|
|
46438
|
+
pinY,
|
|
46439
|
+
transform: transform6(pinX, pinY, locX, locY, angle, flipX === 1, flipY === 1)
|
|
46440
|
+
},
|
|
46441
|
+
edit,
|
|
46442
|
+
edit.anchor
|
|
46443
|
+
);
|
|
46444
|
+
if (!geometry || [geometry.pinX, geometry.pinY, geometry.locPinX, geometry.locPinY].some(
|
|
46445
|
+
(value) => Math.abs(value) > 1e6
|
|
46446
|
+
))
|
|
46447
|
+
fail2("UNSUPPORTED_GEOMETRY_EDIT", "Anchored geometry exceeds coordinate limits.");
|
|
46448
|
+
const writes = [];
|
|
46449
|
+
const writable = (name) => editableCell(
|
|
46450
|
+
local.get(name),
|
|
46451
|
+
(reference2) => source2(
|
|
46452
|
+
key({
|
|
46453
|
+
pageId: edit.pageId,
|
|
46454
|
+
shapeId: reference2.shapeId ?? edit.shapeId,
|
|
46455
|
+
cell: reference2.cell
|
|
46456
|
+
})
|
|
46457
|
+
)
|
|
46458
|
+
);
|
|
46459
|
+
const unlocked = (name) => {
|
|
46460
|
+
if (numeric4(local.get(name), 0) !== 0)
|
|
46461
|
+
fail2("EDIT_PROTECTED_CELL", `${name} prevents this operation.`);
|
|
46462
|
+
};
|
|
46463
|
+
for (const [name, value, old] of [
|
|
46464
|
+
["Width", edit.width, width],
|
|
46465
|
+
["Height", edit.height, height]
|
|
46466
|
+
])
|
|
46467
|
+
if (value !== old) {
|
|
46468
|
+
unlocked(`Lock${name}`);
|
|
46469
|
+
writable(name);
|
|
46470
|
+
writes.push({ name, value });
|
|
46471
|
+
}
|
|
46472
|
+
const changedDimensions = writes.map((write) => id(write.name));
|
|
46473
|
+
const dimensionClosure = closure(graph, changedDimensions, check3);
|
|
46474
|
+
for (const [name, value, old] of [
|
|
46475
|
+
["PinX", geometry.pinX, pinX],
|
|
46476
|
+
["PinY", geometry.pinY, pinY]
|
|
46477
|
+
])
|
|
46478
|
+
if (!local.has(name) || !close(value, old) || dimensionClosure.has(id(name)) && !guardedCell(local.get(name))) {
|
|
46479
|
+
if (!close(value, old)) unlocked(name === "PinX" ? "LockMoveX" : "LockMoveY");
|
|
46480
|
+
writable(name);
|
|
46481
|
+
writes.push({ name, value: close(value, old) ? old : value });
|
|
46482
|
+
}
|
|
46483
|
+
const projected = new Map(graph);
|
|
46484
|
+
const install = (write) => {
|
|
46485
|
+
const original = local.get(write.name);
|
|
46486
|
+
const node = original ? original.cloneNode(true) : shape2.ownerDocument.createElementNS(shape2.namespaceURI, "Cell");
|
|
46487
|
+
node.setAttribute("N", write.name);
|
|
46488
|
+
node.setAttribute("V", String(write.value));
|
|
46489
|
+
if (write.formula) node.setAttribute("F", write.formula);
|
|
46490
|
+
else node.removeAttribute("F");
|
|
46491
|
+
const cell = {
|
|
46492
|
+
pageId: edit.pageId,
|
|
46493
|
+
shapeId: edit.shapeId,
|
|
46494
|
+
cell: write.name,
|
|
46495
|
+
node,
|
|
46496
|
+
unsafe: false,
|
|
46497
|
+
unit: "length",
|
|
46498
|
+
dependencies: []
|
|
46499
|
+
};
|
|
46500
|
+
if (write.formula) {
|
|
46501
|
+
cell.formula = parseVisioFormula(write.formula);
|
|
46502
|
+
cell.dependencies = [id(write.name === "LocPinX" ? "Width" : "Height")];
|
|
46503
|
+
}
|
|
46504
|
+
projected.set(id(write.name), cell);
|
|
46505
|
+
};
|
|
46506
|
+
for (const write of writes) install(write);
|
|
46507
|
+
const guardedPins = [];
|
|
46508
|
+
for (const [name, dimension2, old, oldDimension, next] of [
|
|
46509
|
+
["LocPinX", "Width", locX, width, geometry.locPinX],
|
|
46510
|
+
["LocPinY", "Height", locY, height, geometry.locPinY]
|
|
46511
|
+
]) {
|
|
46512
|
+
if ((dimension2 === "Width" ? edit.width : edit.height) === oldDimension) continue;
|
|
46513
|
+
if (guardedCell(local.get(name))) {
|
|
46514
|
+
guardedPins.push({ name, value: next });
|
|
46515
|
+
} else {
|
|
46516
|
+
writable(name);
|
|
46517
|
+
const write = { name, value: next, formula: `${dimension2}*${old / oldDimension}` };
|
|
46518
|
+
writes.push(write);
|
|
46519
|
+
install(write);
|
|
46520
|
+
}
|
|
46521
|
+
}
|
|
46522
|
+
const projectedPins = createVisioCellEvaluator(projected, { check: check3 });
|
|
46523
|
+
for (const pin of guardedPins)
|
|
46524
|
+
if (!close(projectedPins(id(pin.name)).value, pin.value))
|
|
46525
|
+
fail2(
|
|
46526
|
+
"EDIT_PROTECTED_CELL",
|
|
46527
|
+
"Guarded local pin does not scale proportionally with the requested dimension."
|
|
46528
|
+
);
|
|
46529
|
+
const affected = closure(
|
|
46530
|
+
projected,
|
|
46531
|
+
writes.map((write) => id(write.name)),
|
|
46532
|
+
check3
|
|
46533
|
+
);
|
|
46534
|
+
for (const name of ["Angle", "FlipX", "FlipY"])
|
|
46535
|
+
if (affected.has(id(name)))
|
|
46536
|
+
fail2(
|
|
46537
|
+
"UNSUPPORTED_GEOMETRY_EDIT",
|
|
46538
|
+
"Anchored resizing cannot change dependent Angle or Flip formulas."
|
|
46539
|
+
);
|
|
46540
|
+
for (const cellId of affected)
|
|
46541
|
+
if (/^Field\./i.test(projected.get(cellId).cell))
|
|
46542
|
+
fail2(
|
|
46543
|
+
"UNSUPPORTED_GEOMETRY_EDIT",
|
|
46544
|
+
"Affected text fields need native display-cache regeneration."
|
|
46545
|
+
);
|
|
46546
|
+
const evaluate = createVisioCellEvaluator(projected, { check: check3 }), values2 = /* @__PURE__ */ new Map();
|
|
46547
|
+
for (const cellId of affected) {
|
|
46548
|
+
if (graph.has(cellId)) source2(cellId);
|
|
46549
|
+
values2.set(cellId, evaluate(cellId).value);
|
|
46550
|
+
}
|
|
46551
|
+
for (const [name, expected] of [
|
|
46552
|
+
["Width", edit.width],
|
|
46553
|
+
["Height", edit.height],
|
|
46554
|
+
["PinX", geometry.pinX],
|
|
46555
|
+
["PinY", geometry.pinY],
|
|
46556
|
+
["LocPinX", geometry.locPinX],
|
|
46557
|
+
["LocPinY", geometry.locPinY]
|
|
46558
|
+
])
|
|
46559
|
+
if (!close(projected.has(id(name)) ? evaluate(id(name)).value : read(name), expected))
|
|
46560
|
+
fail2(
|
|
46561
|
+
"EDIT_UNSUPPORTED_DEPENDENCY",
|
|
46562
|
+
"Dependent formulas would violate the requested anchor or dimensions."
|
|
46563
|
+
);
|
|
46564
|
+
check3();
|
|
46565
|
+
for (const write of writes) setCell(shape2, write.name, write.value, write.formula);
|
|
46566
|
+
const dirty = /* @__PURE__ */ new Set([edit.pageId]);
|
|
46567
|
+
for (const [cellId, value] of values2) {
|
|
46568
|
+
const item = graph.get(cellId);
|
|
46569
|
+
if (!item?.node || !item.formula || writes.some((write) => id(write.name) === cellId)) continue;
|
|
46570
|
+
if (attribute3(item.node, "V") !== String(value)) {
|
|
46571
|
+
item.node.setAttribute("V", String(value));
|
|
46572
|
+
dirty.add(item.pageId);
|
|
46573
|
+
}
|
|
46574
|
+
}
|
|
46575
|
+
return [...dirty];
|
|
46576
|
+
}
|
|
46577
|
+
|
|
44945
46578
|
// visio/edit-transform-formula.ts
|
|
44946
46579
|
function editableTransformCell(roots, edit, node, check3, options = {}) {
|
|
44947
46580
|
const formula = executableCellFormula(attribute3(node, "F"));
|
|
@@ -45011,7 +46644,16 @@ function createBox(root, document, edit) {
|
|
|
45011
46644
|
return shape2;
|
|
45012
46645
|
}
|
|
45013
46646
|
function createRectangle(root, document, edit) {
|
|
46647
|
+
if (edit.type === "create-text-box") {
|
|
46648
|
+
const planned = root.ownerDocument.createElementNS(root.namespaceURI, "Shape");
|
|
46649
|
+
applyShapeCreationStyles(planned, document);
|
|
46650
|
+
assertShapeLocks(planned, document, ["LockTextEdit"]);
|
|
46651
|
+
}
|
|
45014
46652
|
const shape2 = createBox(root, document, edit);
|
|
46653
|
+
if (edit.type === "create-text-box") {
|
|
46654
|
+
setCell(shape2, "LinePattern", 0);
|
|
46655
|
+
setCell(shape2, "FillPattern", 0);
|
|
46656
|
+
}
|
|
45015
46657
|
const doc = root.ownerDocument;
|
|
45016
46658
|
const node = (name) => doc.createElementNS(root.namespaceURI, name);
|
|
45017
46659
|
const section = node("Section");
|
|
@@ -45033,7 +46675,7 @@ function createRectangle(root, document, edit) {
|
|
|
45033
46675
|
}
|
|
45034
46676
|
shape2.appendChild(section);
|
|
45035
46677
|
const text2 = node("Text");
|
|
45036
|
-
text2.appendChild(doc.createTextNode(edit.text ?? ""));
|
|
46678
|
+
text2.appendChild(doc.createTextNode(encodeVisioPlainText(edit.text ?? "")));
|
|
45037
46679
|
shape2.appendChild(text2);
|
|
45038
46680
|
return shape2;
|
|
45039
46681
|
}
|
|
@@ -45042,7 +46684,7 @@ function createEllipse(root, document, edit) {
|
|
|
45042
46684
|
appendEllipseGeometry(shape2, edit.width, edit.height);
|
|
45043
46685
|
if (edit.text !== void 0) {
|
|
45044
46686
|
const text2 = root.ownerDocument.createElementNS(root.namespaceURI, "Text");
|
|
45045
|
-
text2.appendChild(root.ownerDocument.createTextNode(edit.text));
|
|
46687
|
+
text2.appendChild(root.ownerDocument.createTextNode(encodeVisioPlainText(edit.text)));
|
|
45046
46688
|
shape2.appendChild(text2);
|
|
45047
46689
|
}
|
|
45048
46690
|
return shape2;
|
|
@@ -45412,6 +47054,8 @@ function moveLocalLineEndpoint(shape2, edit) {
|
|
|
45412
47054
|
function applyGeometryEdit(roots, document, edit, check3, masterMoveProof = emptyMasterMoveProof()) {
|
|
45413
47055
|
const masterMovePins = masterMoveProof.pins, masterDimensions = masterMoveProof.dimensions;
|
|
45414
47056
|
check3();
|
|
47057
|
+
if (edit.type === "resize-shape" && edit.anchor)
|
|
47058
|
+
return resizeVisioShapeAtAnchor(roots, document, edit, check3);
|
|
45415
47059
|
const root = roots.get(edit.pageId);
|
|
45416
47060
|
if (!root) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
|
|
45417
47061
|
const groupRotation = proveLocalGroupRotation(root, edit, check3);
|
|
@@ -45433,11 +47077,15 @@ function applyGeometryEdit(roots, document, edit, check3, masterMoveProof = empt
|
|
|
45433
47077
|
y: (edit.beginY + edit.endY) / 2
|
|
45434
47078
|
};
|
|
45435
47079
|
for (const name of geometryChangedCells(edit)) add3(name);
|
|
45436
|
-
} else if (edit.type === "create-rectangle" || edit.type === "create-ellipse") {
|
|
47080
|
+
} else if (edit.type === "create-rectangle" || edit.type === "create-ellipse" || edit.type === "create-text-box") {
|
|
45437
47081
|
if (edit.type === "create-ellipse") createEllipse(root, document, edit);
|
|
45438
47082
|
else createRectangle(root, document, edit);
|
|
45439
47083
|
expected = { width: edit.width, height: edit.height, x: edit.x, y: edit.y };
|
|
45440
47084
|
for (const name of ["Width", "Height", "PinX", "PinY"]) add3(name);
|
|
47085
|
+
if (edit.type === "create-text-box") {
|
|
47086
|
+
add3("LinePattern");
|
|
47087
|
+
add3("FillPattern");
|
|
47088
|
+
}
|
|
45441
47089
|
} else {
|
|
45442
47090
|
const shape2 = admitted(
|
|
45443
47091
|
root,
|
|
@@ -45630,6 +47278,114 @@ function applyGeometryEdit(roots, document, edit, check3, masterMoveProof = empt
|
|
|
45630
47278
|
return [.../* @__PURE__ */ new Set([edit.pageId, ...affectedPages])];
|
|
45631
47279
|
}
|
|
45632
47280
|
|
|
47281
|
+
// visio/edit-shape-order.ts
|
|
47282
|
+
async function assertShapeOrderPackageScope(pkg, check3) {
|
|
47283
|
+
for (const path2 of pkg.paths()) {
|
|
47284
|
+
if (!/^visio\/.*\.xml$/i.test(path2)) continue;
|
|
47285
|
+
const pending2 = [await pkg.readXml(path2)];
|
|
47286
|
+
while (pending2.length) {
|
|
47287
|
+
check3();
|
|
47288
|
+
const node = pending2.pop();
|
|
47289
|
+
const source2 = executableCellFormula(attribute3(node, "F"));
|
|
47290
|
+
if (source2) {
|
|
47291
|
+
try {
|
|
47292
|
+
if (analyzeVisioFormula(source2, { onStep: check3 }).dynamic)
|
|
47293
|
+
fail2(
|
|
47294
|
+
"UNSUPPORTED_SHAPE_ORDER",
|
|
47295
|
+
"Dynamic or container formulas may depend on stacking order."
|
|
47296
|
+
);
|
|
47297
|
+
} catch {
|
|
47298
|
+
fail2(
|
|
47299
|
+
"UNSUPPORTED_SHAPE_ORDER",
|
|
47300
|
+
"Package formulas cannot be proven independent of stacking order."
|
|
47301
|
+
);
|
|
47302
|
+
}
|
|
47303
|
+
}
|
|
47304
|
+
for (const child6 of Array.from(node.childNodes))
|
|
47305
|
+
if (child6.nodeType === 1) pending2.push(child6);
|
|
47306
|
+
}
|
|
47307
|
+
}
|
|
47308
|
+
}
|
|
47309
|
+
function ordinaryDisplayBand(shape2, document) {
|
|
47310
|
+
for (const category of ["LineStyle", "FillStyle", "TextStyle"]) {
|
|
47311
|
+
const node = effectiveShapeCell(shape2, document, "DisplayLevel", category);
|
|
47312
|
+
if (!node) continue;
|
|
47313
|
+
const cached3 = visioFormulaCachedValue(attribute3(node, "V") ?? "", attribute3(node, "U"));
|
|
47314
|
+
if (node.hasAttribute("E") || cached3.unit !== "scalar" || cached3.value !== 0)
|
|
47315
|
+
fail2("UNSUPPORTED_SHAPE_ORDER", "Only the ordinary zero display band can be reordered.");
|
|
47316
|
+
const source2 = executableCellFormula(attribute3(node, "F"));
|
|
47317
|
+
if (!source2) continue;
|
|
47318
|
+
const analysis = analyzeVisioFormula(source2);
|
|
47319
|
+
if (analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length)
|
|
47320
|
+
fail2("UNSUPPORTED_SHAPE_ORDER", "Display band formulas must be constant.");
|
|
47321
|
+
const result2 = evaluateVisioFormula(
|
|
47322
|
+
source2,
|
|
47323
|
+
() => fail2("UNSUPPORTED_SHAPE_ORDER", "Display band dependencies cannot be resolved.")
|
|
47324
|
+
);
|
|
47325
|
+
if (result2.unit !== "scalar" || result2.value !== cached3.value)
|
|
47326
|
+
fail2("UNSUPPORTED_SHAPE_ORDER", "Display band formula cache is stale.");
|
|
47327
|
+
}
|
|
47328
|
+
}
|
|
47329
|
+
function reorderVisioShape(root, document, edit, check3) {
|
|
47330
|
+
check3();
|
|
47331
|
+
const containers = children3(root, "Shapes");
|
|
47332
|
+
if (containers.length !== 1)
|
|
47333
|
+
fail2("UNSUPPORTED_SHAPE_ORDER", "One local Shapes container is required.");
|
|
47334
|
+
const container = containers[0];
|
|
47335
|
+
const siblings = children3(container, "Shape");
|
|
47336
|
+
const ids = /* @__PURE__ */ new Set();
|
|
47337
|
+
for (const shape2 of siblings) {
|
|
47338
|
+
check3();
|
|
47339
|
+
const id = attribute3(shape2, "ID");
|
|
47340
|
+
if (!id || ids.has(id)) fail2("INVALID_SHAPE_ID", "Shape IDs must be present and unique.");
|
|
47341
|
+
ids.add(id);
|
|
47342
|
+
if (shape2.hasAttribute("Master") || shape2.hasAttribute("MasterShape") || shape2.hasAttribute("Del") || children3(shape2, "Shapes").length || children3(shape2, "ForeignData").length || children3(shape2, "Rel").length || attribute3(shape2, "Type") !== void 0 && attribute3(shape2, "Type") !== "Shape")
|
|
47343
|
+
fail2(
|
|
47344
|
+
"UNSUPPORTED_SHAPE_ORDER",
|
|
47345
|
+
"Ordering requires local ordinary shapes in one display band."
|
|
47346
|
+
);
|
|
47347
|
+
ordinaryDisplayBand(shape2, document);
|
|
47348
|
+
}
|
|
47349
|
+
const index2 = siblings.findIndex((shape2) => attribute3(shape2, "ID") === edit.shapeId);
|
|
47350
|
+
if (index2 < 0) fail2("EDIT_TARGET_NOT_FOUND", "A top-level local shape is required.");
|
|
47351
|
+
const target = siblings[index2];
|
|
47352
|
+
assertShapeLocks(target, document, ["LockSelect", "LockFormat"]);
|
|
47353
|
+
assertUnlayeredShape(target, document);
|
|
47354
|
+
const destination = edit.order === "front" ? siblings.length - 1 : edit.order === "back" ? 0 : edit.order === "forward" ? Math.min(siblings.length - 1, index2 + 1) : Math.max(0, index2 - 1);
|
|
47355
|
+
if (destination === index2) return false;
|
|
47356
|
+
const anchor = siblings[destination];
|
|
47357
|
+
container.insertBefore(target, destination > index2 ? anchor.nextSibling : anchor);
|
|
47358
|
+
return true;
|
|
47359
|
+
}
|
|
47360
|
+
|
|
47361
|
+
// visio/edit-duplicate-scope.ts
|
|
47362
|
+
async function assertDuplicateScope(pkg, pagePaths, targetPage, newIds, check3) {
|
|
47363
|
+
const existing = /* @__PURE__ */ new Set();
|
|
47364
|
+
for (const node of Array.from(targetPage.getElementsByTagName("*"))) {
|
|
47365
|
+
check3();
|
|
47366
|
+
if (node.localName !== "Shape" || node.namespaceURI !== targetPage.namespaceURI) continue;
|
|
47367
|
+
const id = attribute3(node, "ID");
|
|
47368
|
+
if (!id || existing.has(id)) fail2("INVALID_SHAPE_ID", "Source shape IDs must be unique.");
|
|
47369
|
+
if (newIds.has(id)) fail2("INVALID_SHAPE_ID", "New shape ID already exists.");
|
|
47370
|
+
existing.add(id);
|
|
47371
|
+
}
|
|
47372
|
+
await assertShapeOrderPackageScope(pkg, check3);
|
|
47373
|
+
const inspect2 = (root) => {
|
|
47374
|
+
for (const node of [root, ...Array.from(root.getElementsByTagName("*"))]) {
|
|
47375
|
+
check3();
|
|
47376
|
+
const source2 = executableCellFormula(attribute3(node, "F"));
|
|
47377
|
+
if (!source2) continue;
|
|
47378
|
+
if (analyzeVisioFormula(source2).references.some(
|
|
47379
|
+
(ref) => ref.shapeId !== void 0 && newIds.has(ref.shapeId)
|
|
47380
|
+
))
|
|
47381
|
+
fail2("EDIT_DUPLICATE_DEPENDENCY", "New IDs are already referenced by existing formulas.");
|
|
47382
|
+
}
|
|
47383
|
+
};
|
|
47384
|
+
inspect2(targetPage);
|
|
47385
|
+
for (const path2 of pkg.paths())
|
|
47386
|
+
if (/^visio\/.*\.xml$/i.test(path2) && !pagePaths.has(path2)) inspect2(await pkg.readXml(path2));
|
|
47387
|
+
}
|
|
47388
|
+
|
|
45633
47389
|
// visio/formula-master.ts
|
|
45634
47390
|
function analyzeVisioMasterFormula(source2, options) {
|
|
45635
47391
|
const ast = parseVisioFormula(source2);
|
|
@@ -45907,11 +47663,11 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check3) {
|
|
|
45907
47663
|
}
|
|
45908
47664
|
const tops = children3(children3(root, "Shapes")[0], "Shape");
|
|
45909
47665
|
if (tops.length !== 1) problem("Only a uniquely rooted master can prove independence.");
|
|
45910
|
-
const
|
|
47666
|
+
const templates2 = masterShapes(root), context = /* @__PURE__ */ new Map();
|
|
45911
47667
|
assertMasterMarkup(
|
|
45912
47668
|
root,
|
|
45913
47669
|
new Set(
|
|
45914
|
-
|
|
47670
|
+
templates2.flatMap((shape2) => {
|
|
45915
47671
|
charge();
|
|
45916
47672
|
return [...masterCells(shape2, charge).values()];
|
|
45917
47673
|
})
|
|
@@ -45933,7 +47689,7 @@ async function assertVisioMasterIndependence(pkg, roots, commands, check3) {
|
|
|
45933
47689
|
if (byTemplate.has(id)) problem("MasterShape mappings are ambiguous.");
|
|
45934
47690
|
byTemplate.set(id, local);
|
|
45935
47691
|
}
|
|
45936
|
-
for (const template of
|
|
47692
|
+
for (const template of templates2) {
|
|
45937
47693
|
charge();
|
|
45938
47694
|
if (bindings.length >= 1e4) problem("Master effective binding limit exceeded.");
|
|
45939
47695
|
check3();
|
|
@@ -46261,10 +48017,17 @@ async function assertGeometryPackageScope(pkg, pagePaths, commands, check3, root
|
|
|
46261
48017
|
for (const [pageId, root] of roots) {
|
|
46262
48018
|
const shapes = Array.from(root.getElementsByTagNameNS(root.namespaceURI, "Shape"));
|
|
46263
48019
|
for (const command2 of commands)
|
|
46264
|
-
if ((command2.type === "create-rectangle" || command2.type === "create-ellipse" || command2.type === "create-line") && command2.pageId === pageId && !shapes.some((shape2) => attribute3(shape2, "ID") === command2.shapeId)) {
|
|
48020
|
+
if ((command2.type === "create-rectangle" || command2.type === "create-ellipse" || command2.type === "create-text-box" || command2.type === "create-line") && command2.pageId === pageId && !shapes.some((shape2) => attribute3(shape2, "ID") === command2.shapeId)) {
|
|
46265
48021
|
const shape2 = root.ownerDocument.createElementNS(root.namespaceURI, "Shape");
|
|
46266
48022
|
shape2.setAttribute("ID", command2.shapeId);
|
|
46267
48023
|
applyShapeCreationStyles(shape2, documentRoot);
|
|
48024
|
+
if (command2.type === "create-text-box")
|
|
48025
|
+
for (const name of ["LinePattern", "FillPattern"]) {
|
|
48026
|
+
const node = root.ownerDocument.createElementNS(root.namespaceURI, "Cell");
|
|
48027
|
+
node.setAttribute("N", name);
|
|
48028
|
+
node.setAttribute("V", "0");
|
|
48029
|
+
shape2.appendChild(node);
|
|
48030
|
+
}
|
|
46268
48031
|
for (const name of ["PinX", "PinY", "Width", "Height", "LocPinX", "LocPinY", "Angle"]) {
|
|
46269
48032
|
const node = root.ownerDocument.createElementNS(root.namespaceURI, "Cell");
|
|
46270
48033
|
node.setAttribute("N", name);
|
|
@@ -47005,6 +48768,787 @@ async function editVsdxPages(original, pkg, parts, commands, limits, maxOutput,
|
|
|
47005
48768
|
};
|
|
47006
48769
|
}
|
|
47007
48770
|
|
|
48771
|
+
// visio/edit-formatting-font.ts
|
|
48772
|
+
function formattingFont(document, family) {
|
|
48773
|
+
const containers = children3(document, "FaceNames");
|
|
48774
|
+
if (containers.length !== 1)
|
|
48775
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Font family requires existing document FaceNames.");
|
|
48776
|
+
const fonts = children3(containers[0], "FaceName");
|
|
48777
|
+
const ids = /* @__PURE__ */ new Set();
|
|
48778
|
+
for (const font3 of fonts) {
|
|
48779
|
+
const id2 = attribute3(font3, "ID");
|
|
48780
|
+
if (id2 === void 0) continue;
|
|
48781
|
+
if (!/^\d+$/.test(id2) || ids.has(id2))
|
|
48782
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Explicit document font IDs must be numeric and unique.");
|
|
48783
|
+
ids.add(id2);
|
|
48784
|
+
}
|
|
48785
|
+
const matches2 = fonts.filter(
|
|
48786
|
+
(font3) => (attribute3(font3, "Name") ?? attribute3(font3, "NameU"))?.toLowerCase() === family.toLowerCase()
|
|
48787
|
+
);
|
|
48788
|
+
if (matches2.length !== 1)
|
|
48789
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Font family must match one existing document FaceName.");
|
|
48790
|
+
const font2 = matches2[0], id = attribute3(font2, "ID");
|
|
48791
|
+
if (id !== void 0) return { value: id };
|
|
48792
|
+
const name = attribute3(font2, "Name") ?? attribute3(font2, "NameU");
|
|
48793
|
+
return { value: name, formula: `FONT("${name.replaceAll('"', '""')}")` };
|
|
48794
|
+
}
|
|
48795
|
+
|
|
48796
|
+
// visio/edit-formatting-text.ts
|
|
48797
|
+
function textFormattingWrites(shape2, document, edit, check3) {
|
|
48798
|
+
const rows = /* @__PURE__ */ new Map();
|
|
48799
|
+
if (["fontSize", "fontFamily", "fontColor", "bold", "italic", "underline", "strikethrough"].some(
|
|
48800
|
+
(key2) => edit[key2] !== void 0
|
|
48801
|
+
))
|
|
48802
|
+
rows.set("Character", formattingRowContext(shape2, document, "Character"));
|
|
48803
|
+
if (edit.bullets !== void 0 || edit.indentLeft !== void 0 || edit.horizontalAlign !== void 0)
|
|
48804
|
+
rows.set("Paragraph", formattingRowContext(shape2, document, "Paragraph"));
|
|
48805
|
+
const characters = rows.get("Character")?.source;
|
|
48806
|
+
const paragraphs = rows.get("Paragraph")?.source;
|
|
48807
|
+
if (rows.size) assertFormattingText(shape2, characters, paragraphs);
|
|
48808
|
+
const writes = [];
|
|
48809
|
+
const add3 = (name, value, unit, formula) => writes.push({
|
|
48810
|
+
name,
|
|
48811
|
+
value: String(value),
|
|
48812
|
+
category: "TextStyle",
|
|
48813
|
+
...unit ? { unit } : {},
|
|
48814
|
+
...formula ? { formula } : {}
|
|
48815
|
+
});
|
|
48816
|
+
const scalar4 = (name, max, description) => {
|
|
48817
|
+
const cell = effectiveShapeCell(
|
|
48818
|
+
shape2,
|
|
48819
|
+
document,
|
|
48820
|
+
name,
|
|
48821
|
+
"TextStyle",
|
|
48822
|
+
rows.get(name.split(".")[0])
|
|
48823
|
+
);
|
|
48824
|
+
const cached3 = cell ? visioFormulaCachedValue(attribute3(cell, "V") ?? "", attribute3(cell, "U")) : { value: 0, unit: "scalar" };
|
|
48825
|
+
if (cached3.unit !== "scalar" || !Number.isSafeInteger(cached3.value) || cached3.value < 0 || cached3.value > max)
|
|
48826
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", `${description} requires a supported scalar value.`);
|
|
48827
|
+
return cached3.value;
|
|
48828
|
+
};
|
|
48829
|
+
const font2 = edit.fontFamily === void 0 ? void 0 : formattingFont(document, edit.fontFamily);
|
|
48830
|
+
for (const index2 of characters ? /* @__PURE__ */ new Set(["0", ...characters.keys()]) : []) {
|
|
48831
|
+
check3();
|
|
48832
|
+
const name = (cell) => `Character.${index2}.${cell}`;
|
|
48833
|
+
if (edit.fontSize !== void 0) add3(name("Size"), edit.fontSize / 72, "PT");
|
|
48834
|
+
if (font2) add3(name("Font"), font2.value, void 0, font2.formula);
|
|
48835
|
+
if (edit.fontColor !== void 0) {
|
|
48836
|
+
add3(
|
|
48837
|
+
name("Color"),
|
|
48838
|
+
edit.fontColor,
|
|
48839
|
+
void 0,
|
|
48840
|
+
`RGB(${[1, 3, 5].map((i2) => parseInt(edit.fontColor.slice(i2, i2 + 2), 16)).join(",")})`
|
|
48841
|
+
);
|
|
48842
|
+
add3(name("ColorTrans"), 0);
|
|
48843
|
+
}
|
|
48844
|
+
if (edit.strikethrough !== void 0) add3(name("Strikethru"), edit.strikethrough ? 1 : 0);
|
|
48845
|
+
if ([edit.bold, edit.italic, edit.underline].some((value) => value !== void 0)) {
|
|
48846
|
+
let bits = scalar4(name("Style"), 255, "Character style");
|
|
48847
|
+
for (const [value, bit] of [
|
|
48848
|
+
[edit.bold, 1],
|
|
48849
|
+
[edit.italic, 2],
|
|
48850
|
+
[edit.underline, 4]
|
|
48851
|
+
])
|
|
48852
|
+
if (value !== void 0) bits = value ? bits | bit : bits & ~bit;
|
|
48853
|
+
add3(name("Style"), bits);
|
|
48854
|
+
}
|
|
48855
|
+
}
|
|
48856
|
+
for (const index2 of paragraphs ? /* @__PURE__ */ new Set(["0", ...paragraphs.keys()]) : []) {
|
|
48857
|
+
check3();
|
|
48858
|
+
const name = (cell) => `Paragraph.${index2}.${cell}`;
|
|
48859
|
+
if (edit.indentLeft !== void 0) add3(name("IndLeft"), edit.indentLeft / 72, "PT");
|
|
48860
|
+
if (edit.bullets !== void 0) {
|
|
48861
|
+
const bullet = scalar4(name("Bullet"), 7, "Paragraph bullet style");
|
|
48862
|
+
add3(name("Bullet"), edit.bullets ? bullet || 1 : 0);
|
|
48863
|
+
}
|
|
48864
|
+
if (edit.horizontalAlign !== void 0)
|
|
48865
|
+
add3(name("HorzAlign"), ["left", "center", "right", "justify"].indexOf(edit.horizontalAlign));
|
|
48866
|
+
}
|
|
48867
|
+
if (edit.verticalAlign !== void 0)
|
|
48868
|
+
add3("VerticalAlign", ["top", "middle", "bottom"].indexOf(edit.verticalAlign));
|
|
48869
|
+
return { writes, rows };
|
|
48870
|
+
}
|
|
48871
|
+
|
|
48872
|
+
// visio/edit-formatting-paint-scope.ts
|
|
48873
|
+
var selectors = [
|
|
48874
|
+
"ColorSchemeIndex",
|
|
48875
|
+
"EffectSchemeIndex",
|
|
48876
|
+
"ConnectorSchemeIndex",
|
|
48877
|
+
"VariationStyleIndex",
|
|
48878
|
+
"VariationColorIndex",
|
|
48879
|
+
"QuickStyleType",
|
|
48880
|
+
"QuickStyleVariation",
|
|
48881
|
+
"QuickStyleFillMatrix",
|
|
48882
|
+
"QuickStyleLineMatrix",
|
|
48883
|
+
"OneD"
|
|
48884
|
+
];
|
|
48885
|
+
function scalar3(cell) {
|
|
48886
|
+
if (!cell) return void 0;
|
|
48887
|
+
if (cell.hasAttribute("E")) fail2("UNSUPPORTED_FORMAT_EDIT", "Paint state has an error cache.");
|
|
48888
|
+
const cached3 = visioFormulaCachedValue(attribute3(cell, "V") ?? "", attribute3(cell, "U"));
|
|
48889
|
+
if (cached3.unit !== "scalar") fail2("EDIT_FORMULA_UNIT", "Paint state requires scalar units.");
|
|
48890
|
+
const source2 = executableCellFormula(attribute3(cell, "F"));
|
|
48891
|
+
if (source2) {
|
|
48892
|
+
const analysis = analyzeVisioFormula(source2);
|
|
48893
|
+
if (analysis.dynamic || analysis.references.length || analysis.unsupportedFunctions.length)
|
|
48894
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Paint state dependencies cannot be proven.");
|
|
48895
|
+
const actual = evaluateVisioFormula(
|
|
48896
|
+
source2,
|
|
48897
|
+
() => fail2("UNSUPPORTED_FORMAT_EDIT", "Unknown paint dependency.")
|
|
48898
|
+
);
|
|
48899
|
+
if (actual.unit !== "scalar" || actual.value !== cached3.value)
|
|
48900
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Paint state formula cache is stale.");
|
|
48901
|
+
}
|
|
48902
|
+
return cached3.value;
|
|
48903
|
+
}
|
|
48904
|
+
async function assertNonGradientPaint(pkg, document, shape2, pageId, paint2, check3) {
|
|
48905
|
+
const category = paint2 === "Fill" ? "FillStyle" : "LineStyle";
|
|
48906
|
+
const pattern = effectiveShapeCell(shape2, document, `${paint2}Pattern`, category);
|
|
48907
|
+
if (pattern && attribute3(pattern, "V") !== "Themed") {
|
|
48908
|
+
const value = scalar3(pattern);
|
|
48909
|
+
if (value === 0) return;
|
|
48910
|
+
if (paint2 === "Fill" && value !== void 0 && value >= 25)
|
|
48911
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Classic gradient and custom fill edits are unsupported.");
|
|
48912
|
+
}
|
|
48913
|
+
const enabled2 = effectiveShapeCell(shape2, document, `${paint2}GradientEnabled`, category);
|
|
48914
|
+
if (!enabled2) return;
|
|
48915
|
+
if (attribute3(enabled2, "V") !== "Themed") {
|
|
48916
|
+
if (scalar3(enabled2) === 0) return;
|
|
48917
|
+
fail2(
|
|
48918
|
+
"UNSUPPORTED_FORMAT_EDIT",
|
|
48919
|
+
"Gradient paint transparency and background edits are unsupported."
|
|
48920
|
+
);
|
|
48921
|
+
}
|
|
48922
|
+
assertEditableFormattingCell(enabled2);
|
|
48923
|
+
const report = () => fail2("UNSUPPORTED_FORMAT_EDIT", "Theme paint context cannot be resolved safely.");
|
|
48924
|
+
if (children3(document, "StyleSheets").length > 1)
|
|
48925
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Ambiguous style containers cannot supply theme paint.");
|
|
48926
|
+
const styles = /* @__PURE__ */ new Map();
|
|
48927
|
+
for (const container of children3(document, "StyleSheets"))
|
|
48928
|
+
for (const node of children3(container, "StyleSheet")) {
|
|
48929
|
+
check3();
|
|
48930
|
+
const id = attribute3(node, "ID");
|
|
48931
|
+
if (!id || styles.has(id)) fail2("UNSUPPORTED_FORMAT_EDIT", "Ambiguous style IDs.");
|
|
48932
|
+
uniqueFormattingCells(node);
|
|
48933
|
+
styles.set(id, {
|
|
48934
|
+
sheet: readSheet(node),
|
|
48935
|
+
attributes: new Map(Array.from(node.attributes).map((item) => [item.name, item.value]))
|
|
48936
|
+
});
|
|
48937
|
+
}
|
|
48938
|
+
const context = { styles, styleCache: /* @__PURE__ */ new Map(), report, checkTime: check3 };
|
|
48939
|
+
let sheet = emptySheet();
|
|
48940
|
+
for (const name of ["LineStyle", "FillStyle", "TextStyle"]) {
|
|
48941
|
+
for (const selector of selectors) scalar3(effectiveShapeCell(shape2, document, selector, name));
|
|
48942
|
+
const id = attribute3(shape2, name) ?? attribute3(child5(document, "DocumentSheet"), name) ?? (styles.has("0") ? "0" : void 0);
|
|
48943
|
+
if (id !== void 0) sheet = mergeSheets(sheet, styleSheet(id, name, context));
|
|
48944
|
+
}
|
|
48945
|
+
sheet = mergeSheets(sheet, readSheet(shape2));
|
|
48946
|
+
const documentPath = await related(pkg, "", "document");
|
|
48947
|
+
const pagesPath = await related(pkg, documentPath, "pages");
|
|
48948
|
+
const page = children3(await visioXml(pkg, pagesPath, "Pages"), "Page").find(
|
|
48949
|
+
(node) => attribute3(node, "ID") === pageId
|
|
48950
|
+
);
|
|
48951
|
+
const pageSheet = child5(page, "PageSheet");
|
|
48952
|
+
const pageCells = /* @__PURE__ */ new Map();
|
|
48953
|
+
if (pageSheet) uniqueFormattingCells(pageSheet);
|
|
48954
|
+
for (const name of ["LineStyle", "FillStyle", "TextStyle"]) {
|
|
48955
|
+
const id = attribute3(pageSheet, name);
|
|
48956
|
+
if (id !== void 0 && pageSheet) {
|
|
48957
|
+
for (const selector of selectors)
|
|
48958
|
+
scalar3(effectiveShapeCell(pageSheet, document, selector, name));
|
|
48959
|
+
for (const [key2, value] of styleSheet(id, name, context).cells)
|
|
48960
|
+
if (/^(ColorSchemeIndex|EffectSchemeIndex|ConnectorSchemeIndex|FontSchemeIndex|VariationColorIndex|VariationStyleIndex)$/.test(
|
|
48961
|
+
key2
|
|
48962
|
+
))
|
|
48963
|
+
pageCells.set(key2, value);
|
|
48964
|
+
}
|
|
48965
|
+
}
|
|
48966
|
+
for (const node of children3(pageSheet, "Cell"))
|
|
48967
|
+
if (selectors.includes(attribute3(node, "N") ?? "")) scalar3(node);
|
|
48968
|
+
const root = styles.get("0");
|
|
48969
|
+
const resources = {
|
|
48970
|
+
themes: await loadVisioThemes(pkg, documentPath, report),
|
|
48971
|
+
pageCells: new Map([...pageCells, ...readSheet(pageSheet).cells]),
|
|
48972
|
+
...root?.attributes.get("NameU") === "No Style" ? { rootSheet: root.sheet } : {}
|
|
48973
|
+
};
|
|
48974
|
+
sheet = rootThemeSheet(sheet, resources, report);
|
|
48975
|
+
const resolved = number(sheet.cells, `${paint2}GradientEnabled`, NaN);
|
|
48976
|
+
if (resolved === 0) {
|
|
48977
|
+
const source2 = styles.get("0");
|
|
48978
|
+
if (!source2 || root?.attributes.get("NameU") !== "No Style")
|
|
48979
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Root gradient context cannot be proven.");
|
|
48980
|
+
const node = children3(child5(document, "StyleSheets"), "StyleSheet").find(
|
|
48981
|
+
(item) => attribute3(item, "ID") === "0"
|
|
48982
|
+
);
|
|
48983
|
+
if (scalar3(node ? uniqueFormattingCells(node).get(`${paint2}GradientEnabled`) : void 0) !== 0)
|
|
48984
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "Root gradient state cannot be proven inactive.");
|
|
48985
|
+
return;
|
|
48986
|
+
}
|
|
48987
|
+
const selected2 = themeFormat(sheet.cells, paint2, resources);
|
|
48988
|
+
if (paint2 === "Fill" && selected2 && ["solidFill", "noFill"].includes(selected2.localName)) return;
|
|
48989
|
+
if (paint2 === "Line" && selected2 && !themeChild(selected2, "gradFill") && (themeChild(selected2, "solidFill") || themeChild(selected2, "noFill")))
|
|
48990
|
+
return;
|
|
48991
|
+
fail2(
|
|
48992
|
+
"UNSUPPORTED_FORMAT_EDIT",
|
|
48993
|
+
"Active or unresolved theme gradients cannot be edited through paint transparency."
|
|
48994
|
+
);
|
|
48995
|
+
}
|
|
48996
|
+
|
|
48997
|
+
// visio/edit-formatting-paint.ts
|
|
48998
|
+
function shapeFormattingWrites(edit) {
|
|
48999
|
+
const writes = /* @__PURE__ */ new Map();
|
|
49000
|
+
const add3 = (name, value, category, unit, formula) => writes.set(name, {
|
|
49001
|
+
name,
|
|
49002
|
+
value: String(value),
|
|
49003
|
+
category,
|
|
49004
|
+
...unit ? { unit } : {},
|
|
49005
|
+
...formula ? { formula } : {}
|
|
49006
|
+
});
|
|
49007
|
+
if (edit.fillColor !== void 0) {
|
|
49008
|
+
add3("FillPattern", edit.fillColor === "none" ? 0 : 1, "FillStyle");
|
|
49009
|
+
add3("FillGradientEnabled", 0, "FillStyle");
|
|
49010
|
+
if (edit.fillColor !== "none") {
|
|
49011
|
+
add3("FillForegnd", edit.fillColor, "FillStyle", void 0, rgb2(edit.fillColor));
|
|
49012
|
+
add3("FillForegndTrans", 0, "FillStyle");
|
|
49013
|
+
}
|
|
49014
|
+
}
|
|
49015
|
+
if (edit.fillPattern !== void 0) {
|
|
49016
|
+
add3("FillPattern", edit.fillPattern, "FillStyle");
|
|
49017
|
+
add3("FillGradientEnabled", 0, "FillStyle");
|
|
49018
|
+
}
|
|
49019
|
+
if (edit.fillBackgroundColor !== void 0) {
|
|
49020
|
+
add3(
|
|
49021
|
+
"FillBkgnd",
|
|
49022
|
+
edit.fillBackgroundColor,
|
|
49023
|
+
"FillStyle",
|
|
49024
|
+
void 0,
|
|
49025
|
+
rgb2(edit.fillBackgroundColor)
|
|
49026
|
+
);
|
|
49027
|
+
}
|
|
49028
|
+
if (edit.fillTransparency !== void 0) {
|
|
49029
|
+
for (const name of ["FillForegndTrans", "FillBkgndTrans"])
|
|
49030
|
+
add3(name, edit.fillTransparency / 100, "FillStyle");
|
|
49031
|
+
}
|
|
49032
|
+
if (edit.lineColor !== void 0) {
|
|
49033
|
+
add3("LineColor", edit.lineColor, "LineStyle", void 0, rgb2(edit.lineColor));
|
|
49034
|
+
add3("LineColorTrans", 0, "LineStyle");
|
|
49035
|
+
add3("LineGradientEnabled", 0, "LineStyle");
|
|
49036
|
+
}
|
|
49037
|
+
if (edit.linePattern !== void 0) add3("LinePattern", edit.linePattern, "LineStyle");
|
|
49038
|
+
if (edit.lineTransparency !== void 0) {
|
|
49039
|
+
add3("LineColorTrans", edit.lineTransparency / 100, "LineStyle");
|
|
49040
|
+
}
|
|
49041
|
+
if (edit.lineWeight !== void 0) add3("LineWeight", edit.lineWeight / 72, "LineStyle", "PT");
|
|
49042
|
+
return [...writes.values()];
|
|
49043
|
+
}
|
|
49044
|
+
async function assertShapeFormattingPaintScope(pkg, document, shape2, edit, changed, check3) {
|
|
49045
|
+
if (edit.fillColor === void 0 && edit.fillPattern === void 0 && ["FillBkgnd", "FillForegndTrans", "FillBkgndTrans"].some((name) => changed.has(name)))
|
|
49046
|
+
await assertNonGradientPaint(pkg, document, shape2, edit.pageId, "Fill", check3);
|
|
49047
|
+
if (edit.lineColor === void 0 && changed.has("LineColorTrans"))
|
|
49048
|
+
await assertNonGradientPaint(pkg, document, shape2, edit.pageId, "Line", check3);
|
|
49049
|
+
}
|
|
49050
|
+
function rgb2(color2) {
|
|
49051
|
+
return `RGB(${[1, 3, 5].map((index2) => parseInt(color2.slice(index2, index2 + 2), 16)).join(",")})`;
|
|
49052
|
+
}
|
|
49053
|
+
|
|
49054
|
+
// visio/edit-formatting.ts
|
|
49055
|
+
function targetShape(root, shapeId) {
|
|
49056
|
+
const containers = children3(root, "Shapes");
|
|
49057
|
+
if (containers.length !== 1)
|
|
49058
|
+
fail2("UNSUPPORTED_FORMAT_EDIT", "One local Shapes container is required.");
|
|
49059
|
+
const candidates = children3(containers[0], "Shape").filter(
|
|
49060
|
+
(shape3) => attribute3(shape3, "ID") === shapeId
|
|
49061
|
+
);
|
|
49062
|
+
if (candidates.length !== 1)
|
|
49063
|
+
fail2("EDIT_TARGET_NOT_FOUND", "A unique top-level local shape is required.");
|
|
49064
|
+
const shape2 = candidates[0];
|
|
49065
|
+
if (shape2.hasAttribute("Master") || shape2.hasAttribute("MasterShape") || shape2.hasAttribute("Del") || children3(shape2, "Shapes").length || children3(shape2, "ForeignData").length || children3(shape2, "Rel").length || !["Shape", void 0].includes(attribute3(shape2, "Type")))
|
|
49066
|
+
fail2(
|
|
49067
|
+
"UNSUPPORTED_FORMAT_EDIT",
|
|
49068
|
+
"Master, group, foreign, deleted and non-shape formatting is unsupported."
|
|
49069
|
+
);
|
|
49070
|
+
return shape2;
|
|
49071
|
+
}
|
|
49072
|
+
async function applyFormattingEdit(pkg, pagePaths, roots, document, edit, check3) {
|
|
49073
|
+
const root = roots.get(edit.pageId);
|
|
49074
|
+
if (!root) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
|
|
49075
|
+
const shape2 = targetShape(root, edit.shapeId);
|
|
49076
|
+
assertUnlayeredShape(shape2, document);
|
|
49077
|
+
assertShapeLocks(
|
|
49078
|
+
shape2,
|
|
49079
|
+
document,
|
|
49080
|
+
edit.type === "format-text" ? ["LockFormat", "LockTextEdit"] : ["LockFormat"]
|
|
49081
|
+
);
|
|
49082
|
+
let writes = [];
|
|
49083
|
+
let rows;
|
|
49084
|
+
if (edit.type === "format-text") {
|
|
49085
|
+
const plan = textFormattingWrites(shape2, document, edit, check3);
|
|
49086
|
+
writes = plan.writes;
|
|
49087
|
+
rows = plan.rows;
|
|
49088
|
+
} else {
|
|
49089
|
+
writes = shapeFormattingWrites(edit);
|
|
49090
|
+
}
|
|
49091
|
+
const changed = /* @__PURE__ */ new Map();
|
|
49092
|
+
for (const write of writes) {
|
|
49093
|
+
check3();
|
|
49094
|
+
const [section, index2, name] = write.name.split(".");
|
|
49095
|
+
const rowContext = rows?.get(section);
|
|
49096
|
+
const effective = effectiveShapeCell(shape2, document, write.name, write.category, rowContext);
|
|
49097
|
+
assertEditableFormattingCell(effective);
|
|
49098
|
+
if (/^(LinePattern|FillPattern|FillGradientEnabled|LineGradientEnabled|LineColorTrans|FillForegndTrans|FillBkgndTrans|FillBkgnd)$/.test(
|
|
49099
|
+
write.name
|
|
49100
|
+
) && effective?.hasAttribute("U") && visioFormulaCachedValue("0", attribute3(effective, "U")).unit !== "scalar")
|
|
49101
|
+
fail2("EDIT_FORMULA_UNIT", "Paint patterns and transparency require scalar units.");
|
|
49102
|
+
if (write.unit && effective?.hasAttribute("U") && visioFormulaCachedValue("0", attribute3(effective, "U")).unit !== "length")
|
|
49103
|
+
fail2(
|
|
49104
|
+
"EDIT_FORMULA_UNIT",
|
|
49105
|
+
"Font size, paragraph indent and line weight require length units."
|
|
49106
|
+
);
|
|
49107
|
+
const parent = name ? rowContext.local.get(index2) : shape2;
|
|
49108
|
+
const local = parent ? formattingCell(parent, name ?? write.name) : void 0;
|
|
49109
|
+
if (local && attribute3(local, "F") !== "Inh" && attribute3(local, "V") === write.value && (!write.formula || attribute3(local, "F") === write.formula))
|
|
49110
|
+
continue;
|
|
49111
|
+
changed.set(write.name, local);
|
|
49112
|
+
}
|
|
49113
|
+
if (!changed.size) return false;
|
|
49114
|
+
if (edit.type === "format-shape")
|
|
49115
|
+
await assertShapeFormattingPaintScope(pkg, document, shape2, edit, changed, check3);
|
|
49116
|
+
await assertFormattingDependencies(pkg, pagePaths, roots, edit.pageId, shape2, changed, check3);
|
|
49117
|
+
for (const write of writes) {
|
|
49118
|
+
check3();
|
|
49119
|
+
if (!changed.has(write.name)) continue;
|
|
49120
|
+
const [sectionName, index2, cellName] = write.name.split(".");
|
|
49121
|
+
let parent = shape2;
|
|
49122
|
+
if (cellName) {
|
|
49123
|
+
const localRows = rows.get(sectionName).local;
|
|
49124
|
+
let row2 = localRows.get(index2);
|
|
49125
|
+
if (!row2) {
|
|
49126
|
+
let section = children3(shape2, "Section").find(
|
|
49127
|
+
(node) => attribute3(node, "N") === sectionName
|
|
49128
|
+
);
|
|
49129
|
+
if (!section) {
|
|
49130
|
+
section = shape2.ownerDocument.createElementNS(shape2.namespaceURI, "Section");
|
|
49131
|
+
section.setAttribute("N", sectionName);
|
|
49132
|
+
shape2.insertBefore(section, children3(shape2, "Text")[0] ?? null);
|
|
49133
|
+
}
|
|
49134
|
+
row2 = shape2.ownerDocument.createElementNS(shape2.namespaceURI, "Row");
|
|
49135
|
+
row2.setAttribute("IX", index2);
|
|
49136
|
+
section.appendChild(row2);
|
|
49137
|
+
localRows.set(index2, row2);
|
|
49138
|
+
}
|
|
49139
|
+
parent = row2;
|
|
49140
|
+
}
|
|
49141
|
+
let cell = formattingCell(parent, cellName ?? write.name);
|
|
49142
|
+
if (!cell) {
|
|
49143
|
+
cell = shape2.ownerDocument.createElementNS(shape2.namespaceURI, "Cell");
|
|
49144
|
+
cell.setAttribute("N", cellName ?? write.name);
|
|
49145
|
+
parent.insertBefore(
|
|
49146
|
+
cell,
|
|
49147
|
+
Array.from(parent.childNodes).find(
|
|
49148
|
+
(node) => node.nodeType === 1 && node.localName !== "Cell"
|
|
49149
|
+
) ?? null
|
|
49150
|
+
);
|
|
49151
|
+
}
|
|
49152
|
+
cell.setAttribute("V", write.value);
|
|
49153
|
+
if (write.unit) cell.setAttribute("U", write.unit);
|
|
49154
|
+
if (write.formula) cell.setAttribute("F", write.formula);
|
|
49155
|
+
else if (attribute3(cell, "F") !== "No Formula") cell.removeAttribute("F");
|
|
49156
|
+
}
|
|
49157
|
+
return true;
|
|
49158
|
+
}
|
|
49159
|
+
|
|
49160
|
+
// visio/edit-duplicate.ts
|
|
49161
|
+
function copyIdentity(shape2, newId, names) {
|
|
49162
|
+
shape2.setAttribute("ID", newId);
|
|
49163
|
+
shape2.removeAttribute("UniqueID");
|
|
49164
|
+
for (const name of ["Name", "NameU"]) {
|
|
49165
|
+
const value = attribute3(shape2, name);
|
|
49166
|
+
if (value === void 0) continue;
|
|
49167
|
+
const occupied = names.get(name);
|
|
49168
|
+
let next = `${value.replace(/\.\d+$/, "")}.${newId}`;
|
|
49169
|
+
if (occupied.has(next.toLowerCase())) next = `Sheet.${newId}`;
|
|
49170
|
+
if (occupied.has(next.toLowerCase()))
|
|
49171
|
+
fail2("UNSUPPORTED_DUPLICATE", "Duplicated default shape name is already occupied.");
|
|
49172
|
+
if (next.length > 4096)
|
|
49173
|
+
fail2("UNSUPPORTED_DUPLICATE", "Duplicated name exceeds metadata limits.");
|
|
49174
|
+
shape2.setAttribute(name, next);
|
|
49175
|
+
occupied.add(next.toLowerCase());
|
|
49176
|
+
}
|
|
49177
|
+
}
|
|
49178
|
+
async function duplicateVisioShapes(pkg, pagePaths, roots, document, edit, check3, detached) {
|
|
49179
|
+
const root = roots.get(edit.pageId);
|
|
49180
|
+
if (!root) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
|
|
49181
|
+
const ids = /* @__PURE__ */ new Set();
|
|
49182
|
+
for (const node of Array.from(root.getElementsByTagName("*")))
|
|
49183
|
+
if (node.localName === "Shape" && node.namespaceURI === root.namespaceURI) {
|
|
49184
|
+
const id = attribute3(node, "ID");
|
|
49185
|
+
if (!id || ids.has(id)) fail2("INVALID_SHAPE_ID", "Source shape IDs must be unique.");
|
|
49186
|
+
ids.add(id);
|
|
49187
|
+
}
|
|
49188
|
+
const newIds = new Set(edit.copies.map((copy2) => copy2.newShapeId));
|
|
49189
|
+
if ([...newIds].some((id) => ids.has(id)))
|
|
49190
|
+
fail2("INVALID_SHAPE_ID", "Duplicate shape ID already exists.");
|
|
49191
|
+
await assertDuplicateScope(pkg, pagePaths, root, newIds, check3);
|
|
49192
|
+
const sourceRoot = detached?.root ?? root;
|
|
49193
|
+
const sourcePageId = detached?.pageId ?? edit.pageId;
|
|
49194
|
+
const indexed = indexCells(detached ? /* @__PURE__ */ new Map([[sourcePageId, sourceRoot]]) : roots, { check: check3 });
|
|
49195
|
+
const evaluate = createVisioCellEvaluator(indexed, { check: check3 }, true);
|
|
49196
|
+
const containers = children3(root, "Shapes");
|
|
49197
|
+
if (containers.length > 1) fail2("INVALID_SHAPE_ID", "Duplicate Shapes containers.");
|
|
49198
|
+
const container = containers[0] ?? root.ownerDocument.createElementNS(root.namespaceURI, "Shapes");
|
|
49199
|
+
const mapping = new Map(edit.copies.map((copy2) => [copy2.shapeId, copy2.newShapeId]));
|
|
49200
|
+
const names = new Map(["Name", "NameU"].map((name) => [name, /* @__PURE__ */ new Set()]));
|
|
49201
|
+
for (const node of Array.from(root.getElementsByTagName("*")))
|
|
49202
|
+
if (node.localName === "Shape")
|
|
49203
|
+
for (const [name, occupied] of names) {
|
|
49204
|
+
const value = attribute3(node, name);
|
|
49205
|
+
if (value !== void 0) occupied.add(value.toLowerCase());
|
|
49206
|
+
}
|
|
49207
|
+
const plans = [];
|
|
49208
|
+
let cloneNodes = 0, cloneCharacters = buildXml(root).length;
|
|
49209
|
+
for (const copy2 of edit.copies) {
|
|
49210
|
+
check3();
|
|
49211
|
+
const source2 = admitted(sourceRoot, copy2.shapeId);
|
|
49212
|
+
assertCloneLeaf(source2);
|
|
49213
|
+
assertUnlayeredShape(source2, document);
|
|
49214
|
+
assertShapeLocks(source2, document, ["LockSelect"]);
|
|
49215
|
+
for (const connects of children3(sourceRoot, "Connects"))
|
|
49216
|
+
for (const connection of children3(connects, "Connect"))
|
|
49217
|
+
if (["FromSheet", "ToSheet"].some((name) => attribute3(connection, name) === copy2.shapeId))
|
|
49218
|
+
fail2("UNSUPPORTED_DUPLICATE", "Glued shapes cannot be duplicated safely.");
|
|
49219
|
+
const x = numeric4(formattingCell(source2, "PinX")), y = numeric4(formattingCell(source2, "PinY"));
|
|
49220
|
+
for (const [name, offset2] of [
|
|
49221
|
+
["PinX", edit.offsetX],
|
|
49222
|
+
["PinY", edit.offsetY]
|
|
49223
|
+
]) {
|
|
49224
|
+
if (offset2 !== 0) assertEditableFormattingCell(formattingCell(source2, name));
|
|
49225
|
+
evaluate(key({ pageId: sourcePageId, shapeId: copy2.shapeId, cell: name }));
|
|
49226
|
+
}
|
|
49227
|
+
if (Math.abs(x + edit.offsetX) > 1e6 || Math.abs(y + edit.offsetY) > 1e6)
|
|
49228
|
+
fail2("UNSUPPORTED_DUPLICATE", "Duplicated pins exceed coordinate limits.");
|
|
49229
|
+
cloneNodes += source2.getElementsByTagName("*").length + 1;
|
|
49230
|
+
cloneCharacters += buildXml(source2).length;
|
|
49231
|
+
if (cloneNodes > 1e5 || cloneCharacters > 16 * 1024 * 1024)
|
|
49232
|
+
fail2("LIMIT_DUPLICATE", "Duplicated XML exceeds bounded expansion limits.");
|
|
49233
|
+
plans.push({ source: source2, id: copy2.newShapeId, x: x + edit.offsetX, y: y + edit.offsetY });
|
|
49234
|
+
}
|
|
49235
|
+
const order = new Map(
|
|
49236
|
+
children3(children3(sourceRoot, "Shapes")[0], "Shape").map((source2, index2) => [source2, index2])
|
|
49237
|
+
);
|
|
49238
|
+
plans.sort((a2, b) => order.get(a2.source) - order.get(b.source));
|
|
49239
|
+
if (!container.parentNode) root.insertBefore(container, children3(root, "Connects")[0] ?? null);
|
|
49240
|
+
const changed = [];
|
|
49241
|
+
for (const plan of plans) {
|
|
49242
|
+
check3();
|
|
49243
|
+
const shape2 = root.ownerDocument.importNode(plan.source, true);
|
|
49244
|
+
copyIdentity(shape2, plan.id, names);
|
|
49245
|
+
for (const node of [shape2, ...Array.from(shape2.getElementsByTagName("*"))]) {
|
|
49246
|
+
const source2 = executableCellFormula(attribute3(node, "F"));
|
|
49247
|
+
if (!source2) continue;
|
|
49248
|
+
const analysis = analyzeVisioFormula(source2);
|
|
49249
|
+
if (analysis.references.some((ref) => ref.shapeId !== void 0 && mapping.has(ref.shapeId)))
|
|
49250
|
+
node.setAttribute(
|
|
49251
|
+
"F",
|
|
49252
|
+
mapVisioFormulaSyntax(
|
|
49253
|
+
source2,
|
|
49254
|
+
(segment) => segment.replace(
|
|
49255
|
+
/\bSheet\.(\d+)!/gi,
|
|
49256
|
+
(match2, id) => mapping.has(id) ? `Sheet.${mapping.get(id)}!` : match2
|
|
49257
|
+
)
|
|
49258
|
+
)
|
|
49259
|
+
);
|
|
49260
|
+
}
|
|
49261
|
+
for (const [name, value, offset2] of [
|
|
49262
|
+
["PinX", plan.x, edit.offsetX],
|
|
49263
|
+
["PinY", plan.y, edit.offsetY]
|
|
49264
|
+
])
|
|
49265
|
+
if (offset2 !== 0) {
|
|
49266
|
+
setCell(shape2, name, value);
|
|
49267
|
+
changed.push({ pageId: edit.pageId, shapeId: plan.id, cell: name });
|
|
49268
|
+
}
|
|
49269
|
+
container.appendChild(shape2);
|
|
49270
|
+
}
|
|
49271
|
+
if (changed.length) {
|
|
49272
|
+
await assertGeometryPackageScope(
|
|
49273
|
+
pkg,
|
|
49274
|
+
pagePaths,
|
|
49275
|
+
plans.map((plan) => ({
|
|
49276
|
+
type: "move-shape",
|
|
49277
|
+
pageId: edit.pageId,
|
|
49278
|
+
shapeId: plan.id,
|
|
49279
|
+
x: plan.x,
|
|
49280
|
+
y: plan.y
|
|
49281
|
+
})),
|
|
49282
|
+
check3,
|
|
49283
|
+
roots
|
|
49284
|
+
);
|
|
49285
|
+
const depends = createVisioDependencyQuery(roots, { check: check3 });
|
|
49286
|
+
for (const plan of plans) {
|
|
49287
|
+
const clone = children3(container, "Shape").find((node) => attribute3(node, "ID") === plan.id);
|
|
49288
|
+
for (const section of children3(clone, "Section"))
|
|
49289
|
+
if (attribute3(section, "N") === "Field")
|
|
49290
|
+
for (const row2 of children3(section, "Row"))
|
|
49291
|
+
for (const cell of children3(row2, "Cell")) {
|
|
49292
|
+
check3();
|
|
49293
|
+
const name = `Field.${attribute3(row2, "N") ?? attribute3(row2, "IX") ?? "0"}.${attribute3(cell, "N") ?? ""}`;
|
|
49294
|
+
if (depends({ pageId: edit.pageId, shapeId: plan.id, cell: name }, changed))
|
|
49295
|
+
fail2(
|
|
49296
|
+
"UNSUPPORTED_DUPLICATE",
|
|
49297
|
+
"Pin-dependent text fields need native display-cache regeneration."
|
|
49298
|
+
);
|
|
49299
|
+
}
|
|
49300
|
+
}
|
|
49301
|
+
}
|
|
49302
|
+
const dirty = /* @__PURE__ */ new Set([edit.pageId]);
|
|
49303
|
+
for (const id of recalculateVisioCells(roots, changed, { check: check3 })) dirty.add(id);
|
|
49304
|
+
return [...dirty];
|
|
49305
|
+
}
|
|
49306
|
+
function assertCloneLeaf(source2) {
|
|
49307
|
+
if (Array.from(source2.getElementsByTagName("*")).some(
|
|
49308
|
+
(node) => node.localName === "Shape" && (node.namespaceURI === VISIO_NS || node.namespaceURI === VISIO_LEGACY_NS)
|
|
49309
|
+
))
|
|
49310
|
+
fail2("UNSUPPORTED_DUPLICATE", "Nested Visio shape identities cannot be copied as leaf XML.");
|
|
49311
|
+
}
|
|
49312
|
+
|
|
49313
|
+
// visio/clipboard-resources.ts
|
|
49314
|
+
async function clipboardResources(pkg) {
|
|
49315
|
+
const path2 = await related(pkg, "", "document");
|
|
49316
|
+
if (path2 !== "visio/document.xml")
|
|
49317
|
+
fail2("UNSUPPORTED_CLIPBOARD", "Clipboard requires the conventional document part.");
|
|
49318
|
+
const document = (await visioXml(pkg, path2, "VisioDocument")).cloneNode(true);
|
|
49319
|
+
for (const node of Array.from(document.childNodes))
|
|
49320
|
+
if (node.nodeType !== 1 || !["Colors", "FaceNames", "StyleSheets", "DocumentSheet"].includes(node.localName))
|
|
49321
|
+
document.removeChild(node);
|
|
49322
|
+
const resources = [{ path: path2, xml: buildXml(document) }];
|
|
49323
|
+
const relationships = (await pkg.readXml("visio/_rels/document.xml.rels")).cloneNode(
|
|
49324
|
+
true
|
|
49325
|
+
);
|
|
49326
|
+
for (const node of Array.from(relationships.childNodes))
|
|
49327
|
+
if (node.nodeType !== 1 || !(attribute3(node, "Type") ?? "").endsWith("/theme"))
|
|
49328
|
+
relationships.removeChild(node);
|
|
49329
|
+
resources.push({ path: "visio/_rels/document.xml.rels", xml: buildXml(relationships) });
|
|
49330
|
+
for (const name of pkg.paths().sort())
|
|
49331
|
+
if (/^visio\/theme\/(?:[^/]+\.xml|_rels\/[^/]+\.rels)$/.test(name))
|
|
49332
|
+
resources.push({ path: name, xml: buildXml(await pkg.readXml(name)) });
|
|
49333
|
+
return resources.sort((a2, b) => a2.path.localeCompare(b.path));
|
|
49334
|
+
}
|
|
49335
|
+
async function clipboardPageContext(pkg, pageId) {
|
|
49336
|
+
const document = await related(pkg, "", "document");
|
|
49337
|
+
const pagesPath = await related(pkg, document, "pages");
|
|
49338
|
+
const pages = children3(await visioXml(pkg, pagesPath, "Pages"), "Page");
|
|
49339
|
+
const matches2 = pages.filter((page2) => attribute3(page2, "ID") === pageId);
|
|
49340
|
+
if (matches2.length !== 1) fail2("EDIT_TARGET_NOT_FOUND", "Clipboard page must exist uniquely.");
|
|
49341
|
+
const page = matches2[0], sheets = children3(page, "PageSheet");
|
|
49342
|
+
if (sheets.length !== 1) fail2("UNSUPPORTED_CLIPBOARD", "One explicit PageSheet is required.");
|
|
49343
|
+
const scale2 = visioPageGeometryScale(
|
|
49344
|
+
readSheet(sheets[0]).cells,
|
|
49345
|
+
() => fail2("UNSUPPORTED_CLIPBOARD", "Page drawing ratio is unresolved.")
|
|
49346
|
+
);
|
|
49347
|
+
const context = page.ownerDocument.createElementNS(page.namespaceURI, "PageContext");
|
|
49348
|
+
context.setAttribute("PageNumber", String(pages.indexOf(page) + 1));
|
|
49349
|
+
context.setAttribute("PageCount", String(pages.length));
|
|
49350
|
+
for (const name of ["Background", "BackPage"]) {
|
|
49351
|
+
const value = attribute3(page, name);
|
|
49352
|
+
if (value !== void 0) context.setAttribute(name, value);
|
|
49353
|
+
}
|
|
49354
|
+
context.appendChild(sheets[0].cloneNode(true));
|
|
49355
|
+
return { xml: buildXml(context), scale: scale2 };
|
|
49356
|
+
}
|
|
49357
|
+
function assertClipboardResourceReferences(root, document) {
|
|
49358
|
+
const styles = new Map(
|
|
49359
|
+
children3(children3(document, "StyleSheets")[0], "StyleSheet").map((style2) => [
|
|
49360
|
+
attribute3(style2, "ID"),
|
|
49361
|
+
style2
|
|
49362
|
+
])
|
|
49363
|
+
);
|
|
49364
|
+
const fonts = children3(children3(document, "FaceNames")[0], "FaceName");
|
|
49365
|
+
const fontIds = new Set(fonts.map((font2, index2) => attribute3(font2, "ID") ?? String(index2)));
|
|
49366
|
+
const fontNames = new Set(
|
|
49367
|
+
fonts.map((font2) => attribute3(font2, "Name") ?? attribute3(font2, "NameU"))
|
|
49368
|
+
);
|
|
49369
|
+
const fontById = new Map(
|
|
49370
|
+
fonts.map((font2, index2) => [
|
|
49371
|
+
attribute3(font2, "ID") ?? String(index2),
|
|
49372
|
+
attribute3(font2, "Name") ?? attribute3(font2, "NameU")
|
|
49373
|
+
])
|
|
49374
|
+
);
|
|
49375
|
+
if (fontIds.size !== fonts.length || fontNames.size !== fonts.length || new Set([...fontNames].map((name) => name?.toLowerCase())).size !== fonts.length)
|
|
49376
|
+
fail2(
|
|
49377
|
+
"UNSUPPORTED_CLIPBOARD",
|
|
49378
|
+
"Clipboard font definitions must have unique IDs and family names."
|
|
49379
|
+
);
|
|
49380
|
+
const pool = [root, ...Array.from(root.getElementsByTagName("*"))], included = /* @__PURE__ */ new Set();
|
|
49381
|
+
const validateStyle = (id, category, seen = /* @__PURE__ */ new Set()) => {
|
|
49382
|
+
if (seen.has(id) || seen.size >= 64)
|
|
49383
|
+
fail2("UNSUPPORTED_CLIPBOARD", "Cyclic clipboard style ancestry.");
|
|
49384
|
+
const style2 = styles.get(id);
|
|
49385
|
+
if (!style2)
|
|
49386
|
+
fail2("UNSUPPORTED_CLIPBOARD", "Clipboard style reference does not exist in target.");
|
|
49387
|
+
if (!included.has(style2)) {
|
|
49388
|
+
included.add(style2);
|
|
49389
|
+
pool.push(style2, ...Array.from(style2.getElementsByTagName("*")));
|
|
49390
|
+
}
|
|
49391
|
+
seen.add(id);
|
|
49392
|
+
const parent = attribute3(style2, category);
|
|
49393
|
+
if (parent !== void 0 && parent !== id) validateStyle(parent, category, seen);
|
|
49394
|
+
};
|
|
49395
|
+
for (const node of pool) {
|
|
49396
|
+
for (const attr3 of Array.from(node.attributes))
|
|
49397
|
+
if (attr3.namespaceURI === "http://schemas.openxmlformats.org/officeDocument/2006/relationships")
|
|
49398
|
+
fail2("UNSUPPORTED_CLIPBOARD", "Relationship-bearing clipboard fragments are unsupported.");
|
|
49399
|
+
for (const category of ["FillStyle", "LineStyle", "TextStyle"]) {
|
|
49400
|
+
const id = attribute3(node, category);
|
|
49401
|
+
if (id !== void 0) validateStyle(id, category);
|
|
49402
|
+
}
|
|
49403
|
+
if (node.localName === "Cell" && ["Font", "BulletFont"].includes(attribute3(node, "N") ?? "")) {
|
|
49404
|
+
const value = attribute3(node, "V");
|
|
49405
|
+
if (value !== void 0 && value !== "Themed" && attribute3(node, "F") !== "Inh" && !fontIds.has(value) && !fontNames.has(value))
|
|
49406
|
+
fail2("UNSUPPORTED_CLIPBOARD", "Clipboard font does not exist in target FaceNames.");
|
|
49407
|
+
const formula = executableCellFormula(attribute3(node, "F"));
|
|
49408
|
+
const ast = formula ? parseVisioFormula(formula) : void 0;
|
|
49409
|
+
if (ast?.kind === "call" && ast.name === "FONT") {
|
|
49410
|
+
const arg = ast.args[0];
|
|
49411
|
+
if (ast.args.length !== 1 || arg?.kind !== "string" || !fontNames.has(arg.value) || value !== void 0 && (fontById.get(value) ?? value) !== arg.value)
|
|
49412
|
+
fail2("UNSUPPORTED_CLIPBOARD", "Clipboard font formula and existing font cache disagree.");
|
|
49413
|
+
}
|
|
49414
|
+
}
|
|
49415
|
+
}
|
|
49416
|
+
}
|
|
49417
|
+
|
|
49418
|
+
// visio/clipboard-xml.ts
|
|
49419
|
+
function assertClipboardXmlLimits(snapshot, check3) {
|
|
49420
|
+
let nodes = 0;
|
|
49421
|
+
for (const xml of [
|
|
49422
|
+
snapshot.pageContext,
|
|
49423
|
+
...snapshot.resources.map((resource) => resource.xml),
|
|
49424
|
+
...snapshot.shapes.map((shape2) => shape2.xml)
|
|
49425
|
+
]) {
|
|
49426
|
+
if (nodes >= 1e5) fail2("LIMIT_CLIPBOARD", "Clipboard aggregate node limit exceeded.");
|
|
49427
|
+
nodes += inspectXml(
|
|
49428
|
+
xml,
|
|
49429
|
+
{ ...DEFAULTS2, maxXmlChars: 8 * 1024 * 1024, maxXmlNodes: 1e5 - nodes },
|
|
49430
|
+
check3
|
|
49431
|
+
);
|
|
49432
|
+
}
|
|
49433
|
+
}
|
|
49434
|
+
function clipboardXml(xml, check3) {
|
|
49435
|
+
inspectXml(xml, { ...DEFAULTS2, maxXmlChars: 8 * 1024 * 1024, maxXmlNodes: 1e5 }, check3);
|
|
49436
|
+
const root = parseXml(xml).documentElement;
|
|
49437
|
+
inspectNamespaces(root, check3);
|
|
49438
|
+
return root;
|
|
49439
|
+
}
|
|
49440
|
+
function assertClipboardFormulaScope(root, ids, check3) {
|
|
49441
|
+
for (const node of [root, ...Array.from(root.getElementsByTagName("*"))]) {
|
|
49442
|
+
check3();
|
|
49443
|
+
const formula = executableCellFormula(attribute3(node, "F"));
|
|
49444
|
+
if (!formula) continue;
|
|
49445
|
+
const analysis = analyzeVisioFormula(formula, { });
|
|
49446
|
+
if (analysis.dynamic || analysis.references.some((ref) => ref.shapeId !== void 0 && !ids.has(ref.shapeId)))
|
|
49447
|
+
fail2(
|
|
49448
|
+
"UNSUPPORTED_CLIPBOARD",
|
|
49449
|
+
"Clipboard formulas reference uncaptured shapes or dynamic lookup."
|
|
49450
|
+
);
|
|
49451
|
+
let pageFunction = false;
|
|
49452
|
+
mapVisioFormulaSyntax(formula, (segment) => {
|
|
49453
|
+
pageFunction ||= /\b(?:PAGENUMBER|PAGECOUNT|PAGES)\s*\(/i.test(segment);
|
|
49454
|
+
return segment;
|
|
49455
|
+
});
|
|
49456
|
+
if (pageFunction)
|
|
49457
|
+
fail2(
|
|
49458
|
+
"UNSUPPORTED_CLIPBOARD",
|
|
49459
|
+
"Page-context clipboard functions require native cache regeneration."
|
|
49460
|
+
);
|
|
49461
|
+
}
|
|
49462
|
+
}
|
|
49463
|
+
function clipboardShapeRoot(snapshot, check3) {
|
|
49464
|
+
assertClipboardXmlLimits(snapshot, check3);
|
|
49465
|
+
const parseShape2 = (shape2) => {
|
|
49466
|
+
const node = clipboardXml(shape2.xml, check3);
|
|
49467
|
+
if (node.localName !== "Shape" || ![VISIO_NS, VISIO_LEGACY_NS].includes(node.namespaceURI ?? "") || attribute3(node, "ID") !== shape2.shapeId)
|
|
49468
|
+
fail2("INVALID_CLIPBOARD", "Clipboard XML must contain the declared Visio Shape.");
|
|
49469
|
+
return node;
|
|
49470
|
+
};
|
|
49471
|
+
const first3 = parseShape2(snapshot.shapes[0]);
|
|
49472
|
+
const root = clipboardXml(
|
|
49473
|
+
`<PageContents xmlns="${first3.namespaceURI}"><Shapes/></PageContents>`,
|
|
49474
|
+
check3
|
|
49475
|
+
);
|
|
49476
|
+
const container = root.firstChild;
|
|
49477
|
+
container.appendChild(root.ownerDocument.importNode(first3, true));
|
|
49478
|
+
for (let index2 = 1; index2 < snapshot.shapes.length; index2++) {
|
|
49479
|
+
check3();
|
|
49480
|
+
container.appendChild(
|
|
49481
|
+
root.ownerDocument.importNode(parseShape2(snapshot.shapes[index2]), true)
|
|
49482
|
+
);
|
|
49483
|
+
}
|
|
49484
|
+
if (root.getElementsByTagName("*").length > 1e5)
|
|
49485
|
+
fail2("LIMIT_CLIPBOARD", "Clipboard node limit exceeded.");
|
|
49486
|
+
assertClipboardFormulaScope(root, new Set(snapshot.selectionIds), check3);
|
|
49487
|
+
return root;
|
|
49488
|
+
}
|
|
49489
|
+
|
|
49490
|
+
// visio/edit-paste.ts
|
|
49491
|
+
async function pasteVisioShapes(pkg, pagePaths, roots, document, edit, check3) {
|
|
49492
|
+
assertClipboardXmlLimits(edit.clipboard, check3);
|
|
49493
|
+
const context = await clipboardPageContext(pkg, edit.pageId);
|
|
49494
|
+
if (context.scale !== edit.clipboard.sourceDrawingScale || buildXml(clipboardXml(edit.clipboard.pageContext, check3)) !== context.xml)
|
|
49495
|
+
fail2(
|
|
49496
|
+
"CLIPBOARD_CONTEXT_MISMATCH",
|
|
49497
|
+
"Clipboard requires matching page settings, ordinal and drawing ratio."
|
|
49498
|
+
);
|
|
49499
|
+
const actual = await clipboardResources(pkg);
|
|
49500
|
+
if (actual.length !== edit.clipboard.resources.length || actual.some((resource, index2) => {
|
|
49501
|
+
const captured = edit.clipboard.resources[index2];
|
|
49502
|
+
return captured.path !== resource.path || buildXml(clipboardXml(captured.xml, check3)) !== resource.xml;
|
|
49503
|
+
}))
|
|
49504
|
+
fail2(
|
|
49505
|
+
"CLIPBOARD_RESOURCE_MISMATCH",
|
|
49506
|
+
"Clipboard font, style and theme definitions differ from target."
|
|
49507
|
+
);
|
|
49508
|
+
const source2 = clipboardShapeRoot(edit.clipboard, check3);
|
|
49509
|
+
assertClipboardResourceReferences(source2, document);
|
|
49510
|
+
return duplicateVisioShapes(
|
|
49511
|
+
pkg,
|
|
49512
|
+
pagePaths,
|
|
49513
|
+
roots,
|
|
49514
|
+
document,
|
|
49515
|
+
{ ...edit},
|
|
49516
|
+
check3,
|
|
49517
|
+
{ root: source2, pageId: edit.clipboard.sourcePageId }
|
|
49518
|
+
);
|
|
49519
|
+
}
|
|
49520
|
+
|
|
49521
|
+
// visio/edit-delete.ts
|
|
49522
|
+
function deleteVisioShapes(roots, document, edits, check3) {
|
|
49523
|
+
const removed = /* @__PURE__ */ new Map();
|
|
49524
|
+
const shapes = [];
|
|
49525
|
+
for (const edit of edits) {
|
|
49526
|
+
check3();
|
|
49527
|
+
const ids = removed.get(edit.pageId) ?? /* @__PURE__ */ new Set();
|
|
49528
|
+
if (ids.has(edit.shapeId)) fail2("INVALID_EDIT", "A deletion target must occur only once.");
|
|
49529
|
+
ids.add(edit.shapeId);
|
|
49530
|
+
removed.set(edit.pageId, ids);
|
|
49531
|
+
const root = roots.get(edit.pageId);
|
|
49532
|
+
if (!root) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
|
|
49533
|
+
const shape2 = admitted(root, edit.shapeId, void 0, void 0, "delete");
|
|
49534
|
+
if (Array.from(shape2.getElementsByTagName("*")).some(
|
|
49535
|
+
(node) => (node.namespaceURI === VISIO_NS || node.namespaceURI === VISIO_LEGACY_NS) && node.localName === "Shape"
|
|
49536
|
+
))
|
|
49537
|
+
fail2(
|
|
49538
|
+
"UNSUPPORTED_GEOMETRY_EDIT",
|
|
49539
|
+
"Nested shape identities cannot be removed as a local leaf."
|
|
49540
|
+
);
|
|
49541
|
+
protectedShape(shape2, document);
|
|
49542
|
+
if (numeric4(cells(shape2).get("LockDelete"), 0) !== 0)
|
|
49543
|
+
fail2("EDIT_PROTECTED_CELL", "LockDelete prevents this operation.");
|
|
49544
|
+
shapes.push(shape2);
|
|
49545
|
+
}
|
|
49546
|
+
assertVisioShapesUnreferenced(roots, removed, { check: check3 });
|
|
49547
|
+
check3();
|
|
49548
|
+
for (const shape2 of shapes) shape2.parentNode.removeChild(shape2);
|
|
49549
|
+
return [...removed.keys()];
|
|
49550
|
+
}
|
|
49551
|
+
|
|
47008
49552
|
// visio/edit.ts
|
|
47009
49553
|
function positive3(value) {
|
|
47010
49554
|
if (!Number.isSafeInteger(value) || value <= 0)
|
|
@@ -47046,26 +49590,50 @@ async function editVsdx(input, edits, options = {}) {
|
|
|
47046
49590
|
}
|
|
47047
49591
|
const dirty = /* @__PURE__ */ new Map();
|
|
47048
49592
|
const roots = /* @__PURE__ */ new Map();
|
|
47049
|
-
const
|
|
49593
|
+
const geometryCommands = commands.filter(
|
|
49594
|
+
(command2) => command2.type !== "replace-plain-text" && command2.type !== "reorder-shape" && command2.type !== "duplicate-shapes" && command2.type !== "paste-shapes" && !isVisioFormatEdit(command2)
|
|
49595
|
+
);
|
|
47050
49596
|
let document;
|
|
47051
49597
|
let masterMovePins = emptyMasterMoveProof();
|
|
47052
|
-
if (
|
|
49598
|
+
if (geometryCommands.length || commands.some(
|
|
49599
|
+
(command2) => command2.type === "replace-plain-text" || isVisioFormatEdit(command2) || command2.type === "reorder-shape" || command2.type === "duplicate-shapes" || command2.type === "paste-shapes"
|
|
49600
|
+
)) {
|
|
47053
49601
|
for (const [pageId, path3] of pages) {
|
|
47054
49602
|
const sourceRoot = await visioXml(pkg, path3, "PageContents");
|
|
47055
49603
|
roots.set(pageId, sourceRoot.ownerDocument.cloneNode(true).documentElement);
|
|
47056
49604
|
}
|
|
47057
|
-
|
|
47058
|
-
|
|
47059
|
-
|
|
47060
|
-
|
|
47061
|
-
check3
|
|
47062
|
-
|
|
47063
|
-
)
|
|
49605
|
+
for (const [pageId, root] of roots) {
|
|
49606
|
+
const ids = new Set(
|
|
49607
|
+
geometryCommands.filter((command2) => command2.type === "create-text-box" && command2.pageId === pageId).map((command2) => command2.shapeId)
|
|
49608
|
+
);
|
|
49609
|
+
if (ids.size) await assertDuplicateScope(pkg, new Set(pages.values()), root, ids, check3);
|
|
49610
|
+
}
|
|
49611
|
+
if (geometryCommands.length)
|
|
49612
|
+
masterMovePins = await assertGeometryPackageScope(
|
|
49613
|
+
pkg,
|
|
49614
|
+
new Set(pages.values()),
|
|
49615
|
+
geometryCommands,
|
|
49616
|
+
check3,
|
|
49617
|
+
roots
|
|
49618
|
+
);
|
|
47064
49619
|
const path2 = await related(pkg, "", "document");
|
|
47065
49620
|
document = await visioXml(pkg, path2, "VisioDocument");
|
|
47066
49621
|
}
|
|
47067
49622
|
let textChanged = false;
|
|
47068
|
-
|
|
49623
|
+
if (commands.some((command2) => command2.type === "reorder-shape"))
|
|
49624
|
+
await assertShapeOrderPackageScope(pkg, check3);
|
|
49625
|
+
let formatChanged = false;
|
|
49626
|
+
let orderChanged = false;
|
|
49627
|
+
let duplicateChanged = false;
|
|
49628
|
+
let pasteChanged = false;
|
|
49629
|
+
const deletions = commands.filter(
|
|
49630
|
+
(command2) => command2.type === "delete-shape"
|
|
49631
|
+
);
|
|
49632
|
+
const deleteOnly = deletions.length > 0 && deletions.length === commands.length;
|
|
49633
|
+
if (deleteOnly)
|
|
49634
|
+
for (const pageId of deleteVisioShapes(roots, document, deletions, check3))
|
|
49635
|
+
dirty.set(pages.get(pageId), roots.get(pageId));
|
|
49636
|
+
for (const command2 of deleteOnly ? [] : commands) {
|
|
47069
49637
|
check3();
|
|
47070
49638
|
const path2 = pages.get(command2.pageId);
|
|
47071
49639
|
if (!path2) fail2("EDIT_TARGET_NOT_FOUND", "Page does not exist.");
|
|
@@ -47076,10 +49644,42 @@ async function editVsdx(input, edits, options = {}) {
|
|
|
47076
49644
|
roots.set(command2.pageId, root);
|
|
47077
49645
|
}
|
|
47078
49646
|
if (command2.type === "replace-plain-text") {
|
|
47079
|
-
if (
|
|
49647
|
+
if (await replaceScopedPlainText(pkg, new Set(pages.values()), roots, document, command2, check3)) {
|
|
47080
49648
|
dirty.set(path2, root);
|
|
47081
49649
|
textChanged = true;
|
|
47082
49650
|
}
|
|
49651
|
+
} else if (isVisioFormatEdit(command2)) {
|
|
49652
|
+
if (await applyFormattingEdit(pkg, new Set(pages.values()), roots, document, command2, check3)) {
|
|
49653
|
+
dirty.set(path2, root);
|
|
49654
|
+
formatChanged = true;
|
|
49655
|
+
}
|
|
49656
|
+
} else if (command2.type === "reorder-shape") {
|
|
49657
|
+
if (reorderVisioShape(root, document, command2, check3)) {
|
|
49658
|
+
dirty.set(path2, root);
|
|
49659
|
+
orderChanged = true;
|
|
49660
|
+
}
|
|
49661
|
+
} else if (command2.type === "paste-shapes") {
|
|
49662
|
+
for (const pageId of await pasteVisioShapes(
|
|
49663
|
+
pkg,
|
|
49664
|
+
new Set(pages.values()),
|
|
49665
|
+
roots,
|
|
49666
|
+
document,
|
|
49667
|
+
command2,
|
|
49668
|
+
check3
|
|
49669
|
+
))
|
|
49670
|
+
dirty.set(pages.get(pageId), roots.get(pageId));
|
|
49671
|
+
pasteChanged = true;
|
|
49672
|
+
} else if (command2.type === "duplicate-shapes") {
|
|
49673
|
+
for (const pageId of await duplicateVisioShapes(
|
|
49674
|
+
pkg,
|
|
49675
|
+
new Set(pages.values()),
|
|
49676
|
+
roots,
|
|
49677
|
+
document,
|
|
49678
|
+
command2,
|
|
49679
|
+
check3
|
|
49680
|
+
))
|
|
49681
|
+
dirty.set(pages.get(pageId), roots.get(pageId));
|
|
49682
|
+
duplicateChanged = true;
|
|
47083
49683
|
} else {
|
|
47084
49684
|
for (const pageId of applyGeometryEdit(roots, document, command2, check3, masterMovePins))
|
|
47085
49685
|
dirty.set(pages.get(pageId), roots.get(pageId));
|
|
@@ -47114,17 +49714,50 @@ async function editVsdx(input, edits, options = {}) {
|
|
|
47114
49714
|
return {
|
|
47115
49715
|
bytes,
|
|
47116
49716
|
changedParts: [...dirty.keys()],
|
|
47117
|
-
diagnostics:
|
|
47118
|
-
|
|
47119
|
-
|
|
47120
|
-
|
|
47121
|
-
|
|
47122
|
-
|
|
47123
|
-
|
|
47124
|
-
|
|
47125
|
-
|
|
47126
|
-
|
|
47127
|
-
|
|
49717
|
+
diagnostics: [
|
|
49718
|
+
...pasteChanged ? [
|
|
49719
|
+
{
|
|
49720
|
+
code: "edit-paste-experimental",
|
|
49721
|
+
message: "Captured shape XML was pasted with compatible resources and page context. Clipboard placement and cross-document fidelity are limited to supported cases."
|
|
49722
|
+
}
|
|
49723
|
+
] : [],
|
|
49724
|
+
...duplicateChanged ? [
|
|
49725
|
+
{
|
|
49726
|
+
code: "edit-duplicate-experimental",
|
|
49727
|
+
message: "Local shape XML was copied and supported pin-dependent caches were recalculated. Native fidelity is limited to tested cases."
|
|
49728
|
+
}
|
|
49729
|
+
] : [],
|
|
49730
|
+
...dirty.size && textChanged ? [
|
|
49731
|
+
{
|
|
49732
|
+
code: "edit-caches-not-recalculated",
|
|
49733
|
+
message: "Plain text changed; affected or unknown formula dependencies were refused. Untouched caches were preserved. Native fidelity is limited to tested cases."
|
|
49734
|
+
}
|
|
49735
|
+
] : [],
|
|
49736
|
+
...dirty.size && deleteOnly ? [
|
|
49737
|
+
{
|
|
49738
|
+
code: "edit-delete-experimental",
|
|
49739
|
+
message: "Reference-closed local shapes were deleted. Retained formulas and caches were preserved; glue healing and inherited shape deletion remain unsupported."
|
|
49740
|
+
}
|
|
49741
|
+
] : [],
|
|
49742
|
+
...dirty.size && geometryCommands.length && !deleteOnly ? [
|
|
49743
|
+
{
|
|
49744
|
+
code: "edit-geometry-experimental",
|
|
49745
|
+
message: "Supported affected geometry caches were recalculated. Native Visio reopen and rendering fidelity remain unverified."
|
|
49746
|
+
}
|
|
49747
|
+
] : [],
|
|
49748
|
+
...formatChanged ? [
|
|
49749
|
+
{
|
|
49750
|
+
code: "edit-formatting-experimental",
|
|
49751
|
+
message: "Text and solid shape formatting was changed without recalculating text layout. Native Visio reopen and rendering fidelity remain unverified."
|
|
49752
|
+
}
|
|
49753
|
+
] : [],
|
|
49754
|
+
...orderChanged ? [
|
|
49755
|
+
{
|
|
49756
|
+
code: "edit-shape-order-experimental",
|
|
49757
|
+
message: "Local sibling shape order was changed. Native Visio reopen and rendering fidelity remain unverified."
|
|
49758
|
+
}
|
|
49759
|
+
] : []
|
|
49760
|
+
]
|
|
47128
49761
|
};
|
|
47129
49762
|
}
|
|
47130
49763
|
|