@ai-matrx/office 0.8.22 → 0.8.23

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.
@@ -45,7 +45,7 @@ interface SheetRange {
45
45
  * column width, worksheet name. C5b: formula text in cells (`f`, array `ref`) and defined names. Shared
46
46
  * formulas (`si`) stay barriers (see transform.ts cellBarrier); ranged resources are C5c.
47
47
  */
48
- type SheetFamily = "cell" | "structure" | "merge" | "size" | "name" | "defname" | "numfmt" | "count" | "sheet" | "sort";
48
+ type SheetFamily = "cell" | "structure" | "merge" | "size" | "name" | "defname" | "numfmt" | "count" | "sheet" | "sort" | "anchor";
49
49
  interface CoveredEntry {
50
50
  readonly kind: "covered";
51
51
  readonly family: SheetFamily;
@@ -45,7 +45,7 @@ interface SheetRange {
45
45
  * column width, worksheet name. C5b: formula text in cells (`f`, array `ref`) and defined names. Shared
46
46
  * formulas (`si`) stay barriers (see transform.ts cellBarrier); ranged resources are C5c.
47
47
  */
48
- type SheetFamily = "cell" | "structure" | "merge" | "size" | "name" | "defname" | "numfmt" | "count" | "sheet" | "sort";
48
+ type SheetFamily = "cell" | "structure" | "merge" | "size" | "name" | "defname" | "numfmt" | "count" | "sheet" | "sort" | "anchor";
49
49
  interface CoveredEntry {
50
50
  readonly kind: "covered";
51
51
  readonly family: SheetFamily;
@@ -32,6 +32,8 @@ var SHEET_MUTATIONS = {
32
32
  "sheet.mutation.insert-sheet": covered("sheet", "index", "sheet"),
33
33
  "sheet.mutation.remove-sheet": covered("sheet", "sheetIndex", "sheetsLeft"),
34
34
  "sheet.mutation.set-worksheet-order": covered("sheet", "fromOrder", "toOrder"),
35
+ // ── covered (C9): our own cell comment anchors (comment-anchor-transform.ts; not emitted by Univer) ──────
36
+ "matrx.mutation.set-comment-anchor": covered("anchor", "anchorId", "cell"),
35
37
  "sheet.mutation.reorder-range": covered("sort", "range", "order"),
36
38
  // ── never travels ────────────────────────────────────────────────────────────────────────────────
37
39
  "formula.mutation.set-formula-calculation-start": never(FORMULA_RESULT),
@@ -483,6 +485,74 @@ function refSheetsFor(texts, sheets) {
483
485
  return Object.keys(out).length ? out : void 0;
484
486
  }
485
487
 
488
+ // src/collab/sheets/comment-anchor-transform.ts
489
+ var SET_SHEET_COMMENT_ANCHOR = "matrx.mutation.set-comment-anchor";
490
+ var REMOVE_SHEET = "sheet.mutation.remove-sheet";
491
+ function structuralAxisOp(id, params) {
492
+ const p = params;
493
+ switch (id) {
494
+ case "sheet.mutation.insert-row":
495
+ return p.range ? { axis: "row", op: { kind: "insert", at: p.range.startRow, count: p.range.endRow - p.range.startRow + 1 } } : null;
496
+ case "sheet.mutation.remove-rows":
497
+ return p.range ? { axis: "row", op: { kind: "remove", start: p.range.startRow, count: p.range.endRow - p.range.startRow + 1 } } : null;
498
+ case "sheet.mutation.insert-col":
499
+ return p.range ? { axis: "col", op: { kind: "insert", at: p.range.startColumn, count: p.range.endColumn - p.range.startColumn + 1 } } : null;
500
+ case "sheet.mutation.remove-col":
501
+ return p.range ? { axis: "col", op: { kind: "remove", start: p.range.startColumn, count: p.range.endColumn - p.range.startColumn + 1 } } : null;
502
+ case "sheet.mutation.move-rows":
503
+ return p.sourceRange && p.targetRange ? { axis: "row", op: { kind: "move", from: p.sourceRange.startRow, count: p.sourceRange.endRow - p.sourceRange.startRow + 1, to: p.targetRange.startRow } } : null;
504
+ case "sheet.mutation.move-columns":
505
+ return p.sourceRange && p.targetRange ? {
506
+ axis: "col",
507
+ op: { kind: "move", from: p.sourceRange.startColumn, count: p.sourceRange.endColumn - p.sourceRange.startColumn + 1, to: p.targetRange.startColumn }
508
+ } : null;
509
+ default:
510
+ return null;
511
+ }
512
+ }
513
+ function moveSheetAnchorCell(cell, sheet, id, params) {
514
+ if (String(params.subUnitId ?? "") !== sheet) return cell;
515
+ if (id === REMOVE_SHEET) return null;
516
+ const s = structuralAxisOp(id, params);
517
+ if (!s) return cell;
518
+ if (s.axis === "row") {
519
+ const row = mapIndex(s.op, cell.row);
520
+ return row === null ? null : row === cell.row ? cell : { row, col: cell.col };
521
+ }
522
+ const col = mapIndex(s.op, cell.col);
523
+ return col === null ? null : col === cell.col ? cell : { row: cell.row, col };
524
+ }
525
+ function colName(c) {
526
+ let s = "";
527
+ for (let n = c + 1; n > 0; n = Math.floor((n - 1) / 26)) s = String.fromCharCode(65 + (n - 1) % 26) + s;
528
+ return s;
529
+ }
530
+ var sheetCellName = (cell) => `${colName(cell.col)}${cell.row + 1}`;
531
+ function cellOf(m) {
532
+ const c = m.params.cell;
533
+ return c && typeof c.row === "number" && typeof c.col === "number" ? c : null;
534
+ }
535
+ var ok = (op, lost = [], dropped = []) => ({ op, lost, dropped });
536
+ var label = (m) => {
537
+ const c = cellOf(m);
538
+ return `${String(m.params.subUnitId ?? "")}!${c ? sheetCellName(c) : "?"} comment`;
539
+ };
540
+ function transformCommentAnchor(x, y, side) {
541
+ const xa = x.id === SET_SHEET_COMMENT_ANCHOR;
542
+ const ya = y.id === SET_SHEET_COMMENT_ANCHOR;
543
+ if (!xa && !ya) return null;
544
+ if (!xa) return ok([x]);
545
+ if (ya) {
546
+ if (x.params.anchorId !== y.params.anchorId || x.params.subUnitId !== y.params.subUnitId) return ok([x]);
547
+ return side === "left" ? ok([x], [label(y)]) : ok([], [], [label(x)]);
548
+ }
549
+ const cell = cellOf(x);
550
+ if (!cell) return ok([x]);
551
+ const moved = moveSheetAnchorCell(cell, String(x.params.subUnitId ?? ""), y.id, y.params);
552
+ if (!moved) return ok([], [], [label(x)]);
553
+ return ok([moved === cell ? x : { id: x.id, params: { ...x.params, cell: moved } }]);
554
+ }
555
+
486
556
  // src/collab/sheets/transform/transform.ts
487
557
  var SHEET_TRANSFORMER_VERSION = "c5c-1";
488
558
  var ID = {
@@ -514,16 +584,16 @@ var ID = {
514
584
  var PAIR_BARRIERS = {};
515
585
  var pairKey = (a, b) => a < b ? `${a}|${b}` : `${b}|${a}`;
516
586
  var barrier2 = (reason) => ({ barrier: true, reason });
517
- var ok = (op, lost = [], dropped = []) => ({ op, lost, dropped });
587
+ var ok2 = (op, lost = [], dropped = []) => ({ op, lost, dropped });
518
588
  var flip = (side) => side === "left" ? "right" : "left";
519
589
  var sheetOf = (m) => String(m.params.subUnitId ?? "");
520
- function colName(c) {
590
+ function colName2(c) {
521
591
  let s = "";
522
592
  for (let n = c + 1; n > 0; n = Math.floor((n - 1) / 26)) s = String.fromCharCode(65 + (n - 1) % 26) + s;
523
593
  return s;
524
594
  }
525
- var cellRef = (sheet, row, col) => `${sheet}!${colName(col)}${row + 1}`;
526
- var rangeRef = (sheet, r) => `${sheet}!${colName(r.startColumn)}${r.startRow + 1}:${colName(r.endColumn)}${r.endRow + 1}`;
595
+ var cellRef = (sheet, row, col) => `${sheet}!${colName2(col)}${row + 1}`;
596
+ var rangeRef = (sheet, r) => `${sheet}!${colName2(r.startColumn)}${r.startRow + 1}:${colName2(r.endColumn)}${r.endRow + 1}`;
527
597
  function structuralOf(m) {
528
598
  const p = m.params;
529
599
  switch (m.id) {
@@ -778,9 +848,9 @@ function transformCell(X, Y, side) {
778
848
  return { entries: Object.keys(out).length ? [out, ...tail] : tail, xLost, yLost };
779
849
  }
780
850
  function transformCellsOverCells(x, y, side) {
781
- if (sheetOf(x) !== sheetOf(y)) return ok([x]);
851
+ if (sheetOf(x) !== sheetOf(y)) return ok2([x]);
782
852
  const ycells = cellsOf(y);
783
- if (!cellsOverlap(cellsOf(x), ycells)) return ok([x]);
853
+ if (!cellsOverlap(cellsOf(x), ycells)) return ok2([x]);
784
854
  const xd = isDerived(x);
785
855
  const yd = isDerived(y);
786
856
  const eff = derivedSide(x, y, side);
@@ -806,7 +876,7 @@ function transformCellsOverCells(x, y, side) {
806
876
  });
807
877
  if (why) return barrier2(why);
808
878
  const op = passes.filter((p) => !isEmptyMatrix(p)).map((p) => cellsMutation(x, p));
809
- return ok(op, lost, dropped);
879
+ return ok2(op, lost, dropped);
810
880
  }
811
881
  var SIDE_CAR_PARAMS = ["refSheets", "previousName", "derived", "sheetIndex", "sheetsLeft"];
812
882
  var isDerived = (m) => m.params.derived === true;
@@ -877,7 +947,7 @@ function cellThrough(sheet, change, r, c) {
877
947
  return nr === null || nc === null ? null : [nr, nc];
878
948
  }
879
949
  function cellsOverChange(x, change) {
880
- if (!hasFormula(x) && (change.kind !== "axis" || change.sheet !== sheetOf(x))) return ok([x]);
950
+ if (!hasFormula(x) && (change.kind !== "axis" || change.sheet !== sheetOf(x))) return ok2([x]);
881
951
  const ctx = formulaCtx(x);
882
952
  const out = {};
883
953
  const dropped = [];
@@ -906,9 +976,9 @@ function cellsOverChange(x, change) {
906
976
  });
907
977
  if (why) return barrier2(why);
908
978
  const rsAfter = refSheetsAfter(ctx.refSheets, change);
909
- if (!changed && JSON.stringify(rsAfter ?? null) === JSON.stringify(ctx.refSheets ?? null)) return ok([x]);
979
+ if (!changed && JSON.stringify(rsAfter ?? null) === JSON.stringify(ctx.refSheets ?? null)) return ok2([x]);
910
980
  const params = { ...withRefSheets(x.params, rsAfter), cellValue: out };
911
- return ok(isEmptyMatrix(out) ? [] : [{ id: x.id, params }], [], dropped);
981
+ return ok2(isEmptyMatrix(out) ? [] : [{ id: x.id, params }], [], dropped);
912
982
  }
913
983
  function rewritesOf(y, change) {
914
984
  if (!hasFormula(y)) return null;
@@ -955,36 +1025,36 @@ function formulaPair(x, y, side) {
955
1025
  const fy = familyOf(y.id);
956
1026
  const SET_NAME_BARRIER = "set-defined-name without previousName (capture must record the name it replaces) against formula text";
957
1027
  if (fx === "defname" && fy === "defname") {
958
- if (String(x.params.id) !== String(y.params.id)) return ok([x]);
1028
+ if (String(x.params.id) !== String(y.params.id)) return ok2([x]);
959
1029
  const eff = derivedSide(x, y, side);
960
- if (eff === "left") return ok([x], isDerived(y) ? [] : [`defined name "${String(y.params.name)}"`]);
961
- return ok([], [], isDerived(x) ? [] : [`defined name "${String(x.params.name)}"`]);
1030
+ if (eff === "left") return ok2([x], isDerived(y) ? [] : [`defined name "${String(y.params.name)}"`]);
1031
+ return ok2([], [], isDerived(x) ? [] : [`defined name "${String(x.params.name)}"`]);
962
1032
  }
963
1033
  if (fx === "defname") {
964
1034
  if (fy === "cell") {
965
1035
  if (setNameWithoutPrevious(x) && hasFormula(y)) return barrier2(SET_NAME_BARRIER);
966
1036
  const ch2 = refChangeOf(x);
967
- if (!ch2) return ok([x]);
1037
+ if (!ch2) return ok2([x]);
968
1038
  const add = rewritesOf(y, ch2);
969
1039
  if (typeof add === "string") return barrier2(add);
970
- return ok(add ? [x, add] : [x]);
1040
+ return ok2(add ? [x, add] : [x]);
971
1041
  }
972
1042
  const ch = refChangeOf(y);
973
- if (!ch) return ok([x]);
1043
+ if (!ch) return ok2([x]);
974
1044
  const r = definedNameThrough(x, ch);
975
- return typeof r === "string" ? barrier2(r) : ok([r.op]);
1045
+ return typeof r === "string" ? barrier2(r) : ok2([r.op]);
976
1046
  }
977
1047
  if (fy === "defname") {
978
1048
  if (fx === "cell") {
979
1049
  if (setNameWithoutPrevious(y) && hasFormula(x)) return barrier2(SET_NAME_BARRIER);
980
1050
  const ch2 = refChangeOf(y);
981
- return ch2 ? cellsOverChange(x, ch2) : ok([x]);
1051
+ return ch2 ? cellsOverChange(x, ch2) : ok2([x]);
982
1052
  }
983
1053
  const ch = refChangeOf(x);
984
- if (!ch) return ok([x]);
1054
+ if (!ch) return ok2([x]);
985
1055
  const r = definedNameThrough(y, ch);
986
1056
  if (typeof r === "string") return barrier2(r);
987
- return ok(r.changed ? [x, asDerived(r.op)] : [x]);
1057
+ return ok2(r.changed ? [x, asDerived(r.op)] : [x]);
988
1058
  }
989
1059
  if (fx === "cell") {
990
1060
  const ch = refChangeOf(y);
@@ -999,7 +1069,7 @@ function formulaPair(x, y, side) {
999
1069
  });
1000
1070
  const add = rewritesOf(y, ch);
1001
1071
  if (typeof add === "string") return barrier2(add);
1002
- return ok(add ? [x, add] : [x], lost);
1072
+ return ok2(add ? [x, add] : [x], lost);
1003
1073
  }
1004
1074
  return null;
1005
1075
  }
@@ -1147,20 +1217,20 @@ function numfmtPair(x, y, side, sx, sy) {
1147
1217
  const nx = isNumfmt(x);
1148
1218
  const ny = isNumfmt(y);
1149
1219
  if (!nx && !ny) return null;
1150
- if (nx && sy) return ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsThrough(sy, p.ranges) }))));
1151
- if (ny && sx) return ok([x]);
1220
+ if (nx && sy) return ok2(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsThrough(sy, p.ranges) }))));
1221
+ if (ny && sx) return ok2([x]);
1152
1222
  if (nx && ny) {
1153
- if (side === "left") return ok([x]);
1223
+ if (side === "left") return ok2([x]);
1154
1224
  const ys = nfParts(y).flatMap((p) => p.ranges);
1155
- return ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) }))));
1225
+ return ok2(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) }))));
1156
1226
  }
