@sofereditor/core 0.2.0 → 0.3.1

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/index.cjs CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  BLOCK_SPECS: () => BLOCK_SPECS,
34
+ CLEAR_ALL_MARKS: () => CLEAR_ALL_MARKS,
34
35
  COMMAND_ORIGIN: () => COMMAND_ORIGIN,
35
36
  DEFAULT_PAGE_SETTINGS: () => DEFAULT_PAGE_SETTINGS,
36
37
  EditorDocument: () => EditorDocument,
@@ -38,8 +39,9 @@ __export(index_exports, {
38
39
  MARGIN_PRESETS: () => MARGIN_PRESETS,
39
40
  MAX_LIST_LEVEL: () => MAX_LIST_LEVEL,
40
41
  PAGE_PRESETS: () => PAGE_PRESETS,
42
+ SOFER_MIME: () => SOFER_MIME,
41
43
  TRACKED_ORIGINS: () => TRACKED_ORIGINS,
42
- Y: () => Y2,
44
+ Y: () => Y3,
43
45
  cellsInRect: () => cellsInRect,
44
46
  clearRectCells: () => clearRectCells,
45
47
  collapsedSelection: () => collapsedSelection,
@@ -47,20 +49,25 @@ __export(index_exports, {
47
49
  createBlock: () => createBlock,
48
50
  createCell: () => createCell,
49
51
  createTableBlock: () => createTableBlock,
52
+ decodeSelection: () => decodeSelection,
50
53
  dedentList: () => dedentList,
51
54
  defaultAttrsFor: () => defaultAttrsFor,
52
55
  deleteBackward: () => deleteBackward,
53
56
  deleteForward: () => deleteForward,
57
+ deleteSelection: () => deleteSelection,
54
58
  deleteTable: () => deleteTable,
55
59
  deleteTableColumn: () => deleteTableColumn,
56
60
  deleteTableRow: () => deleteTableRow,
57
61
  deltaLength: () => deltaLength,
58
62
  detectPreset: () => detectPreset,
63
+ encodeSelection: () => encodeSelection,
59
64
  expandTableRect: () => expandTableRect,
65
+ getBlockId: () => getBlockId,
60
66
  getMarksInRange: () => getMarksInRange,
61
67
  indentList: () => indentList,
62
68
  insertImage: () => insertImage,
63
69
  insertParagraph: () => insertParagraph,
70
+ insertSlice: () => insertSlice,
64
71
  insertTable: () => insertTable,
65
72
  insertTableColumn: () => insertTableColumn,
66
73
  insertTableRow: () => insertTableRow,
@@ -75,19 +82,25 @@ __export(index_exports, {
75
82
  mergeRight: () => mergeRight,
76
83
  mergeSelection: () => mergeSelection,
77
84
  mmToPx: () => mmToPx,
85
+ moveEmbedAnchor: () => moveEmbedAnchor,
78
86
  moveToNextCell: () => moveToNextCell,
79
87
  moveToPrevCell: () => moveToPrevCell,
88
+ newBlockId: () => newBlockId,
80
89
  orderedRange: () => orderedRange,
81
90
  positionsEqual: () => positionsEqual,
82
91
  pxToMm: () => pxToMm,
83
92
  removeMark: () => removeMark,
84
93
  sameTextRun: () => sameTextRun,
94
+ serializeSelection: () => serializeSelection,
85
95
  setBlockAttr: () => setBlockAttr,
86
96
  setBlockType: () => setBlockType,
97
+ setCellAttr: () => setCellAttr,
87
98
  setColumnWidth: () => setColumnWidth,
88
99
  setImageAttrs: () => setImageAttrs,
89
100
  setMark: () => setMark,
90
101
  sliceDelta: () => sliceDelta,
102
+ sliceToInlineDelta: () => sliceToInlineDelta,
103
+ sliceToText: () => sliceToText,
91
104
  spanOf: () => spanOf,
92
105
  splitCell: () => splitCell,
93
106
  splitListItem: () => splitListItem,
@@ -190,6 +203,19 @@ function withDefaults(partial) {
190
203
 
191
204
  // src/document.ts
192
205
  var Y = __toESM(require("yjs"), 1);
206
+ function newBlockId() {
207
+ try {
208
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
209
+ return crypto.randomUUID();
210
+ }
211
+ } catch {
212
+ }
213
+ return `b-${Math.random().toString(36).slice(2, 10)}${Date.now().toString(36)}`;
214
+ }
215
+ function getBlockId(block) {
216
+ const id = block.get("id");
217
+ return typeof id === "string" ? id : void 0;
218
+ }
193
219
  var EditorDocument = class _EditorDocument {
194
220
  ydoc;
195
221
  blocks;
@@ -451,6 +477,7 @@ function createBlock(type, initialText = "", attrs) {
451
477
  return createTableBlock(rows, cols);
452
478
  }
453
479
  const block = new Y.Map();
480
+ block.set("id", newBlockId());
454
481
  block.set("type", type);
455
482
  const yText = new Y.Text();
456
483
  if (initialText.length > 0) yText.insert(0, initialText);
@@ -467,6 +494,7 @@ function createTableBlock(rows, cols) {
467
494
  const r = Math.max(1, Math.trunc(rows));
468
495
  const c = Math.max(1, Math.trunc(cols));
469
496
  const block = new Y.Map();
497
+ block.set("id", newBlockId());
470
498
  block.set("type", "table");
471
499
  const attrsMap = new Y.Map();
472
500
  attrsMap.set("rows", r);
@@ -501,6 +529,7 @@ function buildEmptyBlockFromSerialized(block) {
501
529
  const rows = typeof block.attrs.rows === "number" ? Math.max(1, Math.trunc(block.attrs.rows)) : 1;
502
530
  const cols = typeof block.attrs.cols === "number" ? Math.max(1, Math.trunc(block.attrs.cols)) : 1;
503
531
  const yBlock = new Y.Map();
532
+ yBlock.set("id", typeof block.id === "string" ? block.id : newBlockId());
504
533
  yBlock.set("type", "table");
505
534
  const attrsMap = new Y.Map();
506
535
  attrsMap.set("rows", rows);
@@ -523,7 +552,9 @@ function buildEmptyBlockFromSerialized(block) {
523
552
  yBlock.set("cells", cellsArr);
524
553
  return yBlock;
525
554
  }
526
- return createBlock(block.type, "", block.attrs);
555
+ const yb = createBlock(block.type, "", block.attrs);
556
+ if (typeof block.id === "string") yb.set("id", block.id);
557
+ return yb;
527
558
  }
528
559
  function applyDeltaIntoBlock(yBlock, src) {
529
560
  if (!yBlock) return;
@@ -551,6 +582,95 @@ function spanOf(value) {
551
582
  return Math.max(1, Math.trunc(value));
552
583
  }
553
584
 
585
+ // src/collab-cursor.ts
586
+ var Y2 = __toESM(require("yjs"), 1);
587
+ function toBase64(bytes) {
588
+ if (typeof Buffer !== "undefined") return Buffer.from(bytes).toString("base64");
589
+ let s = "";
590
+ for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);
591
+ return btoa(s);
592
+ }
593
+ function fromBase64(b64) {
594
+ if (typeof Buffer !== "undefined") return new Uint8Array(Buffer.from(b64, "base64"));
595
+ const s = atob(b64);
596
+ const out = new Uint8Array(s.length);
597
+ for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
598
+ return out;
599
+ }
600
+ function yTextAt(doc, pos) {
601
+ const block = doc.blocks.get(pos.blockIndex);
602
+ if (!block) return null;
603
+ if (typeof pos.cellIndex === "number") {
604
+ const cells = block.get("cells");
605
+ const cell = cells?.get(pos.cellIndex);
606
+ const t2 = cell?.get("text");
607
+ return t2 instanceof Y2.Text ? t2 : null;
608
+ }
609
+ const t = block.get("text");
610
+ return t instanceof Y2.Text ? t : null;
611
+ }
612
+ function locateYText(doc, target) {
613
+ const blocks = doc.blocks;
614
+ for (let i = 0; i < blocks.length; i++) {
615
+ const block = blocks.get(i);
616
+ if (block.get("text") === target) return { blockIndex: i };
617
+ const cells = block.get("cells");
618
+ if (cells) {
619
+ for (let c = 0; c < cells.length; c++) {
620
+ if (cells.get(c)?.get("text") === target) {
621
+ return { blockIndex: i, cellIndex: c };
622
+ }
623
+ }
624
+ }
625
+ }
626
+ return null;
627
+ }
628
+ function encodePoint(doc, pos) {
629
+ const yText = yTextAt(doc, pos);
630
+ if (!yText) return null;
631
+ const offset = Math.max(0, Math.min(pos.offset, yText.length));
632
+ const rel = Y2.createRelativePositionFromTypeIndex(yText, offset);
633
+ const block = doc.blocks.get(pos.blockIndex);
634
+ const point = { rel: toBase64(Y2.encodeRelativePosition(rel)) };
635
+ const blockId = block ? getBlockId(block) : void 0;
636
+ if (blockId) point.blockId = blockId;
637
+ if (typeof pos.cellIndex === "number") point.cellIndex = pos.cellIndex;
638
+ return point;
639
+ }
640
+ function decodePoint(doc, enc) {
641
+ try {
642
+ const rel = Y2.decodeRelativePosition(fromBase64(enc.rel));
643
+ const abs = Y2.createAbsolutePositionFromRelativePosition(rel, doc.ydoc);
644
+ if (abs && abs.type instanceof Y2.Text) {
645
+ const loc = locateYText(doc, abs.type);
646
+ if (loc) return { ...loc, offset: abs.index };
647
+ }
648
+ } catch {
649
+ }
650
+ if (enc.blockId) {
651
+ for (let i = 0; i < doc.blocks.length; i++) {
652
+ if (getBlockId(doc.blocks.get(i)) === enc.blockId) {
653
+ const p = { blockIndex: i, offset: 0 };
654
+ if (typeof enc.cellIndex === "number") p.cellIndex = enc.cellIndex;
655
+ return p;
656
+ }
657
+ }
658
+ }
659
+ return null;
660
+ }
661
+ function encodeSelection(doc, sel) {
662
+ const anchor = encodePoint(doc, sel.anchor);
663
+ const focus = encodePoint(doc, sel.focus);
664
+ if (!anchor || !focus) return null;
665
+ return { anchor, focus };
666
+ }
667
+ function decodeSelection(doc, enc) {
668
+ const anchor = decodePoint(doc, enc.anchor);
669
+ const focus = decodePoint(doc, enc.focus);
670
+ if (!anchor || !focus) return null;
671
+ return { anchor, focus };
672
+ }
673
+
554
674
  // src/selection.ts
555
675
  function isCollapsed(sel) {
556
676
  return positionsEqual(sel.anchor, sel.focus);
@@ -579,6 +699,20 @@ function sameTextRun(a, b) {
579
699
  }
580
700
 
581
701
  // src/marks.ts
702
+ var ALL_MARKS = {
703
+ bold: true,
704
+ italic: true,
705
+ underline: true,
706
+ strike: true,
707
+ color: true,
708
+ fontFamily: true,
709
+ fontSize: true,
710
+ link: true,
711
+ comment: true
712
+ };
713
+ var CLEAR_ALL_MARKS = Object.fromEntries(
714
+ Object.keys(ALL_MARKS).map((k) => [k, null])
715
+ );
582
716
  function iterateRunsInRange(yText, start, end, visit) {
583
717
  if (start >= end) return;
584
718
  const delta = yText.toDelta();
@@ -703,7 +837,87 @@ function sameMarkValue(a, b) {
703
837
  }
704
838
 
705
839
  // src/commands.ts
706
- var Y2 = __toESM(require("yjs"), 1);
840
+ var Y3 = __toESM(require("yjs"), 1);
841
+
842
+ // src/clipboard.ts
843
+ var SOFER_MIME = "application/x-sofer-slice";
844
+ function deltaToText(delta) {
845
+ let s = "";
846
+ for (const op of delta) if (typeof op.insert === "string") s += op.insert;
847
+ return s;
848
+ }
849
+ function blockFromDelta(doc, blockIndex, cellIndex, delta) {
850
+ if (cellIndex != null) {
851
+ return { type: "paragraph", text: deltaToText(delta), delta, attrs: {} };
852
+ }
853
+ return {
854
+ type: doc.getBlockType(blockIndex) ?? "paragraph",
855
+ text: deltaToText(delta),
856
+ delta,
857
+ attrs: doc.getBlockAttrs(blockIndex)
858
+ };
859
+ }
860
+ function serializeSelection(doc, sel) {
861
+ if (isCollapsed(sel)) return null;
862
+ const { start, end } = orderedRange(sel);
863
+ if ((start.cellIndex ?? -1) !== (end.cellIndex ?? -1)) return null;
864
+ if (start.blockIndex === end.blockIndex) {
865
+ const yText = doc.textAt(start.blockIndex, start.cellIndex);
866
+ if (!yText) return null;
867
+ const delta = sliceDelta(yText.toDelta(), start.offset, end.offset);
868
+ return {
869
+ blocks: [blockFromDelta(doc, start.blockIndex, start.cellIndex, delta)],
870
+ openStart: start.offset > 0,
871
+ openEnd: end.offset < yText.length
872
+ };
873
+ }
874
+ if (start.cellIndex != null || end.cellIndex != null) return null;
875
+ for (let i = start.blockIndex; i <= end.blockIndex; i++) {
876
+ if (doc.getBlockType(i) === "table") return null;
877
+ }
878
+ const startText = doc.getBlockText(start.blockIndex);
879
+ const endText = doc.getBlockText(end.blockIndex);
880
+ if (!startText || !endText) return null;
881
+ const blocks = [];
882
+ blocks.push(
883
+ blockFromDelta(
884
+ doc,
885
+ start.blockIndex,
886
+ void 0,
887
+ sliceDelta(startText.toDelta(), start.offset, startText.length)
888
+ )
889
+ );
890
+ for (let i = start.blockIndex + 1; i < end.blockIndex; i++) {
891
+ const t = doc.getBlockText(i);
892
+ blocks.push(blockFromDelta(doc, i, void 0, t?.toDelta() ?? []));
893
+ }
894
+ blocks.push(
895
+ blockFromDelta(
896
+ doc,
897
+ end.blockIndex,
898
+ void 0,
899
+ sliceDelta(endText.toDelta(), 0, end.offset)
900
+ )
901
+ );
902
+ return {
903
+ blocks,
904
+ openStart: start.offset > 0,
905
+ openEnd: end.offset < endText.length
906
+ };
907
+ }
908
+ function sliceToText(slice) {
909
+ return slice.blocks.map((b) => deltaToText(b.delta)).join("\n");
910
+ }
911
+ function sliceToInlineDelta(slice) {
912
+ const out = [];
913
+ slice.blocks.forEach((b, i) => {
914
+ if (i > 0) out.push({ insert: "\n" });
915
+ out.push(...b.delta);
916
+ });
917
+ return out;
918
+ }
919
+
920
+ // src/commands.ts
707
921
  var COMMAND_ORIGIN = /* @__PURE__ */ Symbol("editor-command");
708
922
  function transact(doc, fn) {
709
923
  doc.ydoc.transact(fn, COMMAND_ORIGIN);
@@ -912,7 +1126,7 @@ function setBlockType(ctx, type, attrs) {
912
1126
  const block = ctx.doc.getBlock(i);
913
1127
  if (!block) continue;
914
1128
  block.set("type", type);
915
- const attrsMap = block.get("attrs") ?? new Y2.Map();
1129
+ const attrsMap = block.get("attrs") ?? new Y3.Map();
916
1130
  if (!block.get("attrs")) block.set("attrs", attrsMap);
917
1131
  const next = { ...defaultAttrsFor(type), ...attrs ?? {} };
918
1132
  const keep = new Set(Object.keys(next));
@@ -935,7 +1149,7 @@ function setBlockAttr(ctx, key, value) {
935
1149
  for (const i of indices) {
936
1150
  const block = ctx.doc.getBlock(i);
937
1151
  if (!block) continue;
938
- const attrsMap = block.get("attrs") ?? new Y2.Map();
1152
+ const attrsMap = block.get("attrs") ?? new Y3.Map();
939
1153
  if (!block.get("attrs")) block.set("attrs", attrsMap);
940
1154
  if (value === null || value === void 0) {
941
1155
  attrsMap.delete(key);
@@ -946,6 +1160,109 @@ function setBlockAttr(ctx, key, value) {
946
1160
  ctx.setSelection(sel);
947
1161
  });
948
1162
  }
1163
+ function setCellAttr(ctx, key, value) {
1164
+ transact(ctx.doc, () => {
1165
+ const sel = ctx.getSelection();
1166
+ const { blockIndex, cellIndex } = sel.focus;
1167
+ if (cellIndex == null || !ctx.doc.isTable(blockIndex)) return;
1168
+ const { cols } = ctx.doc.getTableSize(blockIndex);
1169
+ if (cols <= 0) return;
1170
+ const rect = tableRectSelection(ctx.doc, sel);
1171
+ const targets = [];
1172
+ if (rect) {
1173
+ for (let r = rect.top; r <= rect.bottom; r++)
1174
+ for (let c = rect.left; c <= rect.right; c++) targets.push(r * cols + c);
1175
+ } else {
1176
+ const real = ctx.doc.realCellIndex(blockIndex, cellIndex);
1177
+ if (real != null) targets.push(real);
1178
+ }
1179
+ for (const flat of targets) {
1180
+ if (ctx.doc.getCellAttrs(blockIndex, flat).covered) continue;
1181
+ const m = ctx.doc.getCellAttrsMap(blockIndex, flat);
1182
+ if (!m) continue;
1183
+ if (value === null || value === void 0) m.delete(key);
1184
+ else m.set(key, value);
1185
+ }
1186
+ ctx.setSelection(sel);
1187
+ });
1188
+ }
1189
+ function deleteSelection(ctx) {
1190
+ transact(ctx.doc, () => {
1191
+ const s = deleteRange(ctx.doc, ctx.getSelection());
1192
+ ctx.setSelection(s);
1193
+ });
1194
+ }
1195
+ function insertSlice(ctx, slice) {
1196
+ if (!slice.blocks || slice.blocks.length === 0) return;
1197
+ transact(ctx.doc, () => {
1198
+ let sel = ctx.getSelection();
1199
+ if (!isCollapsed(sel)) sel = deleteRange(ctx.doc, sel);
1200
+ const { blockIndex, cellIndex, offset } = sel.focus;
1201
+ if (cellIndex != null) {
1202
+ const cellText = ctx.doc.textAt(blockIndex, cellIndex);
1203
+ if (!cellText) return;
1204
+ const after = writeDeltaInto(cellText, offset, sliceToInlineDelta(slice));
1205
+ ctx.setSelection(collapsedSelection({ blockIndex, cellIndex, offset: after }));
1206
+ return;
1207
+ }
1208
+ const targetText = ctx.doc.getBlockText(blockIndex);
1209
+ if (!targetText) return;
1210
+ const full = targetText.toDelta();
1211
+ const tailDelta = sliceDelta(full, offset, deltaLength(full));
1212
+ targetText.delete(offset, targetText.length - offset);
1213
+ const blocks = slice.blocks;
1214
+ if (blocks.length === 1) {
1215
+ const afterS0 = writeDeltaInto(targetText, offset, blocks[0].delta);
1216
+ writeDeltaInto(targetText, afterS0, tailDelta);
1217
+ ctx.setSelection(collapsedSelection({ blockIndex, offset: afterS0 }));
1218
+ return;
1219
+ }
1220
+ const originalType = ctx.doc.getBlockType(blockIndex);
1221
+ const originalAttrs = ctx.doc.getBlockAttrs(blockIndex);
1222
+ let insertAt = blockIndex;
1223
+ if (slice.openStart) {
1224
+ writeDeltaInto(targetText, offset, blocks[0].delta);
1225
+ } else if (offset === 0) {
1226
+ const blk = ctx.doc.blocks.get(blockIndex);
1227
+ blk.set("type", blocks[0].type);
1228
+ const am = blk.get("attrs");
1229
+ am.clear();
1230
+ for (const [k, v] of Object.entries(blocks[0].attrs)) {
1231
+ if (v !== void 0) am.set(k, v);
1232
+ }
1233
+ writeDeltaInto(targetText, 0, blocks[0].delta);
1234
+ } else {
1235
+ const b = createBlock(blocks[0].type, "", blocks[0].attrs);
1236
+ ctx.doc.blocks.insert(++insertAt, [b]);
1237
+ writeDeltaInto(b.get("text"), 0, blocks[0].delta);
1238
+ }
1239
+ for (let i = 1; i < blocks.length - 1; i++) {
1240
+ const b = createBlock(blocks[i].type, "", blocks[i].attrs);
1241
+ ctx.doc.blocks.insert(++insertAt, [b]);
1242
+ writeDeltaInto(b.get("text"), 0, blocks[i].delta);
1243
+ }
1244
+ const last = blocks[blocks.length - 1];
1245
+ if (slice.openEnd) {
1246
+ const b = createBlock(last.type, "", last.attrs);
1247
+ ctx.doc.blocks.insert(++insertAt, [b]);
1248
+ const t = b.get("text");
1249
+ const caretPos = writeDeltaInto(t, 0, last.delta);
1250
+ writeDeltaInto(t, caretPos, tailDelta);
1251
+ ctx.setSelection(collapsedSelection({ blockIndex: insertAt, offset: caretPos }));
1252
+ } else {
1253
+ const b = createBlock(last.type, "", last.attrs);
1254
+ ctx.doc.blocks.insert(++insertAt, [b]);
1255
+ const lastLen = writeDeltaInto(b.get("text"), 0, last.delta);
1256
+ const lastIdx = insertAt;
1257
+ if (tailDelta.length > 0) {
1258
+ const tb = createBlock(originalType ?? "paragraph", "", originalAttrs);
1259
+ ctx.doc.blocks.insert(++insertAt, [tb]);
1260
+ writeDeltaInto(tb.get("text"), 0, tailDelta);
1261
+ }
1262
+ ctx.setSelection(collapsedSelection({ blockIndex: lastIdx, offset: lastLen }));
1263
+ }
1264
+ });
1265
+ }
949
1266
  function selectedBlockIndices(sel, blockCount) {
950
1267
  const { start, end } = orderedRange(sel);
951
1268
  const out = [];
@@ -1095,7 +1412,7 @@ function setBlockTypeAtIndex(doc, index, type, attrs) {
1095
1412
  const block = doc.getBlock(index);
1096
1413
  if (!block) return;
1097
1414
  block.set("type", type);
1098
- const attrsMap = block.get("attrs") ?? new Y2.Map();
1415
+ const attrsMap = block.get("attrs") ?? new Y3.Map();
1099
1416
  if (!block.get("attrs")) block.set("attrs", attrsMap);
1100
1417
  const next = { ...defaultAttrsFor(type), ...attrs };
1101
1418
  const keep = new Set(Object.keys(next));
@@ -1119,6 +1436,9 @@ function insertTable(ctx, rows, cols) {
1119
1436
  const focusBlock = Math.max(0, Math.min(sel.focus.blockIndex, ctx.doc.blockCount() - 1));
1120
1437
  const insertAt = focusBlock + 1;
1121
1438
  ctx.doc.blocks.insert(insertAt, [createTableBlock(r, c)]);
1439
+ if (insertAt === ctx.doc.blockCount() - 1) {
1440
+ ctx.doc.blocks.insert(insertAt + 1, [createBlock("paragraph")]);
1441
+ }
1122
1442
  ctx.setSelection(
1123
1443
  collapsedSelection({ blockIndex: insertAt, cellIndex: 0, offset: 0 })
1124
1444
  );
@@ -1727,11 +2047,10 @@ function writeDeltaInto(yText, pos, delta) {
1727
2047
  for (const op of delta) {
1728
2048
  if (typeof op.insert === "string") {
1729
2049
  if (op.insert.length === 0) continue;
1730
- if (op.attributes && Object.keys(op.attributes).length > 0) {
1731
- yText.insert(cursor, op.insert, op.attributes);
1732
- } else {
1733
- yText.insert(cursor, op.insert);
1734
- }
2050
+ yText.insert(cursor, op.insert, {
2051
+ ...CLEAR_ALL_MARKS,
2052
+ ...op.attributes ?? {}
2053
+ });
1735
2054
  cursor += op.insert.length;
1736
2055
  } else if (op.insert != null) {
1737
2056
  if (op.attributes && Object.keys(op.attributes).length > 0) {
@@ -1791,17 +2110,56 @@ function setImageAttrs(ctx, blockIndex, embedOffset, partial, cellIndex, newOffs
1791
2110
  yText.insert(insertAt, merged);
1792
2111
  });
1793
2112
  }
2113
+ var REANCHORABLE_LAYOUTS = /* @__PURE__ */ new Set(["front", "behind"]);
2114
+ function moveEmbedAnchor(ctx, from, to, newOffsetX, newOffsetY) {
2115
+ transact(ctx.doc, () => {
2116
+ const srcText = ctx.doc.textAt(from.blockIndex, from.cellIndex);
2117
+ if (!srcText) return;
2118
+ const delta = srcText.toDelta();
2119
+ let cursor = 0;
2120
+ let prev = null;
2121
+ for (const op of delta) {
2122
+ if (typeof op.insert === "string") {
2123
+ cursor += op.insert.length;
2124
+ continue;
2125
+ }
2126
+ if (cursor === from.offset && isImageEmbed(op.insert)) {
2127
+ prev = op.insert;
2128
+ break;
2129
+ }
2130
+ cursor += 1;
2131
+ }
2132
+ if (!prev) return;
2133
+ const layout = prev.layout ?? "inline";
2134
+ if (!REANCHORABLE_LAYOUTS.has(layout)) return;
2135
+ const dstText = ctx.doc.textAt(to.blockIndex, to.cellIndex);
2136
+ if (!dstText) return;
2137
+ const merged = { ...prev, offsetX: newOffsetX, offsetY: newOffsetY };
2138
+ const sameRun = srcText === dstText;
2139
+ srcText.delete(from.offset, 1);
2140
+ let landed = to.offset;
2141
+ if (sameRun && to.offset > from.offset) {
2142
+ landed = to.offset - 1;
2143
+ }
2144
+ landed = Math.max(0, Math.min(landed, dstText.length));
2145
+ dstText.insert(landed, merged);
2146
+ ctx.setSelection({
2147
+ anchor: { blockIndex: to.blockIndex, cellIndex: to.cellIndex, offset: landed },
2148
+ focus: { blockIndex: to.blockIndex, cellIndex: to.cellIndex, offset: landed + 1 }
2149
+ });
2150
+ });
2151
+ }
1794
2152
  function isCommandOrigin(origin) {
1795
2153
  return origin === COMMAND_ORIGIN;
1796
2154
  }
1797
2155
  var TRACKED_ORIGINS = /* @__PURE__ */ new Set([COMMAND_ORIGIN]);
1798
2156
 
1799
2157
  // src/history.ts
1800
- var Y3 = __toESM(require("yjs"), 1);
2158
+ var Y4 = __toESM(require("yjs"), 1);
1801
2159
  var EditorHistory = class {
1802
2160
  undoManager;
1803
2161
  constructor(doc) {
1804
- this.undoManager = new Y3.UndoManager(doc.blocks, {
2162
+ this.undoManager = new Y4.UndoManager(doc.blocks, {
1805
2163
  trackedOrigins: TRACKED_ORIGINS,
1806
2164
  captureTimeout: 400
1807
2165
  });
@@ -1819,6 +2177,7 @@ var EditorHistory = class {
1819
2177
  // Annotate the CommonJS export names for ESM import in node:
1820
2178
  0 && (module.exports = {
1821
2179
  BLOCK_SPECS,
2180
+ CLEAR_ALL_MARKS,
1822
2181
  COMMAND_ORIGIN,
1823
2182
  DEFAULT_PAGE_SETTINGS,
1824
2183
  EditorDocument,
@@ -1826,6 +2185,7 @@ var EditorHistory = class {
1826
2185
  MARGIN_PRESETS,
1827
2186
  MAX_LIST_LEVEL,
1828
2187
  PAGE_PRESETS,
2188
+ SOFER_MIME,
1829
2189
  TRACKED_ORIGINS,
1830
2190
  Y,
1831
2191
  cellsInRect,
@@ -1835,20 +2195,25 @@ var EditorHistory = class {
1835
2195
  createBlock,
1836
2196
  createCell,
1837
2197
  createTableBlock,
2198
+ decodeSelection,
1838
2199
  dedentList,
1839
2200
  defaultAttrsFor,
1840
2201
  deleteBackward,
1841
2202
  deleteForward,
2203
+ deleteSelection,
1842
2204
  deleteTable,
1843
2205
  deleteTableColumn,
1844
2206
  deleteTableRow,
1845
2207
  deltaLength,
1846
2208
  detectPreset,
2209
+ encodeSelection,
1847
2210
  expandTableRect,
2211
+ getBlockId,
1848
2212
  getMarksInRange,
1849
2213
  indentList,
1850
2214
  insertImage,
1851
2215
  insertParagraph,
2216
+ insertSlice,
1852
2217
  insertTable,
1853
2218
  insertTableColumn,
1854
2219
  insertTableRow,
@@ -1863,19 +2228,25 @@ var EditorHistory = class {
1863
2228
  mergeRight,
1864
2229
  mergeSelection,
1865
2230
  mmToPx,
2231
+ moveEmbedAnchor,
1866
2232
  moveToNextCell,
1867
2233
  moveToPrevCell,
2234
+ newBlockId,
1868
2235
  orderedRange,
1869
2236
  positionsEqual,
1870
2237
  pxToMm,
1871
2238
  removeMark,
1872
2239
  sameTextRun,
2240
+ serializeSelection,
1873
2241
  setBlockAttr,
1874
2242
  setBlockType,
2243
+ setCellAttr,
1875
2244
  setColumnWidth,
1876
2245
  setImageAttrs,
1877
2246
  setMark,
1878
2247
  sliceDelta,
2248
+ sliceToInlineDelta,
2249
+ sliceToText,
1879
2250
  spanOf,
1880
2251
  splitCell,
1881
2252
  splitListItem,