@codemirror/view 6.9.4 → 6.9.6
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 +24 -0
- package/dist/index.cjs +119 -46
- package/dist/index.js +119 -46
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
## 6.9.6 (2023-04-21)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix an issue where, when escape was pressed followed by a key that the editor handled, followed by tab, the tab would still move focus.
|
|
6
|
+
|
|
7
|
+
Fix an issue where, in some circumstances, the editor would ignore text changes at the end of a composition.
|
|
8
|
+
|
|
9
|
+
Allow inline widgets to be updated to a different length via `updateDOM`.
|
|
10
|
+
|
|
11
|
+
## 6.9.5 (2023-04-17)
|
|
12
|
+
|
|
13
|
+
### Bug fixes
|
|
14
|
+
|
|
15
|
+
Avoid disrupting the composition in specific cases where Safari invasively changes the DOM structure in the middle of a composition.
|
|
16
|
+
|
|
17
|
+
Fix a bug that prevented `destroy` being called on hover tooltips.
|
|
18
|
+
|
|
19
|
+
Fix a bug where the editor could take focus when content changes required it to restore the DOM selection.
|
|
20
|
+
|
|
21
|
+
Fix height layout corruption caused by a division by zero.
|
|
22
|
+
|
|
23
|
+
Make sure styles targeting the editor's focus status are specific enough to not cause them to apply to editors nested inside another focused editor. This will require themes to adjust their selection background styles to match the new specificity.
|
|
24
|
+
|
|
1
25
|
## 6.9.4 (2023-04-11)
|
|
2
26
|
|
|
3
27
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -856,15 +856,15 @@ class WidgetView extends ContentView {
|
|
|
856
856
|
return true;
|
|
857
857
|
}
|
|
858
858
|
become(other) {
|
|
859
|
-
if (other
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
859
|
+
if (other instanceof WidgetView && other.side == this.side &&
|
|
860
|
+
this.widget.constructor == other.widget.constructor) {
|
|
861
|
+
if (!this.widget.compare(other.widget))
|
|
862
|
+
this.markDirty(true);
|
|
863
|
+
if (this.dom && !this.prevWidget)
|
|
864
|
+
this.prevWidget = this.widget;
|
|
865
|
+
this.widget = other.widget;
|
|
866
|
+
this.length = other.length;
|
|
867
|
+
return true;
|
|
868
868
|
}
|
|
869
869
|
return false;
|
|
870
870
|
}
|
|
@@ -910,14 +910,14 @@ class CompositionView extends WidgetView {
|
|
|
910
910
|
let { topView, text } = this.widget;
|
|
911
911
|
if (!topView)
|
|
912
912
|
return new DOMPos(text, Math.min(pos, text.nodeValue.length));
|
|
913
|
-
return scanCompositionTree(pos, 0, topView, text, (v, p) => v.domAtPos(p), p => new DOMPos(text, Math.min(p, text.nodeValue.length)));
|
|
913
|
+
return scanCompositionTree(pos, 0, topView, text, this.length - topView.length, (v, p) => v.domAtPos(p), (text, p) => new DOMPos(text, Math.min(p, text.nodeValue.length)));
|
|
914
914
|
}
|
|
915
915
|
sync() { this.setDOM(this.widget.toDOM()); }
|
|
916
916
|
localPosFromDOM(node, offset) {
|
|
917
917
|
let { topView, text } = this.widget;
|
|
918
918
|
if (!topView)
|
|
919
919
|
return Math.min(offset, this.length);
|
|
920
|
-
return posFromDOMInCompositionTree(node, offset, topView, text);
|
|
920
|
+
return posFromDOMInCompositionTree(node, offset, topView, text, this.length - topView.length);
|
|
921
921
|
}
|
|
922
922
|
ignoreMutation() { return false; }
|
|
923
923
|
get overrideDOMText() { return null; }
|
|
@@ -925,7 +925,7 @@ class CompositionView extends WidgetView {
|
|
|
925
925
|
let { topView, text } = this.widget;
|
|
926
926
|
if (!topView)
|
|
927
927
|
return textCoords(text, pos, side);
|
|
928
|
-
return scanCompositionTree(pos, side, topView, text, (v, pos, side) => v.coordsAt(pos, side), (pos, side) => textCoords(text, pos, side));
|
|
928
|
+
return scanCompositionTree(pos, side, topView, text, this.length - topView.length, (v, pos, side) => v.coordsAt(pos, side), (text, pos, side) => textCoords(text, pos, side));
|
|
929
929
|
}
|
|
930
930
|
destroy() {
|
|
931
931
|
var _a;
|
|
@@ -938,35 +938,68 @@ class CompositionView extends WidgetView {
|
|
|
938
938
|
// Uses the old structure of a chunk of content view frozen for
|
|
939
939
|
// composition to try and find a reasonable DOM location for the given
|
|
940
940
|
// offset.
|
|
941
|
-
function scanCompositionTree(pos, side, view, text, enterView, fromText) {
|
|
941
|
+
function scanCompositionTree(pos, side, view, text, dLen, enterView, fromText) {
|
|
942
942
|
if (view instanceof MarkView) {
|
|
943
943
|
for (let child = view.dom.firstChild; child; child = child.nextSibling) {
|
|
944
944
|
let desc = ContentView.get(child);
|
|
945
|
-
if (!desc)
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
945
|
+
if (!desc) {
|
|
946
|
+
let inner = scanCompositionNode(pos, side, child, fromText);
|
|
947
|
+
if (typeof inner != "number")
|
|
948
|
+
return inner;
|
|
949
|
+
pos = inner;
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
let hasComp = contains(child, text);
|
|
953
|
+
let len = desc.length + (hasComp ? dLen : 0);
|
|
954
|
+
if (pos < len || pos == len && desc.getSide() <= 0)
|
|
955
|
+
return hasComp ? scanCompositionTree(pos, side, desc, text, dLen, enterView, fromText) : enterView(desc, pos, side);
|
|
956
|
+
pos -= len;
|
|
957
|
+
}
|
|
952
958
|
}
|
|
953
959
|
return enterView(view, view.length, -1);
|
|
954
960
|
}
|
|
955
961
|
else if (view.dom == text) {
|
|
956
|
-
return fromText(pos, side);
|
|
962
|
+
return fromText(text, pos, side);
|
|
957
963
|
}
|
|
958
964
|
else {
|
|
959
965
|
return enterView(view, pos, side);
|
|
960
966
|
}
|
|
961
967
|
}
|
|
962
|
-
function
|
|
968
|
+
function scanCompositionNode(pos, side, node, fromText) {
|
|
969
|
+
if (node.nodeType == 3) {
|
|
970
|
+
let len = node.nodeValue.length;
|
|
971
|
+
if (pos <= len)
|
|
972
|
+
return fromText(node, pos, side);
|
|
973
|
+
pos -= len;
|
|
974
|
+
}
|
|
975
|
+
else if (node.nodeType == 1 && node.contentEditable != "false") {
|
|
976
|
+
for (let child = node.firstChild; child; child = child.nextSibling) {
|
|
977
|
+
let inner = scanCompositionNode(pos, side, child, fromText);
|
|
978
|
+
if (typeof inner != "number")
|
|
979
|
+
return inner;
|
|
980
|
+
pos = inner;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return pos;
|
|
984
|
+
}
|
|
985
|
+
function posFromDOMInCompositionTree(node, offset, view, text, dLen) {
|
|
963
986
|
if (view instanceof MarkView) {
|
|
964
987
|
let pos = 0;
|
|
965
|
-
for (let child
|
|
966
|
-
let
|
|
967
|
-
if (
|
|
968
|
-
|
|
969
|
-
|
|
988
|
+
for (let child = view.dom.firstChild; child; child = child.nextSibling) {
|
|
989
|
+
let childView = ContentView.get(child);
|
|
990
|
+
if (childView) {
|
|
991
|
+
let hasComp = contains(child, text);
|
|
992
|
+
if (contains(child, node))
|
|
993
|
+
return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, childView, text, dLen)
|
|
994
|
+
: childView.localPosFromDOM(node, offset));
|
|
995
|
+
pos += childView.length + (hasComp ? dLen : 0);
|
|
996
|
+
}
|
|
997
|
+
else {
|
|
998
|
+
let inner = posFromDOMInOpaqueNode(node, offset, child);
|
|
999
|
+
if (inner.result != null)
|
|
1000
|
+
return pos + inner.result;
|
|
1001
|
+
pos += inner.size;
|
|
1002
|
+
}
|
|
970
1003
|
}
|
|
971
1004
|
}
|
|
972
1005
|
else if (view.dom == text) {
|
|
@@ -974,6 +1007,27 @@ function posFromDOMInCompositionTree(node, offset, view, text) {
|
|
|
974
1007
|
}
|
|
975
1008
|
return view.localPosFromDOM(node, offset);
|
|
976
1009
|
}
|
|
1010
|
+
function posFromDOMInOpaqueNode(node, offset, target) {
|
|
1011
|
+
if (target.nodeType == 3) {
|
|
1012
|
+
return node == target ? { result: offset } : { size: target.nodeValue.length };
|
|
1013
|
+
}
|
|
1014
|
+
else if (target.nodeType == 1 && target.contentEditable != "false") {
|
|
1015
|
+
let pos = 0;
|
|
1016
|
+
for (let child = target.firstChild, i = 0;; child = child.nextSibling, i++) {
|
|
1017
|
+
if (node == target && i == offset)
|
|
1018
|
+
return { result: pos };
|
|
1019
|
+
if (!child)
|
|
1020
|
+
return { size: pos };
|
|
1021
|
+
let inner = posFromDOMInOpaqueNode(node, offset, child);
|
|
1022
|
+
if (inner.result != null)
|
|
1023
|
+
return { result: offset + inner.result };
|
|
1024
|
+
pos += inner.size;
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
else {
|
|
1028
|
+
return target.contains(node) ? { result: 0 } : { size: 0 };
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
977
1031
|
// These are drawn around uneditable widgets to avoid a number of
|
|
978
1032
|
// browser bugs that show up when the cursor is directly next to
|
|
979
1033
|
// uneditable inline content.
|
|
@@ -2648,7 +2702,10 @@ class DocView extends ContentView {
|
|
|
2648
2702
|
updateSelection(mustRead = false, fromPointer = false) {
|
|
2649
2703
|
if (mustRead || !this.view.observer.selectionRange.focusNode)
|
|
2650
2704
|
this.view.observer.readSelectionRange();
|
|
2651
|
-
|
|
2705
|
+
let activeElt = this.view.root.activeElement, focused = activeElt == this.dom;
|
|
2706
|
+
let selectionNotFocus = !focused &&
|
|
2707
|
+
hasSelection(this.dom, this.view.observer.selectionRange) && !(activeElt && this.dom.contains(activeElt));
|
|
2708
|
+
if (!(focused || fromPointer || selectionNotFocus))
|
|
2652
2709
|
return;
|
|
2653
2710
|
let force = this.forceSelection;
|
|
2654
2711
|
this.forceSelection = false;
|
|
@@ -2718,6 +2775,11 @@ class DocView extends ContentView {
|
|
|
2718
2775
|
rawSel.removeAllRanges();
|
|
2719
2776
|
rawSel.addRange(range);
|
|
2720
2777
|
}
|
|
2778
|
+
if (selectionNotFocus && this.view.root.activeElement == this.dom) {
|
|
2779
|
+
this.dom.blur();
|
|
2780
|
+
if (activeElt)
|
|
2781
|
+
activeElt.focus();
|
|
2782
|
+
}
|
|
2721
2783
|
});
|
|
2722
2784
|
this.view.observer.setSelectionRange(anchor, head);
|
|
2723
2785
|
}
|
|
@@ -2751,11 +2813,6 @@ class DocView extends ContentView {
|
|
|
2751
2813
|
if (view.docView.posFromDOM(newRange.anchorNode, newRange.anchorOffset) != cursor.from)
|
|
2752
2814
|
sel.collapse(anchorNode, anchorOffset);
|
|
2753
2815
|
}
|
|
2754
|
-
mayControlSelection() {
|
|
2755
|
-
let active = this.view.root.activeElement;
|
|
2756
|
-
return active == this.dom ||
|
|
2757
|
-
hasSelection(this.dom, this.view.observer.selectionRange) && !(active && this.dom.contains(active));
|
|
2758
|
-
}
|
|
2759
2816
|
nearest(dom) {
|
|
2760
2817
|
for (let cur = dom; cur;) {
|
|
2761
2818
|
let domView = ContentView.get(cur);
|
|
@@ -3574,6 +3631,8 @@ class InputState {
|
|
|
3574
3631
|
this.lastKeyTime = Date.now();
|
|
3575
3632
|
if (event.keyCode == 9 && Date.now() < this.lastEscPress + 2000)
|
|
3576
3633
|
return true;
|
|
3634
|
+
if (event.keyCode != 27 && modifierCodes.indexOf(event.keyCode) < 0)
|
|
3635
|
+
view.inputState.lastEscPress = 0;
|
|
3577
3636
|
// Chrome for Android usually doesn't fire proper key events, but
|
|
3578
3637
|
// occasionally does, usually surrounded by a bunch of complicated
|
|
3579
3638
|
// composition changes. When an enter or backspace key event is
|
|
@@ -3843,8 +3902,6 @@ handlers.keydown = (view, event) => {
|
|
|
3843
3902
|
view.inputState.setSelectionOrigin("select");
|
|
3844
3903
|
if (event.keyCode == 27)
|
|
3845
3904
|
view.inputState.lastEscPress = Date.now();
|
|
3846
|
-
else if (modifierCodes.indexOf(event.keyCode) < 0)
|
|
3847
|
-
view.inputState.lastEscPress = 0;
|
|
3848
3905
|
};
|
|
3849
3906
|
handlers.touchstart = (view, e) => {
|
|
3850
3907
|
view.inputState.lastTouchTime = Date.now();
|
|
@@ -4146,13 +4203,23 @@ handlers.compositionend = view => {
|
|
|
4146
4203
|
view.inputState.compositionPendingKey = true;
|
|
4147
4204
|
view.inputState.compositionPendingChange = view.observer.pendingRecords().length > 0;
|
|
4148
4205
|
view.inputState.compositionFirstChange = null;
|
|
4149
|
-
if (browser.chrome && browser.android)
|
|
4206
|
+
if (browser.chrome && browser.android) {
|
|
4207
|
+
// Delay flushing for a bit on Android because it'll often fire a
|
|
4208
|
+
// bunch of contradictory changes in a row at end of compositon
|
|
4150
4209
|
view.observer.flushSoon();
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
}
|
|
4210
|
+
}
|
|
4211
|
+
else if (view.inputState.compositionPendingChange) {
|
|
4212
|
+
// If we found pending records, schedule a flush.
|
|
4213
|
+
Promise.resolve().then(() => view.observer.flush());
|
|
4214
|
+
}
|
|
4215
|
+
else {
|
|
4216
|
+
// Otherwise, make sure that, if no changes come in soon, the
|
|
4217
|
+
// composition view is cleared.
|
|
4218
|
+
setTimeout(() => {
|
|
4219
|
+
if (view.inputState.composing < 0 && view.docView.compositionDeco.size)
|
|
4220
|
+
view.update([]);
|
|
4221
|
+
}, 50);
|
|
4222
|
+
}
|
|
4156
4223
|
};
|
|
4157
4224
|
handlers.contextmenu = view => {
|
|
4158
4225
|
view.inputState.lastContextMenu = Date.now();
|
|
@@ -4492,7 +4559,8 @@ class HeightMapGap extends HeightMap {
|
|
|
4492
4559
|
if (oracle.lineWrapping) {
|
|
4493
4560
|
let totalPerLine = Math.min(this.height, oracle.lineHeight * lines);
|
|
4494
4561
|
perLine = totalPerLine / lines;
|
|
4495
|
-
|
|
4562
|
+
if (this.length > lines + 1)
|
|
4563
|
+
perChar = (this.height - totalPerLine) / (this.length - lines - 1);
|
|
4496
4564
|
}
|
|
4497
4565
|
else {
|
|
4498
4566
|
perLine = this.height / lines;
|
|
@@ -5508,16 +5576,16 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5508
5576
|
"&dark .cm-selectionBackground": {
|
|
5509
5577
|
background: "#222"
|
|
5510
5578
|
},
|
|
5511
|
-
"&light.cm-focused .cm-selectionBackground": {
|
|
5579
|
+
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
5512
5580
|
background: "#d7d4f0"
|
|
5513
5581
|
},
|
|
5514
|
-
"&dark.cm-focused .cm-selectionBackground": {
|
|
5582
|
+
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
5515
5583
|
background: "#233"
|
|
5516
5584
|
},
|
|
5517
5585
|
".cm-cursorLayer": {
|
|
5518
5586
|
pointerEvents: "none"
|
|
5519
5587
|
},
|
|
5520
|
-
"&.cm-focused .cm-cursorLayer": {
|
|
5588
|
+
"&.cm-focused > .cm-scroller > .cm-cursorLayer": {
|
|
5521
5589
|
animation: "steps(1) cm-blink 1.2s infinite"
|
|
5522
5590
|
},
|
|
5523
5591
|
// Two animations defined so that we can switch between them to
|
|
@@ -5539,7 +5607,7 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5539
5607
|
".cm-dropCursor": {
|
|
5540
5608
|
position: "absolute"
|
|
5541
5609
|
},
|
|
5542
|
-
"&.cm-focused .cm-cursor": {
|
|
5610
|
+
"&.cm-focused > .cm-scroller > .cm-cursorLayer .cm-cursor": {
|
|
5543
5611
|
display: "block"
|
|
5544
5612
|
},
|
|
5545
5613
|
"&light .cm-activeLine": { backgroundColor: "#cceeff44" },
|
|
@@ -8811,6 +8879,11 @@ class HoverTooltipHost {
|
|
|
8811
8879
|
update(update) {
|
|
8812
8880
|
this.manager.update(update);
|
|
8813
8881
|
}
|
|
8882
|
+
destroy() {
|
|
8883
|
+
var _a;
|
|
8884
|
+
for (let t of this.manager.tooltipViews)
|
|
8885
|
+
(_a = t.destroy) === null || _a === void 0 ? void 0 : _a.call(t);
|
|
8886
|
+
}
|
|
8814
8887
|
}
|
|
8815
8888
|
const showHoverTooltipHost = showTooltip.compute([showHoverTooltip], state => {
|
|
8816
8889
|
let tooltips = state.facet(showHoverTooltip).filter(t => t);
|
package/dist/index.js
CHANGED
|
@@ -852,15 +852,15 @@ class WidgetView extends ContentView {
|
|
|
852
852
|
return true;
|
|
853
853
|
}
|
|
854
854
|
become(other) {
|
|
855
|
-
if (other
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
855
|
+
if (other instanceof WidgetView && other.side == this.side &&
|
|
856
|
+
this.widget.constructor == other.widget.constructor) {
|
|
857
|
+
if (!this.widget.compare(other.widget))
|
|
858
|
+
this.markDirty(true);
|
|
859
|
+
if (this.dom && !this.prevWidget)
|
|
860
|
+
this.prevWidget = this.widget;
|
|
861
|
+
this.widget = other.widget;
|
|
862
|
+
this.length = other.length;
|
|
863
|
+
return true;
|
|
864
864
|
}
|
|
865
865
|
return false;
|
|
866
866
|
}
|
|
@@ -906,14 +906,14 @@ class CompositionView extends WidgetView {
|
|
|
906
906
|
let { topView, text } = this.widget;
|
|
907
907
|
if (!topView)
|
|
908
908
|
return new DOMPos(text, Math.min(pos, text.nodeValue.length));
|
|
909
|
-
return scanCompositionTree(pos, 0, topView, text, (v, p) => v.domAtPos(p), p => new DOMPos(text, Math.min(p, text.nodeValue.length)));
|
|
909
|
+
return scanCompositionTree(pos, 0, topView, text, this.length - topView.length, (v, p) => v.domAtPos(p), (text, p) => new DOMPos(text, Math.min(p, text.nodeValue.length)));
|
|
910
910
|
}
|
|
911
911
|
sync() { this.setDOM(this.widget.toDOM()); }
|
|
912
912
|
localPosFromDOM(node, offset) {
|
|
913
913
|
let { topView, text } = this.widget;
|
|
914
914
|
if (!topView)
|
|
915
915
|
return Math.min(offset, this.length);
|
|
916
|
-
return posFromDOMInCompositionTree(node, offset, topView, text);
|
|
916
|
+
return posFromDOMInCompositionTree(node, offset, topView, text, this.length - topView.length);
|
|
917
917
|
}
|
|
918
918
|
ignoreMutation() { return false; }
|
|
919
919
|
get overrideDOMText() { return null; }
|
|
@@ -921,7 +921,7 @@ class CompositionView extends WidgetView {
|
|
|
921
921
|
let { topView, text } = this.widget;
|
|
922
922
|
if (!topView)
|
|
923
923
|
return textCoords(text, pos, side);
|
|
924
|
-
return scanCompositionTree(pos, side, topView, text, (v, pos, side) => v.coordsAt(pos, side), (pos, side) => textCoords(text, pos, side));
|
|
924
|
+
return scanCompositionTree(pos, side, topView, text, this.length - topView.length, (v, pos, side) => v.coordsAt(pos, side), (text, pos, side) => textCoords(text, pos, side));
|
|
925
925
|
}
|
|
926
926
|
destroy() {
|
|
927
927
|
var _a;
|
|
@@ -934,35 +934,68 @@ class CompositionView extends WidgetView {
|
|
|
934
934
|
// Uses the old structure of a chunk of content view frozen for
|
|
935
935
|
// composition to try and find a reasonable DOM location for the given
|
|
936
936
|
// offset.
|
|
937
|
-
function scanCompositionTree(pos, side, view, text, enterView, fromText) {
|
|
937
|
+
function scanCompositionTree(pos, side, view, text, dLen, enterView, fromText) {
|
|
938
938
|
if (view instanceof MarkView) {
|
|
939
939
|
for (let child = view.dom.firstChild; child; child = child.nextSibling) {
|
|
940
940
|
let desc = ContentView.get(child);
|
|
941
|
-
if (!desc)
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
941
|
+
if (!desc) {
|
|
942
|
+
let inner = scanCompositionNode(pos, side, child, fromText);
|
|
943
|
+
if (typeof inner != "number")
|
|
944
|
+
return inner;
|
|
945
|
+
pos = inner;
|
|
946
|
+
}
|
|
947
|
+
else {
|
|
948
|
+
let hasComp = contains(child, text);
|
|
949
|
+
let len = desc.length + (hasComp ? dLen : 0);
|
|
950
|
+
if (pos < len || pos == len && desc.getSide() <= 0)
|
|
951
|
+
return hasComp ? scanCompositionTree(pos, side, desc, text, dLen, enterView, fromText) : enterView(desc, pos, side);
|
|
952
|
+
pos -= len;
|
|
953
|
+
}
|
|
948
954
|
}
|
|
949
955
|
return enterView(view, view.length, -1);
|
|
950
956
|
}
|
|
951
957
|
else if (view.dom == text) {
|
|
952
|
-
return fromText(pos, side);
|
|
958
|
+
return fromText(text, pos, side);
|
|
953
959
|
}
|
|
954
960
|
else {
|
|
955
961
|
return enterView(view, pos, side);
|
|
956
962
|
}
|
|
957
963
|
}
|
|
958
|
-
function
|
|
964
|
+
function scanCompositionNode(pos, side, node, fromText) {
|
|
965
|
+
if (node.nodeType == 3) {
|
|
966
|
+
let len = node.nodeValue.length;
|
|
967
|
+
if (pos <= len)
|
|
968
|
+
return fromText(node, pos, side);
|
|
969
|
+
pos -= len;
|
|
970
|
+
}
|
|
971
|
+
else if (node.nodeType == 1 && node.contentEditable != "false") {
|
|
972
|
+
for (let child = node.firstChild; child; child = child.nextSibling) {
|
|
973
|
+
let inner = scanCompositionNode(pos, side, child, fromText);
|
|
974
|
+
if (typeof inner != "number")
|
|
975
|
+
return inner;
|
|
976
|
+
pos = inner;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
return pos;
|
|
980
|
+
}
|
|
981
|
+
function posFromDOMInCompositionTree(node, offset, view, text, dLen) {
|
|
959
982
|
if (view instanceof MarkView) {
|
|
960
983
|
let pos = 0;
|
|
961
|
-
for (let child
|
|
962
|
-
let
|
|
963
|
-
if (
|
|
964
|
-
|
|
965
|
-
|
|
984
|
+
for (let child = view.dom.firstChild; child; child = child.nextSibling) {
|
|
985
|
+
let childView = ContentView.get(child);
|
|
986
|
+
if (childView) {
|
|
987
|
+
let hasComp = contains(child, text);
|
|
988
|
+
if (contains(child, node))
|
|
989
|
+
return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, childView, text, dLen)
|
|
990
|
+
: childView.localPosFromDOM(node, offset));
|
|
991
|
+
pos += childView.length + (hasComp ? dLen : 0);
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
let inner = posFromDOMInOpaqueNode(node, offset, child);
|
|
995
|
+
if (inner.result != null)
|
|
996
|
+
return pos + inner.result;
|
|
997
|
+
pos += inner.size;
|
|
998
|
+
}
|
|
966
999
|
}
|
|
967
1000
|
}
|
|
968
1001
|
else if (view.dom == text) {
|
|
@@ -970,6 +1003,27 @@ function posFromDOMInCompositionTree(node, offset, view, text) {
|
|
|
970
1003
|
}
|
|
971
1004
|
return view.localPosFromDOM(node, offset);
|
|
972
1005
|
}
|
|
1006
|
+
function posFromDOMInOpaqueNode(node, offset, target) {
|
|
1007
|
+
if (target.nodeType == 3) {
|
|
1008
|
+
return node == target ? { result: offset } : { size: target.nodeValue.length };
|
|
1009
|
+
}
|
|
1010
|
+
else if (target.nodeType == 1 && target.contentEditable != "false") {
|
|
1011
|
+
let pos = 0;
|
|
1012
|
+
for (let child = target.firstChild, i = 0;; child = child.nextSibling, i++) {
|
|
1013
|
+
if (node == target && i == offset)
|
|
1014
|
+
return { result: pos };
|
|
1015
|
+
if (!child)
|
|
1016
|
+
return { size: pos };
|
|
1017
|
+
let inner = posFromDOMInOpaqueNode(node, offset, child);
|
|
1018
|
+
if (inner.result != null)
|
|
1019
|
+
return { result: offset + inner.result };
|
|
1020
|
+
pos += inner.size;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
else {
|
|
1024
|
+
return target.contains(node) ? { result: 0 } : { size: 0 };
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
973
1027
|
// These are drawn around uneditable widgets to avoid a number of
|
|
974
1028
|
// browser bugs that show up when the cursor is directly next to
|
|
975
1029
|
// uneditable inline content.
|
|
@@ -2642,7 +2696,10 @@ class DocView extends ContentView {
|
|
|
2642
2696
|
updateSelection(mustRead = false, fromPointer = false) {
|
|
2643
2697
|
if (mustRead || !this.view.observer.selectionRange.focusNode)
|
|
2644
2698
|
this.view.observer.readSelectionRange();
|
|
2645
|
-
|
|
2699
|
+
let activeElt = this.view.root.activeElement, focused = activeElt == this.dom;
|
|
2700
|
+
let selectionNotFocus = !focused &&
|
|
2701
|
+
hasSelection(this.dom, this.view.observer.selectionRange) && !(activeElt && this.dom.contains(activeElt));
|
|
2702
|
+
if (!(focused || fromPointer || selectionNotFocus))
|
|
2646
2703
|
return;
|
|
2647
2704
|
let force = this.forceSelection;
|
|
2648
2705
|
this.forceSelection = false;
|
|
@@ -2712,6 +2769,11 @@ class DocView extends ContentView {
|
|
|
2712
2769
|
rawSel.removeAllRanges();
|
|
2713
2770
|
rawSel.addRange(range);
|
|
2714
2771
|
}
|
|
2772
|
+
if (selectionNotFocus && this.view.root.activeElement == this.dom) {
|
|
2773
|
+
this.dom.blur();
|
|
2774
|
+
if (activeElt)
|
|
2775
|
+
activeElt.focus();
|
|
2776
|
+
}
|
|
2715
2777
|
});
|
|
2716
2778
|
this.view.observer.setSelectionRange(anchor, head);
|
|
2717
2779
|
}
|
|
@@ -2745,11 +2807,6 @@ class DocView extends ContentView {
|
|
|
2745
2807
|
if (view.docView.posFromDOM(newRange.anchorNode, newRange.anchorOffset) != cursor.from)
|
|
2746
2808
|
sel.collapse(anchorNode, anchorOffset);
|
|
2747
2809
|
}
|
|
2748
|
-
mayControlSelection() {
|
|
2749
|
-
let active = this.view.root.activeElement;
|
|
2750
|
-
return active == this.dom ||
|
|
2751
|
-
hasSelection(this.dom, this.view.observer.selectionRange) && !(active && this.dom.contains(active));
|
|
2752
|
-
}
|
|
2753
2810
|
nearest(dom) {
|
|
2754
2811
|
for (let cur = dom; cur;) {
|
|
2755
2812
|
let domView = ContentView.get(cur);
|
|
@@ -3568,6 +3625,8 @@ class InputState {
|
|
|
3568
3625
|
this.lastKeyTime = Date.now();
|
|
3569
3626
|
if (event.keyCode == 9 && Date.now() < this.lastEscPress + 2000)
|
|
3570
3627
|
return true;
|
|
3628
|
+
if (event.keyCode != 27 && modifierCodes.indexOf(event.keyCode) < 0)
|
|
3629
|
+
view.inputState.lastEscPress = 0;
|
|
3571
3630
|
// Chrome for Android usually doesn't fire proper key events, but
|
|
3572
3631
|
// occasionally does, usually surrounded by a bunch of complicated
|
|
3573
3632
|
// composition changes. When an enter or backspace key event is
|
|
@@ -3837,8 +3896,6 @@ handlers.keydown = (view, event) => {
|
|
|
3837
3896
|
view.inputState.setSelectionOrigin("select");
|
|
3838
3897
|
if (event.keyCode == 27)
|
|
3839
3898
|
view.inputState.lastEscPress = Date.now();
|
|
3840
|
-
else if (modifierCodes.indexOf(event.keyCode) < 0)
|
|
3841
|
-
view.inputState.lastEscPress = 0;
|
|
3842
3899
|
};
|
|
3843
3900
|
handlers.touchstart = (view, e) => {
|
|
3844
3901
|
view.inputState.lastTouchTime = Date.now();
|
|
@@ -4140,13 +4197,23 @@ handlers.compositionend = view => {
|
|
|
4140
4197
|
view.inputState.compositionPendingKey = true;
|
|
4141
4198
|
view.inputState.compositionPendingChange = view.observer.pendingRecords().length > 0;
|
|
4142
4199
|
view.inputState.compositionFirstChange = null;
|
|
4143
|
-
if (browser.chrome && browser.android)
|
|
4200
|
+
if (browser.chrome && browser.android) {
|
|
4201
|
+
// Delay flushing for a bit on Android because it'll often fire a
|
|
4202
|
+
// bunch of contradictory changes in a row at end of compositon
|
|
4144
4203
|
view.observer.flushSoon();
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
}
|
|
4204
|
+
}
|
|
4205
|
+
else if (view.inputState.compositionPendingChange) {
|
|
4206
|
+
// If we found pending records, schedule a flush.
|
|
4207
|
+
Promise.resolve().then(() => view.observer.flush());
|
|
4208
|
+
}
|
|
4209
|
+
else {
|
|
4210
|
+
// Otherwise, make sure that, if no changes come in soon, the
|
|
4211
|
+
// composition view is cleared.
|
|
4212
|
+
setTimeout(() => {
|
|
4213
|
+
if (view.inputState.composing < 0 && view.docView.compositionDeco.size)
|
|
4214
|
+
view.update([]);
|
|
4215
|
+
}, 50);
|
|
4216
|
+
}
|
|
4150
4217
|
};
|
|
4151
4218
|
handlers.contextmenu = view => {
|
|
4152
4219
|
view.inputState.lastContextMenu = Date.now();
|
|
@@ -4485,7 +4552,8 @@ class HeightMapGap extends HeightMap {
|
|
|
4485
4552
|
if (oracle.lineWrapping) {
|
|
4486
4553
|
let totalPerLine = Math.min(this.height, oracle.lineHeight * lines);
|
|
4487
4554
|
perLine = totalPerLine / lines;
|
|
4488
|
-
|
|
4555
|
+
if (this.length > lines + 1)
|
|
4556
|
+
perChar = (this.height - totalPerLine) / (this.length - lines - 1);
|
|
4489
4557
|
}
|
|
4490
4558
|
else {
|
|
4491
4559
|
perLine = this.height / lines;
|
|
@@ -5501,16 +5569,16 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5501
5569
|
"&dark .cm-selectionBackground": {
|
|
5502
5570
|
background: "#222"
|
|
5503
5571
|
},
|
|
5504
|
-
"&light.cm-focused .cm-selectionBackground": {
|
|
5572
|
+
"&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
5505
5573
|
background: "#d7d4f0"
|
|
5506
5574
|
},
|
|
5507
|
-
"&dark.cm-focused .cm-selectionBackground": {
|
|
5575
|
+
"&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
|
|
5508
5576
|
background: "#233"
|
|
5509
5577
|
},
|
|
5510
5578
|
".cm-cursorLayer": {
|
|
5511
5579
|
pointerEvents: "none"
|
|
5512
5580
|
},
|
|
5513
|
-
"&.cm-focused .cm-cursorLayer": {
|
|
5581
|
+
"&.cm-focused > .cm-scroller > .cm-cursorLayer": {
|
|
5514
5582
|
animation: "steps(1) cm-blink 1.2s infinite"
|
|
5515
5583
|
},
|
|
5516
5584
|
// Two animations defined so that we can switch between them to
|
|
@@ -5532,7 +5600,7 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5532
5600
|
".cm-dropCursor": {
|
|
5533
5601
|
position: "absolute"
|
|
5534
5602
|
},
|
|
5535
|
-
"&.cm-focused .cm-cursor": {
|
|
5603
|
+
"&.cm-focused > .cm-scroller > .cm-cursorLayer .cm-cursor": {
|
|
5536
5604
|
display: "block"
|
|
5537
5605
|
},
|
|
5538
5606
|
"&light .cm-activeLine": { backgroundColor: "#cceeff44" },
|
|
@@ -8804,6 +8872,11 @@ class HoverTooltipHost {
|
|
|
8804
8872
|
update(update) {
|
|
8805
8873
|
this.manager.update(update);
|
|
8806
8874
|
}
|
|
8875
|
+
destroy() {
|
|
8876
|
+
var _a;
|
|
8877
|
+
for (let t of this.manager.tooltipViews)
|
|
8878
|
+
(_a = t.destroy) === null || _a === void 0 ? void 0 : _a.call(t);
|
|
8879
|
+
}
|
|
8807
8880
|
}
|
|
8808
8881
|
const showHoverTooltipHost = /*@__PURE__*/showTooltip.compute([showHoverTooltip], state => {
|
|
8809
8882
|
let tooltips = state.facet(showHoverTooltip).filter(t => t);
|