@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 +384 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -1
- package/dist/index.d.ts +97 -1
- package/dist/index.js +371 -13
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
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: () =>
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
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
|
|
2158
|
+
var Y4 = __toESM(require("yjs"), 1);
|
|
1801
2159
|
var EditorHistory = class {
|
|
1802
2160
|
undoManager;
|
|
1803
2161
|
constructor(doc) {
|
|
1804
|
-
this.undoManager = new
|
|
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,
|