1157
1227
  if (nx && y.id === ID.values) {
1158
- if (side === "left") return ok([x]);
1228
+ if (side === "left") return ok2([x]);
1159
1229
  const ys = nWrites(y);
1160
- return ys.length ? ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) })))) : ok([x]);
1230
+ return ys.length ? ok2(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) })))) : ok2([x]);
1161
1231
  }
1162
1232
  if (ny && x.id === ID.values) {
1163
- if (side === "left") return ok([x]);
1233
+ if (side === "left") return ok2([x]);
1164
1234
  const out = {};
1165
1235
  const tail = {};
1166
1236
  let touched = false;
@@ -1186,31 +1256,31 @@ function numfmtPair(x, y, side, sx, sy) {
1186
1256
  }
1187
1257
  putCell(out, r, c, v);
1188
1258
  });
1189
- if (!touched) return ok([x]);
1259
+ if (!touched) return ok2([x]);
1190
1260
  const ops = [];
1191
1261
  if (!isEmptyMatrix(out)) ops.push(cellsMutation(x, out));
1192
1262
  if (!isEmptyMatrix(tail)) ops.push({ id: ID.values, params: { subUnitId: sheetOf(x), cellValue: tail } });
1193
- return ok(ops);
1263
+ return ok2(ops);
1194
1264
  }
