@sofereditor/core 0.1.0 → 0.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/index.js CHANGED
@@ -89,6 +89,19 @@ function withDefaults(partial) {
89
89
 
90
90
  // src/document.ts
91
91
  import * as Y from "yjs";
92
+ function newBlockId() {
93
+ try {
94
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
95
+ return crypto.randomUUID();
96
+ }
97
+ } catch {
98
+ }
99
+ return `b-${Math.random().toString(36).slice(2, 10)}${Date.now().toString(36)}`;
100
+ }
101
+ function getBlockId(block) {
102
+ const id = block.get("id");
103
+ return typeof id === "string" ? id : void 0;
104
+ }
92
105
  var EditorDocument = class _EditorDocument {
93
106
  ydoc;
94
107
  blocks;
@@ -121,7 +134,9 @@ var EditorDocument = class _EditorDocument {
121
134
  marginTop: pick("marginTop") ?? DEFAULT_PAGE_SETTINGS.marginTop,
122
135
  marginBottom: pick("marginBottom") ?? DEFAULT_PAGE_SETTINGS.marginBottom,
123
136
  marginLeft: pick("marginLeft") ?? DEFAULT_PAGE_SETTINGS.marginLeft,
124
- marginRight: pick("marginRight") ?? DEFAULT_PAGE_SETTINGS.marginRight
137
+ marginRight: pick("marginRight") ?? DEFAULT_PAGE_SETTINGS.marginRight,
138
+ systemHeaderTitle: pick("systemHeaderTitle"),
139
+ systemHeaderAuthor: pick("systemHeaderAuthor")
125
140
  };
126
141
  merged.preset = detectPreset(merged.width, merged.height);
127
142
  return merged;
@@ -257,6 +272,17 @@ var EditorDocument = class _EditorDocument {
257
272
  */
258
273
  loadFromJSON(serialized) {
259
274
  const { blocks: sourceBlocks, pageSettings } = normalizeSerialized(serialized);
275
+ const LOCK_KEY = "__importLock";
276
+ const LOCK_TTL_MS = 5e3;
277
+ const existing = this.docSettings.get(LOCK_KEY);
278
+ if (typeof existing === "number" && Date.now() - existing < LOCK_TTL_MS) {
279
+ const ageMs = Date.now() - existing;
280
+ console.warn(
281
+ `[EditorDocument.loadFromJSON] import j\xE1 em andamento (${ageMs}ms atr\xE1s, TTL ${LOCK_TTL_MS}ms) \u2014 ignorando esta chamada para evitar duplica\xE7\xE3o de blocks.`
282
+ );
283
+ return;
284
+ }
285
+ this.docSettings.set(LOCK_KEY, Date.now());
260
286
  this.ydoc.transact(() => {
261
287
  if (this.blocks.length > 0) {
262
288
  this.blocks.delete(0, this.blocks.length);
@@ -276,6 +302,7 @@ var EditorDocument = class _EditorDocument {
276
302
  this.docSettings.set(k, v);
277
303
  }
278
304
  }
305
+ this.docSettings.delete(LOCK_KEY);
279
306
  }, "import");
280
307
  }
281
308
  /** Build a fresh `EditorDocument` from a `SerializedDocument`. */
@@ -336,6 +363,7 @@ function createBlock(type, initialText = "", attrs) {
336
363
  return createTableBlock(rows, cols);
337
364
  }
338
365
  const block = new Y.Map();
366
+ block.set("id", newBlockId());
339
367
  block.set("type", type);
340
368
  const yText = new Y.Text();
341
369
  if (initialText.length > 0) yText.insert(0, initialText);
@@ -352,6 +380,7 @@ function createTableBlock(rows, cols) {
352
380
  const r = Math.max(1, Math.trunc(rows));
353
381
  const c = Math.max(1, Math.trunc(cols));
354
382
  const block = new Y.Map();
383
+ block.set("id", newBlockId());
355
384
  block.set("type", "table");
356
385
  const attrsMap = new Y.Map();
357
386
  attrsMap.set("rows", r);
@@ -386,6 +415,7 @@ function buildEmptyBlockFromSerialized(block) {
386
415
  const rows = typeof block.attrs.rows === "number" ? Math.max(1, Math.trunc(block.attrs.rows)) : 1;
387
416
  const cols = typeof block.attrs.cols === "number" ? Math.max(1, Math.trunc(block.attrs.cols)) : 1;
388
417
  const yBlock = new Y.Map();
418
+ yBlock.set("id", typeof block.id === "string" ? block.id : newBlockId());
389
419
  yBlock.set("type", "table");
390
420
  const attrsMap = new Y.Map();
391
421
  attrsMap.set("rows", rows);
@@ -408,7 +438,9 @@ function buildEmptyBlockFromSerialized(block) {
408
438
  yBlock.set("cells", cellsArr);
409
439
  return yBlock;
410
440
  }
411
- return createBlock(block.type, "", block.attrs);
441
+ const yb = createBlock(block.type, "", block.attrs);
442
+ if (typeof block.id === "string") yb.set("id", block.id);
443
+ return yb;
412
444
  }
413
445
  function applyDeltaIntoBlock(yBlock, src) {
414
446
  if (!yBlock) return;
@@ -436,6 +468,95 @@ function spanOf(value) {
436
468
  return Math.max(1, Math.trunc(value));
437
469
  }
438
470
 
471
+ // src/collab-cursor.ts
472
+ import * as Y2 from "yjs";
473
+ function toBase64(bytes) {
474
+ if (typeof Buffer !== "undefined") return Buffer.from(bytes).toString("base64");
475
+ let s = "";
476
+ for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);
477
+ return btoa(s);
478
+ }
479
+ function fromBase64(b64) {
480
+ if (typeof Buffer !== "undefined") return new Uint8Array(Buffer.from(b64, "base64"));
481
+ const s = atob(b64);
482
+ const out = new Uint8Array(s.length);
483
+ for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
484
+ return out;
485
+ }
486
+ function yTextAt(doc, pos) {
487
+ const block = doc.blocks.get(pos.blockIndex);
488
+ if (!block) return null;
489
+ if (typeof pos.cellIndex === "number") {
490
+ const cells = block.get("cells");
491
+ const cell = cells?.get(pos.cellIndex);
492
+ const t2 = cell?.get("text");
493
+ return t2 instanceof Y2.Text ? t2 : null;
494
+ }
495
+ const t = block.get("text");
496
+ return t instanceof Y2.Text ? t : null;
497
+ }
498
+ function locateYText(doc, target) {
499
+ const blocks = doc.blocks;
500
+ for (let i = 0; i < blocks.length; i++) {
501
+ const block = blocks.get(i);
502
+ if (block.get("text") === target) return { blockIndex: i };
503
+ const cells = block.get("cells");
504
+ if (cells) {
505
+ for (let c = 0; c < cells.length; c++) {
506
+ if (cells.get(c)?.get("text") === target) {
507
+ return { blockIndex: i, cellIndex: c };
508
+ }
509
+ }
510
+ }
511
+ }
512
+ return null;
513
+ }
514
+ function encodePoint(doc, pos) {
515
+ const yText = yTextAt(doc, pos);
516
+ if (!yText) return null;
517
+ const offset = Math.max(0, Math.min(pos.offset, yText.length));
518
+ const rel = Y2.createRelativePositionFromTypeIndex(yText, offset);
519
+ const block = doc.blocks.get(pos.blockIndex);
520
+ const point = { rel: toBase64(Y2.encodeRelativePosition(rel)) };
521
+ const blockId = block ? getBlockId(block) : void 0;
522
+ if (blockId) point.blockId = blockId;
523
+ if (typeof pos.cellIndex === "number") point.cellIndex = pos.cellIndex;
524
+ return point;
525
+ }
526
+ function decodePoint(doc, enc) {
527
+ try {
528
+ const rel = Y2.decodeRelativePosition(fromBase64(enc.rel));
529
+ const abs = Y2.createAbsolutePositionFromRelativePosition(rel, doc.ydoc);
530
+ if (abs && abs.type instanceof Y2.Text) {
531
+ const loc = locateYText(doc, abs.type);
532
+ if (loc) return { ...loc, offset: abs.index };
533
+ }
534
+ } catch {
535
+ }
536
+ if (enc.blockId) {
537
+ for (let i = 0; i < doc.blocks.length; i++) {
538
+ if (getBlockId(doc.blocks.get(i)) === enc.blockId) {
539
+ const p = { blockIndex: i, offset: 0 };
540
+ if (typeof enc.cellIndex === "number") p.cellIndex = enc.cellIndex;
541
+ return p;
542
+ }
543
+ }
544
+ }
545
+ return null;
546
+ }
547
+ function encodeSelection(doc, sel) {
548
+ const anchor = encodePoint(doc, sel.anchor);
549
+ const focus = encodePoint(doc, sel.focus);
550
+ if (!anchor || !focus) return null;
551
+ return { anchor, focus };
552
+ }
553
+ function decodeSelection(doc, enc) {
554
+ const anchor = decodePoint(doc, enc.anchor);
555
+ const focus = decodePoint(doc, enc.focus);
556
+ if (!anchor || !focus) return null;
557
+ return { anchor, focus };
558
+ }
559
+
439
560
  // src/selection.ts
440
561
  function isCollapsed(sel) {
441
562
  return positionsEqual(sel.anchor, sel.focus);
@@ -464,6 +585,20 @@ function sameTextRun(a, b) {
464
585
  }
465
586
 
466
587
  // src/marks.ts
588
+ var ALL_MARKS = {
589
+ bold: true,
590
+ italic: true,
591
+ underline: true,
592
+ strike: true,
593
+ color: true,
594
+ fontFamily: true,
595
+ fontSize: true,
596
+ link: true,
597
+ comment: true
598
+ };
599
+ var CLEAR_ALL_MARKS = Object.fromEntries(
600
+ Object.keys(ALL_MARKS).map((k) => [k, null])
601
+ );
467
602
  function iterateRunsInRange(yText, start, end, visit) {
468
603
  if (start >= end) return;
469
604
  const delta = yText.toDelta();
@@ -588,7 +723,87 @@ function sameMarkValue(a, b) {
588
723
  }
589
724
 
590
725
  // src/commands.ts
591
- import * as Y2 from "yjs";
726
+ import * as Y3 from "yjs";
727
+
728
+ // src/clipboard.ts
729
+ var SOFER_MIME = "application/x-sofer-slice";
730
+ function deltaToText(delta) {
731
+ let s = "";
732
+ for (const op of delta) if (typeof op.insert === "string") s += op.insert;
733
+ return s;
734
+ }
735
+ function blockFromDelta(doc, blockIndex, cellIndex, delta) {
736
+ if (cellIndex != null) {
737
+ return { type: "paragraph", text: deltaToText(delta), delta, attrs: {} };
738
+ }
739
+ return {
740
+ type: doc.getBlockType(blockIndex) ?? "paragraph",
741
+ text: deltaToText(delta),
742
+ delta,
743
+ attrs: doc.getBlockAttrs(blockIndex)
744
+ };
745
+ }
746
+ function serializeSelection(doc, sel) {
747
+ if (isCollapsed(sel)) return null;
748
+ const { start, end } = orderedRange(sel);
749
+ if ((start.cellIndex ?? -1) !== (end.cellIndex ?? -1)) return null;
750
+ if (start.blockIndex === end.blockIndex) {
751
+ const yText = doc.textAt(start.blockIndex, start.cellIndex);
752
+ if (!yText) return null;
753
+ const delta = sliceDelta(yText.toDelta(), start.offset, end.offset);
754
+ return {
755
+ blocks: [blockFromDelta(doc, start.blockIndex, start.cellIndex, delta)],
756
+ openStart: start.offset > 0,
757
+ openEnd: end.offset < yText.length
758
+ };
759
+ }
760
+ if (start.cellIndex != null || end.cellIndex != null) return null;
761
+ for (let i = start.blockIndex; i <= end.blockIndex; i++) {
762
+ if (doc.getBlockType(i) === "table") return null;
763
+ }
764
+ const startText = doc.getBlockText(start.blockIndex);
765
+ const endText = doc.getBlockText(end.blockIndex);
766
+ if (!startText || !endText) return null;
767
+ const blocks = [];
768
+ blocks.push(
769
+ blockFromDelta(
770
+ doc,
771
+ start.blockIndex,
772
+ void 0,
773
+ sliceDelta(startText.toDelta(), start.offset, startText.length)
774
+ )
775
+ );
776
+ for (let i = start.blockIndex + 1; i < end.blockIndex; i++) {
777
+ const t = doc.getBlockText(i);
778
+ blocks.push(blockFromDelta(doc, i, void 0, t?.toDelta() ?? []));
779
+ }
780
+ blocks.push(
781
+ blockFromDelta(
782
+ doc,
783
+ end.blockIndex,
784
+ void 0,
785
+ sliceDelta(endText.toDelta(), 0, end.offset)
786
+ )
787
+ );
788
+ return {
789
+ blocks,
790
+ openStart: start.offset > 0,
791
+ openEnd: end.offset < endText.length
792
+ };
793
+ }
794
+ function sliceToText(slice) {
795
+ return slice.blocks.map((b) => deltaToText(b.delta)).join("\n");
796
+ }
797
+ function sliceToInlineDelta(slice) {
798
+ const out = [];
799
+ slice.blocks.forEach((b, i) => {
800
+ if (i > 0) out.push({ insert: "\n" });
801
+ out.push(...b.delta);
802
+ });
803
+ return out;
804
+ }
805
+
806
+ // src/commands.ts
592
807
  var COMMAND_ORIGIN = /* @__PURE__ */ Symbol("editor-command");
593
808
  function transact(doc, fn) {
594
809
  doc.ydoc.transact(fn, COMMAND_ORIGIN);
@@ -797,7 +1012,7 @@ function setBlockType(ctx, type, attrs) {
797
1012
  const block = ctx.doc.getBlock(i);
798
1013
  if (!block) continue;
799
1014
  block.set("type", type);
800
- const attrsMap = block.get("attrs") ?? new Y2.Map();
1015
+ const attrsMap = block.get("attrs") ?? new Y3.Map();
801
1016
  if (!block.get("attrs")) block.set("attrs", attrsMap);
802
1017
  const next = { ...defaultAttrsFor(type), ...attrs ?? {} };
803
1018
  const keep = new Set(Object.keys(next));
@@ -820,7 +1035,7 @@ function setBlockAttr(ctx, key, value) {
820
1035
  for (const i of indices) {
821
1036
  const block = ctx.doc.getBlock(i);
822
1037
  if (!block) continue;
823
- const attrsMap = block.get("attrs") ?? new Y2.Map();
1038
+ const attrsMap = block.get("attrs") ?? new Y3.Map();
824
1039
  if (!block.get("attrs")) block.set("attrs", attrsMap);
825
1040
  if (value === null || value === void 0) {
826
1041
  attrsMap.delete(key);
@@ -831,6 +1046,109 @@ function setBlockAttr(ctx, key, value) {
831
1046
  ctx.setSelection(sel);
832
1047
  });
833
1048
  }
1049
+ function setCellAttr(ctx, key, value) {
1050
+ transact(ctx.doc, () => {
1051
+ const sel = ctx.getSelection();
1052
+ const { blockIndex, cellIndex } = sel.focus;
1053
+ if (cellIndex == null || !ctx.doc.isTable(blockIndex)) return;
1054
+ const { cols } = ctx.doc.getTableSize(blockIndex);
1055
+ if (cols <= 0) return;
1056
+ const rect = tableRectSelection(ctx.doc, sel);
1057
+ const targets = [];
1058
+ if (rect) {
1059
+ for (let r = rect.top; r <= rect.bottom; r++)
1060
+ for (let c = rect.left; c <= rect.right; c++) targets.push(r * cols + c);
1061
+ } else {
1062
+ const real = ctx.doc.realCellIndex(blockIndex, cellIndex);
1063
+ if (real != null) targets.push(real);
1064
+ }
1065
+ for (const flat of targets) {
1066
+ if (ctx.doc.getCellAttrs(blockIndex, flat).covered) continue;
1067
+ const m = ctx.doc.getCellAttrsMap(blockIndex, flat);
1068
+ if (!m) continue;
1069
+ if (value === null || value === void 0) m.delete(key);
1070
+ else m.set(key, value);
1071
+ }
1072
+ ctx.setSelection(sel);
1073
+ });
1074
+ }
1075
+ function deleteSelection(ctx) {
1076
+ transact(ctx.doc, () => {
1077
+ const s = deleteRange(ctx.doc, ctx.getSelection());
1078
+ ctx.setSelection(s);
1079
+ });
1080
+ }
1081
+ function insertSlice(ctx, slice) {
1082
+ if (!slice.blocks || slice.blocks.length === 0) return;
1083
+ transact(ctx.doc, () => {
1084
+ let sel = ctx.getSelection();
1085
+ if (!isCollapsed(sel)) sel = deleteRange(ctx.doc, sel);
1086
+ const { blockIndex, cellIndex, offset } = sel.focus;
1087
+ if (cellIndex != null) {
1088
+ const cellText = ctx.doc.textAt(blockIndex, cellIndex);
1089
+ if (!cellText) return;
1090
+ const after = writeDeltaInto(cellText, offset, sliceToInlineDelta(slice));
1091
+ ctx.setSelection(collapsedSelection({ blockIndex, cellIndex, offset: after }));
1092
+ return;
1093
+ }
1094
+ const targetText = ctx.doc.getBlockText(blockIndex);
1095
+ if (!targetText) return;
1096
+ const full = targetText.toDelta();
1097
+ const tailDelta = sliceDelta(full, offset, deltaLength(full));
1098
+ targetText.delete(offset, targetText.length - offset);
1099
+ const blocks = slice.blocks;
1100
+ if (blocks.length === 1) {
1101
+ const afterS0 = writeDeltaInto(targetText, offset, blocks[0].delta);
1102
+ writeDeltaInto(targetText, afterS0, tailDelta);
1103
+ ctx.setSelection(collapsedSelection({ blockIndex, offset: afterS0 }));
1104
+ return;
1105
+ }
1106
+ const originalType = ctx.doc.getBlockType(blockIndex);
1107
+ const originalAttrs = ctx.doc.getBlockAttrs(blockIndex);
1108
+ let insertAt = blockIndex;
1109
+ if (slice.openStart) {
1110
+ writeDeltaInto(targetText, offset, blocks[0].delta);
1111
+ } else if (offset === 0) {
1112
+ const blk = ctx.doc.blocks.get(blockIndex);
1113
+ blk.set("type", blocks[0].type);
1114
+ const am = blk.get("attrs");
1115
+ am.clear();
1116
+ for (const [k, v] of Object.entries(blocks[0].attrs)) {
1117
+ if (v !== void 0) am.set(k, v);
1118
+ }
1119
+ writeDeltaInto(targetText, 0, blocks[0].delta);
1120
+ } else {
1121
+ const b = createBlock(blocks[0].type, "", blocks[0].attrs);
1122
+ ctx.doc.blocks.insert(++insertAt, [b]);
1123
+ writeDeltaInto(b.get("text"), 0, blocks[0].delta);
1124
+ }
1125
+ for (let i = 1; i < blocks.length - 1; i++) {
1126
+ const b = createBlock(blocks[i].type, "", blocks[i].attrs);
1127
+ ctx.doc.blocks.insert(++insertAt, [b]);
1128
+ writeDeltaInto(b.get("text"), 0, blocks[i].delta);
1129
+ }
1130
+ const last = blocks[blocks.length - 1];
1131
+ if (slice.openEnd) {
1132
+ const b = createBlock(last.type, "", last.attrs);
1133
+ ctx.doc.blocks.insert(++insertAt, [b]);
1134
+ const t = b.get("text");
1135
+ const caretPos = writeDeltaInto(t, 0, last.delta);
1136
+ writeDeltaInto(t, caretPos, tailDelta);
1137
+ ctx.setSelection(collapsedSelection({ blockIndex: insertAt, offset: caretPos }));
1138
+ } else {
1139
+ const b = createBlock(last.type, "", last.attrs);
1140
+ ctx.doc.blocks.insert(++insertAt, [b]);
1141
+ const lastLen = writeDeltaInto(b.get("text"), 0, last.delta);
1142
+ const lastIdx = insertAt;
1143
+ if (tailDelta.length > 0) {
1144
+ const tb = createBlock(originalType ?? "paragraph", "", originalAttrs);
1145
+ ctx.doc.blocks.insert(++insertAt, [tb]);
1146
+ writeDeltaInto(tb.get("text"), 0, tailDelta);
1147
+ }
1148
+ ctx.setSelection(collapsedSelection({ blockIndex: lastIdx, offset: lastLen }));
1149
+ }
1150
+ });
1151
+ }
834
1152
  function selectedBlockIndices(sel, blockCount) {
835
1153
  const { start, end } = orderedRange(sel);
836
1154
  const out = [];
@@ -980,7 +1298,7 @@ function setBlockTypeAtIndex(doc, index, type, attrs) {
980
1298
  const block = doc.getBlock(index);
981
1299
  if (!block) return;
982
1300
  block.set("type", type);
983
- const attrsMap = block.get("attrs") ?? new Y2.Map();
1301
+ const attrsMap = block.get("attrs") ?? new Y3.Map();
984
1302
  if (!block.get("attrs")) block.set("attrs", attrsMap);
985
1303
  const next = { ...defaultAttrsFor(type), ...attrs };
986
1304
  const keep = new Set(Object.keys(next));
@@ -1004,6 +1322,9 @@ function insertTable(ctx, rows, cols) {
1004
1322
  const focusBlock = Math.max(0, Math.min(sel.focus.blockIndex, ctx.doc.blockCount() - 1));
1005
1323
  const insertAt = focusBlock + 1;
1006
1324
  ctx.doc.blocks.insert(insertAt, [createTableBlock(r, c)]);
1325
+ if (insertAt === ctx.doc.blockCount() - 1) {
1326
+ ctx.doc.blocks.insert(insertAt + 1, [createBlock("paragraph")]);
1327
+ }
1007
1328
  ctx.setSelection(
1008
1329
  collapsedSelection({ blockIndex: insertAt, cellIndex: 0, offset: 0 })
1009
1330
  );
@@ -1612,11 +1933,10 @@ function writeDeltaInto(yText, pos, delta) {
1612
1933
  for (const op of delta) {
1613
1934
  if (typeof op.insert === "string") {
1614
1935
  if (op.insert.length === 0) continue;
1615
- if (op.attributes && Object.keys(op.attributes).length > 0) {
1616
- yText.insert(cursor, op.insert, op.attributes);
1617
- } else {
1618
- yText.insert(cursor, op.insert);
1619
- }
1936
+ yText.insert(cursor, op.insert, {
1937
+ ...CLEAR_ALL_MARKS,
1938
+ ...op.attributes ?? {}
1939
+ });
1620
1940
  cursor += op.insert.length;
1621
1941
  } else if (op.insert != null) {
1622
1942
  if (op.attributes && Object.keys(op.attributes).length > 0) {
@@ -1676,17 +1996,56 @@ function setImageAttrs(ctx, blockIndex, embedOffset, partial, cellIndex, newOffs
1676
1996
  yText.insert(insertAt, merged);
1677
1997
  });
1678
1998
  }
1999
+ var REANCHORABLE_LAYOUTS = /* @__PURE__ */ new Set(["front", "behind"]);
2000
+ function moveEmbedAnchor(ctx, from, to, newOffsetX, newOffsetY) {
2001
+ transact(ctx.doc, () => {
2002
+ const srcText = ctx.doc.textAt(from.blockIndex, from.cellIndex);
2003
+ if (!srcText) return;
2004
+ const delta = srcText.toDelta();
2005
+ let cursor = 0;
2006
+ let prev = null;
2007
+ for (const op of delta) {
2008
+ if (typeof op.insert === "string") {
2009
+ cursor += op.insert.length;
2010
+ continue;
2011
+ }
2012
+ if (cursor === from.offset && isImageEmbed(op.insert)) {
2013
+ prev = op.insert;
2014
+ break;
2015
+ }
2016
+ cursor += 1;
2017
+ }
2018
+ if (!prev) return;
2019
+ const layout = prev.layout ?? "inline";
2020
+ if (!REANCHORABLE_LAYOUTS.has(layout)) return;
2021
+ const dstText = ctx.doc.textAt(to.blockIndex, to.cellIndex);
2022
+ if (!dstText) return;
2023
+ const merged = { ...prev, offsetX: newOffsetX, offsetY: newOffsetY };
2024
+ const sameRun = srcText === dstText;
2025
+ srcText.delete(from.offset, 1);
2026
+ let landed = to.offset;
2027
+ if (sameRun && to.offset > from.offset) {
2028
+ landed = to.offset - 1;
2029
+ }
2030
+ landed = Math.max(0, Math.min(landed, dstText.length));
2031
+ dstText.insert(landed, merged);
2032
+ ctx.setSelection({
2033
+ anchor: { blockIndex: to.blockIndex, cellIndex: to.cellIndex, offset: landed },
2034
+ focus: { blockIndex: to.blockIndex, cellIndex: to.cellIndex, offset: landed + 1 }
2035
+ });
2036
+ });
2037
+ }
1679
2038
  function isCommandOrigin(origin) {
1680
2039
  return origin === COMMAND_ORIGIN;
1681
2040
  }
1682
2041
  var TRACKED_ORIGINS = /* @__PURE__ */ new Set([COMMAND_ORIGIN]);
1683
2042
 
1684
2043
  // src/history.ts
1685
- import * as Y3 from "yjs";
2044
+ import * as Y4 from "yjs";
1686
2045
  var EditorHistory = class {
1687
2046
  undoManager;
1688
2047
  constructor(doc) {
1689
- this.undoManager = new Y3.UndoManager(doc.blocks, {
2048
+ this.undoManager = new Y4.UndoManager(doc.blocks, {
1690
2049
  trackedOrigins: TRACKED_ORIGINS,
1691
2050
  captureTimeout: 400
1692
2051
  });
@@ -1703,6 +2062,7 @@ var EditorHistory = class {
1703
2062
  };
1704
2063
  export {
1705
2064
  BLOCK_SPECS,
2065
+ CLEAR_ALL_MARKS,
1706
2066
  COMMAND_ORIGIN,
1707
2067
  DEFAULT_PAGE_SETTINGS,
1708
2068
  EditorDocument,
@@ -1710,8 +2070,9 @@ export {
1710
2070
  MARGIN_PRESETS,
1711
2071
  MAX_LIST_LEVEL,
1712
2072
  PAGE_PRESETS,
2073
+ SOFER_MIME,
1713
2074
  TRACKED_ORIGINS,
1714
- Y2 as Y,
2075
+ Y3 as Y,
1715
2076
  cellsInRect,
1716
2077
  clearRectCells,
1717
2078
  collapsedSelection,
@@ -1719,20 +2080,25 @@ export {
1719
2080
  createBlock,
1720
2081
  createCell,
1721
2082
  createTableBlock,
2083
+ decodeSelection,
1722
2084
  dedentList,
1723
2085
  defaultAttrsFor,
1724
2086
  deleteBackward,
1725
2087
  deleteForward,
2088
+ deleteSelection,
1726
2089
  deleteTable,
1727
2090
  deleteTableColumn,
1728
2091
  deleteTableRow,
1729
2092
  deltaLength,
1730
2093
  detectPreset,
2094
+ encodeSelection,
1731
2095
  expandTableRect,
2096
+ getBlockId,
1732
2097
  getMarksInRange,
1733
2098
  indentList,
1734
2099
  insertImage,
1735
2100
  insertParagraph,
2101
+ insertSlice,
1736
2102
  insertTable,
1737
2103
  insertTableColumn,
1738
2104
  insertTableRow,
@@ -1747,19 +2113,25 @@ export {
1747
2113
  mergeRight,
1748
2114
  mergeSelection,
1749
2115
  mmToPx,
2116
+ moveEmbedAnchor,
1750
2117
  moveToNextCell,
1751
2118
  moveToPrevCell,
2119
+ newBlockId,
1752
2120
  orderedRange,
1753
2121
  positionsEqual,
1754
2122
  pxToMm,
1755
2123
  removeMark,
1756
2124
  sameTextRun,
2125
+ serializeSelection,
1757
2126
  setBlockAttr,
1758
2127
  setBlockType,
2128
+ setCellAttr,
1759
2129
  setColumnWidth,
1760
2130
  setImageAttrs,
1761
2131
  setMark,
1762
2132
  sliceDelta,
2133
+ sliceToInlineDelta,
2134
+ sliceToText,
1763
2135
  spanOf,
1764
2136
  splitCell,
1765
2137
  splitListItem,