@codemirror/view 6.11.1 → 6.11.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/CHANGELOG.md +22 -0
- package/dist/index.cjs +87 -42
- package/dist/index.js +87 -42
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## 6.11.3 (2023-05-17)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Make sure pointer selection respects `EditorView.atomicRanges`.
|
|
6
|
+
|
|
7
|
+
Preserve DOM widgets when their decoration type changes but they otherwise stay in the same place.
|
|
8
|
+
|
|
9
|
+
Fix a bug in `drawSelection` that could lead to invisible or incorrect selections for a blank line below a block widget.
|
|
10
|
+
|
|
11
|
+
## 6.11.2 (2023-05-13)
|
|
12
|
+
|
|
13
|
+
### Bug fixes
|
|
14
|
+
|
|
15
|
+
Fix a bug where the `crosshairCursor` extension could, when non-native key events were fired, trigger disruptive and needless view updates.
|
|
16
|
+
|
|
17
|
+
Fix an Android issue where backspacing at the front of a line with widget decorations could replace those decorations with their text content.
|
|
18
|
+
|
|
19
|
+
Respect scroll margins when scrolling the target of drag-selection into view.
|
|
20
|
+
|
|
21
|
+
Validate selection offsets reported by the browser, to work around Safari giving us invalid values in some cases.
|
|
22
|
+
|
|
1
23
|
## 6.11.1 (2023-05-09)
|
|
2
24
|
|
|
3
25
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -222,7 +222,9 @@ class DOMSelectionState {
|
|
|
222
222
|
this.focusNode == domSel.focusNode && this.focusOffset == domSel.focusOffset;
|
|
223
223
|
}
|
|
224
224
|
setRange(range) {
|
|
225
|
-
|
|
225
|
+
let { anchorNode, focusNode } = range;
|
|
226
|
+
// Clip offsets to node size to avoid crashes when Safari reports bogus offsets (#1152)
|
|
227
|
+
this.set(anchorNode, Math.min(range.anchorOffset, anchorNode ? maxOffset(anchorNode) : 0), focusNode, Math.min(range.focusOffset, focusNode ? maxOffset(focusNode) : 0));
|
|
226
228
|
}
|
|
227
229
|
set(anchorNode, anchorOffset, focusNode, focusOffset) {
|
|
228
230
|
this.anchorNode = anchorNode;
|
|
@@ -295,6 +297,8 @@ function atElementStart(doc, selection) {
|
|
|
295
297
|
let node = selection.focusNode, offset = selection.focusOffset;
|
|
296
298
|
if (!node || selection.anchorNode != node || selection.anchorOffset != offset)
|
|
297
299
|
return false;
|
|
300
|
+
// Safari can report bogus offsets (#1152)
|
|
301
|
+
offset = Math.min(offset, maxOffset(node));
|
|
298
302
|
for (;;) {
|
|
299
303
|
if (offset) {
|
|
300
304
|
if (node.nodeType != 1)
|
|
@@ -1643,7 +1647,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1643
1647
|
}
|
|
1644
1648
|
domBoundsAround() { return null; }
|
|
1645
1649
|
become(other) {
|
|
1646
|
-
if (other instanceof BlockWidgetView &&
|
|
1650
|
+
if (other instanceof BlockWidgetView &&
|
|
1647
1651
|
other.widget.constructor == this.widget.constructor) {
|
|
1648
1652
|
if (!other.widget.compare(this.widget))
|
|
1649
1653
|
this.markDirty(true);
|
|
@@ -1651,6 +1655,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1651
1655
|
this.prevWidget = this.widget;
|
|
1652
1656
|
this.widget = other.widget;
|
|
1653
1657
|
this.length = other.length;
|
|
1658
|
+
this.type = other.type;
|
|
1654
1659
|
this.breakAfter = other.breakAfter;
|
|
1655
1660
|
return true;
|
|
1656
1661
|
}
|
|
@@ -2007,6 +2012,23 @@ const contentAttributes = state.Facet.define();
|
|
|
2007
2012
|
const decorations = state.Facet.define();
|
|
2008
2013
|
const atomicRanges = state.Facet.define();
|
|
2009
2014
|
const scrollMargins = state.Facet.define();
|
|
2015
|
+
function getScrollMargins(view) {
|
|
2016
|
+
let left = 0, right = 0, top = 0, bottom = 0;
|
|
2017
|
+
for (let source of view.state.facet(scrollMargins)) {
|
|
2018
|
+
let m = source(view);
|
|
2019
|
+
if (m) {
|
|
2020
|
+
if (m.left != null)
|
|
2021
|
+
left = Math.max(left, m.left);
|
|
2022
|
+
if (m.right != null)
|
|
2023
|
+
right = Math.max(right, m.right);
|
|
2024
|
+
if (m.top != null)
|
|
2025
|
+
top = Math.max(top, m.top);
|
|
2026
|
+
if (m.bottom != null)
|
|
2027
|
+
bottom = Math.max(bottom, m.bottom);
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
return { left, right, top, bottom };
|
|
2031
|
+
}
|
|
2010
2032
|
const styleModule = state.Facet.define();
|
|
2011
2033
|
class ChangedRange {
|
|
2012
2034
|
constructor(fromA, toA, fromB, toB) {
|
|
@@ -2460,6 +2482,7 @@ class DOMReader {
|
|
|
2460
2482
|
constructor(points, state$1) {
|
|
2461
2483
|
this.points = points;
|
|
2462
2484
|
this.text = "";
|
|
2485
|
+
console.log("make reader");
|
|
2463
2486
|
this.lineSeparator = state$1.facet(state.EditorState.lineSeparator);
|
|
2464
2487
|
}
|
|
2465
2488
|
append(text) {
|
|
@@ -2474,6 +2497,7 @@ class DOMReader {
|
|
|
2474
2497
|
let parent = start.parentNode;
|
|
2475
2498
|
for (let cur = start;;) {
|
|
2476
2499
|
this.findPointBefore(parent, cur);
|
|
2500
|
+
let oldLen = this.text.length;
|
|
2477
2501
|
this.readNode(cur);
|
|
2478
2502
|
let next = cur.nextSibling;
|
|
2479
2503
|
if (next == end)
|
|
@@ -2481,7 +2505,7 @@ class DOMReader {
|
|
|
2481
2505
|
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
2482
2506
|
if (view && nextView ? view.breakAfter :
|
|
2483
2507
|
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
2484
|
-
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore)))
|
|
2508
|
+
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
2485
2509
|
this.lineBreak();
|
|
2486
2510
|
cur = next;
|
|
2487
2511
|
}
|
|
@@ -2938,22 +2962,10 @@ class DocView extends ContentView {
|
|
|
2938
2962
|
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
2939
2963
|
rect = { left: Math.min(rect.left, other.left), top: Math.min(rect.top, other.top),
|
|
2940
2964
|
right: Math.max(rect.right, other.right), bottom: Math.max(rect.bottom, other.bottom) };
|
|
2941
|
-
let
|
|
2942
|
-
for (let margins of this.view.state.facet(scrollMargins).map(f => f(this.view)))
|
|
2943
|
-
if (margins) {
|
|
2944
|
-
let { left, right, top, bottom } = margins;
|
|
2945
|
-
if (left != null)
|
|
2946
|
-
mLeft = Math.max(mLeft, left);
|
|
2947
|
-
if (right != null)
|
|
2948
|
-
mRight = Math.max(mRight, right);
|
|
2949
|
-
if (top != null)
|
|
2950
|
-
mTop = Math.max(mTop, top);
|
|
2951
|
-
if (bottom != null)
|
|
2952
|
-
mBottom = Math.max(mBottom, bottom);
|
|
2953
|
-
}
|
|
2965
|
+
let margins = getScrollMargins(this.view);
|
|
2954
2966
|
let targetRect = {
|
|
2955
|
-
left: rect.left -
|
|
2956
|
-
right: rect.right +
|
|
2967
|
+
left: rect.left - margins.left, top: rect.top - margins.top,
|
|
2968
|
+
right: rect.right + margins.right, bottom: rect.bottom + margins.bottom
|
|
2957
2969
|
};
|
|
2958
2970
|
scrollRectIntoView(this.view.scrollDOM, targetRect, range.head < range.anchor ? -1 : 1, target.x, target.y, target.xMargin, target.yMargin, this.view.textDirection == exports.Direction.LTR);
|
|
2959
2971
|
}
|
|
@@ -3442,15 +3454,15 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3442
3454
|
return state.EditorSelection.cursor(pos, start.assoc, undefined, goal);
|
|
3443
3455
|
}
|
|
3444
3456
|
}
|
|
3445
|
-
function
|
|
3446
|
-
let atoms = view.state.facet(atomicRanges).map(f => f(view));
|
|
3457
|
+
function skipAtomicRanges(atoms, pos, bias) {
|
|
3447
3458
|
for (;;) {
|
|
3448
|
-
let moved =
|
|
3459
|
+
let moved = 0;
|
|
3449
3460
|
for (let set of atoms) {
|
|
3450
|
-
set.between(pos
|
|
3451
|
-
if (pos
|
|
3452
|
-
|
|
3453
|
-
|
|
3461
|
+
set.between(pos - 1, pos + 1, (from, to, value) => {
|
|
3462
|
+
if (pos > from && pos < to) {
|
|
3463
|
+
let side = moved || bias || (pos - from < to - pos ? -1 : 1);
|
|
3464
|
+
pos = side < 0 ? from : to;
|
|
3465
|
+
moved = side;
|
|
3454
3466
|
}
|
|
3455
3467
|
});
|
|
3456
3468
|
}
|
|
@@ -3458,6 +3470,10 @@ function skipAtoms(view, oldPos, pos) {
|
|
|
3458
3470
|
return pos;
|
|
3459
3471
|
}
|
|
3460
3472
|
}
|
|
3473
|
+
function skipAtoms(view, oldPos, pos) {
|
|
3474
|
+
let newPos = skipAtomicRanges(view.state.facet(atomicRanges).map(f => f(view)), pos.from, oldPos.head > pos.from ? -1 : 1);
|
|
3475
|
+
return newPos == pos.from ? pos : state.EditorSelection.cursor(newPos, newPos < pos.from ? 1 : -1);
|
|
3476
|
+
}
|
|
3461
3477
|
|
|
3462
3478
|
// This will also be where dragging info and such goes
|
|
3463
3479
|
class InputState {
|
|
@@ -3707,6 +3723,7 @@ class MouseSelection {
|
|
|
3707
3723
|
this.scrolling = -1;
|
|
3708
3724
|
this.lastEvent = startEvent;
|
|
3709
3725
|
this.scrollParent = scrollableParent(view.contentDOM);
|
|
3726
|
+
this.atoms = view.state.facet(atomicRanges).map(f => f(view));
|
|
3710
3727
|
let doc = view.contentDOM.ownerDocument;
|
|
3711
3728
|
doc.addEventListener("mousemove", this.move = this.move.bind(this));
|
|
3712
3729
|
doc.addEventListener("mouseup", this.up = this.up.bind(this));
|
|
@@ -3733,13 +3750,14 @@ class MouseSelection {
|
|
|
3733
3750
|
let sx = 0, sy = 0;
|
|
3734
3751
|
let rect = ((_a = this.scrollParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect())
|
|
3735
3752
|
|| { left: 0, top: 0, right: this.view.win.innerWidth, bottom: this.view.win.innerHeight };
|
|
3736
|
-
|
|
3753
|
+
let margins = getScrollMargins(this.view);
|
|
3754
|
+
if (event.clientX - margins.left <= rect.left + dragScrollMargin)
|
|
3737
3755
|
sx = -dragScrollSpeed(rect.left - event.clientX);
|
|
3738
|
-
else if (event.clientX >= rect.right - dragScrollMargin)
|
|
3756
|
+
else if (event.clientX + margins.right >= rect.right - dragScrollMargin)
|
|
3739
3757
|
sx = dragScrollSpeed(event.clientX - rect.right);
|
|
3740
|
-
if (event.clientY <= rect.top + dragScrollMargin)
|
|
3758
|
+
if (event.clientY - margins.top <= rect.top + dragScrollMargin)
|
|
3741
3759
|
sy = -dragScrollSpeed(rect.top - event.clientY);
|
|
3742
|
-
else if (event.clientY >= rect.bottom - dragScrollMargin)
|
|
3760
|
+
else if (event.clientY + margins.bottom >= rect.bottom - dragScrollMargin)
|
|
3743
3761
|
sy = dragScrollSpeed(event.clientY - rect.bottom);
|
|
3744
3762
|
this.setScrollSpeed(sx, sy);
|
|
3745
3763
|
}
|
|
@@ -3779,10 +3797,33 @@ class MouseSelection {
|
|
|
3779
3797
|
if (this.dragging === false)
|
|
3780
3798
|
this.select(this.lastEvent);
|
|
3781
3799
|
}
|
|
3800
|
+
skipAtoms(sel) {
|
|
3801
|
+
let ranges = null;
|
|
3802
|
+
for (let i = 0; i < sel.ranges.length; i++) {
|
|
3803
|
+
let range = sel.ranges[i], updated = null;
|
|
3804
|
+
if (range.empty) {
|
|
3805
|
+
let pos = skipAtomicRanges(this.atoms, range.from, 0);
|
|
3806
|
+
if (pos != range.from)
|
|
3807
|
+
updated = state.EditorSelection.cursor(pos, -1);
|
|
3808
|
+
}
|
|
3809
|
+
else {
|
|
3810
|
+
let from = skipAtomicRanges(this.atoms, range.from, -1);
|
|
3811
|
+
let to = skipAtomicRanges(this.atoms, range.to, 1);
|
|
3812
|
+
if (from != range.from || to != range.to)
|
|
3813
|
+
updated = state.EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to);
|
|
3814
|
+
}
|
|
3815
|
+
if (updated) {
|
|
3816
|
+
if (!ranges)
|
|
3817
|
+
ranges = sel.ranges.slice();
|
|
3818
|
+
ranges[i] = updated;
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
return ranges ? state.EditorSelection.create(ranges, sel.mainIndex) : sel;
|
|
3822
|
+
}
|
|
3782
3823
|
select(event) {
|
|
3783
|
-
let selection = this.style.get(event, this.extend, this.multiple);
|
|
3784
|
-
if (this.mustSelect || !selection.eq(
|
|
3785
|
-
selection.main.assoc !=
|
|
3824
|
+
let { view } = this, selection = this.skipAtoms(this.style.get(event, this.extend, this.multiple));
|
|
3825
|
+
if (this.mustSelect || !selection.eq(view.state.selection) ||
|
|
3826
|
+
selection.main.assoc != view.state.selection.main.assoc)
|
|
3786
3827
|
this.view.dispatch({
|
|
3787
3828
|
selection,
|
|
3788
3829
|
userEvent: "select.pointer"
|
|
@@ -5781,13 +5822,13 @@ class DOMChange {
|
|
|
5781
5822
|
function applyDOMChange(view, domChange) {
|
|
5782
5823
|
let change;
|
|
5783
5824
|
let { newSel } = domChange, sel = view.state.selection.main;
|
|
5825
|
+
let lastKey = view.inputState.lastKeyTime > Date.now() - 100 ? view.inputState.lastKeyCode : -1;
|
|
5784
5826
|
if (domChange.bounds) {
|
|
5785
5827
|
let { from, to } = domChange.bounds;
|
|
5786
5828
|
let preferredPos = sel.from, preferredSide = null;
|
|
5787
5829
|
// Prefer anchoring to end when Backspace is pressed (or, on
|
|
5788
5830
|
// Android, when something was deleted)
|
|
5789
|
-
if (
|
|
5790
|
-
browser.android && domChange.text.length < to - from) {
|
|
5831
|
+
if (lastKey === 8 || browser.android && domChange.text.length < to - from) {
|
|
5791
5832
|
preferredPos = sel.to;
|
|
5792
5833
|
preferredSide = "end";
|
|
5793
5834
|
}
|
|
@@ -5795,7 +5836,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5795
5836
|
if (diff) {
|
|
5796
5837
|
// Chrome inserts two newlines when pressing shift-enter at the
|
|
5797
5838
|
// end of a line. DomChange drops one of those.
|
|
5798
|
-
if (browser.chrome &&
|
|
5839
|
+
if (browser.chrome && lastKey == 13 &&
|
|
5799
5840
|
diff.toB == diff.from + 2 && domChange.text.slice(diff.from, diff.toB) == LineBreakPlaceholder + LineBreakPlaceholder)
|
|
5800
5841
|
diff.toB--;
|
|
5801
5842
|
change = { from: from + diff.from, to: from + diff.toA,
|
|
@@ -5853,7 +5894,8 @@ function applyDOMChange(view, domChange) {
|
|
|
5853
5894
|
((change.from == sel.from && change.to == sel.to &&
|
|
5854
5895
|
change.insert.length == 1 && change.insert.lines == 2 &&
|
|
5855
5896
|
dispatchKey(view.contentDOM, "Enter", 13)) ||
|
|
5856
|
-
(change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0
|
|
5897
|
+
((change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0 ||
|
|
5898
|
+
lastKey == 8 && change.insert.length < change.to - change.from) &&
|
|
5857
5899
|
dispatchKey(view.contentDOM, "Backspace", 8)) ||
|
|
5858
5900
|
(change.from == sel.from && change.to == sel.to + 1 && change.insert.length == 0 &&
|
|
5859
5901
|
dispatchKey(view.contentDOM, "Delete", 46))))
|
|
@@ -6251,7 +6293,10 @@ class DOMObserver {
|
|
|
6251
6293
|
let key = this.delayedAndroidKey;
|
|
6252
6294
|
if (key) {
|
|
6253
6295
|
this.clearDelayedAndroidKey();
|
|
6254
|
-
|
|
6296
|
+
this.view.inputState.lastKeyCode = key.keyCode;
|
|
6297
|
+
this.view.inputState.lastKeyTime = Date.now();
|
|
6298
|
+
let flushed = this.flush();
|
|
6299
|
+
if (!flushed && key.force)
|
|
6255
6300
|
dispatchKey(this.dom, key.key, key.keyCode);
|
|
6256
6301
|
}
|
|
6257
6302
|
};
|
|
@@ -7704,7 +7749,7 @@ function rectanglesForRange(view, className, range) {
|
|
|
7704
7749
|
let top = visualStart ? drawForLine(range.from, null, visualStart) : drawForWidget(startBlock, false);
|
|
7705
7750
|
let bottom = visualEnd ? drawForLine(null, range.to, visualEnd) : drawForWidget(endBlock, true);
|
|
7706
7751
|
let between = [];
|
|
7707
|
-
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - 1)
|
|
7752
|
+
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - (visualStart && visualEnd ? 1 : 0))
|
|
7708
7753
|
between.push(piece(leftSide, top.bottom, rightSide, bottom.top));
|
|
7709
7754
|
else if (top.bottom < bottom.top && view.elementAtHeight((top.bottom + bottom.top) / 2).type == exports.BlockType.Text)
|
|
7710
7755
|
top.bottom = bottom.top = (top.bottom + bottom.top) / 2;
|
|
@@ -8480,10 +8525,10 @@ function rectangularSelection(options) {
|
|
|
8480
8525
|
return EditorView.mouseSelectionStyle.of((view, event) => filter(event) ? rectangleSelectionStyle(view, event) : null);
|
|
8481
8526
|
}
|
|
8482
8527
|
const keys = {
|
|
8483
|
-
Alt: [18, e => e.altKey],
|
|
8484
|
-
Control: [17, e => e.ctrlKey],
|
|
8485
|
-
Shift: [16, e => e.shiftKey],
|
|
8486
|
-
Meta: [91, e => e.metaKey]
|
|
8528
|
+
Alt: [18, e => !!e.altKey],
|
|
8529
|
+
Control: [17, e => !!e.ctrlKey],
|
|
8530
|
+
Shift: [16, e => !!e.shiftKey],
|
|
8531
|
+
Meta: [91, e => !!e.metaKey]
|
|
8487
8532
|
};
|
|
8488
8533
|
const showCrosshair = { style: "cursor: crosshair" };
|
|
8489
8534
|
/**
|
package/dist/index.js
CHANGED
|
@@ -218,7 +218,9 @@ class DOMSelectionState {
|
|
|
218
218
|
this.focusNode == domSel.focusNode && this.focusOffset == domSel.focusOffset;
|
|
219
219
|
}
|
|
220
220
|
setRange(range) {
|
|
221
|
-
|
|
221
|
+
let { anchorNode, focusNode } = range;
|
|
222
|
+
// Clip offsets to node size to avoid crashes when Safari reports bogus offsets (#1152)
|
|
223
|
+
this.set(anchorNode, Math.min(range.anchorOffset, anchorNode ? maxOffset(anchorNode) : 0), focusNode, Math.min(range.focusOffset, focusNode ? maxOffset(focusNode) : 0));
|
|
222
224
|
}
|
|
223
225
|
set(anchorNode, anchorOffset, focusNode, focusOffset) {
|
|
224
226
|
this.anchorNode = anchorNode;
|
|
@@ -291,6 +293,8 @@ function atElementStart(doc, selection) {
|
|
|
291
293
|
let node = selection.focusNode, offset = selection.focusOffset;
|
|
292
294
|
if (!node || selection.anchorNode != node || selection.anchorOffset != offset)
|
|
293
295
|
return false;
|
|
296
|
+
// Safari can report bogus offsets (#1152)
|
|
297
|
+
offset = Math.min(offset, maxOffset(node));
|
|
294
298
|
for (;;) {
|
|
295
299
|
if (offset) {
|
|
296
300
|
if (node.nodeType != 1)
|
|
@@ -1638,7 +1642,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1638
1642
|
}
|
|
1639
1643
|
domBoundsAround() { return null; }
|
|
1640
1644
|
become(other) {
|
|
1641
|
-
if (other instanceof BlockWidgetView &&
|
|
1645
|
+
if (other instanceof BlockWidgetView &&
|
|
1642
1646
|
other.widget.constructor == this.widget.constructor) {
|
|
1643
1647
|
if (!other.widget.compare(this.widget))
|
|
1644
1648
|
this.markDirty(true);
|
|
@@ -1646,6 +1650,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1646
1650
|
this.prevWidget = this.widget;
|
|
1647
1651
|
this.widget = other.widget;
|
|
1648
1652
|
this.length = other.length;
|
|
1653
|
+
this.type = other.type;
|
|
1649
1654
|
this.breakAfter = other.breakAfter;
|
|
1650
1655
|
return true;
|
|
1651
1656
|
}
|
|
@@ -2002,6 +2007,23 @@ const contentAttributes = /*@__PURE__*/Facet.define();
|
|
|
2002
2007
|
const decorations = /*@__PURE__*/Facet.define();
|
|
2003
2008
|
const atomicRanges = /*@__PURE__*/Facet.define();
|
|
2004
2009
|
const scrollMargins = /*@__PURE__*/Facet.define();
|
|
2010
|
+
function getScrollMargins(view) {
|
|
2011
|
+
let left = 0, right = 0, top = 0, bottom = 0;
|
|
2012
|
+
for (let source of view.state.facet(scrollMargins)) {
|
|
2013
|
+
let m = source(view);
|
|
2014
|
+
if (m) {
|
|
2015
|
+
if (m.left != null)
|
|
2016
|
+
left = Math.max(left, m.left);
|
|
2017
|
+
if (m.right != null)
|
|
2018
|
+
right = Math.max(right, m.right);
|
|
2019
|
+
if (m.top != null)
|
|
2020
|
+
top = Math.max(top, m.top);
|
|
2021
|
+
if (m.bottom != null)
|
|
2022
|
+
bottom = Math.max(bottom, m.bottom);
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
return { left, right, top, bottom };
|
|
2026
|
+
}
|
|
2005
2027
|
const styleModule = /*@__PURE__*/Facet.define();
|
|
2006
2028
|
class ChangedRange {
|
|
2007
2029
|
constructor(fromA, toA, fromB, toB) {
|
|
@@ -2454,6 +2476,7 @@ class DOMReader {
|
|
|
2454
2476
|
constructor(points, state) {
|
|
2455
2477
|
this.points = points;
|
|
2456
2478
|
this.text = "";
|
|
2479
|
+
console.log("make reader");
|
|
2457
2480
|
this.lineSeparator = state.facet(EditorState.lineSeparator);
|
|
2458
2481
|
}
|
|
2459
2482
|
append(text) {
|
|
@@ -2468,6 +2491,7 @@ class DOMReader {
|
|
|
2468
2491
|
let parent = start.parentNode;
|
|
2469
2492
|
for (let cur = start;;) {
|
|
2470
2493
|
this.findPointBefore(parent, cur);
|
|
2494
|
+
let oldLen = this.text.length;
|
|
2471
2495
|
this.readNode(cur);
|
|
2472
2496
|
let next = cur.nextSibling;
|
|
2473
2497
|
if (next == end)
|
|
@@ -2475,7 +2499,7 @@ class DOMReader {
|
|
|
2475
2499
|
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
2476
2500
|
if (view && nextView ? view.breakAfter :
|
|
2477
2501
|
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
2478
|
-
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore)))
|
|
2502
|
+
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
2479
2503
|
this.lineBreak();
|
|
2480
2504
|
cur = next;
|
|
2481
2505
|
}
|
|
@@ -2932,22 +2956,10 @@ class DocView extends ContentView {
|
|
|
2932
2956
|
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
2933
2957
|
rect = { left: Math.min(rect.left, other.left), top: Math.min(rect.top, other.top),
|
|
2934
2958
|
right: Math.max(rect.right, other.right), bottom: Math.max(rect.bottom, other.bottom) };
|
|
2935
|
-
let
|
|
2936
|
-
for (let margins of this.view.state.facet(scrollMargins).map(f => f(this.view)))
|
|
2937
|
-
if (margins) {
|
|
2938
|
-
let { left, right, top, bottom } = margins;
|
|
2939
|
-
if (left != null)
|
|
2940
|
-
mLeft = Math.max(mLeft, left);
|
|
2941
|
-
if (right != null)
|
|
2942
|
-
mRight = Math.max(mRight, right);
|
|
2943
|
-
if (top != null)
|
|
2944
|
-
mTop = Math.max(mTop, top);
|
|
2945
|
-
if (bottom != null)
|
|
2946
|
-
mBottom = Math.max(mBottom, bottom);
|
|
2947
|
-
}
|
|
2959
|
+
let margins = getScrollMargins(this.view);
|
|
2948
2960
|
let targetRect = {
|
|
2949
|
-
left: rect.left -
|
|
2950
|
-
right: rect.right +
|
|
2961
|
+
left: rect.left - margins.left, top: rect.top - margins.top,
|
|
2962
|
+
right: rect.right + margins.right, bottom: rect.bottom + margins.bottom
|
|
2951
2963
|
};
|
|
2952
2964
|
scrollRectIntoView(this.view.scrollDOM, targetRect, range.head < range.anchor ? -1 : 1, target.x, target.y, target.xMargin, target.yMargin, this.view.textDirection == Direction.LTR);
|
|
2953
2965
|
}
|
|
@@ -3436,15 +3448,15 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3436
3448
|
return EditorSelection.cursor(pos, start.assoc, undefined, goal);
|
|
3437
3449
|
}
|
|
3438
3450
|
}
|
|
3439
|
-
function
|
|
3440
|
-
let atoms = view.state.facet(atomicRanges).map(f => f(view));
|
|
3451
|
+
function skipAtomicRanges(atoms, pos, bias) {
|
|
3441
3452
|
for (;;) {
|
|
3442
|
-
let moved =
|
|
3453
|
+
let moved = 0;
|
|
3443
3454
|
for (let set of atoms) {
|
|
3444
|
-
set.between(pos
|
|
3445
|
-
if (pos
|
|
3446
|
-
|
|
3447
|
-
|
|
3455
|
+
set.between(pos - 1, pos + 1, (from, to, value) => {
|
|
3456
|
+
if (pos > from && pos < to) {
|
|
3457
|
+
let side = moved || bias || (pos - from < to - pos ? -1 : 1);
|
|
3458
|
+
pos = side < 0 ? from : to;
|
|
3459
|
+
moved = side;
|
|
3448
3460
|
}
|
|
3449
3461
|
});
|
|
3450
3462
|
}
|
|
@@ -3452,6 +3464,10 @@ function skipAtoms(view, oldPos, pos) {
|
|
|
3452
3464
|
return pos;
|
|
3453
3465
|
}
|
|
3454
3466
|
}
|
|
3467
|
+
function skipAtoms(view, oldPos, pos) {
|
|
3468
|
+
let newPos = skipAtomicRanges(view.state.facet(atomicRanges).map(f => f(view)), pos.from, oldPos.head > pos.from ? -1 : 1);
|
|
3469
|
+
return newPos == pos.from ? pos : EditorSelection.cursor(newPos, newPos < pos.from ? 1 : -1);
|
|
3470
|
+
}
|
|
3455
3471
|
|
|
3456
3472
|
// This will also be where dragging info and such goes
|
|
3457
3473
|
class InputState {
|
|
@@ -3701,6 +3717,7 @@ class MouseSelection {
|
|
|
3701
3717
|
this.scrolling = -1;
|
|
3702
3718
|
this.lastEvent = startEvent;
|
|
3703
3719
|
this.scrollParent = scrollableParent(view.contentDOM);
|
|
3720
|
+
this.atoms = view.state.facet(atomicRanges).map(f => f(view));
|
|
3704
3721
|
let doc = view.contentDOM.ownerDocument;
|
|
3705
3722
|
doc.addEventListener("mousemove", this.move = this.move.bind(this));
|
|
3706
3723
|
doc.addEventListener("mouseup", this.up = this.up.bind(this));
|
|
@@ -3727,13 +3744,14 @@ class MouseSelection {
|
|
|
3727
3744
|
let sx = 0, sy = 0;
|
|
3728
3745
|
let rect = ((_a = this.scrollParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect())
|
|
3729
3746
|
|| { left: 0, top: 0, right: this.view.win.innerWidth, bottom: this.view.win.innerHeight };
|
|
3730
|
-
|
|
3747
|
+
let margins = getScrollMargins(this.view);
|
|
3748
|
+
if (event.clientX - margins.left <= rect.left + dragScrollMargin)
|
|
3731
3749
|
sx = -dragScrollSpeed(rect.left - event.clientX);
|
|
3732
|
-
else if (event.clientX >= rect.right - dragScrollMargin)
|
|
3750
|
+
else if (event.clientX + margins.right >= rect.right - dragScrollMargin)
|
|
3733
3751
|
sx = dragScrollSpeed(event.clientX - rect.right);
|
|
3734
|
-
if (event.clientY <= rect.top + dragScrollMargin)
|
|
3752
|
+
if (event.clientY - margins.top <= rect.top + dragScrollMargin)
|
|
3735
3753
|
sy = -dragScrollSpeed(rect.top - event.clientY);
|
|
3736
|
-
else if (event.clientY >= rect.bottom - dragScrollMargin)
|
|
3754
|
+
else if (event.clientY + margins.bottom >= rect.bottom - dragScrollMargin)
|
|
3737
3755
|
sy = dragScrollSpeed(event.clientY - rect.bottom);
|
|
3738
3756
|
this.setScrollSpeed(sx, sy);
|
|
3739
3757
|
}
|
|
@@ -3773,10 +3791,33 @@ class MouseSelection {
|
|
|
3773
3791
|
if (this.dragging === false)
|
|
3774
3792
|
this.select(this.lastEvent);
|
|
3775
3793
|
}
|
|
3794
|
+
skipAtoms(sel) {
|
|
3795
|
+
let ranges = null;
|
|
3796
|
+
for (let i = 0; i < sel.ranges.length; i++) {
|
|
3797
|
+
let range = sel.ranges[i], updated = null;
|
|
3798
|
+
if (range.empty) {
|
|
3799
|
+
let pos = skipAtomicRanges(this.atoms, range.from, 0);
|
|
3800
|
+
if (pos != range.from)
|
|
3801
|
+
updated = EditorSelection.cursor(pos, -1);
|
|
3802
|
+
}
|
|
3803
|
+
else {
|
|
3804
|
+
let from = skipAtomicRanges(this.atoms, range.from, -1);
|
|
3805
|
+
let to = skipAtomicRanges(this.atoms, range.to, 1);
|
|
3806
|
+
if (from != range.from || to != range.to)
|
|
3807
|
+
updated = EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to);
|
|
3808
|
+
}
|
|
3809
|
+
if (updated) {
|
|
3810
|
+
if (!ranges)
|
|
3811
|
+
ranges = sel.ranges.slice();
|
|
3812
|
+
ranges[i] = updated;
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3815
|
+
return ranges ? EditorSelection.create(ranges, sel.mainIndex) : sel;
|
|
3816
|
+
}
|
|
3776
3817
|
select(event) {
|
|
3777
|
-
let selection = this.style.get(event, this.extend, this.multiple);
|
|
3778
|
-
if (this.mustSelect || !selection.eq(
|
|
3779
|
-
selection.main.assoc !=
|
|
3818
|
+
let { view } = this, selection = this.skipAtoms(this.style.get(event, this.extend, this.multiple));
|
|
3819
|
+
if (this.mustSelect || !selection.eq(view.state.selection) ||
|
|
3820
|
+
selection.main.assoc != view.state.selection.main.assoc)
|
|
3780
3821
|
this.view.dispatch({
|
|
3781
3822
|
selection,
|
|
3782
3823
|
userEvent: "select.pointer"
|
|
@@ -5774,13 +5815,13 @@ class DOMChange {
|
|
|
5774
5815
|
function applyDOMChange(view, domChange) {
|
|
5775
5816
|
let change;
|
|
5776
5817
|
let { newSel } = domChange, sel = view.state.selection.main;
|
|
5818
|
+
let lastKey = view.inputState.lastKeyTime > Date.now() - 100 ? view.inputState.lastKeyCode : -1;
|
|
5777
5819
|
if (domChange.bounds) {
|
|
5778
5820
|
let { from, to } = domChange.bounds;
|
|
5779
5821
|
let preferredPos = sel.from, preferredSide = null;
|
|
5780
5822
|
// Prefer anchoring to end when Backspace is pressed (or, on
|
|
5781
5823
|
// Android, when something was deleted)
|
|
5782
|
-
if (
|
|
5783
|
-
browser.android && domChange.text.length < to - from) {
|
|
5824
|
+
if (lastKey === 8 || browser.android && domChange.text.length < to - from) {
|
|
5784
5825
|
preferredPos = sel.to;
|
|
5785
5826
|
preferredSide = "end";
|
|
5786
5827
|
}
|
|
@@ -5788,7 +5829,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5788
5829
|
if (diff) {
|
|
5789
5830
|
// Chrome inserts two newlines when pressing shift-enter at the
|
|
5790
5831
|
// end of a line. DomChange drops one of those.
|
|
5791
|
-
if (browser.chrome &&
|
|
5832
|
+
if (browser.chrome && lastKey == 13 &&
|
|
5792
5833
|
diff.toB == diff.from + 2 && domChange.text.slice(diff.from, diff.toB) == LineBreakPlaceholder + LineBreakPlaceholder)
|
|
5793
5834
|
diff.toB--;
|
|
5794
5835
|
change = { from: from + diff.from, to: from + diff.toA,
|
|
@@ -5846,7 +5887,8 @@ function applyDOMChange(view, domChange) {
|
|
|
5846
5887
|
((change.from == sel.from && change.to == sel.to &&
|
|
5847
5888
|
change.insert.length == 1 && change.insert.lines == 2 &&
|
|
5848
5889
|
dispatchKey(view.contentDOM, "Enter", 13)) ||
|
|
5849
|
-
(change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0
|
|
5890
|
+
((change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0 ||
|
|
5891
|
+
lastKey == 8 && change.insert.length < change.to - change.from) &&
|
|
5850
5892
|
dispatchKey(view.contentDOM, "Backspace", 8)) ||
|
|
5851
5893
|
(change.from == sel.from && change.to == sel.to + 1 && change.insert.length == 0 &&
|
|
5852
5894
|
dispatchKey(view.contentDOM, "Delete", 46))))
|
|
@@ -6244,7 +6286,10 @@ class DOMObserver {
|
|
|
6244
6286
|
let key = this.delayedAndroidKey;
|
|
6245
6287
|
if (key) {
|
|
6246
6288
|
this.clearDelayedAndroidKey();
|
|
6247
|
-
|
|
6289
|
+
this.view.inputState.lastKeyCode = key.keyCode;
|
|
6290
|
+
this.view.inputState.lastKeyTime = Date.now();
|
|
6291
|
+
let flushed = this.flush();
|
|
6292
|
+
if (!flushed && key.force)
|
|
6248
6293
|
dispatchKey(this.dom, key.key, key.keyCode);
|
|
6249
6294
|
}
|
|
6250
6295
|
};
|
|
@@ -7697,7 +7742,7 @@ function rectanglesForRange(view, className, range) {
|
|
|
7697
7742
|
let top = visualStart ? drawForLine(range.from, null, visualStart) : drawForWidget(startBlock, false);
|
|
7698
7743
|
let bottom = visualEnd ? drawForLine(null, range.to, visualEnd) : drawForWidget(endBlock, true);
|
|
7699
7744
|
let between = [];
|
|
7700
|
-
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - 1)
|
|
7745
|
+
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - (visualStart && visualEnd ? 1 : 0))
|
|
7701
7746
|
between.push(piece(leftSide, top.bottom, rightSide, bottom.top));
|
|
7702
7747
|
else if (top.bottom < bottom.top && view.elementAtHeight((top.bottom + bottom.top) / 2).type == BlockType.Text)
|
|
7703
7748
|
top.bottom = bottom.top = (top.bottom + bottom.top) / 2;
|
|
@@ -8473,10 +8518,10 @@ function rectangularSelection(options) {
|
|
|
8473
8518
|
return EditorView.mouseSelectionStyle.of((view, event) => filter(event) ? rectangleSelectionStyle(view, event) : null);
|
|
8474
8519
|
}
|
|
8475
8520
|
const keys = {
|
|
8476
|
-
Alt: [18, e => e.altKey],
|
|
8477
|
-
Control: [17, e => e.ctrlKey],
|
|
8478
|
-
Shift: [16, e => e.shiftKey],
|
|
8479
|
-
Meta: [91, e => e.metaKey]
|
|
8521
|
+
Alt: [18, e => !!e.altKey],
|
|
8522
|
+
Control: [17, e => !!e.ctrlKey],
|
|
8523
|
+
Shift: [16, e => !!e.shiftKey],
|
|
8524
|
+
Meta: [91, e => !!e.metaKey]
|
|
8480
8525
|
};
|
|
8481
8526
|
const showCrosshair = { style: "cursor: crosshair" };
|
|
8482
8527
|
/**
|