1195
- return ok([x]);
1265
+ return ok2([x]);
1196
1266
  }
1197
1267
  var isCount = (m) => m.id === ID.rowCount || m.id === ID.colCount;
1198
1268
  var countAxis = (m) => m.id === ID.rowCount ? "row" : "col";
1199
1269
  var countKey = (m) => m.id === ID.rowCount ? "rowCount" : "columnCount";
1200
1270
  function countPair(x, y, sy) {
1201
- if (!isCount(x)) return isCount(y) ? ok([x]) : null;
1271
+ if (!isCount(x)) return isCount(y) ? ok2([x]) : null;
1202
1272
  const k = countKey(x);
1203
1273
  const v = Number(x.params[k]);
1204
1274
  if (sy) {
1205
- if (sy.axis !== countAxis(x) || sy.op.kind === "move") return ok([x]);
1275
+ if (sy.axis !== countAxis(x) || sy.op.kind === "move") return ok2([x]);
1206
1276
  const d = sy.op.kind === "insert" ? sy.op.count : -sy.op.count;
1207
- return ok([{ id: x.id, params: { ...x.params, [k]: Math.max(1, v + d) } }]);
1277
+ return ok2([{ id: x.id, params: { ...x.params, [k]: Math.max(1, v + d) } }]);
1208
1278
  }
1209
1279
  if (isCount(y) && y.id === x.id) {
1210
1280
  const w = Number(y.params[k]);
1211
- return ok([w > v ? { id: x.id, params: { ...x.params, [k]: w } } : x]);
1281
+ return ok2([w > v ? { id: x.id, params: { ...x.params, [k]: w } } : x]);
1212
1282
  }
1213
- return ok([x]);
1283
+ return ok2([x]);
1214
1284
  }
