@codemirror/view 0.19.39 → 0.19.40
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 +78 -30
- package/dist/index.d.ts +1 -1
- package/dist/index.js +78 -30
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## 0.19.40 (2022-01-19)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Make composition input properly appear at secondary cursors (except when those are in the DOM node with the composition, in which case the browser won't allow us to intervene without aborting the composition).
|
|
6
|
+
|
|
7
|
+
Fix a bug that cause the editor to get confused about which content was visible after scrolling something into view.
|
|
8
|
+
|
|
9
|
+
Fix a bug where the dummy elements rendered around widgets could end up in a separate set of wrapping marks, and thus become visible.
|
|
10
|
+
|
|
11
|
+
`EditorView.moveVertically` now preserves the `assoc` property of the input range.
|
|
12
|
+
|
|
13
|
+
Get rid of gaps between selection elements drawn by `drawSelection`.
|
|
14
|
+
|
|
15
|
+
Fix an issue where replacing text next to a widget might leak bogus zero-width spaces into the document.
|
|
16
|
+
|
|
17
|
+
Avoid browser selection mishandling when a focused view has `setState` called by eagerly refocusing it.
|
|
18
|
+
|
|
1
19
|
## 0.19.39 (2022-01-06)
|
|
2
20
|
|
|
3
21
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -1237,7 +1237,7 @@ function widgetsEq(a, b) {
|
|
|
1237
1237
|
}
|
|
1238
1238
|
function addRange(from, to, ranges, margin = 0) {
|
|
1239
1239
|
let last = ranges.length - 1;
|
|
1240
|
-
if (last >= 0 && ranges[last] + margin
|
|
1240
|
+
if (last >= 0 && ranges[last] + margin >= from)
|
|
1241
1241
|
ranges[last] = Math.max(ranges[last], to);
|
|
1242
1242
|
else
|
|
1243
1243
|
ranges.push(from, to);
|
|
@@ -1518,7 +1518,7 @@ class ContentBuilder {
|
|
|
1518
1518
|
}
|
|
1519
1519
|
}
|
|
1520
1520
|
let take = Math.min(this.text.length - this.textOff, length, 512 /* Chunk */);
|
|
1521
|
-
this.flushBuffer(active);
|
|
1521
|
+
this.flushBuffer(active.slice(0, openStart));
|
|
1522
1522
|
this.getLine().append(wrapMarks(new TextView(this.text.slice(this.textOff, this.textOff + take)), active), openStart);
|
|
1523
1523
|
this.atCursorPos = true;
|
|
1524
1524
|
this.textOff += take;
|
|
@@ -2332,6 +2332,15 @@ class DOMReader {
|
|
|
2332
2332
|
this.findPointBefore(parent, end);
|
|
2333
2333
|
return this;
|
|
2334
2334
|
}
|
|
2335
|
+
readTextNode(node) {
|
|
2336
|
+
var _a, _b;
|
|
2337
|
+
let text = node.nodeValue;
|
|
2338
|
+
if (/^\u200b/.test(text) && ((_a = node.previousSibling) === null || _a === void 0 ? void 0 : _a.contentEditable) == "false")
|
|
2339
|
+
text = text.slice(1);
|
|
2340
|
+
if (/\u200b$/.test(text) && ((_b = node.nextSibling) === null || _b === void 0 ? void 0 : _b.contentEditable) == "false")
|
|
2341
|
+
text = text.slice(0, text.length - 1);
|
|
2342
|
+
return text;
|
|
2343
|
+
}
|
|
2335
2344
|
readNode(node) {
|
|
2336
2345
|
if (node.cmIgnore)
|
|
2337
2346
|
return;
|
|
@@ -2341,7 +2350,7 @@ class DOMReader {
|
|
|
2341
2350
|
if (fromView != null)
|
|
2342
2351
|
text = fromView.sliceString(0, undefined, this.lineBreak);
|
|
2343
2352
|
else if (node.nodeType == 3)
|
|
2344
|
-
text = node
|
|
2353
|
+
text = this.readTextNode(node);
|
|
2345
2354
|
else if (node.nodeName == "BR")
|
|
2346
2355
|
text = node.nextSibling ? this.lineBreak : "";
|
|
2347
2356
|
else if (node.nodeType == 1)
|
|
@@ -2768,39 +2777,45 @@ class BlockGapWidget extends WidgetType {
|
|
|
2768
2777
|
}
|
|
2769
2778
|
get estimatedHeight() { return this.height; }
|
|
2770
2779
|
}
|
|
2771
|
-
function
|
|
2780
|
+
function compositionSurroundingNode(view) {
|
|
2772
2781
|
let sel = view.observer.selectionRange;
|
|
2773
2782
|
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
2774
2783
|
if (!textNode)
|
|
2775
|
-
return
|
|
2784
|
+
return null;
|
|
2776
2785
|
let cView = view.docView.nearest(textNode);
|
|
2777
2786
|
if (!cView)
|
|
2778
|
-
return
|
|
2779
|
-
let from, to, topNode = textNode;
|
|
2787
|
+
return null;
|
|
2780
2788
|
if (cView instanceof LineView) {
|
|
2789
|
+
let topNode = textNode;
|
|
2781
2790
|
while (topNode.parentNode != cView.dom)
|
|
2782
2791
|
topNode = topNode.parentNode;
|
|
2783
2792
|
let prev = topNode.previousSibling;
|
|
2784
2793
|
while (prev && !ContentView.get(prev))
|
|
2785
2794
|
prev = prev.previousSibling;
|
|
2786
|
-
|
|
2795
|
+
let pos = prev ? ContentView.get(prev).posAtEnd : cView.posAtStart;
|
|
2796
|
+
return { from: pos, to: pos, node: topNode, text: textNode };
|
|
2787
2797
|
}
|
|
2788
2798
|
else {
|
|
2789
2799
|
for (;;) {
|
|
2790
2800
|
let { parent } = cView;
|
|
2791
2801
|
if (!parent)
|
|
2792
|
-
return
|
|
2802
|
+
return null;
|
|
2793
2803
|
if (parent instanceof LineView)
|
|
2794
2804
|
break;
|
|
2795
2805
|
cView = parent;
|
|
2796
2806
|
}
|
|
2797
|
-
from = cView.posAtStart;
|
|
2798
|
-
|
|
2799
|
-
topNode = cView.dom;
|
|
2807
|
+
let from = cView.posAtStart;
|
|
2808
|
+
return { from, to: from + cView.length, node: cView.dom, text: textNode };
|
|
2800
2809
|
}
|
|
2810
|
+
}
|
|
2811
|
+
function computeCompositionDeco(view, changes) {
|
|
2812
|
+
let surrounding = compositionSurroundingNode(view);
|
|
2813
|
+
if (!surrounding)
|
|
2814
|
+
return Decoration.none;
|
|
2815
|
+
let { from, to, node, text: textNode } = surrounding;
|
|
2801
2816
|
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
2802
|
-
let { state } = view, text =
|
|
2803
|
-
new DOMReader([], view).readRange(
|
|
2817
|
+
let { state } = view, text = node.nodeType == 3 ? node.nodeValue :
|
|
2818
|
+
new DOMReader([], view).readRange(node.firstChild, null).text;
|
|
2804
2819
|
if (newTo - newFrom < text.length) {
|
|
2805
2820
|
if (state.sliceDoc(newFrom, Math.min(state.doc.length, newFrom + text.length)) == text)
|
|
2806
2821
|
newTo = newFrom + text.length;
|
|
@@ -2812,7 +2827,7 @@ function computeCompositionDeco(view, changes) {
|
|
|
2812
2827
|
else if (state.sliceDoc(newFrom, newTo) != text) {
|
|
2813
2828
|
return Decoration.none;
|
|
2814
2829
|
}
|
|
2815
|
-
return Decoration.set(Decoration.replace({ widget: new CompositionWidget(
|
|
2830
|
+
return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode) }).range(newFrom, newTo));
|
|
2816
2831
|
}
|
|
2817
2832
|
class CompositionWidget extends WidgetType {
|
|
2818
2833
|
constructor(top, text) {
|
|
@@ -3149,7 +3164,7 @@ function byGroup(view, pos, start) {
|
|
|
3149
3164
|
function moveVertically(view, start, forward, distance) {
|
|
3150
3165
|
let startPos = start.head, dir = forward ? 1 : -1;
|
|
3151
3166
|
if (startPos == (forward ? view.state.doc.length : 0))
|
|
3152
|
-
return state.EditorSelection.cursor(startPos);
|
|
3167
|
+
return state.EditorSelection.cursor(startPos, start.assoc);
|
|
3153
3168
|
let goal = start.goalColumn, startY;
|
|
3154
3169
|
let rect = view.contentDOM.getBoundingClientRect();
|
|
3155
3170
|
let startCoords = view.coordsAtPos(startPos), docTop = view.documentTop;
|
|
@@ -3170,7 +3185,7 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3170
3185
|
let curY = startY + (dist + extra) * dir;
|
|
3171
3186
|
let pos = posAtCoords(view, { x: resolvedGoal, y: curY }, false, dir);
|
|
3172
3187
|
if (curY < rect.top || curY > rect.bottom || (dir < 0 ? pos < startPos : pos > startPos))
|
|
3173
|
-
return state.EditorSelection.cursor(pos,
|
|
3188
|
+
return state.EditorSelection.cursor(pos, start.assoc, undefined, goal);
|
|
3174
3189
|
}
|
|
3175
3190
|
}
|
|
3176
3191
|
function skipAtoms(view, oldPos, pos) {
|
|
@@ -4694,7 +4709,8 @@ class ViewState {
|
|
|
4694
4709
|
}
|
|
4695
4710
|
}
|
|
4696
4711
|
// Pixel viewport
|
|
4697
|
-
let pixelViewport = this.printing ? { top: -1e8, bottom: 1e8, left: -1e8, right: 1e8 }
|
|
4712
|
+
let pixelViewport = this.printing ? { top: -1e8, bottom: 1e8, left: -1e8, right: 1e8 }
|
|
4713
|
+
: visiblePixelRange(dom, this.paddingTop);
|
|
4698
4714
|
let dTop = pixelViewport.top - this.pixelViewport.top, dBottom = pixelViewport.bottom - this.pixelViewport.bottom;
|
|
4699
4715
|
this.pixelViewport = pixelViewport;
|
|
4700
4716
|
let inView = this.pixelViewport.bottom > this.pixelViewport.top && this.pixelViewport.right > this.pixelViewport.left;
|
|
@@ -5637,19 +5653,47 @@ function applyDOMChange(view, start, end, typeOver) {
|
|
|
5637
5653
|
view.inputState.composing++;
|
|
5638
5654
|
let tr;
|
|
5639
5655
|
if (change.from >= sel.from && change.to <= sel.to && change.to - change.from >= (sel.to - sel.from) / 3 &&
|
|
5640
|
-
(!newSel || newSel.main.empty && newSel.main.from == change.from + change.insert.length)
|
|
5656
|
+
(!newSel || newSel.main.empty && newSel.main.from == change.from + change.insert.length) &&
|
|
5657
|
+
view.inputState.composing < 0) {
|
|
5641
5658
|
let before = sel.from < change.from ? startState.sliceDoc(sel.from, change.from) : "";
|
|
5642
5659
|
let after = sel.to > change.to ? startState.sliceDoc(change.to, sel.to) : "";
|
|
5643
|
-
tr = startState.replaceSelection(view.state.toText(before + change.insert.sliceString(0, undefined, view.state.lineBreak) +
|
|
5644
|
-
after));
|
|
5660
|
+
tr = startState.replaceSelection(view.state.toText(before + change.insert.sliceString(0, undefined, view.state.lineBreak) + after));
|
|
5645
5661
|
}
|
|
5646
5662
|
else {
|
|
5647
5663
|
let changes = startState.changes(change);
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5664
|
+
let mainSel = newSel && !startState.selection.main.eq(newSel.main) && newSel.main.to <= changes.newLength
|
|
5665
|
+
? newSel.main : undefined;
|
|
5666
|
+
// Try to apply a composition change to all cursors
|
|
5667
|
+
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
5668
|
+
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
5669
|
+
let replaced = view.state.sliceDoc(change.from, change.to);
|
|
5670
|
+
let compositionRange = compositionSurroundingNode(view) || view.state.doc.lineAt(sel.head);
|
|
5671
|
+
let offset = sel.to - change.to, size = sel.to - sel.from;
|
|
5672
|
+
tr = startState.changeByRange(range => {
|
|
5673
|
+
if (range.from == sel.from && range.to == sel.to)
|
|
5674
|
+
return { changes, range: mainSel || range.map(changes) };
|
|
5675
|
+
let to = range.to - offset, from = to - replaced.length;
|
|
5676
|
+
if (range.to - range.from != size || view.state.sliceDoc(from, to) != replaced ||
|
|
5677
|
+
// Unfortunately, there's no way to make multiple
|
|
5678
|
+
// changes in the same node work without aborting
|
|
5679
|
+
// composition, so cursors in the composition range are
|
|
5680
|
+
// ignored.
|
|
5681
|
+
compositionRange && range.to >= compositionRange.from && range.from <= compositionRange.to)
|
|
5682
|
+
return { range };
|
|
5683
|
+
let rangeChanges = startState.changes({ from, to, insert: change.insert }), selOff = range.to - sel.to;
|
|
5684
|
+
return {
|
|
5685
|
+
changes: rangeChanges,
|
|
5686
|
+
range: !mainSel ? range.map(rangeChanges) :
|
|
5687
|
+
state.EditorSelection.range(Math.max(0, mainSel.anchor + selOff), Math.max(0, mainSel.head + selOff))
|
|
5688
|
+
};
|
|
5689
|
+
});
|
|
5690
|
+
}
|
|
5691
|
+
else {
|
|
5692
|
+
tr = {
|
|
5693
|
+
changes,
|
|
5694
|
+
selection: mainSel && startState.selection.replaceRange(mainSel)
|
|
5695
|
+
};
|
|
5696
|
+
}
|
|
5653
5697
|
}
|
|
5654
5698
|
let userEvent = "input.type";
|
|
5655
5699
|
if (view.composing) {
|
|
@@ -5920,6 +5964,7 @@ class EditorView {
|
|
|
5920
5964
|
return;
|
|
5921
5965
|
}
|
|
5922
5966
|
this.updateState = 2 /* Updating */;
|
|
5967
|
+
let hadFocus = this.hasFocus;
|
|
5923
5968
|
try {
|
|
5924
5969
|
for (let plugin of this.plugins)
|
|
5925
5970
|
plugin.destroy(this);
|
|
@@ -5937,6 +5982,8 @@ class EditorView {
|
|
|
5937
5982
|
finally {
|
|
5938
5983
|
this.updateState = 0 /* Idle */;
|
|
5939
5984
|
}
|
|
5985
|
+
if (hadFocus)
|
|
5986
|
+
this.focus();
|
|
5940
5987
|
this.requestMeasure();
|
|
5941
5988
|
}
|
|
5942
5989
|
updatePlugins(update) {
|
|
@@ -6006,7 +6053,7 @@ class EditorView {
|
|
|
6006
6053
|
return BadMeasure;
|
|
6007
6054
|
}
|
|
6008
6055
|
});
|
|
6009
|
-
let update = new ViewUpdate(this, this.state), redrawn = false;
|
|
6056
|
+
let update = new ViewUpdate(this, this.state), redrawn = false, scrolled = false;
|
|
6010
6057
|
update.flags |= changed;
|
|
6011
6058
|
if (!updated)
|
|
6012
6059
|
updated = update;
|
|
@@ -6033,11 +6080,12 @@ class EditorView {
|
|
|
6033
6080
|
if (this.viewState.scrollTarget) {
|
|
6034
6081
|
this.docView.scrollIntoView(this.viewState.scrollTarget);
|
|
6035
6082
|
this.viewState.scrollTarget = null;
|
|
6083
|
+
scrolled = true;
|
|
6036
6084
|
}
|
|
6037
6085
|
if (redrawn)
|
|
6038
6086
|
this.docView.updateSelection(true);
|
|
6039
6087
|
if (this.viewport.from == oldViewport.from && this.viewport.to == oldViewport.to &&
|
|
6040
|
-
this.measureRequests.length == 0)
|
|
6088
|
+
!scrolled && this.measureRequests.length == 0)
|
|
6041
6089
|
break;
|
|
6042
6090
|
}
|
|
6043
6091
|
}
|
|
@@ -6173,7 +6221,7 @@ class EditorView {
|
|
|
6173
6221
|
(`view.contentDOM.getBoundingClientRect().top`) to limit layout
|
|
6174
6222
|
queries.
|
|
6175
6223
|
|
|
6176
|
-
*Deprecated: use `
|
|
6224
|
+
*Deprecated: use `elementAtHeight` instead.*
|
|
6177
6225
|
*/
|
|
6178
6226
|
blockAtHeight(height, docTop) {
|
|
6179
6227
|
let top = ensureTop(docTop, this);
|
|
@@ -7018,7 +7066,7 @@ function measureRange(view, range) {
|
|
|
7018
7066
|
return pieces(top).concat(between).concat(pieces(bottom));
|
|
7019
7067
|
}
|
|
7020
7068
|
function piece(left, top, right, bottom) {
|
|
7021
|
-
return new Piece(left - base.left, top - base.top
|
|
7069
|
+
return new Piece(left - base.left, top - base.top - 0.01 /* Epsilon */, right - left, bottom - top + 0.01 /* Epsilon */, "cm-selectionBackground");
|
|
7022
7070
|
}
|
|
7023
7071
|
function pieces({ top, bottom, horizontal }) {
|
|
7024
7072
|
let pieces = [];
|
package/dist/index.d.ts
CHANGED
|
@@ -802,7 +802,7 @@ declare class EditorView {
|
|
|
802
802
|
(`view.contentDOM.getBoundingClientRect().top`) to limit layout
|
|
803
803
|
queries.
|
|
804
804
|
|
|
805
|
-
*Deprecated: use `
|
|
805
|
+
*Deprecated: use `elementAtHeight` instead.*
|
|
806
806
|
*/
|
|
807
807
|
blockAtHeight(height: number, docTop?: number): BlockInfo;
|
|
808
808
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1233,7 +1233,7 @@ function widgetsEq(a, b) {
|
|
|
1233
1233
|
}
|
|
1234
1234
|
function addRange(from, to, ranges, margin = 0) {
|
|
1235
1235
|
let last = ranges.length - 1;
|
|
1236
|
-
if (last >= 0 && ranges[last] + margin
|
|
1236
|
+
if (last >= 0 && ranges[last] + margin >= from)
|
|
1237
1237
|
ranges[last] = Math.max(ranges[last], to);
|
|
1238
1238
|
else
|
|
1239
1239
|
ranges.push(from, to);
|
|
@@ -1514,7 +1514,7 @@ class ContentBuilder {
|
|
|
1514
1514
|
}
|
|
1515
1515
|
}
|
|
1516
1516
|
let take = Math.min(this.text.length - this.textOff, length, 512 /* Chunk */);
|
|
1517
|
-
this.flushBuffer(active);
|
|
1517
|
+
this.flushBuffer(active.slice(0, openStart));
|
|
1518
1518
|
this.getLine().append(wrapMarks(new TextView(this.text.slice(this.textOff, this.textOff + take)), active), openStart);
|
|
1519
1519
|
this.atCursorPos = true;
|
|
1520
1520
|
this.textOff += take;
|
|
@@ -2327,6 +2327,15 @@ class DOMReader {
|
|
|
2327
2327
|
this.findPointBefore(parent, end);
|
|
2328
2328
|
return this;
|
|
2329
2329
|
}
|
|
2330
|
+
readTextNode(node) {
|
|
2331
|
+
var _a, _b;
|
|
2332
|
+
let text = node.nodeValue;
|
|
2333
|
+
if (/^\u200b/.test(text) && ((_a = node.previousSibling) === null || _a === void 0 ? void 0 : _a.contentEditable) == "false")
|
|
2334
|
+
text = text.slice(1);
|
|
2335
|
+
if (/\u200b$/.test(text) && ((_b = node.nextSibling) === null || _b === void 0 ? void 0 : _b.contentEditable) == "false")
|
|
2336
|
+
text = text.slice(0, text.length - 1);
|
|
2337
|
+
return text;
|
|
2338
|
+
}
|
|
2330
2339
|
readNode(node) {
|
|
2331
2340
|
if (node.cmIgnore)
|
|
2332
2341
|
return;
|
|
@@ -2336,7 +2345,7 @@ class DOMReader {
|
|
|
2336
2345
|
if (fromView != null)
|
|
2337
2346
|
text = fromView.sliceString(0, undefined, this.lineBreak);
|
|
2338
2347
|
else if (node.nodeType == 3)
|
|
2339
|
-
text = node
|
|
2348
|
+
text = this.readTextNode(node);
|
|
2340
2349
|
else if (node.nodeName == "BR")
|
|
2341
2350
|
text = node.nextSibling ? this.lineBreak : "";
|
|
2342
2351
|
else if (node.nodeType == 1)
|
|
@@ -2763,39 +2772,45 @@ class BlockGapWidget extends WidgetType {
|
|
|
2763
2772
|
}
|
|
2764
2773
|
get estimatedHeight() { return this.height; }
|
|
2765
2774
|
}
|
|
2766
|
-
function
|
|
2775
|
+
function compositionSurroundingNode(view) {
|
|
2767
2776
|
let sel = view.observer.selectionRange;
|
|
2768
2777
|
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
2769
2778
|
if (!textNode)
|
|
2770
|
-
return
|
|
2779
|
+
return null;
|
|
2771
2780
|
let cView = view.docView.nearest(textNode);
|
|
2772
2781
|
if (!cView)
|
|
2773
|
-
return
|
|
2774
|
-
let from, to, topNode = textNode;
|
|
2782
|
+
return null;
|
|
2775
2783
|
if (cView instanceof LineView) {
|
|
2784
|
+
let topNode = textNode;
|
|
2776
2785
|
while (topNode.parentNode != cView.dom)
|
|
2777
2786
|
topNode = topNode.parentNode;
|
|
2778
2787
|
let prev = topNode.previousSibling;
|
|
2779
2788
|
while (prev && !ContentView.get(prev))
|
|
2780
2789
|
prev = prev.previousSibling;
|
|
2781
|
-
|
|
2790
|
+
let pos = prev ? ContentView.get(prev).posAtEnd : cView.posAtStart;
|
|
2791
|
+
return { from: pos, to: pos, node: topNode, text: textNode };
|
|
2782
2792
|
}
|
|
2783
2793
|
else {
|
|
2784
2794
|
for (;;) {
|
|
2785
2795
|
let { parent } = cView;
|
|
2786
2796
|
if (!parent)
|
|
2787
|
-
return
|
|
2797
|
+
return null;
|
|
2788
2798
|
if (parent instanceof LineView)
|
|
2789
2799
|
break;
|
|
2790
2800
|
cView = parent;
|
|
2791
2801
|
}
|
|
2792
|
-
from = cView.posAtStart;
|
|
2793
|
-
|
|
2794
|
-
topNode = cView.dom;
|
|
2802
|
+
let from = cView.posAtStart;
|
|
2803
|
+
return { from, to: from + cView.length, node: cView.dom, text: textNode };
|
|
2795
2804
|
}
|
|
2805
|
+
}
|
|
2806
|
+
function computeCompositionDeco(view, changes) {
|
|
2807
|
+
let surrounding = compositionSurroundingNode(view);
|
|
2808
|
+
if (!surrounding)
|
|
2809
|
+
return Decoration.none;
|
|
2810
|
+
let { from, to, node, text: textNode } = surrounding;
|
|
2796
2811
|
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
2797
|
-
let { state } = view, text =
|
|
2798
|
-
new DOMReader([], view).readRange(
|
|
2812
|
+
let { state } = view, text = node.nodeType == 3 ? node.nodeValue :
|
|
2813
|
+
new DOMReader([], view).readRange(node.firstChild, null).text;
|
|
2799
2814
|
if (newTo - newFrom < text.length) {
|
|
2800
2815
|
if (state.sliceDoc(newFrom, Math.min(state.doc.length, newFrom + text.length)) == text)
|
|
2801
2816
|
newTo = newFrom + text.length;
|
|
@@ -2807,7 +2822,7 @@ function computeCompositionDeco(view, changes) {
|
|
|
2807
2822
|
else if (state.sliceDoc(newFrom, newTo) != text) {
|
|
2808
2823
|
return Decoration.none;
|
|
2809
2824
|
}
|
|
2810
|
-
return Decoration.set(Decoration.replace({ widget: new CompositionWidget(
|
|
2825
|
+
return Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode) }).range(newFrom, newTo));
|
|
2811
2826
|
}
|
|
2812
2827
|
class CompositionWidget extends WidgetType {
|
|
2813
2828
|
constructor(top, text) {
|
|
@@ -3144,7 +3159,7 @@ function byGroup(view, pos, start) {
|
|
|
3144
3159
|
function moveVertically(view, start, forward, distance) {
|
|
3145
3160
|
let startPos = start.head, dir = forward ? 1 : -1;
|
|
3146
3161
|
if (startPos == (forward ? view.state.doc.length : 0))
|
|
3147
|
-
return EditorSelection.cursor(startPos);
|
|
3162
|
+
return EditorSelection.cursor(startPos, start.assoc);
|
|
3148
3163
|
let goal = start.goalColumn, startY;
|
|
3149
3164
|
let rect = view.contentDOM.getBoundingClientRect();
|
|
3150
3165
|
let startCoords = view.coordsAtPos(startPos), docTop = view.documentTop;
|
|
@@ -3165,7 +3180,7 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3165
3180
|
let curY = startY + (dist + extra) * dir;
|
|
3166
3181
|
let pos = posAtCoords(view, { x: resolvedGoal, y: curY }, false, dir);
|
|
3167
3182
|
if (curY < rect.top || curY > rect.bottom || (dir < 0 ? pos < startPos : pos > startPos))
|
|
3168
|
-
return EditorSelection.cursor(pos,
|
|
3183
|
+
return EditorSelection.cursor(pos, start.assoc, undefined, goal);
|
|
3169
3184
|
}
|
|
3170
3185
|
}
|
|
3171
3186
|
function skipAtoms(view, oldPos, pos) {
|
|
@@ -4688,7 +4703,8 @@ class ViewState {
|
|
|
4688
4703
|
}
|
|
4689
4704
|
}
|
|
4690
4705
|
// Pixel viewport
|
|
4691
|
-
let pixelViewport = this.printing ? { top: -1e8, bottom: 1e8, left: -1e8, right: 1e8 }
|
|
4706
|
+
let pixelViewport = this.printing ? { top: -1e8, bottom: 1e8, left: -1e8, right: 1e8 }
|
|
4707
|
+
: visiblePixelRange(dom, this.paddingTop);
|
|
4692
4708
|
let dTop = pixelViewport.top - this.pixelViewport.top, dBottom = pixelViewport.bottom - this.pixelViewport.bottom;
|
|
4693
4709
|
this.pixelViewport = pixelViewport;
|
|
4694
4710
|
let inView = this.pixelViewport.bottom > this.pixelViewport.top && this.pixelViewport.right > this.pixelViewport.left;
|
|
@@ -5631,19 +5647,47 @@ function applyDOMChange(view, start, end, typeOver) {
|
|
|
5631
5647
|
view.inputState.composing++;
|
|
5632
5648
|
let tr;
|
|
5633
5649
|
if (change.from >= sel.from && change.to <= sel.to && change.to - change.from >= (sel.to - sel.from) / 3 &&
|
|
5634
|
-
(!newSel || newSel.main.empty && newSel.main.from == change.from + change.insert.length)
|
|
5650
|
+
(!newSel || newSel.main.empty && newSel.main.from == change.from + change.insert.length) &&
|
|
5651
|
+
view.inputState.composing < 0) {
|
|
5635
5652
|
let before = sel.from < change.from ? startState.sliceDoc(sel.from, change.from) : "";
|
|
5636
5653
|
let after = sel.to > change.to ? startState.sliceDoc(change.to, sel.to) : "";
|
|
5637
|
-
tr = startState.replaceSelection(view.state.toText(before + change.insert.sliceString(0, undefined, view.state.lineBreak) +
|
|
5638
|
-
after));
|
|
5654
|
+
tr = startState.replaceSelection(view.state.toText(before + change.insert.sliceString(0, undefined, view.state.lineBreak) + after));
|
|
5639
5655
|
}
|
|
5640
5656
|
else {
|
|
5641
5657
|
let changes = startState.changes(change);
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5658
|
+
let mainSel = newSel && !startState.selection.main.eq(newSel.main) && newSel.main.to <= changes.newLength
|
|
5659
|
+
? newSel.main : undefined;
|
|
5660
|
+
// Try to apply a composition change to all cursors
|
|
5661
|
+
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
5662
|
+
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
5663
|
+
let replaced = view.state.sliceDoc(change.from, change.to);
|
|
5664
|
+
let compositionRange = compositionSurroundingNode(view) || view.state.doc.lineAt(sel.head);
|
|
5665
|
+
let offset = sel.to - change.to, size = sel.to - sel.from;
|
|
5666
|
+
tr = startState.changeByRange(range => {
|
|
5667
|
+
if (range.from == sel.from && range.to == sel.to)
|
|
5668
|
+
return { changes, range: mainSel || range.map(changes) };
|
|
5669
|
+
let to = range.to - offset, from = to - replaced.length;
|
|
5670
|
+
if (range.to - range.from != size || view.state.sliceDoc(from, to) != replaced ||
|
|
5671
|
+
// Unfortunately, there's no way to make multiple
|
|
5672
|
+
// changes in the same node work without aborting
|
|
5673
|
+
// composition, so cursors in the composition range are
|
|
5674
|
+
// ignored.
|
|
5675
|
+
compositionRange && range.to >= compositionRange.from && range.from <= compositionRange.to)
|
|
5676
|
+
return { range };
|
|
5677
|
+
let rangeChanges = startState.changes({ from, to, insert: change.insert }), selOff = range.to - sel.to;
|
|
5678
|
+
return {
|
|
5679
|
+
changes: rangeChanges,
|
|
5680
|
+
range: !mainSel ? range.map(rangeChanges) :
|
|
5681
|
+
EditorSelection.range(Math.max(0, mainSel.anchor + selOff), Math.max(0, mainSel.head + selOff))
|
|
5682
|
+
};
|
|
5683
|
+
});
|
|
5684
|
+
}
|
|
5685
|
+
else {
|
|
5686
|
+
tr = {
|
|
5687
|
+
changes,
|
|
5688
|
+
selection: mainSel && startState.selection.replaceRange(mainSel)
|
|
5689
|
+
};
|
|
5690
|
+
}
|
|
5647
5691
|
}
|
|
5648
5692
|
let userEvent = "input.type";
|
|
5649
5693
|
if (view.composing) {
|
|
@@ -5914,6 +5958,7 @@ class EditorView {
|
|
|
5914
5958
|
return;
|
|
5915
5959
|
}
|
|
5916
5960
|
this.updateState = 2 /* Updating */;
|
|
5961
|
+
let hadFocus = this.hasFocus;
|
|
5917
5962
|
try {
|
|
5918
5963
|
for (let plugin of this.plugins)
|
|
5919
5964
|
plugin.destroy(this);
|
|
@@ -5931,6 +5976,8 @@ class EditorView {
|
|
|
5931
5976
|
finally {
|
|
5932
5977
|
this.updateState = 0 /* Idle */;
|
|
5933
5978
|
}
|
|
5979
|
+
if (hadFocus)
|
|
5980
|
+
this.focus();
|
|
5934
5981
|
this.requestMeasure();
|
|
5935
5982
|
}
|
|
5936
5983
|
updatePlugins(update) {
|
|
@@ -6000,7 +6047,7 @@ class EditorView {
|
|
|
6000
6047
|
return BadMeasure;
|
|
6001
6048
|
}
|
|
6002
6049
|
});
|
|
6003
|
-
let update = new ViewUpdate(this, this.state), redrawn = false;
|
|
6050
|
+
let update = new ViewUpdate(this, this.state), redrawn = false, scrolled = false;
|
|
6004
6051
|
update.flags |= changed;
|
|
6005
6052
|
if (!updated)
|
|
6006
6053
|
updated = update;
|
|
@@ -6027,11 +6074,12 @@ class EditorView {
|
|
|
6027
6074
|
if (this.viewState.scrollTarget) {
|
|
6028
6075
|
this.docView.scrollIntoView(this.viewState.scrollTarget);
|
|
6029
6076
|
this.viewState.scrollTarget = null;
|
|
6077
|
+
scrolled = true;
|
|
6030
6078
|
}
|
|
6031
6079
|
if (redrawn)
|
|
6032
6080
|
this.docView.updateSelection(true);
|
|
6033
6081
|
if (this.viewport.from == oldViewport.from && this.viewport.to == oldViewport.to &&
|
|
6034
|
-
this.measureRequests.length == 0)
|
|
6082
|
+
!scrolled && this.measureRequests.length == 0)
|
|
6035
6083
|
break;
|
|
6036
6084
|
}
|
|
6037
6085
|
}
|
|
@@ -6167,7 +6215,7 @@ class EditorView {
|
|
|
6167
6215
|
(`view.contentDOM.getBoundingClientRect().top`) to limit layout
|
|
6168
6216
|
queries.
|
|
6169
6217
|
|
|
6170
|
-
*Deprecated: use `
|
|
6218
|
+
*Deprecated: use `elementAtHeight` instead.*
|
|
6171
6219
|
*/
|
|
6172
6220
|
blockAtHeight(height, docTop) {
|
|
6173
6221
|
let top = ensureTop(docTop, this);
|
|
@@ -7012,7 +7060,7 @@ function measureRange(view, range) {
|
|
|
7012
7060
|
return pieces(top).concat(between).concat(pieces(bottom));
|
|
7013
7061
|
}
|
|
7014
7062
|
function piece(left, top, right, bottom) {
|
|
7015
|
-
return new Piece(left - base.left, top - base.top
|
|
7063
|
+
return new Piece(left - base.left, top - base.top - 0.01 /* Epsilon */, right - left, bottom - top + 0.01 /* Epsilon */, "cm-selectionBackground");
|
|
7016
7064
|
}
|
|
7017
7065
|
function pieces({ top, bottom, horizontal }) {
|
|
7018
7066
|
let pieces = [];
|