@blankdotpage/cake 0.1.2 → 0.1.3
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/cake/core/runtime.d.ts +50 -13
- package/dist/cake/engine/cake-engine.d.ts +14 -0
- package/dist/cake/engine/selection/selection-layout-dom.d.ts +7 -0
- package/dist/cake/extensions/blockquote/blockquote.d.ts +1 -2
- package/dist/cake/extensions/bold/bold.d.ts +1 -2
- package/dist/cake/extensions/combined-emphasis/combined-emphasis.d.ts +1 -2
- package/dist/cake/extensions/heading/heading.d.ts +1 -2
- package/dist/cake/extensions/image/image.d.ts +1 -2
- package/dist/cake/extensions/index.d.ts +1 -0
- package/dist/cake/extensions/italic/italic.d.ts +1 -2
- package/dist/cake/extensions/link/link-popover.d.ts +6 -0
- package/dist/cake/extensions/link/link.d.ts +15 -2
- package/dist/cake/extensions/list/list.d.ts +11 -2
- package/dist/cake/extensions/pipe-link/pipe-link.d.ts +1 -2
- package/dist/cake/extensions/scrollbar/index.d.ts +1 -2
- package/dist/cake/extensions/strikethrough/strikethrough.d.ts +1 -2
- package/dist/cake/react/CakeEditor.d.ts +2 -0
- package/dist/cake/test/harness.d.ts +12 -0
- package/dist/index.cjs +652 -176
- package/dist/index.js +652 -176
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -997,15 +997,36 @@ class CursorSourceBuilder {
|
|
|
997
997
|
if (!text) {
|
|
998
998
|
return;
|
|
999
999
|
}
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1000
|
+
let isAllAscii = true;
|
|
1001
|
+
for (let i = 0; i < text.length; i++) {
|
|
1002
|
+
if (text.charCodeAt(i) >= 128) {
|
|
1003
|
+
isAllAscii = false;
|
|
1004
|
+
break;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
if (isAllAscii) {
|
|
1008
|
+
for (let i = 0; i < text.length; i++) {
|
|
1009
|
+
const char = text[i];
|
|
1010
|
+
this.sourceParts.push(char);
|
|
1011
|
+
this.sourceLengthValue += 1;
|
|
1012
|
+
const sourceLength = this.sourceLengthValue;
|
|
1013
|
+
this.cursorLength += 1;
|
|
1014
|
+
this.boundaries.push({
|
|
1015
|
+
sourceBackward: sourceLength,
|
|
1016
|
+
sourceForward: sourceLength
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
} else {
|
|
1020
|
+
for (const segment of graphemeSegments(text)) {
|
|
1021
|
+
this.sourceParts.push(segment.segment);
|
|
1022
|
+
this.sourceLengthValue += segment.segment.length;
|
|
1023
|
+
const sourceLength = this.sourceLengthValue;
|
|
1024
|
+
this.cursorLength += 1;
|
|
1025
|
+
this.boundaries.push({
|
|
1026
|
+
sourceBackward: sourceLength,
|
|
1027
|
+
sourceForward: sourceLength
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1009
1030
|
}
|
|
1010
1031
|
}
|
|
1011
1032
|
appendCursorAtom(sourceText, cursorUnits = 1) {
|
|
@@ -1055,6 +1076,15 @@ class CursorSourceBuilder {
|
|
|
1055
1076
|
};
|
|
1056
1077
|
}
|
|
1057
1078
|
}
|
|
1079
|
+
function isStructuralEdit(command) {
|
|
1080
|
+
return command.type === "insert" || command.type === "delete-backward" || command.type === "delete-forward" || command.type === "insert-line-break" || command.type === "exit-block-wrapper";
|
|
1081
|
+
}
|
|
1082
|
+
function isApplyEditCommand(command) {
|
|
1083
|
+
return command.type === "insert" || command.type === "insert-line-break" || command.type === "delete-backward" || command.type === "delete-forward";
|
|
1084
|
+
}
|
|
1085
|
+
function defineExtension(extension) {
|
|
1086
|
+
return extension;
|
|
1087
|
+
}
|
|
1058
1088
|
const defaultSelection$1 = { start: 0, end: 0, affinity: "forward" };
|
|
1059
1089
|
function createRuntime(extensions) {
|
|
1060
1090
|
const toggleMarkerToKind = /* @__PURE__ */ new Map();
|
|
@@ -1296,7 +1326,7 @@ function createRuntime(extensions) {
|
|
|
1296
1326
|
}
|
|
1297
1327
|
}
|
|
1298
1328
|
const selection = normalizeSelection$1(state.selection);
|
|
1299
|
-
if (command
|
|
1329
|
+
if (isStructuralEdit(command)) {
|
|
1300
1330
|
const structural = applyStructuralEdit(command, state.doc, selection);
|
|
1301
1331
|
if (!structural) {
|
|
1302
1332
|
if (command.type === "delete-backward" || command.type === "delete-forward") {
|
|
@@ -1338,6 +1368,39 @@ function createRuntime(extensions) {
|
|
|
1338
1368
|
}
|
|
1339
1369
|
};
|
|
1340
1370
|
}
|
|
1371
|
+
if (command.type === "insert" || command.type === "insert-line-break") {
|
|
1372
|
+
const cursorLength = state.map.cursorLength;
|
|
1373
|
+
const cursorStart = Math.max(
|
|
1374
|
+
0,
|
|
1375
|
+
Math.min(cursorLength, Math.min(selection.start, selection.end))
|
|
1376
|
+
);
|
|
1377
|
+
const cursorEnd = Math.max(
|
|
1378
|
+
0,
|
|
1379
|
+
Math.min(cursorLength, Math.max(selection.start, selection.end))
|
|
1380
|
+
);
|
|
1381
|
+
const range = { start: cursorStart, end: cursorEnd };
|
|
1382
|
+
const fullDocReplace = range.start === 0 && range.end === cursorLength;
|
|
1383
|
+
const from = fullDocReplace ? 0 : state.map.cursorToSource(range.start, "backward");
|
|
1384
|
+
const to = fullDocReplace ? state.source.length : state.map.cursorToSource(range.end, "forward");
|
|
1385
|
+
const fromClamped = Math.max(0, Math.min(from, state.source.length));
|
|
1386
|
+
const toClamped = Math.max(
|
|
1387
|
+
fromClamped,
|
|
1388
|
+
Math.min(to, state.source.length)
|
|
1389
|
+
);
|
|
1390
|
+
const insertText = command.type === "insert" ? command.text : "\n";
|
|
1391
|
+
const nextSource = state.source.slice(0, fromClamped) + insertText + state.source.slice(toClamped);
|
|
1392
|
+
const next2 = createState(nextSource);
|
|
1393
|
+
const caretSource2 = fromClamped + insertText.length;
|
|
1394
|
+
const caretCursor2 = next2.map.sourceToCursor(caretSource2, "forward");
|
|
1395
|
+
return {
|
|
1396
|
+
...next2,
|
|
1397
|
+
selection: {
|
|
1398
|
+
start: caretCursor2.cursorOffset,
|
|
1399
|
+
end: caretCursor2.cursorOffset,
|
|
1400
|
+
affinity: caretCursor2.affinity
|
|
1401
|
+
}
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1341
1404
|
return state;
|
|
1342
1405
|
}
|
|
1343
1406
|
const interim = createStateFromDoc(structural.doc);
|
|
@@ -2580,7 +2643,20 @@ function parseLiteralBlock(source, start, context) {
|
|
|
2580
2643
|
return { block: { type: "paragraph", content }, nextPos: end };
|
|
2581
2644
|
}
|
|
2582
2645
|
function parseLiteralInline(source, start, end) {
|
|
2583
|
-
const
|
|
2646
|
+
const code = source.charCodeAt(start);
|
|
2647
|
+
if (code < 128) {
|
|
2648
|
+
const text2 = source[start] ?? "";
|
|
2649
|
+
return { inline: { type: "text", text: text2 }, nextPos: start + 1 };
|
|
2650
|
+
}
|
|
2651
|
+
if (code >= 55296 && code <= 56319) {
|
|
2652
|
+
const lowCode = source.charCodeAt(start + 1);
|
|
2653
|
+
if (lowCode >= 56320 && lowCode <= 57343) {
|
|
2654
|
+
const segment2 = graphemeSegments(source.slice(start, Math.min(start + 10, end)))[0];
|
|
2655
|
+
const text2 = segment2 ? segment2.segment : source.slice(start, start + 2);
|
|
2656
|
+
return { inline: { type: "text", text: text2 }, nextPos: start + text2.length };
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
const segment = graphemeSegments(source.slice(start, Math.min(start + 10, end)))[0];
|
|
2584
2660
|
const text = segment ? segment.segment : source[start] ?? "";
|
|
2585
2661
|
return { inline: { type: "text", text }, nextPos: start + text.length };
|
|
2586
2662
|
}
|
|
@@ -2623,29 +2699,66 @@ function normalizeSelection$1(selection) {
|
|
|
2623
2699
|
affinity: isRange ? "backward" : selection.affinity
|
|
2624
2700
|
};
|
|
2625
2701
|
}
|
|
2702
|
+
const graphemeCache = /* @__PURE__ */ new WeakMap();
|
|
2626
2703
|
function createTextRun(node, cursorStart) {
|
|
2627
|
-
const
|
|
2704
|
+
const data = node.data;
|
|
2705
|
+
const cached = graphemeCache.get(node);
|
|
2706
|
+
if (cached && cached.data === data) {
|
|
2707
|
+
const segmentCount = Math.max(0, cached.boundaryOffsets.length - 1);
|
|
2708
|
+
return {
|
|
2709
|
+
node,
|
|
2710
|
+
cursorStart,
|
|
2711
|
+
cursorEnd: cursorStart + segmentCount,
|
|
2712
|
+
boundaryOffsets: cached.boundaryOffsets
|
|
2713
|
+
};
|
|
2714
|
+
}
|
|
2715
|
+
const segments = graphemeSegments(data);
|
|
2628
2716
|
const boundaryOffsets = [0];
|
|
2629
2717
|
for (const segment of segments) {
|
|
2630
2718
|
boundaryOffsets.push(segment.index + segment.segment.length);
|
|
2631
2719
|
}
|
|
2632
2720
|
const cursorEnd = cursorStart + segments.length;
|
|
2721
|
+
graphemeCache.set(node, { data, boundaryOffsets });
|
|
2633
2722
|
return { node, cursorStart, cursorEnd, boundaryOffsets };
|
|
2634
2723
|
}
|
|
2635
2724
|
function boundaryIndexForOffset(boundaryOffsets, offset) {
|
|
2636
2725
|
if (offset <= 0) {
|
|
2637
2726
|
return 0;
|
|
2638
2727
|
}
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2728
|
+
const lastIndex = boundaryOffsets.length - 1;
|
|
2729
|
+
if (lastIndex <= 0) {
|
|
2730
|
+
return 0;
|
|
2731
|
+
}
|
|
2732
|
+
const lastBoundary = boundaryOffsets[lastIndex];
|
|
2733
|
+
if (offset >= lastBoundary) {
|
|
2734
|
+
return lastIndex;
|
|
2735
|
+
}
|
|
2736
|
+
let low = 1;
|
|
2737
|
+
let high = lastIndex;
|
|
2738
|
+
while (low < high) {
|
|
2739
|
+
const mid = low + high >>> 1;
|
|
2740
|
+
const boundary2 = boundaryOffsets[mid];
|
|
2741
|
+
if (boundary2 < offset) {
|
|
2742
|
+
low = mid + 1;
|
|
2743
|
+
} else {
|
|
2744
|
+
high = mid;
|
|
2643
2745
|
}
|
|
2644
|
-
|
|
2645
|
-
|
|
2746
|
+
}
|
|
2747
|
+
const boundary = boundaryOffsets[low];
|
|
2748
|
+
return boundary === offset ? low : low - 1;
|
|
2749
|
+
}
|
|
2750
|
+
function firstRunStartingAfterCursor(runs, cursorOffset) {
|
|
2751
|
+
let low = 0;
|
|
2752
|
+
let high = runs.length;
|
|
2753
|
+
while (low < high) {
|
|
2754
|
+
const mid = low + high >>> 1;
|
|
2755
|
+
if (runs[mid].cursorStart <= cursorOffset) {
|
|
2756
|
+
low = mid + 1;
|
|
2757
|
+
} else {
|
|
2758
|
+
high = mid;
|
|
2646
2759
|
}
|
|
2647
2760
|
}
|
|
2648
|
-
return
|
|
2761
|
+
return low;
|
|
2649
2762
|
}
|
|
2650
2763
|
function createDomMap(runs) {
|
|
2651
2764
|
const runForNode = /* @__PURE__ */ new Map();
|
|
@@ -2660,33 +2773,34 @@ function createDomMap(runs) {
|
|
|
2660
2773
|
if (runs.length === 0) {
|
|
2661
2774
|
return null;
|
|
2662
2775
|
}
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
const
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
if (cursorOffset === run.cursorEnd && affinity === "forward" && next && next.cursorStart === cursorOffset) {
|
|
2682
|
-
return { node: next.node, offset: next.boundaryOffsets[0] };
|
|
2683
|
-
}
|
|
2684
|
-
const index = Math.max(0, cursorOffset - run.cursorStart);
|
|
2685
|
-
const boundedIndex = Math.min(index, run.boundaryOffsets.length - 1);
|
|
2686
|
-
return { node: run.node, offset: run.boundaryOffsets[boundedIndex] };
|
|
2776
|
+
const nextIndex = firstRunStartingAfterCursor(runs, cursorOffset);
|
|
2777
|
+
const runIndex = nextIndex - 1;
|
|
2778
|
+
if (runIndex < 0) {
|
|
2779
|
+
const first = runs[0];
|
|
2780
|
+
return { node: first.node, offset: first.boundaryOffsets[0] };
|
|
2781
|
+
}
|
|
2782
|
+
const run = runs[runIndex];
|
|
2783
|
+
const previous = runIndex > 0 ? runs[runIndex - 1] : null;
|
|
2784
|
+
const next = nextIndex < runs.length ? runs[nextIndex] : null;
|
|
2785
|
+
if (cursorOffset === run.cursorStart && previous && affinity === "backward") {
|
|
2786
|
+
return {
|
|
2787
|
+
node: previous.node,
|
|
2788
|
+
offset: previous.boundaryOffsets[previous.boundaryOffsets.length - 1]
|
|
2789
|
+
};
|
|
2790
|
+
}
|
|
2791
|
+
if (cursorOffset <= run.cursorEnd) {
|
|
2792
|
+
if (cursorOffset === run.cursorEnd && affinity === "forward" && next && next.cursorStart === cursorOffset) {
|
|
2793
|
+
return { node: next.node, offset: next.boundaryOffsets[0] };
|
|
2687
2794
|
}
|
|
2795
|
+
const index = Math.max(0, cursorOffset - run.cursorStart);
|
|
2796
|
+
const boundedIndex = Math.min(index, run.boundaryOffsets.length - 1);
|
|
2797
|
+
return { node: run.node, offset: run.boundaryOffsets[boundedIndex] };
|
|
2798
|
+
}
|
|
2799
|
+
if (next) {
|
|
2800
|
+
const runEndOffset = run.boundaryOffsets[run.boundaryOffsets.length - 1];
|
|
2801
|
+
return affinity === "backward" ? { node: run.node, offset: runEndOffset } : { node: next.node, offset: next.boundaryOffsets[0] };
|
|
2688
2802
|
}
|
|
2689
|
-
const last =
|
|
2803
|
+
const last = run;
|
|
2690
2804
|
return {
|
|
2691
2805
|
node: last.node,
|
|
2692
2806
|
offset: last.boundaryOffsets[last.boundaryOffsets.length - 1]
|
|
@@ -3074,7 +3188,9 @@ function applyDomSelection(selection, map) {
|
|
|
3074
3188
|
if (!anchorPoint || !focusPoint) {
|
|
3075
3189
|
return;
|
|
3076
3190
|
}
|
|
3077
|
-
domSelection.
|
|
3191
|
+
if (domSelection.rangeCount > 0 && domSelection.anchorNode === anchorPoint.node && domSelection.anchorOffset === anchorPoint.offset && domSelection.focusNode === focusPoint.node && domSelection.focusOffset === focusPoint.offset) {
|
|
3192
|
+
return;
|
|
3193
|
+
}
|
|
3078
3194
|
if (isCollapsed) {
|
|
3079
3195
|
domSelection.collapse(anchorPoint.node, anchorPoint.offset);
|
|
3080
3196
|
return;
|
|
@@ -3094,6 +3210,7 @@ function applyDomSelection(selection, map) {
|
|
|
3094
3210
|
domSelection.extend(focusPoint.node, focusPoint.offset);
|
|
3095
3211
|
return;
|
|
3096
3212
|
}
|
|
3213
|
+
domSelection.removeAllRanges();
|
|
3097
3214
|
const range = document.createRange();
|
|
3098
3215
|
const rangeStart = isForward ? anchorPoint : focusPoint;
|
|
3099
3216
|
const rangeEnd = isForward ? focusPoint : anchorPoint;
|
|
@@ -3237,7 +3354,7 @@ function findTextNodeAtOrBefore$1(nodes, start) {
|
|
|
3237
3354
|
return null;
|
|
3238
3355
|
}
|
|
3239
3356
|
const BOLD_KIND$1 = "bold";
|
|
3240
|
-
const boldExtension = {
|
|
3357
|
+
const boldExtension = defineExtension({
|
|
3241
3358
|
name: "bold",
|
|
3242
3359
|
toggleInline: { kind: BOLD_KIND$1, markers: ["**"] },
|
|
3243
3360
|
keybindings: [
|
|
@@ -3320,7 +3437,7 @@ const boldExtension = {
|
|
|
3320
3437
|
}
|
|
3321
3438
|
return element;
|
|
3322
3439
|
}
|
|
3323
|
-
};
|
|
3440
|
+
});
|
|
3324
3441
|
function countSingleAsterisks(source, start, end) {
|
|
3325
3442
|
let count = 0;
|
|
3326
3443
|
for (let i = start; i < end; i += 1) {
|
|
@@ -3339,7 +3456,7 @@ function countSingleAsterisks(source, start, end) {
|
|
|
3339
3456
|
const BOLD_KIND = "bold";
|
|
3340
3457
|
const ITALIC_KIND$1 = "italic";
|
|
3341
3458
|
const MARKERS = ["***", "___"];
|
|
3342
|
-
const combinedEmphasisExtension = {
|
|
3459
|
+
const combinedEmphasisExtension = defineExtension({
|
|
3343
3460
|
name: "combined-emphasis",
|
|
3344
3461
|
parseInline(source, start, end, context) {
|
|
3345
3462
|
const marker = MARKERS.find((m) => source.slice(start, start + 3) === m);
|
|
@@ -3373,7 +3490,7 @@ const combinedEmphasisExtension = {
|
|
|
3373
3490
|
nextPos: close + 3
|
|
3374
3491
|
};
|
|
3375
3492
|
}
|
|
3376
|
-
};
|
|
3493
|
+
});
|
|
3377
3494
|
function ensureHttpsProtocol(url) {
|
|
3378
3495
|
const trimmedUrl = url.trim();
|
|
3379
3496
|
if (!trimmedUrl) {
|
|
@@ -3421,7 +3538,7 @@ function getPopoverPosition(params) {
|
|
|
3421
3538
|
};
|
|
3422
3539
|
}
|
|
3423
3540
|
function CakeLinkPopover(params) {
|
|
3424
|
-
const { container, contentRoot, toOverlayRect } = params;
|
|
3541
|
+
const { container, contentRoot, toOverlayRect, getSelection, executeCommand } = params;
|
|
3425
3542
|
const anchorRef = useRef(null);
|
|
3426
3543
|
const popoverRef = useRef(null);
|
|
3427
3544
|
const inputRef = useRef(null);
|
|
@@ -3585,6 +3702,12 @@ function CakeLinkPopover(params) {
|
|
|
3585
3702
|
window.open(displayUrl, "_blank", "noopener,noreferrer");
|
|
3586
3703
|
};
|
|
3587
3704
|
const handleUnlink = () => {
|
|
3705
|
+
const selection = getSelection();
|
|
3706
|
+
if (!selection) {
|
|
3707
|
+
close();
|
|
3708
|
+
return;
|
|
3709
|
+
}
|
|
3710
|
+
executeCommand({ type: "unlink", start: selection.start, end: selection.end });
|
|
3588
3711
|
close();
|
|
3589
3712
|
};
|
|
3590
3713
|
const handleInputKeyDown = (event) => {
|
|
@@ -3888,7 +4011,7 @@ function cursorOffsetToVisibleOffset(lines, cursorOffset) {
|
|
|
3888
4011
|
return codeUnitIndex + (lastLine.cursorToCodeUnit[lastOffset] ?? lastLine.text.length);
|
|
3889
4012
|
}
|
|
3890
4013
|
const LINK_KIND = "link";
|
|
3891
|
-
const linkExtension = {
|
|
4014
|
+
const linkExtension = defineExtension({
|
|
3892
4015
|
name: "link",
|
|
3893
4016
|
inlineWrapperAffinity: [{ kind: LINK_KIND, inclusive: false }],
|
|
3894
4017
|
keybindings: [
|
|
@@ -3916,6 +4039,39 @@ const linkExtension = {
|
|
|
3916
4039
|
}
|
|
3917
4040
|
],
|
|
3918
4041
|
onEdit(command, state) {
|
|
4042
|
+
if (command.type === "unlink") {
|
|
4043
|
+
const cursorPos = command.start;
|
|
4044
|
+
const sourcePos = state.map.cursorToSource(cursorPos, "forward");
|
|
4045
|
+
const source = state.source;
|
|
4046
|
+
let linkStart = sourcePos;
|
|
4047
|
+
while (linkStart > 0 && source[linkStart] !== "[") {
|
|
4048
|
+
linkStart--;
|
|
4049
|
+
}
|
|
4050
|
+
if (source[linkStart] !== "[") {
|
|
4051
|
+
return null;
|
|
4052
|
+
}
|
|
4053
|
+
const labelClose = source.indexOf("](", linkStart + 1);
|
|
4054
|
+
if (labelClose === -1) {
|
|
4055
|
+
return null;
|
|
4056
|
+
}
|
|
4057
|
+
const urlClose = source.indexOf(")", labelClose + 2);
|
|
4058
|
+
if (urlClose === -1) {
|
|
4059
|
+
return null;
|
|
4060
|
+
}
|
|
4061
|
+
const label2 = source.slice(linkStart + 1, labelClose);
|
|
4062
|
+
const nextSource2 = source.slice(0, linkStart) + label2 + source.slice(urlClose + 1);
|
|
4063
|
+
const newState = state.runtime.createState(nextSource2);
|
|
4064
|
+
const labelEndSource = linkStart + label2.length;
|
|
4065
|
+
const newCursor = newState.map.sourceToCursor(labelEndSource, "forward");
|
|
4066
|
+
return {
|
|
4067
|
+
source: nextSource2,
|
|
4068
|
+
selection: {
|
|
4069
|
+
start: newCursor.cursorOffset,
|
|
4070
|
+
end: newCursor.cursorOffset,
|
|
4071
|
+
affinity: "forward"
|
|
4072
|
+
}
|
|
4073
|
+
};
|
|
4074
|
+
}
|
|
3919
4075
|
if (command.type !== "wrap-link") {
|
|
3920
4076
|
return null;
|
|
3921
4077
|
}
|
|
@@ -4042,13 +4198,15 @@ const linkExtension = {
|
|
|
4042
4198
|
{
|
|
4043
4199
|
container: context.container,
|
|
4044
4200
|
contentRoot: context.contentRoot,
|
|
4045
|
-
toOverlayRect: context.toOverlayRect
|
|
4201
|
+
toOverlayRect: context.toOverlayRect,
|
|
4202
|
+
getSelection: context.getSelection,
|
|
4203
|
+
executeCommand: context.executeCommand
|
|
4046
4204
|
}
|
|
4047
4205
|
);
|
|
4048
4206
|
}
|
|
4049
|
-
};
|
|
4207
|
+
});
|
|
4050
4208
|
const PIPE_LINK_KIND = "pipe-link";
|
|
4051
|
-
const pipeLinkExtension = {
|
|
4209
|
+
const pipeLinkExtension = defineExtension({
|
|
4052
4210
|
name: "pipe-link",
|
|
4053
4211
|
parseInline(source, start, end) {
|
|
4054
4212
|
if (source[start] !== "|") {
|
|
@@ -4119,10 +4277,10 @@ const pipeLinkExtension = {
|
|
|
4119
4277
|
}
|
|
4120
4278
|
return element;
|
|
4121
4279
|
}
|
|
4122
|
-
};
|
|
4280
|
+
});
|
|
4123
4281
|
const BLOCKQUOTE_KIND = "blockquote";
|
|
4124
4282
|
const PREFIX = "> ";
|
|
4125
|
-
const blockquoteExtension = {
|
|
4283
|
+
const blockquoteExtension = defineExtension({
|
|
4126
4284
|
name: "blockquote",
|
|
4127
4285
|
parseBlock(source, start, context) {
|
|
4128
4286
|
if (source.slice(start, start + PREFIX.length) !== PREFIX) {
|
|
@@ -4191,9 +4349,9 @@ const blockquoteExtension = {
|
|
|
4191
4349
|
}
|
|
4192
4350
|
return element;
|
|
4193
4351
|
}
|
|
4194
|
-
};
|
|
4352
|
+
});
|
|
4195
4353
|
const ITALIC_KIND = "italic";
|
|
4196
|
-
const italicExtension = {
|
|
4354
|
+
const italicExtension = defineExtension({
|
|
4197
4355
|
name: "italic",
|
|
4198
4356
|
toggleInline: { kind: ITALIC_KIND, markers: ["*", "_"] },
|
|
4199
4357
|
keybindings: [
|
|
@@ -4263,7 +4421,7 @@ const italicExtension = {
|
|
|
4263
4421
|
}
|
|
4264
4422
|
return element;
|
|
4265
4423
|
}
|
|
4266
|
-
};
|
|
4424
|
+
});
|
|
4267
4425
|
const HEADING_KIND = "heading";
|
|
4268
4426
|
const HEADING_PATTERN = /^(#{1,3}) /;
|
|
4269
4427
|
function findLineStartInSource(source, sourceOffset) {
|
|
@@ -4364,7 +4522,7 @@ function shouldExitHeadingOnLineBreak(state) {
|
|
|
4364
4522
|
const contentStart = lineStart + marker.length;
|
|
4365
4523
|
return sourcePos >= contentStart && sourcePos <= lineEnd;
|
|
4366
4524
|
}
|
|
4367
|
-
const headingExtension = {
|
|
4525
|
+
const headingExtension = defineExtension({
|
|
4368
4526
|
name: "heading",
|
|
4369
4527
|
onEdit(command, state) {
|
|
4370
4528
|
if (command.type === "delete-backward") {
|
|
@@ -4505,7 +4663,7 @@ const headingExtension = {
|
|
|
4505
4663
|
}
|
|
4506
4664
|
return lineElement;
|
|
4507
4665
|
}
|
|
4508
|
-
};
|
|
4666
|
+
});
|
|
4509
4667
|
const IMAGE_KIND = "image";
|
|
4510
4668
|
const IMAGE_PATTERN = /^!\[([^\]]*)\]\(([^)]*)\)$/;
|
|
4511
4669
|
const UPLOADING_PATTERN = /^!\[uploading:([^\]]+)\]\(\)$/;
|
|
@@ -4523,7 +4681,7 @@ function isImageData(data) {
|
|
|
4523
4681
|
}
|
|
4524
4682
|
return false;
|
|
4525
4683
|
}
|
|
4526
|
-
const imageExtension = {
|
|
4684
|
+
const imageExtension = defineExtension({
|
|
4527
4685
|
name: "image",
|
|
4528
4686
|
parseBlock(source, start) {
|
|
4529
4687
|
let lineEnd = source.indexOf("\n", start);
|
|
@@ -4618,7 +4776,7 @@ const imageExtension = {
|
|
|
4618
4776
|
}
|
|
4619
4777
|
return element;
|
|
4620
4778
|
}
|
|
4621
|
-
};
|
|
4779
|
+
});
|
|
4622
4780
|
const LIST_LINE_REGEX$2 = /^(\s*)([-*+]|\d+\.)( )(.*)$/;
|
|
4623
4781
|
const INDENT_SIZE = 2;
|
|
4624
4782
|
function parseMarkerType(marker) {
|
|
@@ -5437,7 +5595,7 @@ function getParagraphText(block) {
|
|
|
5437
5595
|
}
|
|
5438
5596
|
return text;
|
|
5439
5597
|
}
|
|
5440
|
-
const listExtension = {
|
|
5598
|
+
const listExtension = defineExtension({
|
|
5441
5599
|
name: "list",
|
|
5442
5600
|
keybindings: [
|
|
5443
5601
|
{
|
|
@@ -5530,7 +5688,7 @@ const listExtension = {
|
|
|
5530
5688
|
}
|
|
5531
5689
|
return element;
|
|
5532
5690
|
}
|
|
5533
|
-
};
|
|
5691
|
+
});
|
|
5534
5692
|
const THUMB_MIN_HEIGHT = 30;
|
|
5535
5693
|
const SCROLL_HIDE_DELAY = 500;
|
|
5536
5694
|
const TRACK_PADDING = 8;
|
|
@@ -5767,14 +5925,14 @@ function ScrollbarOverlay({ container }) {
|
|
|
5767
5925
|
}
|
|
5768
5926
|
) });
|
|
5769
5927
|
}
|
|
5770
|
-
const scrollbarExtension = {
|
|
5928
|
+
const scrollbarExtension = defineExtension({
|
|
5771
5929
|
name: "scrollbar",
|
|
5772
5930
|
renderOverlay(context) {
|
|
5773
5931
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollbarOverlay, { container: context.container });
|
|
5774
5932
|
}
|
|
5775
|
-
};
|
|
5933
|
+
});
|
|
5776
5934
|
const STRIKE_KIND = "strikethrough";
|
|
5777
|
-
const strikethroughExtension = {
|
|
5935
|
+
const strikethroughExtension = defineExtension({
|
|
5778
5936
|
name: "strikethrough",
|
|
5779
5937
|
toggleInline: { kind: STRIKE_KIND, markers: ["~~"] },
|
|
5780
5938
|
keybindings: [
|
|
@@ -5847,8 +6005,8 @@ const strikethroughExtension = {
|
|
|
5847
6005
|
}
|
|
5848
6006
|
return element;
|
|
5849
6007
|
}
|
|
5850
|
-
};
|
|
5851
|
-
const
|
|
6008
|
+
});
|
|
6009
|
+
const bundledExtensionsWithoutImage = [
|
|
5852
6010
|
blockquoteExtension,
|
|
5853
6011
|
headingExtension,
|
|
5854
6012
|
listExtension,
|
|
@@ -5857,7 +6015,10 @@ const bundledExtensions = [
|
|
|
5857
6015
|
italicExtension,
|
|
5858
6016
|
strikethroughExtension,
|
|
5859
6017
|
pipeLinkExtension,
|
|
5860
|
-
linkExtension
|
|
6018
|
+
linkExtension
|
|
6019
|
+
];
|
|
6020
|
+
const bundledExtensions = [
|
|
6021
|
+
...bundledExtensionsWithoutImage,
|
|
5861
6022
|
imageExtension
|
|
5862
6023
|
];
|
|
5863
6024
|
function toLayoutRect(params) {
|
|
@@ -5917,6 +6078,46 @@ function cursorOffsetToCodeUnit(cursorToCodeUnit, offset) {
|
|
|
5917
6078
|
const clamped = Math.max(0, Math.min(offset, cursorToCodeUnit.length - 1));
|
|
5918
6079
|
return cursorToCodeUnit[clamped] ?? 0;
|
|
5919
6080
|
}
|
|
6081
|
+
function createDomPositionResolver(lineElement) {
|
|
6082
|
+
const textNodes = [];
|
|
6083
|
+
const cumulativeEnds = [];
|
|
6084
|
+
const walker = createTextWalker(lineElement);
|
|
6085
|
+
let current = walker.nextNode();
|
|
6086
|
+
let total = 0;
|
|
6087
|
+
while (current) {
|
|
6088
|
+
if (current instanceof Text) {
|
|
6089
|
+
const length = current.data.length;
|
|
6090
|
+
textNodes.push(current);
|
|
6091
|
+
total += length;
|
|
6092
|
+
cumulativeEnds.push(total);
|
|
6093
|
+
}
|
|
6094
|
+
current = walker.nextNode();
|
|
6095
|
+
}
|
|
6096
|
+
if (textNodes.length === 0) {
|
|
6097
|
+
return () => {
|
|
6098
|
+
if (!lineElement.textContent) {
|
|
6099
|
+
return { node: lineElement, offset: 0 };
|
|
6100
|
+
}
|
|
6101
|
+
return { node: lineElement, offset: lineElement.childNodes.length };
|
|
6102
|
+
};
|
|
6103
|
+
}
|
|
6104
|
+
return (offsetInLine) => {
|
|
6105
|
+
const clamped = Math.max(0, Math.min(offsetInLine, total));
|
|
6106
|
+
let low = 0;
|
|
6107
|
+
let high = cumulativeEnds.length - 1;
|
|
6108
|
+
while (low < high) {
|
|
6109
|
+
const mid = low + high >>> 1;
|
|
6110
|
+
if ((cumulativeEnds[mid] ?? 0) < clamped) {
|
|
6111
|
+
low = mid + 1;
|
|
6112
|
+
} else {
|
|
6113
|
+
high = mid;
|
|
6114
|
+
}
|
|
6115
|
+
}
|
|
6116
|
+
const node = textNodes[low] ?? lineElement;
|
|
6117
|
+
const prevEnd = low > 0 ? cumulativeEnds[low - 1] ?? 0 : 0;
|
|
6118
|
+
return { node, offset: clamped - prevEnd };
|
|
6119
|
+
};
|
|
6120
|
+
}
|
|
5920
6121
|
function measureCharacterRect(params) {
|
|
5921
6122
|
if (params.lineLength <= 0) {
|
|
5922
6123
|
return null;
|
|
@@ -5929,101 +6130,155 @@ function measureCharacterRect(params) {
|
|
|
5929
6130
|
params.cursorToCodeUnit,
|
|
5930
6131
|
Math.min(params.offset + 1, params.lineLength)
|
|
5931
6132
|
);
|
|
5932
|
-
const startPosition = resolveDomPosition(
|
|
5933
|
-
const endPosition = resolveDomPosition(
|
|
5934
|
-
|
|
5935
|
-
range.
|
|
5936
|
-
range.
|
|
5937
|
-
const rects = range.getClientRects();
|
|
6133
|
+
const startPosition = params.resolveDomPosition(startCodeUnit);
|
|
6134
|
+
const endPosition = params.resolveDomPosition(endCodeUnit);
|
|
6135
|
+
params.range.setStart(startPosition.node, startPosition.offset);
|
|
6136
|
+
params.range.setEnd(endPosition.node, endPosition.offset);
|
|
6137
|
+
const rects = params.range.getClientRects();
|
|
5938
6138
|
if (rects.length > 0) {
|
|
5939
6139
|
return rects[0] ?? null;
|
|
5940
6140
|
}
|
|
5941
|
-
const rect = range.getBoundingClientRect();
|
|
6141
|
+
const rect = params.range.getBoundingClientRect();
|
|
5942
6142
|
if (rect.width === 0 && rect.height === 0) {
|
|
5943
6143
|
return null;
|
|
5944
6144
|
}
|
|
5945
6145
|
return rect;
|
|
5946
6146
|
}
|
|
5947
6147
|
function measureLineRows(params) {
|
|
6148
|
+
var _a, _b;
|
|
6149
|
+
const fallbackLineBox = toLayoutRect({
|
|
6150
|
+
rect: params.lineRect,
|
|
6151
|
+
containerRect: params.containerRect,
|
|
6152
|
+
scroll: params.scroll
|
|
6153
|
+
});
|
|
5948
6154
|
if (params.lineLength === 0) {
|
|
5949
|
-
const lineBox = toLayoutRect({
|
|
5950
|
-
rect: params.lineRect,
|
|
5951
|
-
containerRect: params.containerRect,
|
|
5952
|
-
scroll: params.scroll
|
|
5953
|
-
});
|
|
5954
6155
|
return [
|
|
5955
6156
|
{
|
|
5956
6157
|
startOffset: 0,
|
|
5957
6158
|
endOffset: 0,
|
|
5958
|
-
rect: { ...
|
|
6159
|
+
rect: { ...fallbackLineBox, width: 0 }
|
|
5959
6160
|
}
|
|
5960
6161
|
];
|
|
5961
6162
|
}
|
|
5962
|
-
const
|
|
5963
|
-
const
|
|
5964
|
-
const
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
);
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
const fullLineRects = groupDomRectsByRow(
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
const fallbackLineBox = toLayoutRect({
|
|
5974
|
-
rect: params.lineRect,
|
|
5975
|
-
containerRect: params.containerRect,
|
|
5976
|
-
scroll: params.scroll
|
|
5977
|
-
});
|
|
5978
|
-
const charRect = measureCharacterRect({
|
|
5979
|
-
lineElement: params.lineElement,
|
|
5980
|
-
offset: 0,
|
|
5981
|
-
lineLength: params.lineLength,
|
|
5982
|
-
cursorToCodeUnit: params.cursorToCodeUnit
|
|
5983
|
-
});
|
|
5984
|
-
const charWidth = (charRect == null ? void 0 : charRect.width) ?? 0;
|
|
5985
|
-
if (fullLineRects.length === 0 || charWidth <= 0) {
|
|
5986
|
-
const rows2 = [
|
|
6163
|
+
const WRAP_THRESHOLD_PX = 3;
|
|
6164
|
+
const resolvePosition = createDomPositionResolver(params.lineElement);
|
|
6165
|
+
const scratchRange = document.createRange();
|
|
6166
|
+
const topCache = /* @__PURE__ */ new Map();
|
|
6167
|
+
const fullLineStart = resolvePosition(0);
|
|
6168
|
+
const fullLineEnd = resolvePosition(params.codeUnitLength);
|
|
6169
|
+
scratchRange.setStart(fullLineStart.node, fullLineStart.offset);
|
|
6170
|
+
scratchRange.setEnd(fullLineEnd.node, fullLineEnd.offset);
|
|
6171
|
+
const fullLineRects = groupDomRectsByRow(Array.from(scratchRange.getClientRects()));
|
|
6172
|
+
if (fullLineRects.length === 0) {
|
|
6173
|
+
return [
|
|
5987
6174
|
{
|
|
5988
6175
|
startOffset: 0,
|
|
5989
6176
|
endOffset: params.lineLength,
|
|
5990
6177
|
rect: fallbackLineBox
|
|
5991
6178
|
}
|
|
5992
6179
|
];
|
|
5993
|
-
|
|
6180
|
+
}
|
|
6181
|
+
function offsetToTop(offset) {
|
|
6182
|
+
if (topCache.has(offset)) {
|
|
6183
|
+
return topCache.get(offset) ?? null;
|
|
6184
|
+
}
|
|
6185
|
+
const rect = measureCharacterRect({
|
|
6186
|
+
lineElement: params.lineElement,
|
|
6187
|
+
offset,
|
|
6188
|
+
lineLength: params.lineLength,
|
|
6189
|
+
cursorToCodeUnit: params.cursorToCodeUnit,
|
|
6190
|
+
resolveDomPosition: resolvePosition,
|
|
6191
|
+
range: scratchRange
|
|
6192
|
+
});
|
|
6193
|
+
const top = rect ? rect.top : null;
|
|
6194
|
+
topCache.set(offset, top);
|
|
6195
|
+
return top;
|
|
6196
|
+
}
|
|
6197
|
+
function findFirstMeasurableOffset(from) {
|
|
6198
|
+
for (let offset = Math.max(0, from); offset < params.lineLength; offset++) {
|
|
6199
|
+
if (offsetToTop(offset) !== null) {
|
|
6200
|
+
return offset;
|
|
6201
|
+
}
|
|
6202
|
+
}
|
|
6203
|
+
return null;
|
|
6204
|
+
}
|
|
6205
|
+
function findNextRowStartOffset(fromExclusive, rowTop) {
|
|
6206
|
+
const lastIndex = params.lineLength - 1;
|
|
6207
|
+
if (fromExclusive > lastIndex) {
|
|
6208
|
+
return null;
|
|
6209
|
+
}
|
|
6210
|
+
const isNewRowAt = (offset) => {
|
|
6211
|
+
const top = offsetToTop(offset);
|
|
6212
|
+
return top !== null && Math.abs(top - rowTop) > WRAP_THRESHOLD_PX;
|
|
6213
|
+
};
|
|
6214
|
+
let step = 1;
|
|
6215
|
+
let lastSame = fromExclusive - 1;
|
|
6216
|
+
let probe = fromExclusive;
|
|
6217
|
+
while (probe <= lastIndex) {
|
|
6218
|
+
if (isNewRowAt(probe)) {
|
|
6219
|
+
break;
|
|
6220
|
+
}
|
|
6221
|
+
lastSame = probe;
|
|
6222
|
+
probe += step;
|
|
6223
|
+
step *= 2;
|
|
6224
|
+
}
|
|
6225
|
+
if (probe > lastIndex) {
|
|
6226
|
+
probe = lastIndex;
|
|
6227
|
+
if (!isNewRowAt(probe)) {
|
|
6228
|
+
return null;
|
|
6229
|
+
}
|
|
6230
|
+
}
|
|
6231
|
+
let low = Math.max(fromExclusive, lastSame + 1);
|
|
6232
|
+
let high = probe;
|
|
6233
|
+
while (low < high) {
|
|
6234
|
+
const mid = low + high >>> 1;
|
|
6235
|
+
if (isNewRowAt(mid)) {
|
|
6236
|
+
high = mid;
|
|
6237
|
+
} else {
|
|
6238
|
+
low = mid + 1;
|
|
6239
|
+
}
|
|
6240
|
+
}
|
|
6241
|
+
return low < params.lineLength ? low : null;
|
|
6242
|
+
}
|
|
6243
|
+
const rows = [];
|
|
6244
|
+
const firstMeasurable = findFirstMeasurableOffset(0);
|
|
6245
|
+
if (firstMeasurable === null) {
|
|
6246
|
+
return [
|
|
5994
6247
|
{
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
top: fallbackLineBox.top,
|
|
5999
|
-
height: fallbackLineBox.height
|
|
6000
|
-
}
|
|
6248
|
+
startOffset: 0,
|
|
6249
|
+
endOffset: params.lineLength,
|
|
6250
|
+
rect: fallbackLineBox
|
|
6001
6251
|
}
|
|
6002
|
-
]
|
|
6252
|
+
];
|
|
6003
6253
|
}
|
|
6004
|
-
let
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
const
|
|
6010
|
-
const
|
|
6011
|
-
|
|
6012
|
-
|
|
6254
|
+
let currentRowStart = 0;
|
|
6255
|
+
let currentRowTop = ((_a = fullLineRects[0]) == null ? void 0 : _a.top) ?? params.lineRect.top;
|
|
6256
|
+
let searchFrom = firstMeasurable + 1;
|
|
6257
|
+
let rowIndex = 0;
|
|
6258
|
+
while (currentRowStart < params.lineLength) {
|
|
6259
|
+
const nextRowStart = findNextRowStartOffset(searchFrom, currentRowTop);
|
|
6260
|
+
const currentRowEnd = nextRowStart ?? params.lineLength;
|
|
6261
|
+
const domRect = fullLineRects[rowIndex] ?? params.lineRect;
|
|
6262
|
+
rows.push({
|
|
6263
|
+
startOffset: currentRowStart,
|
|
6264
|
+
endOffset: currentRowEnd,
|
|
6013
6265
|
rect: toLayoutRect({
|
|
6014
|
-
rect,
|
|
6266
|
+
rect: domRect,
|
|
6015
6267
|
containerRect: params.containerRect,
|
|
6016
6268
|
scroll: params.scroll
|
|
6017
6269
|
})
|
|
6018
|
-
};
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6270
|
+
});
|
|
6271
|
+
if (nextRowStart === null) {
|
|
6272
|
+
break;
|
|
6273
|
+
}
|
|
6274
|
+
currentRowStart = nextRowStart;
|
|
6275
|
+
rowIndex += 1;
|
|
6276
|
+
const nextMeasurable = findFirstMeasurableOffset(currentRowStart);
|
|
6277
|
+
if (nextMeasurable === null) {
|
|
6278
|
+
break;
|
|
6279
|
+
}
|
|
6280
|
+
currentRowTop = ((_b = fullLineRects[rowIndex]) == null ? void 0 : _b.top) ?? currentRowTop;
|
|
6281
|
+
searchFrom = nextMeasurable + 1;
|
|
6027
6282
|
}
|
|
6028
6283
|
if (rows.length === 1) {
|
|
6029
6284
|
rows[0] = {
|
|
@@ -6095,6 +6350,44 @@ function measureLayoutModelFromDom(params) {
|
|
|
6095
6350
|
}
|
|
6096
6351
|
return buildLayoutModel(params.lines, measurer);
|
|
6097
6352
|
}
|
|
6353
|
+
function measureLayoutModelRangeFromDom(params) {
|
|
6354
|
+
const measurer = createDomLayoutMeasurer({
|
|
6355
|
+
root: params.root,
|
|
6356
|
+
container: params.container,
|
|
6357
|
+
lines: params.lines
|
|
6358
|
+
});
|
|
6359
|
+
if (!measurer) {
|
|
6360
|
+
return null;
|
|
6361
|
+
}
|
|
6362
|
+
const clampedStart = Math.max(0, Math.min(params.startLineIndex, params.lines.length - 1));
|
|
6363
|
+
const clampedEnd = Math.max(clampedStart, Math.min(params.endLineIndex, params.lines.length - 1));
|
|
6364
|
+
const lineOffsets = getLineOffsets(params.lines);
|
|
6365
|
+
let lineStartOffset = lineOffsets[clampedStart] ?? 0;
|
|
6366
|
+
const layouts = [];
|
|
6367
|
+
for (let lineIndex = clampedStart; lineIndex <= clampedEnd; lineIndex += 1) {
|
|
6368
|
+
const lineInfo = params.lines[lineIndex];
|
|
6369
|
+
if (!lineInfo) {
|
|
6370
|
+
continue;
|
|
6371
|
+
}
|
|
6372
|
+
const measurement = measurer.measureLine({
|
|
6373
|
+
lineIndex: lineInfo.lineIndex,
|
|
6374
|
+
lineText: lineInfo.text,
|
|
6375
|
+
lineLength: lineInfo.cursorLength,
|
|
6376
|
+
lineHasNewline: lineInfo.hasNewline,
|
|
6377
|
+
top: 0
|
|
6378
|
+
});
|
|
6379
|
+
layouts.push({
|
|
6380
|
+
lineIndex: lineInfo.lineIndex,
|
|
6381
|
+
lineStartOffset,
|
|
6382
|
+
lineLength: lineInfo.cursorLength,
|
|
6383
|
+
lineHasNewline: lineInfo.hasNewline,
|
|
6384
|
+
lineBox: measurement.lineBox,
|
|
6385
|
+
rows: measurement.rows
|
|
6386
|
+
});
|
|
6387
|
+
lineStartOffset += lineInfo.cursorLength + (lineInfo.hasNewline ? 1 : 0);
|
|
6388
|
+
}
|
|
6389
|
+
return { container: measurer.container, lines: layouts };
|
|
6390
|
+
}
|
|
6098
6391
|
function getLineElement(root, lineIndex) {
|
|
6099
6392
|
return root.querySelector(`[data-line-index="${lineIndex}"]`);
|
|
6100
6393
|
}
|
|
@@ -6310,7 +6603,17 @@ function getSelectionGeometry(params) {
|
|
|
6310
6603
|
end: selection.start,
|
|
6311
6604
|
affinity: selection.affinity
|
|
6312
6605
|
};
|
|
6313
|
-
const layout = shouldMeasureLayout(normalized) ?
|
|
6606
|
+
const layout = shouldMeasureLayout(normalized) ? (() => {
|
|
6607
|
+
const startLine2 = resolveOffsetToLine(docLines, normalized.start);
|
|
6608
|
+
const endLine = resolveOffsetToLine(docLines, normalized.end);
|
|
6609
|
+
return measureLayoutModelRangeFromDom({
|
|
6610
|
+
lines: docLines,
|
|
6611
|
+
root,
|
|
6612
|
+
container,
|
|
6613
|
+
startLineIndex: startLine2.lineIndex,
|
|
6614
|
+
endLineIndex: endLine.lineIndex
|
|
6615
|
+
});
|
|
6616
|
+
})() : null;
|
|
6314
6617
|
const containerRect = container.getBoundingClientRect();
|
|
6315
6618
|
const scroll = { top: container.scrollTop, left: container.scrollLeft };
|
|
6316
6619
|
const startLine = resolveOffsetToLine(docLines, normalized.start);
|
|
@@ -7318,10 +7621,13 @@ class CakeEngine {
|
|
|
7318
7621
|
this.caretBlinkTimeoutId = null;
|
|
7319
7622
|
this.overlayUpdateId = null;
|
|
7320
7623
|
this.scrollCaretIntoViewId = null;
|
|
7624
|
+
this.selectionRectElements = [];
|
|
7625
|
+
this.lastSelectionRects = null;
|
|
7321
7626
|
this.extensionsRoot = null;
|
|
7322
7627
|
this.placeholderRoot = null;
|
|
7323
7628
|
this.lastFocusRect = null;
|
|
7324
7629
|
this.verticalNavGoalX = null;
|
|
7630
|
+
this.lastRenderPerf = null;
|
|
7325
7631
|
this.history = {
|
|
7326
7632
|
undoStack: [],
|
|
7327
7633
|
redoStack: [],
|
|
@@ -7375,6 +7681,9 @@ class CakeEngine {
|
|
|
7375
7681
|
set state(value) {
|
|
7376
7682
|
this._state = value;
|
|
7377
7683
|
}
|
|
7684
|
+
getLastRenderPerf() {
|
|
7685
|
+
return this.lastRenderPerf;
|
|
7686
|
+
}
|
|
7378
7687
|
isEventTargetInContentRoot(target) {
|
|
7379
7688
|
if (target === this.container) {
|
|
7380
7689
|
return true;
|
|
@@ -7411,6 +7720,9 @@ class CakeEngine {
|
|
|
7411
7720
|
getSelection() {
|
|
7412
7721
|
return this.state.selection;
|
|
7413
7722
|
}
|
|
7723
|
+
getCursorLength() {
|
|
7724
|
+
return this.state.map.cursorLength;
|
|
7725
|
+
}
|
|
7414
7726
|
getFocusRect() {
|
|
7415
7727
|
return this.lastFocusRect;
|
|
7416
7728
|
}
|
|
@@ -7465,6 +7777,7 @@ class CakeEngine {
|
|
|
7465
7777
|
if (!this.isComposing) {
|
|
7466
7778
|
this.applySelection(this.state.selection);
|
|
7467
7779
|
}
|
|
7780
|
+
this.scheduleScrollCaretIntoView();
|
|
7468
7781
|
}
|
|
7469
7782
|
setValue({ value, selection }) {
|
|
7470
7783
|
const valueChanged = value !== this.state.source;
|
|
@@ -7540,7 +7853,7 @@ class CakeEngine {
|
|
|
7540
7853
|
}
|
|
7541
7854
|
executeCommand(command) {
|
|
7542
7855
|
var _a;
|
|
7543
|
-
const shouldOpenLinkPopover =
|
|
7856
|
+
const shouldOpenLinkPopover = "openPopover" in command && command.openPopover === true;
|
|
7544
7857
|
const nextState = this.runtime.applyEdit(command, this.state);
|
|
7545
7858
|
if (nextState === this.state) {
|
|
7546
7859
|
return false;
|
|
@@ -7715,6 +8028,14 @@ class CakeEngine {
|
|
|
7715
8028
|
this.patchedCaretRangeFromPoint = null;
|
|
7716
8029
|
}
|
|
7717
8030
|
render() {
|
|
8031
|
+
const perfEnabled = this.container.dataset.cakePerf === "1";
|
|
8032
|
+
let perfStart = 0;
|
|
8033
|
+
let renderStart = 0;
|
|
8034
|
+
let renderAndMapMs = 0;
|
|
8035
|
+
let applySelectionMs = 0;
|
|
8036
|
+
if (perfEnabled) {
|
|
8037
|
+
perfStart = performance.now();
|
|
8038
|
+
}
|
|
7718
8039
|
if (!this.contentRoot) {
|
|
7719
8040
|
const containerPosition = window.getComputedStyle(
|
|
7720
8041
|
this.container
|
|
@@ -7730,6 +8051,9 @@ class CakeEngine {
|
|
|
7730
8051
|
this.container.replaceChildren(this.contentRoot, overlay, extensionsRoot);
|
|
7731
8052
|
this.attachDragListeners();
|
|
7732
8053
|
}
|
|
8054
|
+
if (perfEnabled) {
|
|
8055
|
+
renderStart = performance.now();
|
|
8056
|
+
}
|
|
7733
8057
|
const { content, map } = renderDocContent(
|
|
7734
8058
|
this.state.doc,
|
|
7735
8059
|
this.extensions,
|
|
@@ -7741,9 +8065,26 @@ class CakeEngine {
|
|
|
7741
8065
|
this.contentRoot.replaceChildren(...content);
|
|
7742
8066
|
}
|
|
7743
8067
|
this.domMap = map;
|
|
7744
|
-
|
|
7745
|
-
|
|
8068
|
+
if (perfEnabled) {
|
|
8069
|
+
renderAndMapMs = performance.now() - renderStart;
|
|
8070
|
+
}
|
|
8071
|
+
if (!this.isComposing && this.hasFocus()) {
|
|
8072
|
+
const selectionStart = perfEnabled ? performance.now() : 0;
|
|
7746
8073
|
this.applySelection(this.state.selection);
|
|
8074
|
+
if (perfEnabled) {
|
|
8075
|
+
applySelectionMs = performance.now() - selectionStart;
|
|
8076
|
+
}
|
|
8077
|
+
}
|
|
8078
|
+
if (perfEnabled) {
|
|
8079
|
+
const totalMs = performance.now() - perfStart;
|
|
8080
|
+
this.lastRenderPerf = {
|
|
8081
|
+
totalMs,
|
|
8082
|
+
renderAndMapMs,
|
|
8083
|
+
applySelectionMs,
|
|
8084
|
+
didUpdateDom: needsUpdate,
|
|
8085
|
+
blockCount: this.state.doc.blocks.length,
|
|
8086
|
+
runCount: map.runs.length
|
|
8087
|
+
};
|
|
7747
8088
|
}
|
|
7748
8089
|
this.updatePlaceholder();
|
|
7749
8090
|
this.scheduleOverlayUpdate();
|
|
@@ -7993,22 +8334,31 @@ class CakeEngine {
|
|
|
7993
8334
|
this.suppressSelectionChange = false;
|
|
7994
8335
|
return;
|
|
7995
8336
|
}
|
|
7996
|
-
const
|
|
7997
|
-
|
|
7998
|
-
if (
|
|
8337
|
+
const pendingHit = this.pendingClickHit;
|
|
8338
|
+
const selection = this.state.selection;
|
|
8339
|
+
if (pendingHit && selection.start !== selection.end) {
|
|
7999
8340
|
const newSelection = {
|
|
8000
|
-
start:
|
|
8001
|
-
end:
|
|
8002
|
-
affinity:
|
|
8341
|
+
start: pendingHit.cursorOffset,
|
|
8342
|
+
end: pendingHit.cursorOffset,
|
|
8343
|
+
affinity: pendingHit.affinity
|
|
8003
8344
|
};
|
|
8345
|
+
this.pendingClickHit = null;
|
|
8346
|
+
this.suppressSelectionChange = true;
|
|
8004
8347
|
this.state = this.runtime.updateSelection(this.state, newSelection, {
|
|
8005
8348
|
kind: "dom"
|
|
8006
8349
|
});
|
|
8007
8350
|
this.applySelection(this.state.selection);
|
|
8008
8351
|
(_b = this.onSelectionChange) == null ? void 0 : _b.call(this, this.state.selection);
|
|
8009
8352
|
this.scheduleOverlayUpdate();
|
|
8353
|
+
setTimeout(() => {
|
|
8354
|
+
this.suppressSelectionChange = false;
|
|
8355
|
+
}, 0);
|
|
8356
|
+
return;
|
|
8010
8357
|
}
|
|
8011
|
-
this.
|
|
8358
|
+
this.pendingClickHit = null;
|
|
8359
|
+
setTimeout(() => {
|
|
8360
|
+
this.suppressSelectionChange = false;
|
|
8361
|
+
}, 0);
|
|
8012
8362
|
return;
|
|
8013
8363
|
}
|
|
8014
8364
|
this.pendingClickHit = null;
|
|
@@ -8386,7 +8736,7 @@ class CakeEngine {
|
|
|
8386
8736
|
if (!command) {
|
|
8387
8737
|
continue;
|
|
8388
8738
|
}
|
|
8389
|
-
if (command
|
|
8739
|
+
if (isApplyEditCommand(command)) {
|
|
8390
8740
|
this.applyEdit(command);
|
|
8391
8741
|
} else {
|
|
8392
8742
|
this.executeCommand(command);
|
|
@@ -8906,6 +9256,39 @@ class CakeEngine {
|
|
|
8906
9256
|
return { start: target, end: target, affinity: direction };
|
|
8907
9257
|
}
|
|
8908
9258
|
const currentPos = selection.start;
|
|
9259
|
+
const currentAffinity = selection.affinity ?? "forward";
|
|
9260
|
+
const measurement = this.getLayoutForNavigation();
|
|
9261
|
+
if (measurement) {
|
|
9262
|
+
const { lines, layout } = measurement;
|
|
9263
|
+
const { rowStart, rowEnd } = getVisualRowBoundaries({
|
|
9264
|
+
lines,
|
|
9265
|
+
layout,
|
|
9266
|
+
offset: currentPos,
|
|
9267
|
+
affinity: currentAffinity
|
|
9268
|
+
});
|
|
9269
|
+
if (direction === "backward" && currentPos === rowStart && currentAffinity === "forward" && currentPos > 0) {
|
|
9270
|
+
const prevBoundaries = getVisualRowBoundaries({
|
|
9271
|
+
lines,
|
|
9272
|
+
layout,
|
|
9273
|
+
offset: currentPos,
|
|
9274
|
+
affinity: "backward"
|
|
9275
|
+
});
|
|
9276
|
+
if (prevBoundaries.rowEnd !== rowEnd || prevBoundaries.rowStart !== rowStart) {
|
|
9277
|
+
return { start: currentPos, end: currentPos, affinity: "backward" };
|
|
9278
|
+
}
|
|
9279
|
+
}
|
|
9280
|
+
if (direction === "forward" && currentPos === rowEnd && currentAffinity === "backward" && currentPos < this.state.map.cursorLength) {
|
|
9281
|
+
const nextBoundaries = getVisualRowBoundaries({
|
|
9282
|
+
lines,
|
|
9283
|
+
layout,
|
|
9284
|
+
offset: currentPos,
|
|
9285
|
+
affinity: "forward"
|
|
9286
|
+
});
|
|
9287
|
+
if (nextBoundaries.rowEnd !== rowEnd || nextBoundaries.rowStart !== rowStart) {
|
|
9288
|
+
return { start: currentPos, end: currentPos, affinity: "forward" };
|
|
9289
|
+
}
|
|
9290
|
+
}
|
|
9291
|
+
}
|
|
8909
9292
|
const nextPos = this.moveOffsetByChar(currentPos, direction);
|
|
8910
9293
|
if (nextPos === null) {
|
|
8911
9294
|
return null;
|
|
@@ -9595,6 +9978,7 @@ class CakeEngine {
|
|
|
9595
9978
|
}
|
|
9596
9979
|
this.overlayUpdateId = window.requestAnimationFrame(() => {
|
|
9597
9980
|
this.overlayUpdateId = null;
|
|
9981
|
+
this.updateExtensionsOverlayPosition();
|
|
9598
9982
|
this.updateSelectionOverlay();
|
|
9599
9983
|
});
|
|
9600
9984
|
}
|
|
@@ -9624,12 +10008,34 @@ class CakeEngine {
|
|
|
9624
10008
|
overlay.style.zIndex = "2";
|
|
9625
10009
|
const caret = document.createElement("div");
|
|
9626
10010
|
caret.className = "cake-caret";
|
|
10011
|
+
caret.style.position = "absolute";
|
|
9627
10012
|
caret.style.display = "none";
|
|
9628
10013
|
overlay.append(caret);
|
|
9629
10014
|
this.overlayRoot = overlay;
|
|
9630
10015
|
this.caretElement = caret;
|
|
10016
|
+
this.selectionRectElements = [];
|
|
10017
|
+
this.lastSelectionRects = null;
|
|
9631
10018
|
return overlay;
|
|
9632
10019
|
}
|
|
10020
|
+
selectionRectsEqual(prev, next) {
|
|
10021
|
+
if (!prev) {
|
|
10022
|
+
return false;
|
|
10023
|
+
}
|
|
10024
|
+
if (prev.length !== next.length) {
|
|
10025
|
+
return false;
|
|
10026
|
+
}
|
|
10027
|
+
for (let index = 0; index < prev.length; index += 1) {
|
|
10028
|
+
const a = prev[index];
|
|
10029
|
+
const b = next[index];
|
|
10030
|
+
if (!a || !b) {
|
|
10031
|
+
return false;
|
|
10032
|
+
}
|
|
10033
|
+
if (a.top !== b.top || a.left !== b.left || a.width !== b.width || a.height !== b.height) {
|
|
10034
|
+
return false;
|
|
10035
|
+
}
|
|
10036
|
+
}
|
|
10037
|
+
return true;
|
|
10038
|
+
}
|
|
9633
10039
|
ensureExtensionsRoot() {
|
|
9634
10040
|
if (this.extensionsRoot) {
|
|
9635
10041
|
return this.extensionsRoot;
|
|
@@ -9690,21 +10096,34 @@ class CakeEngine {
|
|
|
9690
10096
|
if (!this.overlayRoot || !this.caretElement) {
|
|
9691
10097
|
return;
|
|
9692
10098
|
}
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
9696
|
-
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
10099
|
+
if (this.selectionRectsEqual(this.lastSelectionRects, rects)) {
|
|
10100
|
+
return;
|
|
10101
|
+
}
|
|
10102
|
+
this.lastSelectionRects = rects;
|
|
10103
|
+
while (this.selectionRectElements.length > rects.length) {
|
|
10104
|
+
const element = this.selectionRectElements.pop();
|
|
10105
|
+
element == null ? void 0 : element.remove();
|
|
10106
|
+
}
|
|
10107
|
+
if (this.selectionRectElements.length < rects.length) {
|
|
10108
|
+
const fragment = document.createDocumentFragment();
|
|
10109
|
+
while (this.selectionRectElements.length < rects.length) {
|
|
10110
|
+
const element = document.createElement("div");
|
|
10111
|
+
element.className = "cake-selection-rect";
|
|
10112
|
+
fragment.append(element);
|
|
10113
|
+
this.selectionRectElements.push(element);
|
|
10114
|
+
}
|
|
10115
|
+
this.overlayRoot.insertBefore(fragment, this.caretElement);
|
|
10116
|
+
}
|
|
10117
|
+
rects.forEach((rect, index) => {
|
|
10118
|
+
const element = this.selectionRectElements[index];
|
|
10119
|
+
if (!element) {
|
|
10120
|
+
return;
|
|
10121
|
+
}
|
|
9701
10122
|
element.style.top = `${rect.top}px`;
|
|
9702
10123
|
element.style.left = `${rect.left}px`;
|
|
9703
10124
|
element.style.width = `${rect.width}px`;
|
|
9704
10125
|
element.style.height = `${rect.height}px`;
|
|
9705
|
-
fragment.append(element);
|
|
9706
10126
|
});
|
|
9707
|
-
this.overlayRoot.insertBefore(fragment, this.caretElement);
|
|
9708
10127
|
}
|
|
9709
10128
|
updateCaret(position) {
|
|
9710
10129
|
if (!this.caretElement) {
|
|
@@ -9871,7 +10290,7 @@ class CakeEngine {
|
|
|
9871
10290
|
return { cursorOffset: cursor.cursorOffset, affinity: "backward" };
|
|
9872
10291
|
}
|
|
9873
10292
|
handlePointerDown(event) {
|
|
9874
|
-
var _a;
|
|
10293
|
+
var _a, _b, _c;
|
|
9875
10294
|
if (!this.isEventTargetInContentRoot(event.target)) {
|
|
9876
10295
|
return;
|
|
9877
10296
|
}
|
|
@@ -9936,13 +10355,51 @@ class CakeEngine {
|
|
|
9936
10355
|
}
|
|
9937
10356
|
}
|
|
9938
10357
|
}
|
|
9939
|
-
if (
|
|
9940
|
-
this.suppressSelectionChange = true;
|
|
10358
|
+
if (!event.shiftKey) {
|
|
9941
10359
|
const hit2 = this.hitTestFromClientPoint(event.clientX, event.clientY);
|
|
9942
|
-
if (hit2) {
|
|
10360
|
+
if (!hit2) {
|
|
10361
|
+
return;
|
|
10362
|
+
}
|
|
10363
|
+
if (selection.start !== selection.end) {
|
|
10364
|
+
const selStart2 = Math.min(selection.start, selection.end);
|
|
10365
|
+
const selEnd2 = Math.max(selection.start, selection.end);
|
|
10366
|
+
const clickedInsideSelection2 = hit2.cursorOffset >= selStart2 && hit2.cursorOffset <= selEnd2;
|
|
10367
|
+
if (clickedInsideSelection2) {
|
|
10368
|
+
this.suppressSelectionChange = false;
|
|
10369
|
+
this.blockTrustedTextDrag = true;
|
|
10370
|
+
this.pendingClickHit = hit2;
|
|
10371
|
+
} else {
|
|
10372
|
+
this.suppressSelectionChange = true;
|
|
10373
|
+
this.pendingClickHit = hit2;
|
|
10374
|
+
const newSelection = {
|
|
10375
|
+
start: hit2.cursorOffset,
|
|
10376
|
+
end: hit2.cursorOffset,
|
|
10377
|
+
affinity: hit2.affinity
|
|
10378
|
+
};
|
|
10379
|
+
this.state = this.runtime.updateSelection(this.state, newSelection, {
|
|
10380
|
+
kind: "dom"
|
|
10381
|
+
});
|
|
10382
|
+
this.applySelection(this.state.selection);
|
|
10383
|
+
(_b = this.onSelectionChange) == null ? void 0 : _b.call(this, this.state.selection);
|
|
10384
|
+
this.scheduleOverlayUpdate();
|
|
10385
|
+
return;
|
|
10386
|
+
}
|
|
10387
|
+
} else {
|
|
10388
|
+
this.suppressSelectionChange = true;
|
|
9943
10389
|
this.pendingClickHit = hit2;
|
|
10390
|
+
const newSelection = {
|
|
10391
|
+
start: hit2.cursorOffset,
|
|
10392
|
+
end: hit2.cursorOffset,
|
|
10393
|
+
affinity: hit2.affinity
|
|
10394
|
+
};
|
|
10395
|
+
this.state = this.runtime.updateSelection(this.state, newSelection, {
|
|
10396
|
+
kind: "dom"
|
|
10397
|
+
});
|
|
10398
|
+
this.applySelection(this.state.selection);
|
|
10399
|
+
(_c = this.onSelectionChange) == null ? void 0 : _c.call(this, this.state.selection);
|
|
10400
|
+
this.scheduleOverlayUpdate();
|
|
10401
|
+
return;
|
|
9944
10402
|
}
|
|
9945
|
-
return;
|
|
9946
10403
|
}
|
|
9947
10404
|
this.suppressSelectionChange = false;
|
|
9948
10405
|
const selStart = Math.min(selection.start, selection.end);
|
|
@@ -10054,10 +10511,6 @@ class CakeEngine {
|
|
|
10054
10511
|
}
|
|
10055
10512
|
handlePointerUp(event) {
|
|
10056
10513
|
this.blockTrustedTextDrag = false;
|
|
10057
|
-
if (this.pendingClickHit) {
|
|
10058
|
-
this.pendingClickHit = null;
|
|
10059
|
-
this.suppressSelectionChange = false;
|
|
10060
|
-
}
|
|
10061
10514
|
if (this.selectionDragState) {
|
|
10062
10515
|
if (event.pointerId !== this.selectionDragState.pointerId) {
|
|
10063
10516
|
return;
|
|
@@ -10557,7 +11010,7 @@ function findOffsetInTextNode(textNode, clientX, clientY) {
|
|
|
10557
11010
|
let closestDistance = Infinity;
|
|
10558
11011
|
let closestYDistance = Infinity;
|
|
10559
11012
|
let closestCaretX = 0;
|
|
10560
|
-
let
|
|
11013
|
+
let selectedViaRightEdge = false;
|
|
10561
11014
|
const rowInfo = /* @__PURE__ */ new Map();
|
|
10562
11015
|
const range = document.createRange();
|
|
10563
11016
|
let lastCharRect = null;
|
|
@@ -10626,15 +11079,28 @@ function findOffsetInTextNode(textNode, clientX, clientY) {
|
|
|
10626
11079
|
closestDistance = xDistance;
|
|
10627
11080
|
closestOffset = i;
|
|
10628
11081
|
closestCaretX = caretX;
|
|
10629
|
-
|
|
11082
|
+
bestRect.top;
|
|
10630
11083
|
closestYDistance = yDistance;
|
|
11084
|
+
selectedViaRightEdge = false;
|
|
11085
|
+
}
|
|
11086
|
+
if (i < text.length) {
|
|
11087
|
+
const rightEdgeX = bestRect.right;
|
|
11088
|
+
const rightEdgeDistance = Math.abs(clientX - rightEdgeX);
|
|
11089
|
+
if (rightEdgeDistance < closestDistance) {
|
|
11090
|
+
closestDistance = rightEdgeDistance;
|
|
11091
|
+
closestOffset = i + 1;
|
|
11092
|
+
closestCaretX = rightEdgeX;
|
|
11093
|
+
bestRect.top;
|
|
11094
|
+
closestYDistance = yDistance;
|
|
11095
|
+
selectedViaRightEdge = true;
|
|
11096
|
+
}
|
|
10631
11097
|
}
|
|
10632
11098
|
} else if (yDistance < closestYDistance || yDistance === closestYDistance && xDistance < closestDistance) {
|
|
10633
11099
|
closestYDistance = yDistance;
|
|
10634
11100
|
closestDistance = xDistance;
|
|
10635
11101
|
closestOffset = i;
|
|
10636
11102
|
closestCaretX = caretX;
|
|
10637
|
-
|
|
11103
|
+
bestRect.top;
|
|
10638
11104
|
}
|
|
10639
11105
|
}
|
|
10640
11106
|
let closestRow = null;
|
|
@@ -10659,11 +11125,11 @@ function findOffsetInTextNode(textNode, clientX, clientY) {
|
|
|
10659
11125
|
if (clientX < closestRow.left) {
|
|
10660
11126
|
closestOffset = closestRow.startOffset;
|
|
10661
11127
|
closestCaretX = closestRow.left;
|
|
10662
|
-
|
|
11128
|
+
closestRow.top;
|
|
10663
11129
|
} else if (clientX > closestRow.right) {
|
|
10664
|
-
closestOffset = closestRow.endOffset;
|
|
11130
|
+
closestOffset = Math.min(closestRow.endOffset + 1, text.length);
|
|
10665
11131
|
closestCaretX = closestRow.right;
|
|
10666
|
-
|
|
11132
|
+
closestRow.top;
|
|
10667
11133
|
} else if (clientY < closestRow.top || clientY > closestRow.bottom) {
|
|
10668
11134
|
let bestXDistance = Infinity;
|
|
10669
11135
|
const range2 = document.createRange();
|
|
@@ -10683,12 +11149,12 @@ function findOffsetInTextNode(textNode, clientX, clientY) {
|
|
|
10683
11149
|
bestXDistance = xDist;
|
|
10684
11150
|
closestOffset = i;
|
|
10685
11151
|
closestCaretX = rect.left;
|
|
10686
|
-
|
|
11152
|
+
closestRow.top;
|
|
10687
11153
|
}
|
|
10688
11154
|
}
|
|
10689
11155
|
}
|
|
10690
11156
|
}
|
|
10691
|
-
const pastRowEnd = closestRow !== null && clientX > closestRow.right
|
|
11157
|
+
const pastRowEnd = selectedViaRightEdge || closestRow !== null && clientX > closestRow.right;
|
|
10692
11158
|
if (Math.abs(clientX - closestCaretX) <= 2 && closestOffset < text.length && text[closestOffset] === "\n") {
|
|
10693
11159
|
closestOffset = Math.max(0, closestOffset - 1);
|
|
10694
11160
|
}
|
|
@@ -11141,8 +11607,9 @@ const CakeEditor = forwardRef(
|
|
|
11141
11607
|
const lastEmittedSelectionRef = useRef(null);
|
|
11142
11608
|
const [overlayRoot, setOverlayRoot] = useState(null);
|
|
11143
11609
|
const [contentRoot, setContentRoot] = useState(null);
|
|
11610
|
+
const baseExtensions = props.disableImageExtension ? bundledExtensionsWithoutImage : bundledExtensions;
|
|
11144
11611
|
const allExtensionsRef = useRef([
|
|
11145
|
-
...
|
|
11612
|
+
...baseExtensions,
|
|
11146
11613
|
...props.extensions ?? []
|
|
11147
11614
|
]);
|
|
11148
11615
|
useEffect(() => {
|
|
@@ -11300,6 +11767,10 @@ const CakeEditor = forwardRef(
|
|
|
11300
11767
|
}
|
|
11301
11768
|
return { start: selection.start, end: selection.end };
|
|
11302
11769
|
},
|
|
11770
|
+
getCursorLength: () => {
|
|
11771
|
+
var _a;
|
|
11772
|
+
return ((_a = engineRef.current) == null ? void 0 : _a.getCursorLength()) ?? 0;
|
|
11773
|
+
},
|
|
11303
11774
|
insertText: (text) => {
|
|
11304
11775
|
var _a;
|
|
11305
11776
|
(_a = engineRef.current) == null ? void 0 : _a.insertText(text);
|
|
@@ -11353,6 +11824,10 @@ const CakeEditor = forwardRef(
|
|
|
11353
11824
|
}
|
|
11354
11825
|
const focus = selection.start === selection.end ? selection.start : Math.max(selection.start, selection.end);
|
|
11355
11826
|
return { start: focus, end: focus };
|
|
11827
|
+
},
|
|
11828
|
+
executeCommand: (command) => {
|
|
11829
|
+
var _a;
|
|
11830
|
+
return ((_a = engineRef.current) == null ? void 0 : _a.executeCommand(command)) ?? false;
|
|
11356
11831
|
}
|
|
11357
11832
|
} : null;
|
|
11358
11833
|
const hasOverlayExtensions = allExtensionsRef.current.some(
|
|
@@ -11385,6 +11860,7 @@ export {
|
|
|
11385
11860
|
blockquoteExtension,
|
|
11386
11861
|
boldExtension,
|
|
11387
11862
|
bundledExtensions,
|
|
11863
|
+
bundledExtensionsWithoutImage,
|
|
11388
11864
|
combinedEmphasisExtension,
|
|
11389
11865
|
headingExtension,
|
|
11390
11866
|
imageExtension,
|