1215
1285
  var isSheetOp = (m) => m.id === ID.insertSheet || m.id === ID.removeSheet || m.id === ID.sheetOrder;
1216
1286
  var sheetIdOf = (m) => m.id === ID.insertSheet ? String(m.params.sheet?.id ?? "") : sheetOf(m);
@@ -1243,31 +1313,31 @@ function sheetPair(x, y, side) {
1243
1313
  const b = sheetAxisOf(y);
1244
1314
  if (!a || !b) return barrier2("a sheet add or remove without its index (capture must call annotateSheetOps)");
1245
1315
  if (x.id === ID.insertSheet && y.id === ID.insertSheet && sheetIdOf(x) === sheetIdOf(y)) {
1246
- return JSON.stringify(x.params) === JSON.stringify(y.params) ? ok([]) : barrier2("the same sheet id added twice with different content");
1316
+ return JSON.stringify(x.params) === JSON.stringify(y.params) ? ok2([]) : barrier2("the same sheet id added twice with different content");
1247
1317
  }
1248
1318
  if (x.id === ID.removeSheet && typeof x.params.sheetsLeft === "number" && sheetIdOf(x) !== sheetIdOf(y) && (y.id === ID.removeSheet || y.id === ID.insertSheet)) {
1249
1319
  const left = x.params.sheetsLeft + (y.id === ID.insertSheet ? 1 : -1);
1250
1320
  if (left < 1) return barrier2("concurrent sheet removes would leave the workbook without a sheet");
1251
1321
  const out2 = transformAxis(a, b, side);
1252
1322
  if (!out2) return barrier2("sheet order: no transform");
1253
- return ok(out2.map((o) => buildSheetOp({ id: x.id, params: { ...x.params, sheetsLeft: left } }, o)));
1323
+ return ok2(out2.map((o) => buildSheetOp({ id: x.id, params: { ...x.params, sheetsLeft: left } }, o)));
1254
1324
  }
1255
1325
  const out = transformAxis(a, b, side);
1256
1326
  if (!out) return barrier2("sheet order: no transform");
1257
- return ok(out.map((o) => buildSheetOp(x, o)), [], out.length === 0 && x.id === ID.sheetOrder ? [`${sheetIdOf(x)}: sheet order`] : []);
1327
+ return ok2(out.map((o) => buildSheetOp(x, o)), [], out.length === 0 && x.id === ID.sheetOrder ? [`${sheetIdOf(x)}: sheet order`] : []);
1258
1328
  }
