@codemirror/view 6.9.3 → 6.9.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/CHANGELOG.md +18 -0
- package/dist/index.cjs +55 -26
- package/dist/index.js +55 -26
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## 6.9.4 (2023-04-11)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Make the editor scroll while dragging a selection near its sides, even if the cursor isn't outside the scrollable element.
|
|
6
|
+
|
|
7
|
+
Fix a bug that interrupted composition after widgets in some circumstances on Firefox.
|
|
8
|
+
|
|
9
|
+
Make sure the last change in a composition has its user event set to `input.type.compose`, even if the `compositionend` event fires before the changes are applied.
|
|
10
|
+
|
|
11
|
+
Make it possible to remove additional selection ranges by clicking on them with ctrl/cmd held, even if they aren't cursors.
|
|
12
|
+
|
|
13
|
+
Keep widget buffers between widgets and compositions, since removing them confuses IME on macOS Firefox.
|
|
14
|
+
|
|
15
|
+
Fix a bug where, for DOM changes that put the selection in the middle of the changed range, the editor incorrectly set its selection state.
|
|
16
|
+
|
|
17
|
+
Fix a bug where `coordsAtPos` could return a coordinates before the line break when querying a line-wrapped position with a positive `side`.
|
|
18
|
+
|
|
1
19
|
## 6.9.3 (2023-03-21)
|
|
2
20
|
|
|
3
21
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -520,6 +520,7 @@ class ContentView {
|
|
|
520
520
|
static get(node) { return node.cmView; }
|
|
521
521
|
get isEditable() { return true; }
|
|
522
522
|
get isWidget() { return false; }
|
|
523
|
+
get isHidden() { return false; }
|
|
523
524
|
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
524
525
|
return false;
|
|
525
526
|
}
|
|
@@ -857,7 +858,7 @@ class WidgetView extends ContentView {
|
|
|
857
858
|
become(other) {
|
|
858
859
|
if (other.length == this.length && other instanceof WidgetView && other.side == this.side) {
|
|
859
860
|
if (this.widget.constructor == other.widget.constructor) {
|
|
860
|
-
if (!this.widget.
|
|
861
|
+
if (!this.widget.compare(other.widget))
|
|
861
862
|
this.markDirty(true);
|
|
862
863
|
if (this.dom && !this.prevWidget)
|
|
863
864
|
this.prevWidget = this.widget;
|
|
@@ -879,7 +880,9 @@ class WidgetView extends ContentView {
|
|
|
879
880
|
return text ? text.slice(start, start + this.length) : state.Text.empty;
|
|
880
881
|
}
|
|
881
882
|
domAtPos(pos) {
|
|
882
|
-
return pos == 0
|
|
883
|
+
return (this.length ? pos == 0 : this.side > 0)
|
|
884
|
+
? DOMPos.before(this.dom)
|
|
885
|
+
: DOMPos.after(this.dom, pos == this.length);
|
|
883
886
|
}
|
|
884
887
|
domBoundsAround() { return null; }
|
|
885
888
|
coordsAt(pos, side) {
|
|
@@ -895,6 +898,7 @@ class WidgetView extends ContentView {
|
|
|
895
898
|
}
|
|
896
899
|
get isEditable() { return false; }
|
|
897
900
|
get isWidget() { return true; }
|
|
901
|
+
get isHidden() { return this.widget.isHidden; }
|
|
898
902
|
destroy() {
|
|
899
903
|
super.destroy();
|
|
900
904
|
if (this.dom)
|
|
@@ -1007,6 +1011,7 @@ class WidgetBufferView extends ContentView {
|
|
|
1007
1011
|
get overrideDOMText() {
|
|
1008
1012
|
return state.Text.empty;
|
|
1009
1013
|
}
|
|
1014
|
+
get isHidden() { return true; }
|
|
1010
1015
|
}
|
|
1011
1016
|
TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
|
|
1012
1017
|
function inlineSiblingRect(view, side) {
|
|
@@ -1080,7 +1085,8 @@ function coordsInChildren(view, pos, side) {
|
|
|
1080
1085
|
if (child.children.length) {
|
|
1081
1086
|
scan(child, pos - off);
|
|
1082
1087
|
}
|
|
1083
|
-
else if (!after
|
|
1088
|
+
else if ((!after || after instanceof WidgetBufferView && side > 0) &&
|
|
1089
|
+
(end > pos || off == end && child.getSide() > 0)) {
|
|
1084
1090
|
after = child;
|
|
1085
1091
|
afterPos = pos - off;
|
|
1086
1092
|
}
|
|
@@ -1194,6 +1200,10 @@ class WidgetType {
|
|
|
1194
1200
|
*/
|
|
1195
1201
|
get customView() { return null; }
|
|
1196
1202
|
/**
|
|
1203
|
+
@internal
|
|
1204
|
+
*/
|
|
1205
|
+
get isHidden() { return false; }
|
|
1206
|
+
/**
|
|
1197
1207
|
This is called when the an instance of the widget is removed
|
|
1198
1208
|
from the editor view.
|
|
1199
1209
|
*/
|
|
@@ -1605,7 +1615,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1605
1615
|
become(other) {
|
|
1606
1616
|
if (other instanceof BlockWidgetView && other.type == this.type &&
|
|
1607
1617
|
other.widget.constructor == this.widget.constructor) {
|
|
1608
|
-
if (!other.widget.
|
|
1618
|
+
if (!other.widget.compare(this.widget))
|
|
1609
1619
|
this.markDirty(true);
|
|
1610
1620
|
if (this.dom && !this.prevWidget)
|
|
1611
1621
|
this.prevWidget = this.widget;
|
|
@@ -1736,10 +1746,11 @@ class ContentBuilder {
|
|
|
1736
1746
|
}
|
|
1737
1747
|
else {
|
|
1738
1748
|
let view = WidgetView.create(deco.widget || new NullWidget("span"), len, len ? 0 : deco.startSide);
|
|
1739
|
-
let cursorBefore = this.atCursorPos && !view.isEditable && openStart <= active.length &&
|
|
1749
|
+
let cursorBefore = this.atCursorPos && !view.isEditable && openStart <= active.length &&
|
|
1750
|
+
(from < to || deco.startSide > 0);
|
|
1740
1751
|
let cursorAfter = !view.isEditable && (from < to || openStart > active.length || deco.startSide <= 0);
|
|
1741
1752
|
let line = this.getLine();
|
|
1742
|
-
if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore)
|
|
1753
|
+
if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore && !view.isEditable)
|
|
1743
1754
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1744
1755
|
this.flushBuffer(active);
|
|
1745
1756
|
if (cursorBefore) {
|
|
@@ -1793,6 +1804,7 @@ class NullWidget extends WidgetType {
|
|
|
1793
1804
|
eq(other) { return other.tag == this.tag; }
|
|
1794
1805
|
toDOM() { return document.createElement(this.tag); }
|
|
1795
1806
|
updateDOM(elt) { return elt.nodeName.toLowerCase() == this.tag; }
|
|
1807
|
+
get isHidden() { return true; }
|
|
1796
1808
|
}
|
|
1797
1809
|
|
|
1798
1810
|
const clickAddsSelectionRange = state.Facet.define();
|
|
@@ -2646,7 +2658,7 @@ class DocView extends ContentView {
|
|
|
2646
2658
|
let head = main.empty ? anchor : this.domAtPos(main.head);
|
|
2647
2659
|
// Always reset on Firefox when next to an uneditable node to
|
|
2648
2660
|
// avoid invisible cursor bugs (#111)
|
|
2649
|
-
if (browser.gecko && main.empty && betweenUneditable(anchor)) {
|
|
2661
|
+
if (browser.gecko && main.empty && !this.compositionDeco.size && betweenUneditable(anchor)) {
|
|
2650
2662
|
let dummy = document.createTextNode("");
|
|
2651
2663
|
this.view.observer.ignore(() => anchor.node.insertBefore(dummy, anchor.node.childNodes[anchor.offset] || null));
|
|
2652
2664
|
anchor = head = new DOMPos(dummy, 0);
|
|
@@ -3440,7 +3452,15 @@ class InputState {
|
|
|
3440
3452
|
// first, false means first has already been marked for this
|
|
3441
3453
|
// composition)
|
|
3442
3454
|
this.compositionFirstChange = null;
|
|
3455
|
+
// End time of the previous composition
|
|
3443
3456
|
this.compositionEndedAt = 0;
|
|
3457
|
+
// Used in a kludge to detect when an Enter keypress should be
|
|
3458
|
+
// considered part of the composition on Safari, which fires events
|
|
3459
|
+
// in the wrong order
|
|
3460
|
+
this.compositionPendingKey = false;
|
|
3461
|
+
// Used to categorize changes as part of a composition, even when
|
|
3462
|
+
// the mutation events fire shortly after the compositionend event
|
|
3463
|
+
this.compositionPendingChange = false;
|
|
3444
3464
|
this.mouseSelection = null;
|
|
3445
3465
|
let handleEvent = (handler, event) => {
|
|
3446
3466
|
if (this.ignoreDuringComposition(event))
|
|
@@ -3597,8 +3617,8 @@ class InputState {
|
|
|
3597
3617
|
// compositionend and keydown events are sometimes emitted in the
|
|
3598
3618
|
// wrong order. The key event should still be ignored, even when
|
|
3599
3619
|
// it happens after the compositionend event.
|
|
3600
|
-
if (browser.safari && !browser.ios && Date.now() - this.compositionEndedAt < 100) {
|
|
3601
|
-
this.
|
|
3620
|
+
if (browser.safari && !browser.ios && this.compositionPendingKey && Date.now() - this.compositionEndedAt < 100) {
|
|
3621
|
+
this.compositionPendingKey = false;
|
|
3602
3622
|
return true;
|
|
3603
3623
|
}
|
|
3604
3624
|
return false;
|
|
@@ -3630,8 +3650,9 @@ const PendingKeys = [
|
|
|
3630
3650
|
const EmacsyPendingKeys = "dthko";
|
|
3631
3651
|
// Key codes for modifier keys
|
|
3632
3652
|
const modifierCodes = [16, 17, 18, 20, 91, 92, 224, 225];
|
|
3653
|
+
const dragScrollMargin = 6;
|
|
3633
3654
|
function dragScrollSpeed(dist) {
|
|
3634
|
-
return dist * 0.7 + 8;
|
|
3655
|
+
return Math.max(0, dist) * 0.7 + 8;
|
|
3635
3656
|
}
|
|
3636
3657
|
class MouseSelection {
|
|
3637
3658
|
constructor(view, startEvent, style, mustSelect) {
|
|
@@ -3668,13 +3689,13 @@ class MouseSelection {
|
|
|
3668
3689
|
let sx = 0, sy = 0;
|
|
3669
3690
|
let rect = ((_a = this.scrollParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect())
|
|
3670
3691
|
|| { left: 0, top: 0, right: this.view.win.innerWidth, bottom: this.view.win.innerHeight };
|
|
3671
|
-
if (event.clientX <= rect.left)
|
|
3692
|
+
if (event.clientX <= rect.left + dragScrollMargin)
|
|
3672
3693
|
sx = -dragScrollSpeed(rect.left - event.clientX);
|
|
3673
|
-
else if (event.clientX >= rect.right)
|
|
3694
|
+
else if (event.clientX >= rect.right - dragScrollMargin)
|
|
3674
3695
|
sx = dragScrollSpeed(event.clientX - rect.right);
|
|
3675
|
-
if (event.clientY <= rect.top)
|
|
3696
|
+
if (event.clientY <= rect.top + dragScrollMargin)
|
|
3676
3697
|
sy = -dragScrollSpeed(rect.top - event.clientY);
|
|
3677
|
-
else if (event.clientY >= rect.bottom)
|
|
3698
|
+
else if (event.clientY >= rect.bottom - dragScrollMargin)
|
|
3678
3699
|
sy = dragScrollSpeed(event.clientY - rect.bottom);
|
|
3679
3700
|
this.setScrollSpeed(sx, sy);
|
|
3680
3701
|
}
|
|
@@ -3921,7 +3942,7 @@ function basicMouseSelection(view, event) {
|
|
|
3921
3942
|
}
|
|
3922
3943
|
},
|
|
3923
3944
|
get(event, extend, multiple) {
|
|
3924
|
-
let cur = queryPos(view, event);
|
|
3945
|
+
let cur = queryPos(view, event), removed;
|
|
3925
3946
|
let range = rangeForClick(view, cur.pos, cur.bias, type);
|
|
3926
3947
|
if (start.pos != cur.pos && !extend) {
|
|
3927
3948
|
let startRange = rangeForClick(view, start.pos, start.bias, type);
|
|
@@ -3930,8 +3951,8 @@ function basicMouseSelection(view, event) {
|
|
|
3930
3951
|
}
|
|
3931
3952
|
if (extend)
|
|
3932
3953
|
return startSel.replaceRange(startSel.main.extend(range.from, range.to));
|
|
3933
|
-
else if (multiple && startSel.ranges.length > 1 &&
|
|
3934
|
-
return
|
|
3954
|
+
else if (multiple && type == 1 && startSel.ranges.length > 1 && (removed = removeRangeAround(startSel, cur.pos)))
|
|
3955
|
+
return removed;
|
|
3935
3956
|
else if (multiple)
|
|
3936
3957
|
return startSel.addRange(range);
|
|
3937
3958
|
else
|
|
@@ -3939,11 +3960,13 @@ function basicMouseSelection(view, event) {
|
|
|
3939
3960
|
}
|
|
3940
3961
|
};
|
|
3941
3962
|
}
|
|
3942
|
-
function
|
|
3943
|
-
for (let i = 0
|
|
3944
|
-
|
|
3963
|
+
function removeRangeAround(sel, pos) {
|
|
3964
|
+
for (let i = 0; i < sel.ranges.length; i++) {
|
|
3965
|
+
let { from, to } = sel.ranges[i];
|
|
3966
|
+
if (from <= pos && to >= pos)
|
|
3945
3967
|
return state.EditorSelection.create(sel.ranges.slice(0, i).concat(sel.ranges.slice(i + 1)), sel.mainIndex == i ? 0 : sel.mainIndex - (sel.mainIndex > i ? 1 : 0));
|
|
3946
3968
|
}
|
|
3969
|
+
return null;
|
|
3947
3970
|
}
|
|
3948
3971
|
handlers.dragstart = (view, event) => {
|
|
3949
3972
|
let { selection: { main } } = view.state;
|
|
@@ -4120,6 +4143,8 @@ handlers.compositionstart = handlers.compositionupdate = view => {
|
|
|
4120
4143
|
handlers.compositionend = view => {
|
|
4121
4144
|
view.inputState.composing = -1;
|
|
4122
4145
|
view.inputState.compositionEndedAt = Date.now();
|
|
4146
|
+
view.inputState.compositionPendingKey = true;
|
|
4147
|
+
view.inputState.compositionPendingChange = view.observer.pendingRecords().length > 0;
|
|
4123
4148
|
view.inputState.compositionFirstChange = null;
|
|
4124
4149
|
if (browser.chrome && browser.android)
|
|
4125
4150
|
view.observer.flushSoon();
|
|
@@ -5775,8 +5800,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5775
5800
|
}
|
|
5776
5801
|
else {
|
|
5777
5802
|
let changes = startState.changes(change);
|
|
5778
|
-
let mainSel = newSel &&
|
|
5779
|
-
? newSel.main : undefined;
|
|
5803
|
+
let mainSel = newSel && newSel.main.to <= changes.newLength ? newSel.main : undefined;
|
|
5780
5804
|
// Try to apply a composition change to all cursors
|
|
5781
5805
|
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
5782
5806
|
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
@@ -5810,7 +5834,9 @@ function applyDOMChange(view, domChange) {
|
|
|
5810
5834
|
}
|
|
5811
5835
|
}
|
|
5812
5836
|
let userEvent = "input.type";
|
|
5813
|
-
if (view.composing
|
|
5837
|
+
if (view.composing ||
|
|
5838
|
+
view.inputState.compositionPendingChange && view.inputState.compositionEndedAt > Date.now() - 50) {
|
|
5839
|
+
view.inputState.compositionPendingChange = false;
|
|
5814
5840
|
userEvent += ".compose";
|
|
5815
5841
|
if (view.inputState.compositionFirstChange) {
|
|
5816
5842
|
userEvent += ".start";
|
|
@@ -6186,10 +6212,13 @@ class DOMObserver {
|
|
|
6186
6212
|
}
|
|
6187
6213
|
this.flush();
|
|
6188
6214
|
}
|
|
6189
|
-
|
|
6190
|
-
let records = this.queue;
|
|
6215
|
+
pendingRecords() {
|
|
6191
6216
|
for (let mut of this.observer.takeRecords())
|
|
6192
|
-
|
|
6217
|
+
this.queue.push(mut);
|
|
6218
|
+
return this.queue;
|
|
6219
|
+
}
|
|
6220
|
+
processRecords() {
|
|
6221
|
+
let records = this.pendingRecords();
|
|
6193
6222
|
if (records.length)
|
|
6194
6223
|
this.queue = [];
|
|
6195
6224
|
let from = -1, to = -1, typeOver = false;
|
package/dist/index.js
CHANGED
|
@@ -516,6 +516,7 @@ class ContentView {
|
|
|
516
516
|
static get(node) { return node.cmView; }
|
|
517
517
|
get isEditable() { return true; }
|
|
518
518
|
get isWidget() { return false; }
|
|
519
|
+
get isHidden() { return false; }
|
|
519
520
|
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
520
521
|
return false;
|
|
521
522
|
}
|
|
@@ -853,7 +854,7 @@ class WidgetView extends ContentView {
|
|
|
853
854
|
become(other) {
|
|
854
855
|
if (other.length == this.length && other instanceof WidgetView && other.side == this.side) {
|
|
855
856
|
if (this.widget.constructor == other.widget.constructor) {
|
|
856
|
-
if (!this.widget.
|
|
857
|
+
if (!this.widget.compare(other.widget))
|
|
857
858
|
this.markDirty(true);
|
|
858
859
|
if (this.dom && !this.prevWidget)
|
|
859
860
|
this.prevWidget = this.widget;
|
|
@@ -875,7 +876,9 @@ class WidgetView extends ContentView {
|
|
|
875
876
|
return text ? text.slice(start, start + this.length) : Text.empty;
|
|
876
877
|
}
|
|
877
878
|
domAtPos(pos) {
|
|
878
|
-
return pos == 0
|
|
879
|
+
return (this.length ? pos == 0 : this.side > 0)
|
|
880
|
+
? DOMPos.before(this.dom)
|
|
881
|
+
: DOMPos.after(this.dom, pos == this.length);
|
|
879
882
|
}
|
|
880
883
|
domBoundsAround() { return null; }
|
|
881
884
|
coordsAt(pos, side) {
|
|
@@ -891,6 +894,7 @@ class WidgetView extends ContentView {
|
|
|
891
894
|
}
|
|
892
895
|
get isEditable() { return false; }
|
|
893
896
|
get isWidget() { return true; }
|
|
897
|
+
get isHidden() { return this.widget.isHidden; }
|
|
894
898
|
destroy() {
|
|
895
899
|
super.destroy();
|
|
896
900
|
if (this.dom)
|
|
@@ -1003,6 +1007,7 @@ class WidgetBufferView extends ContentView {
|
|
|
1003
1007
|
get overrideDOMText() {
|
|
1004
1008
|
return Text.empty;
|
|
1005
1009
|
}
|
|
1010
|
+
get isHidden() { return true; }
|
|
1006
1011
|
}
|
|
1007
1012
|
TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
|
|
1008
1013
|
function inlineSiblingRect(view, side) {
|
|
@@ -1076,7 +1081,8 @@ function coordsInChildren(view, pos, side) {
|
|
|
1076
1081
|
if (child.children.length) {
|
|
1077
1082
|
scan(child, pos - off);
|
|
1078
1083
|
}
|
|
1079
|
-
else if (!after
|
|
1084
|
+
else if ((!after || after instanceof WidgetBufferView && side > 0) &&
|
|
1085
|
+
(end > pos || off == end && child.getSide() > 0)) {
|
|
1080
1086
|
after = child;
|
|
1081
1087
|
afterPos = pos - off;
|
|
1082
1088
|
}
|
|
@@ -1190,6 +1196,10 @@ class WidgetType {
|
|
|
1190
1196
|
*/
|
|
1191
1197
|
get customView() { return null; }
|
|
1192
1198
|
/**
|
|
1199
|
+
@internal
|
|
1200
|
+
*/
|
|
1201
|
+
get isHidden() { return false; }
|
|
1202
|
+
/**
|
|
1193
1203
|
This is called when the an instance of the widget is removed
|
|
1194
1204
|
from the editor view.
|
|
1195
1205
|
*/
|
|
@@ -1600,7 +1610,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1600
1610
|
become(other) {
|
|
1601
1611
|
if (other instanceof BlockWidgetView && other.type == this.type &&
|
|
1602
1612
|
other.widget.constructor == this.widget.constructor) {
|
|
1603
|
-
if (!other.widget.
|
|
1613
|
+
if (!other.widget.compare(this.widget))
|
|
1604
1614
|
this.markDirty(true);
|
|
1605
1615
|
if (this.dom && !this.prevWidget)
|
|
1606
1616
|
this.prevWidget = this.widget;
|
|
@@ -1731,10 +1741,11 @@ class ContentBuilder {
|
|
|
1731
1741
|
}
|
|
1732
1742
|
else {
|
|
1733
1743
|
let view = WidgetView.create(deco.widget || new NullWidget("span"), len, len ? 0 : deco.startSide);
|
|
1734
|
-
let cursorBefore = this.atCursorPos && !view.isEditable && openStart <= active.length &&
|
|
1744
|
+
let cursorBefore = this.atCursorPos && !view.isEditable && openStart <= active.length &&
|
|
1745
|
+
(from < to || deco.startSide > 0);
|
|
1735
1746
|
let cursorAfter = !view.isEditable && (from < to || openStart > active.length || deco.startSide <= 0);
|
|
1736
1747
|
let line = this.getLine();
|
|
1737
|
-
if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore)
|
|
1748
|
+
if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore && !view.isEditable)
|
|
1738
1749
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1739
1750
|
this.flushBuffer(active);
|
|
1740
1751
|
if (cursorBefore) {
|
|
@@ -1788,6 +1799,7 @@ class NullWidget extends WidgetType {
|
|
|
1788
1799
|
eq(other) { return other.tag == this.tag; }
|
|
1789
1800
|
toDOM() { return document.createElement(this.tag); }
|
|
1790
1801
|
updateDOM(elt) { return elt.nodeName.toLowerCase() == this.tag; }
|
|
1802
|
+
get isHidden() { return true; }
|
|
1791
1803
|
}
|
|
1792
1804
|
|
|
1793
1805
|
const clickAddsSelectionRange = /*@__PURE__*/Facet.define();
|
|
@@ -2640,7 +2652,7 @@ class DocView extends ContentView {
|
|
|
2640
2652
|
let head = main.empty ? anchor : this.domAtPos(main.head);
|
|
2641
2653
|
// Always reset on Firefox when next to an uneditable node to
|
|
2642
2654
|
// avoid invisible cursor bugs (#111)
|
|
2643
|
-
if (browser.gecko && main.empty && betweenUneditable(anchor)) {
|
|
2655
|
+
if (browser.gecko && main.empty && !this.compositionDeco.size && betweenUneditable(anchor)) {
|
|
2644
2656
|
let dummy = document.createTextNode("");
|
|
2645
2657
|
this.view.observer.ignore(() => anchor.node.insertBefore(dummy, anchor.node.childNodes[anchor.offset] || null));
|
|
2646
2658
|
anchor = head = new DOMPos(dummy, 0);
|
|
@@ -3434,7 +3446,15 @@ class InputState {
|
|
|
3434
3446
|
// first, false means first has already been marked for this
|
|
3435
3447
|
// composition)
|
|
3436
3448
|
this.compositionFirstChange = null;
|
|
3449
|
+
// End time of the previous composition
|
|
3437
3450
|
this.compositionEndedAt = 0;
|
|
3451
|
+
// Used in a kludge to detect when an Enter keypress should be
|
|
3452
|
+
// considered part of the composition on Safari, which fires events
|
|
3453
|
+
// in the wrong order
|
|
3454
|
+
this.compositionPendingKey = false;
|
|
3455
|
+
// Used to categorize changes as part of a composition, even when
|
|
3456
|
+
// the mutation events fire shortly after the compositionend event
|
|
3457
|
+
this.compositionPendingChange = false;
|
|
3438
3458
|
this.mouseSelection = null;
|
|
3439
3459
|
let handleEvent = (handler, event) => {
|
|
3440
3460
|
if (this.ignoreDuringComposition(event))
|
|
@@ -3591,8 +3611,8 @@ class InputState {
|
|
|
3591
3611
|
// compositionend and keydown events are sometimes emitted in the
|
|
3592
3612
|
// wrong order. The key event should still be ignored, even when
|
|
3593
3613
|
// it happens after the compositionend event.
|
|
3594
|
-
if (browser.safari && !browser.ios && Date.now() - this.compositionEndedAt < 100) {
|
|
3595
|
-
this.
|
|
3614
|
+
if (browser.safari && !browser.ios && this.compositionPendingKey && Date.now() - this.compositionEndedAt < 100) {
|
|
3615
|
+
this.compositionPendingKey = false;
|
|
3596
3616
|
return true;
|
|
3597
3617
|
}
|
|
3598
3618
|
return false;
|
|
@@ -3624,8 +3644,9 @@ const PendingKeys = [
|
|
|
3624
3644
|
const EmacsyPendingKeys = "dthko";
|
|
3625
3645
|
// Key codes for modifier keys
|
|
3626
3646
|
const modifierCodes = [16, 17, 18, 20, 91, 92, 224, 225];
|
|
3647
|
+
const dragScrollMargin = 6;
|
|
3627
3648
|
function dragScrollSpeed(dist) {
|
|
3628
|
-
return dist * 0.7 + 8;
|
|
3649
|
+
return Math.max(0, dist) * 0.7 + 8;
|
|
3629
3650
|
}
|
|
3630
3651
|
class MouseSelection {
|
|
3631
3652
|
constructor(view, startEvent, style, mustSelect) {
|
|
@@ -3662,13 +3683,13 @@ class MouseSelection {
|
|
|
3662
3683
|
let sx = 0, sy = 0;
|
|
3663
3684
|
let rect = ((_a = this.scrollParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect())
|
|
3664
3685
|
|| { left: 0, top: 0, right: this.view.win.innerWidth, bottom: this.view.win.innerHeight };
|
|
3665
|
-
if (event.clientX <= rect.left)
|
|
3686
|
+
if (event.clientX <= rect.left + dragScrollMargin)
|
|
3666
3687
|
sx = -dragScrollSpeed(rect.left - event.clientX);
|
|
3667
|
-
else if (event.clientX >= rect.right)
|
|
3688
|
+
else if (event.clientX >= rect.right - dragScrollMargin)
|
|
3668
3689
|
sx = dragScrollSpeed(event.clientX - rect.right);
|
|
3669
|
-
if (event.clientY <= rect.top)
|
|
3690
|
+
if (event.clientY <= rect.top + dragScrollMargin)
|
|
3670
3691
|
sy = -dragScrollSpeed(rect.top - event.clientY);
|
|
3671
|
-
else if (event.clientY >= rect.bottom)
|
|
3692
|
+
else if (event.clientY >= rect.bottom - dragScrollMargin)
|
|
3672
3693
|
sy = dragScrollSpeed(event.clientY - rect.bottom);
|
|
3673
3694
|
this.setScrollSpeed(sx, sy);
|
|
3674
3695
|
}
|
|
@@ -3915,7 +3936,7 @@ function basicMouseSelection(view, event) {
|
|
|
3915
3936
|
}
|
|
3916
3937
|
},
|
|
3917
3938
|
get(event, extend, multiple) {
|
|
3918
|
-
let cur = queryPos(view, event);
|
|
3939
|
+
let cur = queryPos(view, event), removed;
|
|
3919
3940
|
let range = rangeForClick(view, cur.pos, cur.bias, type);
|
|
3920
3941
|
if (start.pos != cur.pos && !extend) {
|
|
3921
3942
|
let startRange = rangeForClick(view, start.pos, start.bias, type);
|
|
@@ -3924,8 +3945,8 @@ function basicMouseSelection(view, event) {
|
|
|
3924
3945
|
}
|
|
3925
3946
|
if (extend)
|
|
3926
3947
|
return startSel.replaceRange(startSel.main.extend(range.from, range.to));
|
|
3927
|
-
else if (multiple && startSel.ranges.length > 1 &&
|
|
3928
|
-
return
|
|
3948
|
+
else if (multiple && type == 1 && startSel.ranges.length > 1 && (removed = removeRangeAround(startSel, cur.pos)))
|
|
3949
|
+
return removed;
|
|
3929
3950
|
else if (multiple)
|
|
3930
3951
|
return startSel.addRange(range);
|
|
3931
3952
|
else
|
|
@@ -3933,11 +3954,13 @@ function basicMouseSelection(view, event) {
|
|
|
3933
3954
|
}
|
|
3934
3955
|
};
|
|
3935
3956
|
}
|
|
3936
|
-
function
|
|
3937
|
-
for (let i = 0
|
|
3938
|
-
|
|
3957
|
+
function removeRangeAround(sel, pos) {
|
|
3958
|
+
for (let i = 0; i < sel.ranges.length; i++) {
|
|
3959
|
+
let { from, to } = sel.ranges[i];
|
|
3960
|
+
if (from <= pos && to >= pos)
|
|
3939
3961
|
return EditorSelection.create(sel.ranges.slice(0, i).concat(sel.ranges.slice(i + 1)), sel.mainIndex == i ? 0 : sel.mainIndex - (sel.mainIndex > i ? 1 : 0));
|
|
3940
3962
|
}
|
|
3963
|
+
return null;
|
|
3941
3964
|
}
|
|
3942
3965
|
handlers.dragstart = (view, event) => {
|
|
3943
3966
|
let { selection: { main } } = view.state;
|
|
@@ -4114,6 +4137,8 @@ handlers.compositionstart = handlers.compositionupdate = view => {
|
|
|
4114
4137
|
handlers.compositionend = view => {
|
|
4115
4138
|
view.inputState.composing = -1;
|
|
4116
4139
|
view.inputState.compositionEndedAt = Date.now();
|
|
4140
|
+
view.inputState.compositionPendingKey = true;
|
|
4141
|
+
view.inputState.compositionPendingChange = view.observer.pendingRecords().length > 0;
|
|
4117
4142
|
view.inputState.compositionFirstChange = null;
|
|
4118
4143
|
if (browser.chrome && browser.android)
|
|
4119
4144
|
view.observer.flushSoon();
|
|
@@ -5768,8 +5793,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5768
5793
|
}
|
|
5769
5794
|
else {
|
|
5770
5795
|
let changes = startState.changes(change);
|
|
5771
|
-
let mainSel = newSel &&
|
|
5772
|
-
? newSel.main : undefined;
|
|
5796
|
+
let mainSel = newSel && newSel.main.to <= changes.newLength ? newSel.main : undefined;
|
|
5773
5797
|
// Try to apply a composition change to all cursors
|
|
5774
5798
|
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
5775
5799
|
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
@@ -5803,7 +5827,9 @@ function applyDOMChange(view, domChange) {
|
|
|
5803
5827
|
}
|
|
5804
5828
|
}
|
|
5805
5829
|
let userEvent = "input.type";
|
|
5806
|
-
if (view.composing
|
|
5830
|
+
if (view.composing ||
|
|
5831
|
+
view.inputState.compositionPendingChange && view.inputState.compositionEndedAt > Date.now() - 50) {
|
|
5832
|
+
view.inputState.compositionPendingChange = false;
|
|
5807
5833
|
userEvent += ".compose";
|
|
5808
5834
|
if (view.inputState.compositionFirstChange) {
|
|
5809
5835
|
userEvent += ".start";
|
|
@@ -6179,10 +6205,13 @@ class DOMObserver {
|
|
|
6179
6205
|
}
|
|
6180
6206
|
this.flush();
|
|
6181
6207
|
}
|
|
6182
|
-
|
|
6183
|
-
let records = this.queue;
|
|
6208
|
+
pendingRecords() {
|
|
6184
6209
|
for (let mut of this.observer.takeRecords())
|
|
6185
|
-
|
|
6210
|
+
this.queue.push(mut);
|
|
6211
|
+
return this.queue;
|
|
6212
|
+
}
|
|
6213
|
+
processRecords() {
|
|
6214
|
+
let records = this.pendingRecords();
|
|
6186
6215
|
if (records.length)
|
|
6187
6216
|
this.queue = [];
|
|
6188
6217
|
let from = -1, to = -1, typeOver = false;
|