@blankdotpage/cake 0.1.2 → 0.1.4
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 +15 -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 +662 -179
- package/dist/index.js +662 -179
- 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: [],
|
|
@@ -7354,6 +7660,7 @@ class CakeEngine {
|
|
|
7354
7660
|
this.selectionDragState = null;
|
|
7355
7661
|
this.pointerDownPosition = null;
|
|
7356
7662
|
this.hasMovedSincePointerDown = false;
|
|
7663
|
+
this.lastTouchTime = 0;
|
|
7357
7664
|
this.container = options.container;
|
|
7358
7665
|
this.extensions = options.extensions ?? bundledExtensions;
|
|
7359
7666
|
this.runtime = createRuntime(this.extensions);
|
|
@@ -7375,6 +7682,9 @@ class CakeEngine {
|
|
|
7375
7682
|
set state(value) {
|
|
7376
7683
|
this._state = value;
|
|
7377
7684
|
}
|
|
7685
|
+
getLastRenderPerf() {
|
|
7686
|
+
return this.lastRenderPerf;
|
|
7687
|
+
}
|
|
7378
7688
|
isEventTargetInContentRoot(target) {
|
|
7379
7689
|
if (target === this.container) {
|
|
7380
7690
|
return true;
|
|
@@ -7411,6 +7721,9 @@ class CakeEngine {
|
|
|
7411
7721
|
getSelection() {
|
|
7412
7722
|
return this.state.selection;
|
|
7413
7723
|
}
|
|
7724
|
+
getCursorLength() {
|
|
7725
|
+
return this.state.map.cursorLength;
|
|
7726
|
+
}
|
|
7414
7727
|
getFocusRect() {
|
|
7415
7728
|
return this.lastFocusRect;
|
|
7416
7729
|
}
|
|
@@ -7465,6 +7778,7 @@ class CakeEngine {
|
|
|
7465
7778
|
if (!this.isComposing) {
|
|
7466
7779
|
this.applySelection(this.state.selection);
|
|
7467
7780
|
}
|
|
7781
|
+
this.scheduleScrollCaretIntoView();
|
|
7468
7782
|
}
|
|
7469
7783
|
setValue({ value, selection }) {
|
|
7470
7784
|
const valueChanged = value !== this.state.source;
|
|
@@ -7540,7 +7854,7 @@ class CakeEngine {
|
|
|
7540
7854
|
}
|
|
7541
7855
|
executeCommand(command) {
|
|
7542
7856
|
var _a;
|
|
7543
|
-
const shouldOpenLinkPopover =
|
|
7857
|
+
const shouldOpenLinkPopover = "openPopover" in command && command.openPopover === true;
|
|
7544
7858
|
const nextState = this.runtime.applyEdit(command, this.state);
|
|
7545
7859
|
if (nextState === this.state) {
|
|
7546
7860
|
return false;
|
|
@@ -7715,6 +8029,14 @@ class CakeEngine {
|
|
|
7715
8029
|
this.patchedCaretRangeFromPoint = null;
|
|
7716
8030
|
}
|
|
7717
8031
|
render() {
|
|
8032
|
+
const perfEnabled = this.container.dataset.cakePerf === "1";
|
|
8033
|
+
let perfStart = 0;
|
|
8034
|
+
let renderStart = 0;
|
|
8035
|
+
let renderAndMapMs = 0;
|
|
8036
|
+
let applySelectionMs = 0;
|
|
8037
|
+
if (perfEnabled) {
|
|
8038
|
+
perfStart = performance.now();
|
|
8039
|
+
}
|
|
7718
8040
|
if (!this.contentRoot) {
|
|
7719
8041
|
const containerPosition = window.getComputedStyle(
|
|
7720
8042
|
this.container
|
|
@@ -7730,6 +8052,9 @@ class CakeEngine {
|
|
|
7730
8052
|
this.container.replaceChildren(this.contentRoot, overlay, extensionsRoot);
|
|
7731
8053
|
this.attachDragListeners();
|
|
7732
8054
|
}
|
|
8055
|
+
if (perfEnabled) {
|
|
8056
|
+
renderStart = performance.now();
|
|
8057
|
+
}
|
|
7733
8058
|
const { content, map } = renderDocContent(
|
|
7734
8059
|
this.state.doc,
|
|
7735
8060
|
this.extensions,
|
|
@@ -7741,9 +8066,26 @@ class CakeEngine {
|
|
|
7741
8066
|
this.contentRoot.replaceChildren(...content);
|
|
7742
8067
|
}
|
|
7743
8068
|
this.domMap = map;
|
|
7744
|
-
|
|
7745
|
-
|
|
8069
|
+
if (perfEnabled) {
|
|
8070
|
+
renderAndMapMs = performance.now() - renderStart;
|
|
8071
|
+
}
|
|
8072
|
+
if (!this.isComposing && this.hasFocus()) {
|
|
8073
|
+
const selectionStart = perfEnabled ? performance.now() : 0;
|
|
7746
8074
|
this.applySelection(this.state.selection);
|
|
8075
|
+
if (perfEnabled) {
|
|
8076
|
+
applySelectionMs = performance.now() - selectionStart;
|
|
8077
|
+
}
|
|
8078
|
+
}
|
|
8079
|
+
if (perfEnabled) {
|
|
8080
|
+
const totalMs = performance.now() - perfStart;
|
|
8081
|
+
this.lastRenderPerf = {
|
|
8082
|
+
totalMs,
|
|
8083
|
+
renderAndMapMs,
|
|
8084
|
+
applySelectionMs,
|
|
8085
|
+
didUpdateDom: needsUpdate,
|
|
8086
|
+
blockCount: this.state.doc.blocks.length,
|
|
8087
|
+
runCount: map.runs.length
|
|
8088
|
+
};
|
|
7747
8089
|
}
|
|
7748
8090
|
this.updatePlaceholder();
|
|
7749
8091
|
this.scheduleOverlayUpdate();
|
|
@@ -7993,22 +8335,31 @@ class CakeEngine {
|
|
|
7993
8335
|
this.suppressSelectionChange = false;
|
|
7994
8336
|
return;
|
|
7995
8337
|
}
|
|
7996
|
-
const
|
|
7997
|
-
|
|
7998
|
-
if (
|
|
8338
|
+
const pendingHit = this.pendingClickHit;
|
|
8339
|
+
const selection = this.state.selection;
|
|
8340
|
+
if (pendingHit && selection.start !== selection.end) {
|
|
7999
8341
|
const newSelection = {
|
|
8000
|
-
start:
|
|
8001
|
-
end:
|
|
8002
|
-
affinity:
|
|
8342
|
+
start: pendingHit.cursorOffset,
|
|
8343
|
+
end: pendingHit.cursorOffset,
|
|
8344
|
+
affinity: pendingHit.affinity
|
|
8003
8345
|
};
|
|
8346
|
+
this.pendingClickHit = null;
|
|
8347
|
+
this.suppressSelectionChange = true;
|
|
8004
8348
|
this.state = this.runtime.updateSelection(this.state, newSelection, {
|
|
8005
8349
|
kind: "dom"
|
|
8006
8350
|
});
|
|
8007
8351
|
this.applySelection(this.state.selection);
|
|
8008
8352
|
(_b = this.onSelectionChange) == null ? void 0 : _b.call(this, this.state.selection);
|
|
8009
8353
|
this.scheduleOverlayUpdate();
|
|
8354
|
+
setTimeout(() => {
|
|
8355
|
+
this.suppressSelectionChange = false;
|
|
8356
|
+
}, 0);
|
|
8357
|
+
return;
|
|
8010
8358
|
}
|
|
8011
|
-
this.
|
|
8359
|
+
this.pendingClickHit = null;
|
|
8360
|
+
setTimeout(() => {
|
|
8361
|
+
this.suppressSelectionChange = false;
|
|
8362
|
+
}, 0);
|
|
8012
8363
|
return;
|
|
8013
8364
|
}
|
|
8014
8365
|
this.pendingClickHit = null;
|
|
@@ -8386,7 +8737,7 @@ class CakeEngine {
|
|
|
8386
8737
|
if (!command) {
|
|
8387
8738
|
continue;
|
|
8388
8739
|
}
|
|
8389
|
-
if (command
|
|
8740
|
+
if (isApplyEditCommand(command)) {
|
|
8390
8741
|
this.applyEdit(command);
|
|
8391
8742
|
} else {
|
|
8392
8743
|
this.executeCommand(command);
|
|
@@ -8906,6 +9257,39 @@ class CakeEngine {
|
|
|
8906
9257
|
return { start: target, end: target, affinity: direction };
|
|
8907
9258
|
}
|
|
8908
9259
|
const currentPos = selection.start;
|
|
9260
|
+
const currentAffinity = selection.affinity ?? "forward";
|
|
9261
|
+
const measurement = this.getLayoutForNavigation();
|
|
9262
|
+
if (measurement) {
|
|
9263
|
+
const { lines, layout } = measurement;
|
|
9264
|
+
const { rowStart, rowEnd } = getVisualRowBoundaries({
|
|
9265
|
+
lines,
|
|
9266
|
+
layout,
|
|
9267
|
+
offset: currentPos,
|
|
9268
|
+
affinity: currentAffinity
|
|
9269
|
+
});
|
|
9270
|
+
if (direction === "backward" && currentPos === rowStart && currentAffinity === "forward" && currentPos > 0) {
|
|
9271
|
+
const prevBoundaries = getVisualRowBoundaries({
|
|
9272
|
+
lines,
|
|
9273
|
+
layout,
|
|
9274
|
+
offset: currentPos,
|
|
9275
|
+
affinity: "backward"
|
|
9276
|
+
});
|
|
9277
|
+
if (prevBoundaries.rowEnd !== rowEnd || prevBoundaries.rowStart !== rowStart) {
|
|
9278
|
+
return { start: currentPos, end: currentPos, affinity: "backward" };
|
|
9279
|
+
}
|
|
9280
|
+
}
|
|
9281
|
+
if (direction === "forward" && currentPos === rowEnd && currentAffinity === "backward" && currentPos < this.state.map.cursorLength) {
|
|
9282
|
+
const nextBoundaries = getVisualRowBoundaries({
|
|
9283
|
+
lines,
|
|
9284
|
+
layout,
|
|
9285
|
+
offset: currentPos,
|
|
9286
|
+
affinity: "forward"
|
|
9287
|
+
});
|
|
9288
|
+
if (nextBoundaries.rowEnd !== rowEnd || nextBoundaries.rowStart !== rowStart) {
|
|
9289
|
+
return { start: currentPos, end: currentPos, affinity: "forward" };
|
|
9290
|
+
}
|
|
9291
|
+
}
|
|
9292
|
+
}
|
|
8909
9293
|
const nextPos = this.moveOffsetByChar(currentPos, direction);
|
|
8910
9294
|
if (nextPos === null) {
|
|
8911
9295
|
return null;
|
|
@@ -9595,6 +9979,7 @@ class CakeEngine {
|
|
|
9595
9979
|
}
|
|
9596
9980
|
this.overlayUpdateId = window.requestAnimationFrame(() => {
|
|
9597
9981
|
this.overlayUpdateId = null;
|
|
9982
|
+
this.updateExtensionsOverlayPosition();
|
|
9598
9983
|
this.updateSelectionOverlay();
|
|
9599
9984
|
});
|
|
9600
9985
|
}
|
|
@@ -9624,12 +10009,34 @@ class CakeEngine {
|
|
|
9624
10009
|
overlay.style.zIndex = "2";
|
|
9625
10010
|
const caret = document.createElement("div");
|
|
9626
10011
|
caret.className = "cake-caret";
|
|
10012
|
+
caret.style.position = "absolute";
|
|
9627
10013
|
caret.style.display = "none";
|
|
9628
10014
|
overlay.append(caret);
|
|
9629
10015
|
this.overlayRoot = overlay;
|
|
9630
10016
|
this.caretElement = caret;
|
|
10017
|
+
this.selectionRectElements = [];
|
|
10018
|
+
this.lastSelectionRects = null;
|
|
9631
10019
|
return overlay;
|
|
9632
10020
|
}
|
|
10021
|
+
selectionRectsEqual(prev, next) {
|
|
10022
|
+
if (!prev) {
|
|
10023
|
+
return false;
|
|
10024
|
+
}
|
|
10025
|
+
if (prev.length !== next.length) {
|
|
10026
|
+
return false;
|
|
10027
|
+
}
|
|
10028
|
+
for (let index = 0; index < prev.length; index += 1) {
|
|
10029
|
+
const a = prev[index];
|
|
10030
|
+
const b = next[index];
|
|
10031
|
+
if (!a || !b) {
|
|
10032
|
+
return false;
|
|
10033
|
+
}
|
|
10034
|
+
if (a.top !== b.top || a.left !== b.left || a.width !== b.width || a.height !== b.height) {
|
|
10035
|
+
return false;
|
|
10036
|
+
}
|
|
10037
|
+
}
|
|
10038
|
+
return true;
|
|
10039
|
+
}
|
|
9633
10040
|
ensureExtensionsRoot() {
|
|
9634
10041
|
if (this.extensionsRoot) {
|
|
9635
10042
|
return this.extensionsRoot;
|
|
@@ -9666,6 +10073,14 @@ class CakeEngine {
|
|
|
9666
10073
|
if (!this.overlayRoot || !this.contentRoot) {
|
|
9667
10074
|
return;
|
|
9668
10075
|
}
|
|
10076
|
+
const isRecentTouch = Date.now() - this.lastTouchTime < 2e3;
|
|
10077
|
+
if (isRecentTouch) {
|
|
10078
|
+
this.contentRoot.classList.add("cake-touch-mode");
|
|
10079
|
+
this.updateCaret(null);
|
|
10080
|
+
this.syncSelectionRects([]);
|
|
10081
|
+
return;
|
|
10082
|
+
}
|
|
10083
|
+
this.contentRoot.classList.remove("cake-touch-mode");
|
|
9669
10084
|
const lines = getDocLines(this.state.doc);
|
|
9670
10085
|
const geometry = getSelectionGeometry({
|
|
9671
10086
|
root: this.contentRoot,
|
|
@@ -9690,21 +10105,34 @@ class CakeEngine {
|
|
|
9690
10105
|
if (!this.overlayRoot || !this.caretElement) {
|
|
9691
10106
|
return;
|
|
9692
10107
|
}
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
9696
|
-
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
10108
|
+
if (this.selectionRectsEqual(this.lastSelectionRects, rects)) {
|
|
10109
|
+
return;
|
|
10110
|
+
}
|
|
10111
|
+
this.lastSelectionRects = rects;
|
|
10112
|
+
while (this.selectionRectElements.length > rects.length) {
|
|
10113
|
+
const element = this.selectionRectElements.pop();
|
|
10114
|
+
element == null ? void 0 : element.remove();
|
|
10115
|
+
}
|
|
10116
|
+
if (this.selectionRectElements.length < rects.length) {
|
|
10117
|
+
const fragment = document.createDocumentFragment();
|
|
10118
|
+
while (this.selectionRectElements.length < rects.length) {
|
|
10119
|
+
const element = document.createElement("div");
|
|
10120
|
+
element.className = "cake-selection-rect";
|
|
10121
|
+
fragment.append(element);
|
|
10122
|
+
this.selectionRectElements.push(element);
|
|
10123
|
+
}
|
|
10124
|
+
this.overlayRoot.insertBefore(fragment, this.caretElement);
|
|
10125
|
+
}
|
|
10126
|
+
rects.forEach((rect, index) => {
|
|
10127
|
+
const element = this.selectionRectElements[index];
|
|
10128
|
+
if (!element) {
|
|
10129
|
+
return;
|
|
10130
|
+
}
|
|
9701
10131
|
element.style.top = `${rect.top}px`;
|
|
9702
10132
|
element.style.left = `${rect.left}px`;
|
|
9703
10133
|
element.style.width = `${rect.width}px`;
|
|
9704
10134
|
element.style.height = `${rect.height}px`;
|
|
9705
|
-
fragment.append(element);
|
|
9706
10135
|
});
|
|
9707
|
-
this.overlayRoot.insertBefore(fragment, this.caretElement);
|
|
9708
10136
|
}
|
|
9709
10137
|
updateCaret(position) {
|
|
9710
10138
|
if (!this.caretElement) {
|
|
@@ -9871,7 +10299,7 @@ class CakeEngine {
|
|
|
9871
10299
|
return { cursorOffset: cursor.cursorOffset, affinity: "backward" };
|
|
9872
10300
|
}
|
|
9873
10301
|
handlePointerDown(event) {
|
|
9874
|
-
var _a;
|
|
10302
|
+
var _a, _b, _c;
|
|
9875
10303
|
if (!this.isEventTargetInContentRoot(event.target)) {
|
|
9876
10304
|
return;
|
|
9877
10305
|
}
|
|
@@ -9888,9 +10316,7 @@ class CakeEngine {
|
|
|
9888
10316
|
return;
|
|
9889
10317
|
}
|
|
9890
10318
|
if (event.pointerType === "touch") {
|
|
9891
|
-
this.
|
|
9892
|
-
this.suppressSelectionChangeForTick();
|
|
9893
|
-
event.preventDefault();
|
|
10319
|
+
this.lastTouchTime = Date.now();
|
|
9894
10320
|
return;
|
|
9895
10321
|
}
|
|
9896
10322
|
const selection = this.state.selection;
|
|
@@ -9936,13 +10362,51 @@ class CakeEngine {
|
|
|
9936
10362
|
}
|
|
9937
10363
|
}
|
|
9938
10364
|
}
|
|
9939
|
-
if (
|
|
9940
|
-
this.suppressSelectionChange = true;
|
|
10365
|
+
if (!event.shiftKey) {
|
|
9941
10366
|
const hit2 = this.hitTestFromClientPoint(event.clientX, event.clientY);
|
|
9942
|
-
if (hit2) {
|
|
10367
|
+
if (!hit2) {
|
|
10368
|
+
return;
|
|
10369
|
+
}
|
|
10370
|
+
if (selection.start !== selection.end) {
|
|
10371
|
+
const selStart2 = Math.min(selection.start, selection.end);
|
|
10372
|
+
const selEnd2 = Math.max(selection.start, selection.end);
|
|
10373
|
+
const clickedInsideSelection2 = hit2.cursorOffset >= selStart2 && hit2.cursorOffset <= selEnd2;
|
|
10374
|
+
if (clickedInsideSelection2) {
|
|
10375
|
+
this.suppressSelectionChange = false;
|
|
10376
|
+
this.blockTrustedTextDrag = true;
|
|
10377
|
+
this.pendingClickHit = hit2;
|
|
10378
|
+
} else {
|
|
10379
|
+
this.suppressSelectionChange = true;
|
|
10380
|
+
this.pendingClickHit = hit2;
|
|
10381
|
+
const newSelection = {
|
|
10382
|
+
start: hit2.cursorOffset,
|
|
10383
|
+
end: hit2.cursorOffset,
|
|
10384
|
+
affinity: hit2.affinity
|
|
10385
|
+
};
|
|
10386
|
+
this.state = this.runtime.updateSelection(this.state, newSelection, {
|
|
10387
|
+
kind: "dom"
|
|
10388
|
+
});
|
|
10389
|
+
this.applySelection(this.state.selection);
|
|
10390
|
+
(_b = this.onSelectionChange) == null ? void 0 : _b.call(this, this.state.selection);
|
|
10391
|
+
this.scheduleOverlayUpdate();
|
|
10392
|
+
return;
|
|
10393
|
+
}
|
|
10394
|
+
} else {
|
|
10395
|
+
this.suppressSelectionChange = true;
|
|
9943
10396
|
this.pendingClickHit = hit2;
|
|
10397
|
+
const newSelection = {
|
|
10398
|
+
start: hit2.cursorOffset,
|
|
10399
|
+
end: hit2.cursorOffset,
|
|
10400
|
+
affinity: hit2.affinity
|
|
10401
|
+
};
|
|
10402
|
+
this.state = this.runtime.updateSelection(this.state, newSelection, {
|
|
10403
|
+
kind: "dom"
|
|
10404
|
+
});
|
|
10405
|
+
this.applySelection(this.state.selection);
|
|
10406
|
+
(_c = this.onSelectionChange) == null ? void 0 : _c.call(this, this.state.selection);
|
|
10407
|
+
this.scheduleOverlayUpdate();
|
|
10408
|
+
return;
|
|
9944
10409
|
}
|
|
9945
|
-
return;
|
|
9946
10410
|
}
|
|
9947
10411
|
this.suppressSelectionChange = false;
|
|
9948
10412
|
const selStart = Math.min(selection.start, selection.end);
|
|
@@ -10054,10 +10518,6 @@ class CakeEngine {
|
|
|
10054
10518
|
}
|
|
10055
10519
|
handlePointerUp(event) {
|
|
10056
10520
|
this.blockTrustedTextDrag = false;
|
|
10057
|
-
if (this.pendingClickHit) {
|
|
10058
|
-
this.pendingClickHit = null;
|
|
10059
|
-
this.suppressSelectionChange = false;
|
|
10060
|
-
}
|
|
10061
10521
|
if (this.selectionDragState) {
|
|
10062
10522
|
if (event.pointerId !== this.selectionDragState.pointerId) {
|
|
10063
10523
|
return;
|
|
@@ -10557,7 +11017,7 @@ function findOffsetInTextNode(textNode, clientX, clientY) {
|
|
|
10557
11017
|
let closestDistance = Infinity;
|
|
10558
11018
|
let closestYDistance = Infinity;
|
|
10559
11019
|
let closestCaretX = 0;
|
|
10560
|
-
let
|
|
11020
|
+
let selectedViaRightEdge = false;
|
|
10561
11021
|
const rowInfo = /* @__PURE__ */ new Map();
|
|
10562
11022
|
const range = document.createRange();
|
|
10563
11023
|
let lastCharRect = null;
|
|
@@ -10626,15 +11086,28 @@ function findOffsetInTextNode(textNode, clientX, clientY) {
|
|
|
10626
11086
|
closestDistance = xDistance;
|
|
10627
11087
|
closestOffset = i;
|
|
10628
11088
|
closestCaretX = caretX;
|
|
10629
|
-
|
|
11089
|
+
bestRect.top;
|
|
10630
11090
|
closestYDistance = yDistance;
|
|
11091
|
+
selectedViaRightEdge = false;
|
|
11092
|
+
}
|
|
11093
|
+
if (i < text.length) {
|
|
11094
|
+
const rightEdgeX = bestRect.right;
|
|
11095
|
+
const rightEdgeDistance = Math.abs(clientX - rightEdgeX);
|
|
11096
|
+
if (rightEdgeDistance < closestDistance) {
|
|
11097
|
+
closestDistance = rightEdgeDistance;
|
|
11098
|
+
closestOffset = i + 1;
|
|
11099
|
+
closestCaretX = rightEdgeX;
|
|
11100
|
+
bestRect.top;
|
|
11101
|
+
closestYDistance = yDistance;
|
|
11102
|
+
selectedViaRightEdge = true;
|
|
11103
|
+
}
|
|
10631
11104
|
}
|
|
10632
11105
|
} else if (yDistance < closestYDistance || yDistance === closestYDistance && xDistance < closestDistance) {
|
|
10633
11106
|
closestYDistance = yDistance;
|
|
10634
11107
|
closestDistance = xDistance;
|
|
10635
11108
|
closestOffset = i;
|
|
10636
11109
|
closestCaretX = caretX;
|
|
10637
|
-
|
|
11110
|
+
bestRect.top;
|
|
10638
11111
|
}
|
|
10639
11112
|
}
|
|
10640
11113
|
let closestRow = null;
|
|
@@ -10659,11 +11132,11 @@ function findOffsetInTextNode(textNode, clientX, clientY) {
|
|
|
10659
11132
|
if (clientX < closestRow.left) {
|
|
10660
11133
|
closestOffset = closestRow.startOffset;
|
|
10661
11134
|
closestCaretX = closestRow.left;
|
|
10662
|
-
|
|
11135
|
+
closestRow.top;
|
|
10663
11136
|
} else if (clientX > closestRow.right) {
|
|
10664
|
-
closestOffset = closestRow.endOffset;
|
|
11137
|
+
closestOffset = Math.min(closestRow.endOffset + 1, text.length);
|
|
10665
11138
|
closestCaretX = closestRow.right;
|
|
10666
|
-
|
|
11139
|
+
closestRow.top;
|
|
10667
11140
|
} else if (clientY < closestRow.top || clientY > closestRow.bottom) {
|
|
10668
11141
|
let bestXDistance = Infinity;
|
|
10669
11142
|
const range2 = document.createRange();
|
|
@@ -10683,12 +11156,12 @@ function findOffsetInTextNode(textNode, clientX, clientY) {
|
|
|
10683
11156
|
bestXDistance = xDist;
|
|
10684
11157
|
closestOffset = i;
|
|
10685
11158
|
closestCaretX = rect.left;
|
|
10686
|
-
|
|
11159
|
+
closestRow.top;
|
|
10687
11160
|
}
|
|
10688
11161
|
}
|
|
10689
11162
|
}
|
|
10690
11163
|
}
|
|
10691
|
-
const pastRowEnd = closestRow !== null && clientX > closestRow.right
|
|
11164
|
+
const pastRowEnd = selectedViaRightEdge || closestRow !== null && clientX > closestRow.right;
|
|
10692
11165
|
if (Math.abs(clientX - closestCaretX) <= 2 && closestOffset < text.length && text[closestOffset] === "\n") {
|
|
10693
11166
|
closestOffset = Math.max(0, closestOffset - 1);
|
|
10694
11167
|
}
|
|
@@ -11141,8 +11614,9 @@ const CakeEditor = forwardRef(
|
|
|
11141
11614
|
const lastEmittedSelectionRef = useRef(null);
|
|
11142
11615
|
const [overlayRoot, setOverlayRoot] = useState(null);
|
|
11143
11616
|
const [contentRoot, setContentRoot] = useState(null);
|
|
11617
|
+
const baseExtensions = props.disableImageExtension ? bundledExtensionsWithoutImage : bundledExtensions;
|
|
11144
11618
|
const allExtensionsRef = useRef([
|
|
11145
|
-
...
|
|
11619
|
+
...baseExtensions,
|
|
11146
11620
|
...props.extensions ?? []
|
|
11147
11621
|
]);
|
|
11148
11622
|
useEffect(() => {
|
|
@@ -11300,6 +11774,10 @@ const CakeEditor = forwardRef(
|
|
|
11300
11774
|
}
|
|
11301
11775
|
return { start: selection.start, end: selection.end };
|
|
11302
11776
|
},
|
|
11777
|
+
getCursorLength: () => {
|
|
11778
|
+
var _a;
|
|
11779
|
+
return ((_a = engineRef.current) == null ? void 0 : _a.getCursorLength()) ?? 0;
|
|
11780
|
+
},
|
|
11303
11781
|
insertText: (text) => {
|
|
11304
11782
|
var _a;
|
|
11305
11783
|
(_a = engineRef.current) == null ? void 0 : _a.insertText(text);
|
|
@@ -11353,6 +11831,10 @@ const CakeEditor = forwardRef(
|
|
|
11353
11831
|
}
|
|
11354
11832
|
const focus = selection.start === selection.end ? selection.start : Math.max(selection.start, selection.end);
|
|
11355
11833
|
return { start: focus, end: focus };
|
|
11834
|
+
},
|
|
11835
|
+
executeCommand: (command) => {
|
|
11836
|
+
var _a;
|
|
11837
|
+
return ((_a = engineRef.current) == null ? void 0 : _a.executeCommand(command)) ?? false;
|
|
11356
11838
|
}
|
|
11357
11839
|
} : null;
|
|
11358
11840
|
const hasOverlayExtensions = allExtensionsRef.current.some(
|
|
@@ -11385,6 +11867,7 @@ export {
|
|
|
11385
11867
|
blockquoteExtension,
|
|
11386
11868
|
boldExtension,
|
|
11387
11869
|
bundledExtensions,
|
|
11870
|
+
bundledExtensionsWithoutImage,
|
|
11388
11871
|
combinedEmphasisExtension,
|
|
11389
11872
|
headingExtension,
|
|
11390
11873
|
imageExtension,
|