1259
1329
  if (ys) {
1260
- if (y.id !== ID.removeSheet) return ok([x]);
1330
+ if (y.id !== ID.removeSheet) return ok2([x]);
1261
1331
  const gone2 = sheetOf(y);
1262
1332
  if (namesSheet(x, gone2)) return barrier2("a formula names a sheet removed at the same time");
1263
1333
  if (sheetOf(x) === gone2 && x.id !== ID.setName && x.id !== ID.removeName)
1264
- return ok([], [], isDerived(x) ? [] : [`${gone2}: the sheet was removed`]);
1265
- return ok([x]);
1334
+ return ok2([], [], isDerived(x) ? [] : [`${gone2}: the sheet was removed`]);
1335
+ return ok2([x]);
1266
1336
  }
1267
- if (x.id !== ID.removeSheet) return ok([x]);
1337
+ if (x.id !== ID.removeSheet) return ok2([x]);
1268
1338
  const gone = sheetOf(x);
1269
1339
  if (namesSheet(y, gone)) return barrier2("a formula names a sheet removed at the same time");
1270
- return ok([x], sheetOf(y) === gone && !isDerived(y) && y.id !== ID.setName && y.id !== ID.removeName ? [`${gone}: the sheet was removed`] : []);
1340
+ return ok2([x], sheetOf(y) === gone && !isDerived(y) && y.id !== ID.setName && y.id !== ID.removeName ? [`${gone}: the sheet was removed`] : []);
1271
1341
  }
1272
1342
  function annotateSheetOps(group, sheetOrder) {
1273
1343
  const order = [...sheetOrder];
@@ -1365,22 +1435,22 @@ function sortPair(x, y, sx, sy) {
1365
1435
  const a = sortOf(x).range;
1366
1436
  const b = sortOf(y).range;
1367
1437
  const overlap = a.startRow <= b.endRow && b.startRow <= a.endRow && a.startColumn <= b.endColumn && b.startColumn <= a.endColumn;
1368
- return overlap ? barrier2("two sorts of overlapping ranges at once") : ok([x]);
1438
+ return overlap ? barrier2("two sorts of overlapping ranges at once") : ok2([x]);
1369
1439
  }
1370
1440
  if (xs) {
1371
1441
  if (sy) {
1372
1442
  const t = sortThrough(sortOf(x), sy);
1373
- return t ? ok(buildSort(x, t)) : barrier2("a row or column move through a sorted range");
1443
+ return t ? ok2(buildSort(x, t)) : barrier2("a row or column move through a sorted range");
1374
1444
  }
1375
- return ok([x]);
1445
+ return ok2([x]);
1376
1446
  }
1377
1447
  const o = sortOf(y);
1378
1448
  const Q = sortQ(o);
1379
1449
  const moved = (r) => r >= o.range.startRow && r <= o.range.endRow && Q.has(r);
1380
1450
  if (sx) {
1381
- if (sx.axis === "col") return sx.op.kind === "move" && !sortThrough(o, sx) ? barrier2("a column move through a sorted range") : ok([x]);
1382
- if (sx.op.kind === "insert") return ok([x]);
1383
- if (sx.op.kind === "move") return sortThrough(o, sx) ? ok([x]) : barrier2("a row move through a sorted range");
1451
+ if (sx.axis === "col") return sx.op.kind === "move" && !sortThrough(o, sx) ? barrier2("a column move through a sorted range") : ok2([x]);
1452
+ if (sx.op.kind === "insert") return ok2([x]);
1453
+ if (sx.op.kind === "move") return sortThrough(o, sx) ? ok2([x]) : barrier2("a row move through a sorted range");
1384
1454
  const rows = [];
1385
1455
  let partial = false;
1386
1456
  for (let i = sx.op.start; i < sx.op.start + sx.op.count; i++) {
@@ -1388,7 +1458,7 @@ function sortPair(x, y, sx, sy) {
1388
1458
  rows.push(Q.get(i) ?? i);
1389
1459
  }
1390
1460
  if (partial) return barrier2("a row remove against a concurrent sort of those rows");
1391
- return ok([x]);
1461
+ return ok2([x]);
1392
1462
  }
1393
1463
  if (x.id === ID.values) {
1394
1464
  const out = {};
@@ -1399,7 +1469,7 @@ function sortPair(x, y, sx, sy) {
1399
1469
  changed = true;
1400
1470
  } else putCell(out, r, c, v);
1401
1471
  });
1402
- return changed ? ok([cellsMutation(x, out)]) : ok([x]);
1472
+ return changed ? ok2([cellsMutation(x, out)]) : ok2([x]);
1403
1473
  }
1404
1474
  if (isNumfmt(x)) {
1405
1475
  const parts = nfParts(x).map((p) => {
@@ -1415,9 +1485,9 @@ function sortPair(x, y, sx, sy) {
1415
1485
  }
1416
1486
  return { ...p, ranges };
1417
1487
  });
1418
- return ok(nfBuild(x, parts));
1488
+ return ok2(nfBuild(x, parts));
1419
1489
  }
1420
- return ok([x]);
1490
+ return ok2([x]);
1421
1491
  }
1422
1492
  function familyOf(id) {
1423
1493
  const e = SHEET_MUTATIONS[id];
@@ -1433,13 +1503,15 @@ function transformMutation(x, y, side) {
1433
1503
  if (why) return barrier2(why);
1434
1504
  }
1435
1505
  }
1506
+ const ca = transformCommentAnchor(x, y, side);
1507
+ if (ca) return ca;
1436
1508
  const pb = PAIR_BARRIERS[pairKey(x.id, y.id)];
1437
1509
  if (pb) return barrier2(`${x.id} \xD7 ${y.id}: ${pb.reason}${pb.seed === null ? "" : ` (fuzz seed ${pb.seed})`}`);
1438
1510
  const sp = sheetPair(x, y, side);
1439
1511
  if (sp) return sp;
1440
1512
  const fp = formulaPair(x, y, side);
1441
1513
  if (fp) return fp;
1442
- if (sheetOf(x) !== sheetOf(y)) return ok([x]);
1514
+ if (sheetOf(x) !== sheetOf(y)) return ok2([x]);
1443
1515
  const fx = familyOf(x.id);
1444
1516
  const fy = familyOf(y.id);
1445
1517
  const sy = structuralOf(y);
@@ -1451,11 +1523,11 @@ function transformMutation(x, y, side) {
1451
1523
  const np = numfmtPair(x, y, side, sx, sy);
1452
1524
  if (np) return np;
1453
1525
  if (sx && sy) {
1454
- if (sx.axis !== sy.axis) return ok([x]);
1526
+ if (sx.axis !== sy.axis) return ok2([x]);
1455
1527
  const out = transformAxis(sx.op, sy.op, side);
1456
1528
  if (!out) return barrier2(`${x.id} over ${y.id}: moved blocks overlap in part, or the block would split`);
1457
1529
  const dropped = out.length === 0 && sx.op.kind === "move" ? [`${sheetOf(x)}: moved ${sx.axis}s`] : [];
1458
- return ok(out.map((o) => buildStructural(x, sx.axis, o)), [], dropped);
1530
+ return ok2(out.map((o) => buildStructural(x, sx.axis, o)), [], dropped);
1459
1531
  }
1460
1532
  if (sy) {
1461
1533
  if (fx === "merge") {
@@ -1466,23 +1538,23 @@ function transformMutation(x, y, side) {
1466
1538
  if (t) kept.push(t);
1467
1539
  else dropped.push(rangeRef(sheetOf(x), r));
1468
1540
  }
1469
- return ok(kept.length ? [withRanges(x, kept)] : [], [], x.id === ID.addMerge ? dropped : []);
1541
+ return ok2(kept.length ? [withRanges(x, kept)] : [], [], x.id === ID.addMerge ? dropped : []);
1470
1542
  }
1471
1543
  if (fx === "size") {
1472
1544
  const size = sizeOf(x);
1473
- if (size.axis !== sy.axis) return ok([x]);
1545
+ if (size.axis !== sy.axis) return ok2([x]);
1474
1546
  const next = /* @__PURE__ */ new Map();
1475
1547
  for (const [i, v] of size.values) {
1476
1548
  const m = mapIndex(sy.op, i);
1477
1549
  if (m !== null) next.set(m, v);
1478
1550
  }
1479
1551
  const built = buildSize(x, next);
1480
- return ok(built ? [built] : []);
1552
+ return ok2(built ? [built] : []);
1481
1553
  }
1482
- return ok([x]);
1554
+ return ok2([x]);
1483
1555
  }
1484
1556
  if (sx) {
1485
- if (fy !== "merge" || y.id !== ID.addMerge) return ok([x]);
1557
+ if (fy !== "merge" || y.id !== ID.addMerge) return ok2([x]);
1486
1558
  const remove = [];
1487
1559
  const add = [];
1488
1560
  for (const r of mergeRanges(y)) {
@@ -1492,11 +1564,11 @@ function transformMutation(x, y, side) {
1492
1564
  if (t.range) add.push(t.range);
1493
1565
  }
1494
1566
  const lostMerges = mergeRanges(y).filter((r) => mergeThrough(sx, r).range === null).map((r) => rangeRef(sheetOf(y), r));
1495
- if (!remove.length) return ok([x], lostMerges);
1567
+ if (!remove.length) return ok2([x], lostMerges);
1496
1568
  const sheet = sheetOf(x);
1497
1569
  const pre = sx.op.kind === "insert" ? [] : [mergeMutation(ID.removeMerge, sheet, remove)];
1498
1570
  const mid = sx.op.kind === "insert" ? [mergeMutation(ID.removeMerge, sheet, remove)] : [];
1499
- return ok([...pre, x, ...mid, ...add.length ? [mergeMutation(ID.addMerge, sheet, add)] : []], lostMerges);
1571
+ return ok2([...pre, x, ...mid, ...add.length ? [mergeMutation(ID.addMerge, sheet, add)] : []], lostMerges);
1500
1572
  }
1501
1573
  if (fx === "cell" && fy === "cell") return transformCellsOverCells(x, y, side);
1502
1574
  if (fx === "merge" && fy === "merge") {
@@ -1505,45 +1577,45 @@ function transformMutation(x, y, side) {
1505
1577
  const hit = (r) => yr.some((q) => intersects(r, q));
1506
1578
  const sheet = sheetOf(x);
1507
1579
  if (x.id === ID.addMerge && y.id === ID.addMerge) {
1508
- if (!xr.some(hit)) return ok([x]);
1580
+ if (!xr.some(hit)) return ok2([x]);
1509
1581
  if (side === "left") {
1510
1582
  const lost = yr.filter((q) => xr.some((r) => intersects(r, q))).map((q) => rangeRef(sheet, q));
1511
- return ok([mergeMutation(ID.removeMerge, sheet, xr.filter(hit)), x], lost);
1583
+ return ok2([mergeMutation(ID.removeMerge, sheet, xr.filter(hit)), x], lost);
1512
1584
  }
1513
1585
  const kept = xr.filter((r) => !hit(r));
1514
- return ok(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
1586
+ return ok2(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
1515
1587
  }
1516
1588
  if (x.id === ID.addMerge && y.id === ID.removeMerge) {
1517
- if (side === "left" || !xr.some(hit)) return ok([x], side === "left" && xr.some(hit) ? yr.filter((q) => xr.some((r) => intersects(r, q))).map((q) => rangeRef(sheet, q)) : []);
1589
+ if (side === "left" || !xr.some(hit)) return ok2([x], side === "left" && xr.some(hit) ? yr.filter((q) => xr.some((r) => intersects(r, q))).map((q) => rangeRef(sheet, q)) : []);
1518
1590
  const kept = xr.filter((r) => !hit(r));
1519
- return ok(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
1591
+ return ok2(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
1520
1592
  }
1521
1593
  if (x.id === ID.removeMerge && y.id === ID.addMerge) {
1522
1594
  const touched = yr.filter((q) => xr.some((r) => intersects(r, q)));
1523
- if (!touched.length) return ok([x]);
1524
- if (side === "left") return ok([x], touched.map((q) => rangeRef(sheet, q)));
1525
- return ok([x, mergeMutation(ID.addMerge, sheet, touched)], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
1595
+ if (!touched.length) return ok2([x]);
1596
+ if (side === "left") return ok2([x], touched.map((q) => rangeRef(sheet, q)));
1597
+ return ok2([x, mergeMutation(ID.addMerge, sheet, touched)], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
1526
1598
  }
1527
- return ok([x]);
1599
+ return ok2([x]);
1528
1600
  }
1529
1601
  if (fx === "size" && fy === "size") {
1530
1602
  const a = sizeOf(x);
1531
1603
  const b = sizeOf(y);
1532
- if (a.axis !== b.axis || a.attr !== b.attr) return ok([x]);
1604
+ if (a.axis !== b.axis || a.attr !== b.attr) return ok2([x]);
1533
1605
  if (side === "left") {
1534
1606
  const lost = [...a.values.keys()].filter((i) => b.values.has(i)).map((i) => `${sheetOf(x)}: ${a.axis} ${i + 1} ${a.attr}`);
1535
- return ok([x], lost);
1607
+ return ok2([x], lost);
1536
1608
  }
1537
1609
  const next = new Map([...a.values].filter(([i]) => !b.values.has(i)));
1538
1610
  const built = buildSize(x, next);
1539
1611
  const dropped = [...a.values.keys()].filter((i) => b.values.has(i)).map((i) => `${sheetOf(x)}: ${a.axis} ${i + 1} ${a.attr}`);
1540
- return ok(built ? [built] : [], [], dropped);
1612
+ return ok2(built ? [built] : [], [], dropped);
1541
1613
  }
1542
1614
  if (fx === "name" && fy === "name") {
1543
- if (side === "left") return ok([x], [`${sheetOf(x)}: name "${String(y.params.name)}"`]);
1544
- return ok([], [], [`${sheetOf(x)}: name "${String(x.params.name)}"`]);
1615
+ if (side === "left") return ok2([x], [`${sheetOf(x)}: name "${String(y.params.name)}"`]);
1616
+ return ok2([], [], [`${sheetOf(x)}: name "${String(x.params.name)}"`]);
1545
1617
  }
1546
- return ok([x]);
1618
+ return ok2([x]);
1547
1619
  }
1548
1620
  var blocked = (p) => !Array.isArray(p);
1549
1621
  function tSeq(xs, ys, side, acc) {