@codemirror/view 6.14.0 → 6.14.1
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 +14 -0
- package/dist/index.cjs +55 -45
- package/dist/index.js +55 -45
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 6.14.1 (2023-07-06)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix an issue where scrolling up through line-wrapped text would sometimes cause the scroll position to pop down.
|
|
6
|
+
|
|
7
|
+
Fix an issue where clicking wouldn't focus the editor on Firefox when it was in an iframe and already the active element of the frame.
|
|
8
|
+
|
|
9
|
+
Fix a bug that could cause compositions to be disrupted because their surrounding DOM was repurposed for some other piece of content.
|
|
10
|
+
|
|
11
|
+
Fix a bug where adding content to the editor could inappropriately move the scroll position.
|
|
12
|
+
|
|
13
|
+
Extend detection of Enter presses on Android to `beforeInput` events with an `"insertLineBreak"` type.
|
|
14
|
+
|
|
1
15
|
## 6.14.0 (2023-06-23)
|
|
2
16
|
|
|
3
17
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -320,6 +320,9 @@ function atElementStart(doc, selection) {
|
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
|
+
function isScrolledToBottom(elt) {
|
|
324
|
+
return elt.scrollTop > Math.max(1, elt.scrollHeight - elt.clientHeight - 4);
|
|
325
|
+
}
|
|
323
326
|
|
|
324
327
|
class DOMPos {
|
|
325
328
|
constructor(node, offset, precise = true) {
|
|
@@ -362,7 +365,7 @@ class ContentView {
|
|
|
362
365
|
let prev = null, next;
|
|
363
366
|
for (let child of this.children) {
|
|
364
367
|
if (child.dirty) {
|
|
365
|
-
if (!child.dom && (next = prev ? prev.nextSibling : parent.firstChild)) {
|
|
368
|
+
if (!child.dom && (next = prev ? prev.nextSibling : parent.firstChild) && next != view.docView.compositionNode) {
|
|
366
369
|
let contentView = ContentView.get(next);
|
|
367
370
|
if (!contentView || !contentView.parent && contentView.canReuseDOM(child))
|
|
368
371
|
child.reuseDOM(next);
|
|
@@ -2601,6 +2604,7 @@ class DocView extends ContentView {
|
|
|
2601
2604
|
super();
|
|
2602
2605
|
this.view = view;
|
|
2603
2606
|
this.compositionDeco = Decoration.none;
|
|
2607
|
+
this.compositionNode = null;
|
|
2604
2608
|
this.decorations = [];
|
|
2605
2609
|
this.dynamicDecorationMap = [];
|
|
2606
2610
|
// Track a minimum width for the editor. When measuring sizes in
|
|
@@ -2640,10 +2644,8 @@ class DocView extends ContentView {
|
|
|
2640
2644
|
this.minWidthTo = update.changes.mapPos(this.minWidthTo, 1);
|
|
2641
2645
|
}
|
|
2642
2646
|
}
|
|
2643
|
-
|
|
2644
|
-
this.
|
|
2645
|
-
else if (update.transactions.length || this.dirty)
|
|
2646
|
-
this.compositionDeco = computeCompositionDeco(this.view, update.changes);
|
|
2647
|
+
({ deco: this.compositionDeco, node: this.compositionNode } =
|
|
2648
|
+
this.view.inputState.composing < 0 ? noComp : computeCompositionDeco(this.view, update.changes));
|
|
2647
2649
|
// When the DOM nodes around the selection are moved to another
|
|
2648
2650
|
// parent, Chrome sometimes reports a different selection through
|
|
2649
2651
|
// getSelection than the one that it actually shows to the user.
|
|
@@ -3031,10 +3033,11 @@ function compositionSurroundingNode(view) {
|
|
|
3031
3033
|
return { from, to: from + cView.length, node: cView.dom, text: textNode };
|
|
3032
3034
|
}
|
|
3033
3035
|
}
|
|
3036
|
+
const noComp = { deco: Decoration.none, node: null };
|
|
3034
3037
|
function computeCompositionDeco(view, changes) {
|
|
3035
3038
|
let surrounding = compositionSurroundingNode(view);
|
|
3036
3039
|
if (!surrounding)
|
|
3037
|
-
return
|
|
3040
|
+
return noComp;
|
|
3038
3041
|
let { from, to, node, text: textNode } = surrounding;
|
|
3039
3042
|
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
3040
3043
|
let { state } = view, reader = new DOMReader([], state);
|
|
@@ -3044,25 +3047,26 @@ function computeCompositionDeco(view, changes) {
|
|
|
3044
3047
|
reader.readRange(node.firstChild, null);
|
|
3045
3048
|
let { text } = reader;
|
|
3046
3049
|
if (text.indexOf(LineBreakPlaceholder) > -1)
|
|
3047
|
-
return
|
|
3050
|
+
return noComp; // Don't try to preserve multi-line compositions
|
|
3048
3051
|
if (newTo - newFrom < text.length) {
|
|
3049
3052
|
if (state.doc.sliceString(newFrom, Math.min(state.doc.length, newFrom + text.length)) == text)
|
|
3050
3053
|
newTo = newFrom + text.length;
|
|
3051
3054
|
else if (state.doc.sliceString(Math.max(0, newTo - text.length), newTo) == text)
|
|
3052
3055
|
newFrom = newTo - text.length;
|
|
3053
3056
|
else
|
|
3054
|
-
return
|
|
3057
|
+
return noComp;
|
|
3055
3058
|
}
|
|
3056
3059
|
else if (state.doc.sliceString(newFrom, newTo) != text) {
|
|
3057
|
-
return
|
|
3060
|
+
return noComp;
|
|
3058
3061
|
}
|
|
3059
3062
|
let topView = ContentView.get(node);
|
|
3060
3063
|
if (topView instanceof CompositionView)
|
|
3061
3064
|
topView = topView.widget.topView;
|
|
3062
3065
|
else if (topView)
|
|
3063
3066
|
topView.parent = null;
|
|
3064
|
-
|
|
3067
|
+
let deco = Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode, topView), inclusive: true })
|
|
3065
3068
|
.range(newFrom, newTo));
|
|
3069
|
+
return { deco, node };
|
|
3066
3070
|
}
|
|
3067
3071
|
class CompositionWidget extends WidgetType {
|
|
3068
3072
|
constructor(top, text, topView) {
|
|
@@ -3725,6 +3729,7 @@ class InputState {
|
|
|
3725
3729
|
const PendingKeys = [
|
|
3726
3730
|
{ key: "Backspace", keyCode: 8, inputType: "deleteContentBackward" },
|
|
3727
3731
|
{ key: "Enter", keyCode: 13, inputType: "insertParagraph" },
|
|
3732
|
+
{ key: "Enter", keyCode: 13, inputType: "insertLineBreak" },
|
|
3728
3733
|
{ key: "Delete", keyCode: 46, inputType: "deleteContentForward" }
|
|
3729
3734
|
];
|
|
3730
3735
|
const EmacsyPendingKeys = "dthko";
|
|
@@ -3969,7 +3974,7 @@ handlers.mousedown = (view, event) => {
|
|
|
3969
3974
|
if (!style && event.button == 0)
|
|
3970
3975
|
style = basicMouseSelection(view, event);
|
|
3971
3976
|
if (style) {
|
|
3972
|
-
let mustFocus = view.
|
|
3977
|
+
let mustFocus = !view.hasFocus;
|
|
3973
3978
|
view.inputState.startMouseSelection(new MouseSelection(view, event, style, mustFocus));
|
|
3974
3979
|
if (mustFocus)
|
|
3975
3980
|
view.observer.ignore(() => focusPreventScroll(view.contentDOM));
|
|
@@ -5166,7 +5171,7 @@ class ViewState {
|
|
|
5166
5171
|
let contentChanges = update.changedRanges;
|
|
5167
5172
|
let heightChanges = ChangedRange.extendWithRanges(contentChanges, heightRelevantDecoChanges(prevDeco, this.stateDeco, update ? update.changes : state.ChangeSet.empty(this.state.doc.length)));
|
|
5168
5173
|
let prevHeight = this.heightMap.height;
|
|
5169
|
-
let scrollAnchor = this.scrolledToBottom ? null : this.
|
|
5174
|
+
let scrollAnchor = this.scrolledToBottom ? null : this.scrollAnchorAt(this.scrollTop);
|
|
5170
5175
|
this.heightMap = this.heightMap.applyChanges(this.stateDeco, update.startState.doc, this.heightOracle.setDoc(this.state.doc), heightChanges);
|
|
5171
5176
|
if (this.heightMap.height != prevHeight)
|
|
5172
5177
|
update.flags |= 2 /* Height */;
|
|
@@ -5226,7 +5231,7 @@ class ViewState {
|
|
|
5226
5231
|
this.scrollAnchorHeight = -1;
|
|
5227
5232
|
this.scrollTop = view.scrollDOM.scrollTop;
|
|
5228
5233
|
}
|
|
5229
|
-
this.scrolledToBottom =
|
|
5234
|
+
this.scrolledToBottom = isScrolledToBottom(view.scrollDOM);
|
|
5230
5235
|
// Pixel viewport
|
|
5231
5236
|
let pixelViewport = (this.printing ? fullPixelRange : visiblePixelRange)(dom, this.paddingTop);
|
|
5232
5237
|
let dTop = pixelViewport.top - this.pixelViewport.top, dBottom = pixelViewport.bottom - this.pixelViewport.bottom;
|
|
@@ -5469,6 +5474,10 @@ class ViewState {
|
|
|
5469
5474
|
lineBlockAtHeight(height) {
|
|
5470
5475
|
return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height), QueryType.ByHeight, this.heightOracle, 0, 0), this.scaler);
|
|
5471
5476
|
}
|
|
5477
|
+
scrollAnchorAt(scrollTop) {
|
|
5478
|
+
let block = this.lineBlockAtHeight(scrollTop + 8);
|
|
5479
|
+
return block.from >= this.viewport.from || this.viewportLines[0].top - scrollTop > 200 ? block : this.viewportLines[0];
|
|
5480
|
+
}
|
|
5472
5481
|
elementAtHeight(height) {
|
|
5473
5482
|
return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height), this.heightOracle, 0, 0), this.scaler);
|
|
5474
5483
|
}
|
|
@@ -6841,22 +6850,23 @@ class EditorView {
|
|
|
6841
6850
|
let updated = null;
|
|
6842
6851
|
let sDOM = this.scrollDOM, { scrollTop } = sDOM;
|
|
6843
6852
|
let { scrollAnchorPos, scrollAnchorHeight } = this.viewState;
|
|
6853
|
+
if (scrollTop != this.viewState.scrollTop)
|
|
6854
|
+
scrollAnchorHeight = -1;
|
|
6844
6855
|
this.viewState.scrollAnchorHeight = -1;
|
|
6845
|
-
if (scrollAnchorHeight < 0 || scrollTop != this.viewState.scrollTop) {
|
|
6846
|
-
if (scrollTop > sDOM.scrollHeight - sDOM.clientHeight - 4) {
|
|
6847
|
-
scrollAnchorPos = -1;
|
|
6848
|
-
scrollAnchorHeight = this.viewState.heightMap.height;
|
|
6849
|
-
}
|
|
6850
|
-
else {
|
|
6851
|
-
let block = this.viewState.lineBlockAtHeight(scrollTop);
|
|
6852
|
-
scrollAnchorPos = block.from;
|
|
6853
|
-
scrollAnchorHeight = block.top;
|
|
6854
|
-
}
|
|
6855
|
-
}
|
|
6856
6856
|
try {
|
|
6857
6857
|
for (let i = 0;; i++) {
|
|
6858
|
+
if (scrollAnchorHeight < 0) {
|
|
6859
|
+
if (isScrolledToBottom(sDOM)) {
|
|
6860
|
+
scrollAnchorPos = -1;
|
|
6861
|
+
scrollAnchorHeight = this.viewState.heightMap.height;
|
|
6862
|
+
}
|
|
6863
|
+
else {
|
|
6864
|
+
let block = this.viewState.scrollAnchorAt(scrollTop);
|
|
6865
|
+
scrollAnchorPos = block.from;
|
|
6866
|
+
scrollAnchorHeight = block.top;
|
|
6867
|
+
}
|
|
6868
|
+
}
|
|
6858
6869
|
this.updateState = 1 /* Measuring */;
|
|
6859
|
-
let oldViewport = this.viewport;
|
|
6860
6870
|
let changed = this.viewState.measure(this);
|
|
6861
6871
|
if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null)
|
|
6862
6872
|
break;
|
|
@@ -6879,7 +6889,7 @@ class EditorView {
|
|
|
6879
6889
|
return BadMeasure;
|
|
6880
6890
|
}
|
|
6881
6891
|
});
|
|
6882
|
-
let update = ViewUpdate.create(this, this.state, []), redrawn = false
|
|
6892
|
+
let update = ViewUpdate.create(this, this.state, []), redrawn = false;
|
|
6883
6893
|
update.flags |= changed;
|
|
6884
6894
|
if (!updated)
|
|
6885
6895
|
updated = update;
|
|
@@ -6903,28 +6913,28 @@ class EditorView {
|
|
|
6903
6913
|
logException(this.state, e);
|
|
6904
6914
|
}
|
|
6905
6915
|
}
|
|
6906
|
-
if (this.viewState.editorHeight) {
|
|
6907
|
-
if (this.viewState.scrollTarget) {
|
|
6908
|
-
this.docView.scrollIntoView(this.viewState.scrollTarget);
|
|
6909
|
-
this.viewState.scrollTarget = null;
|
|
6910
|
-
scrolled = true;
|
|
6911
|
-
}
|
|
6912
|
-
else if (scrollAnchorHeight > -1) {
|
|
6913
|
-
let newAnchorHeight = scrollAnchorPos < 0 ? this.viewState.heightMap.height :
|
|
6914
|
-
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
6915
|
-
let diff = newAnchorHeight - scrollAnchorHeight;
|
|
6916
|
-
if (diff > 1 || diff < -1) {
|
|
6917
|
-
sDOM.scrollTop = scrollTop + diff;
|
|
6918
|
-
scrolled = true;
|
|
6919
|
-
}
|
|
6920
|
-
}
|
|
6921
|
-
}
|
|
6922
6916
|
if (redrawn)
|
|
6923
6917
|
this.docView.updateSelection(true);
|
|
6924
|
-
if (
|
|
6925
|
-
|
|
6918
|
+
if (!update.viewportChanged && this.measureRequests.length == 0) {
|
|
6919
|
+
if (this.viewState.editorHeight) {
|
|
6920
|
+
if (this.viewState.scrollTarget) {
|
|
6921
|
+
this.docView.scrollIntoView(this.viewState.scrollTarget);
|
|
6922
|
+
this.viewState.scrollTarget = null;
|
|
6923
|
+
continue;
|
|
6924
|
+
}
|
|
6925
|
+
else {
|
|
6926
|
+
let newAnchorHeight = scrollAnchorPos < 0 ? this.viewState.heightMap.height :
|
|
6927
|
+
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
6928
|
+
let diff = newAnchorHeight - scrollAnchorHeight;
|
|
6929
|
+
if (diff > 1 || diff < -1) {
|
|
6930
|
+
scrollTop = sDOM.scrollTop = scrollTop + diff;
|
|
6931
|
+
scrollAnchorHeight = -1;
|
|
6932
|
+
continue;
|
|
6933
|
+
}
|
|
6934
|
+
}
|
|
6935
|
+
}
|
|
6926
6936
|
break;
|
|
6927
|
-
|
|
6937
|
+
}
|
|
6928
6938
|
}
|
|
6929
6939
|
}
|
|
6930
6940
|
finally {
|
package/dist/index.js
CHANGED
|
@@ -316,6 +316,9 @@ function atElementStart(doc, selection) {
|
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
|
+
function isScrolledToBottom(elt) {
|
|
320
|
+
return elt.scrollTop > Math.max(1, elt.scrollHeight - elt.clientHeight - 4);
|
|
321
|
+
}
|
|
319
322
|
|
|
320
323
|
class DOMPos {
|
|
321
324
|
constructor(node, offset, precise = true) {
|
|
@@ -358,7 +361,7 @@ class ContentView {
|
|
|
358
361
|
let prev = null, next;
|
|
359
362
|
for (let child of this.children) {
|
|
360
363
|
if (child.dirty) {
|
|
361
|
-
if (!child.dom && (next = prev ? prev.nextSibling : parent.firstChild)) {
|
|
364
|
+
if (!child.dom && (next = prev ? prev.nextSibling : parent.firstChild) && next != view.docView.compositionNode) {
|
|
362
365
|
let contentView = ContentView.get(next);
|
|
363
366
|
if (!contentView || !contentView.parent && contentView.canReuseDOM(child))
|
|
364
367
|
child.reuseDOM(next);
|
|
@@ -2595,6 +2598,7 @@ class DocView extends ContentView {
|
|
|
2595
2598
|
super();
|
|
2596
2599
|
this.view = view;
|
|
2597
2600
|
this.compositionDeco = Decoration.none;
|
|
2601
|
+
this.compositionNode = null;
|
|
2598
2602
|
this.decorations = [];
|
|
2599
2603
|
this.dynamicDecorationMap = [];
|
|
2600
2604
|
// Track a minimum width for the editor. When measuring sizes in
|
|
@@ -2634,10 +2638,8 @@ class DocView extends ContentView {
|
|
|
2634
2638
|
this.minWidthTo = update.changes.mapPos(this.minWidthTo, 1);
|
|
2635
2639
|
}
|
|
2636
2640
|
}
|
|
2637
|
-
|
|
2638
|
-
this.
|
|
2639
|
-
else if (update.transactions.length || this.dirty)
|
|
2640
|
-
this.compositionDeco = computeCompositionDeco(this.view, update.changes);
|
|
2641
|
+
({ deco: this.compositionDeco, node: this.compositionNode } =
|
|
2642
|
+
this.view.inputState.composing < 0 ? noComp : computeCompositionDeco(this.view, update.changes));
|
|
2641
2643
|
// When the DOM nodes around the selection are moved to another
|
|
2642
2644
|
// parent, Chrome sometimes reports a different selection through
|
|
2643
2645
|
// getSelection than the one that it actually shows to the user.
|
|
@@ -3025,10 +3027,11 @@ function compositionSurroundingNode(view) {
|
|
|
3025
3027
|
return { from, to: from + cView.length, node: cView.dom, text: textNode };
|
|
3026
3028
|
}
|
|
3027
3029
|
}
|
|
3030
|
+
const noComp = { deco: Decoration.none, node: null };
|
|
3028
3031
|
function computeCompositionDeco(view, changes) {
|
|
3029
3032
|
let surrounding = compositionSurroundingNode(view);
|
|
3030
3033
|
if (!surrounding)
|
|
3031
|
-
return
|
|
3034
|
+
return noComp;
|
|
3032
3035
|
let { from, to, node, text: textNode } = surrounding;
|
|
3033
3036
|
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
3034
3037
|
let { state } = view, reader = new DOMReader([], state);
|
|
@@ -3038,25 +3041,26 @@ function computeCompositionDeco(view, changes) {
|
|
|
3038
3041
|
reader.readRange(node.firstChild, null);
|
|
3039
3042
|
let { text } = reader;
|
|
3040
3043
|
if (text.indexOf(LineBreakPlaceholder) > -1)
|
|
3041
|
-
return
|
|
3044
|
+
return noComp; // Don't try to preserve multi-line compositions
|
|
3042
3045
|
if (newTo - newFrom < text.length) {
|
|
3043
3046
|
if (state.doc.sliceString(newFrom, Math.min(state.doc.length, newFrom + text.length)) == text)
|
|
3044
3047
|
newTo = newFrom + text.length;
|
|
3045
3048
|
else if (state.doc.sliceString(Math.max(0, newTo - text.length), newTo) == text)
|
|
3046
3049
|
newFrom = newTo - text.length;
|
|
3047
3050
|
else
|
|
3048
|
-
return
|
|
3051
|
+
return noComp;
|
|
3049
3052
|
}
|
|
3050
3053
|
else if (state.doc.sliceString(newFrom, newTo) != text) {
|
|
3051
|
-
return
|
|
3054
|
+
return noComp;
|
|
3052
3055
|
}
|
|
3053
3056
|
let topView = ContentView.get(node);
|
|
3054
3057
|
if (topView instanceof CompositionView)
|
|
3055
3058
|
topView = topView.widget.topView;
|
|
3056
3059
|
else if (topView)
|
|
3057
3060
|
topView.parent = null;
|
|
3058
|
-
|
|
3061
|
+
let deco = Decoration.set(Decoration.replace({ widget: new CompositionWidget(node, textNode, topView), inclusive: true })
|
|
3059
3062
|
.range(newFrom, newTo));
|
|
3063
|
+
return { deco, node };
|
|
3060
3064
|
}
|
|
3061
3065
|
class CompositionWidget extends WidgetType {
|
|
3062
3066
|
constructor(top, text, topView) {
|
|
@@ -3719,6 +3723,7 @@ class InputState {
|
|
|
3719
3723
|
const PendingKeys = [
|
|
3720
3724
|
{ key: "Backspace", keyCode: 8, inputType: "deleteContentBackward" },
|
|
3721
3725
|
{ key: "Enter", keyCode: 13, inputType: "insertParagraph" },
|
|
3726
|
+
{ key: "Enter", keyCode: 13, inputType: "insertLineBreak" },
|
|
3722
3727
|
{ key: "Delete", keyCode: 46, inputType: "deleteContentForward" }
|
|
3723
3728
|
];
|
|
3724
3729
|
const EmacsyPendingKeys = "dthko";
|
|
@@ -3963,7 +3968,7 @@ handlers.mousedown = (view, event) => {
|
|
|
3963
3968
|
if (!style && event.button == 0)
|
|
3964
3969
|
style = basicMouseSelection(view, event);
|
|
3965
3970
|
if (style) {
|
|
3966
|
-
let mustFocus = view.
|
|
3971
|
+
let mustFocus = !view.hasFocus;
|
|
3967
3972
|
view.inputState.startMouseSelection(new MouseSelection(view, event, style, mustFocus));
|
|
3968
3973
|
if (mustFocus)
|
|
3969
3974
|
view.observer.ignore(() => focusPreventScroll(view.contentDOM));
|
|
@@ -5159,7 +5164,7 @@ class ViewState {
|
|
|
5159
5164
|
let contentChanges = update.changedRanges;
|
|
5160
5165
|
let heightChanges = ChangedRange.extendWithRanges(contentChanges, heightRelevantDecoChanges(prevDeco, this.stateDeco, update ? update.changes : ChangeSet.empty(this.state.doc.length)));
|
|
5161
5166
|
let prevHeight = this.heightMap.height;
|
|
5162
|
-
let scrollAnchor = this.scrolledToBottom ? null : this.
|
|
5167
|
+
let scrollAnchor = this.scrolledToBottom ? null : this.scrollAnchorAt(this.scrollTop);
|
|
5163
5168
|
this.heightMap = this.heightMap.applyChanges(this.stateDeco, update.startState.doc, this.heightOracle.setDoc(this.state.doc), heightChanges);
|
|
5164
5169
|
if (this.heightMap.height != prevHeight)
|
|
5165
5170
|
update.flags |= 2 /* Height */;
|
|
@@ -5219,7 +5224,7 @@ class ViewState {
|
|
|
5219
5224
|
this.scrollAnchorHeight = -1;
|
|
5220
5225
|
this.scrollTop = view.scrollDOM.scrollTop;
|
|
5221
5226
|
}
|
|
5222
|
-
this.scrolledToBottom =
|
|
5227
|
+
this.scrolledToBottom = isScrolledToBottom(view.scrollDOM);
|
|
5223
5228
|
// Pixel viewport
|
|
5224
5229
|
let pixelViewport = (this.printing ? fullPixelRange : visiblePixelRange)(dom, this.paddingTop);
|
|
5225
5230
|
let dTop = pixelViewport.top - this.pixelViewport.top, dBottom = pixelViewport.bottom - this.pixelViewport.bottom;
|
|
@@ -5462,6 +5467,10 @@ class ViewState {
|
|
|
5462
5467
|
lineBlockAtHeight(height) {
|
|
5463
5468
|
return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height), QueryType.ByHeight, this.heightOracle, 0, 0), this.scaler);
|
|
5464
5469
|
}
|
|
5470
|
+
scrollAnchorAt(scrollTop) {
|
|
5471
|
+
let block = this.lineBlockAtHeight(scrollTop + 8);
|
|
5472
|
+
return block.from >= this.viewport.from || this.viewportLines[0].top - scrollTop > 200 ? block : this.viewportLines[0];
|
|
5473
|
+
}
|
|
5465
5474
|
elementAtHeight(height) {
|
|
5466
5475
|
return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height), this.heightOracle, 0, 0), this.scaler);
|
|
5467
5476
|
}
|
|
@@ -6834,22 +6843,23 @@ class EditorView {
|
|
|
6834
6843
|
let updated = null;
|
|
6835
6844
|
let sDOM = this.scrollDOM, { scrollTop } = sDOM;
|
|
6836
6845
|
let { scrollAnchorPos, scrollAnchorHeight } = this.viewState;
|
|
6846
|
+
if (scrollTop != this.viewState.scrollTop)
|
|
6847
|
+
scrollAnchorHeight = -1;
|
|
6837
6848
|
this.viewState.scrollAnchorHeight = -1;
|
|
6838
|
-
if (scrollAnchorHeight < 0 || scrollTop != this.viewState.scrollTop) {
|
|
6839
|
-
if (scrollTop > sDOM.scrollHeight - sDOM.clientHeight - 4) {
|
|
6840
|
-
scrollAnchorPos = -1;
|
|
6841
|
-
scrollAnchorHeight = this.viewState.heightMap.height;
|
|
6842
|
-
}
|
|
6843
|
-
else {
|
|
6844
|
-
let block = this.viewState.lineBlockAtHeight(scrollTop);
|
|
6845
|
-
scrollAnchorPos = block.from;
|
|
6846
|
-
scrollAnchorHeight = block.top;
|
|
6847
|
-
}
|
|
6848
|
-
}
|
|
6849
6849
|
try {
|
|
6850
6850
|
for (let i = 0;; i++) {
|
|
6851
|
+
if (scrollAnchorHeight < 0) {
|
|
6852
|
+
if (isScrolledToBottom(sDOM)) {
|
|
6853
|
+
scrollAnchorPos = -1;
|
|
6854
|
+
scrollAnchorHeight = this.viewState.heightMap.height;
|
|
6855
|
+
}
|
|
6856
|
+
else {
|
|
6857
|
+
let block = this.viewState.scrollAnchorAt(scrollTop);
|
|
6858
|
+
scrollAnchorPos = block.from;
|
|
6859
|
+
scrollAnchorHeight = block.top;
|
|
6860
|
+
}
|
|
6861
|
+
}
|
|
6851
6862
|
this.updateState = 1 /* Measuring */;
|
|
6852
|
-
let oldViewport = this.viewport;
|
|
6853
6863
|
let changed = this.viewState.measure(this);
|
|
6854
6864
|
if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null)
|
|
6855
6865
|
break;
|
|
@@ -6872,7 +6882,7 @@ class EditorView {
|
|
|
6872
6882
|
return BadMeasure;
|
|
6873
6883
|
}
|
|
6874
6884
|
});
|
|
6875
|
-
let update = ViewUpdate.create(this, this.state, []), redrawn = false
|
|
6885
|
+
let update = ViewUpdate.create(this, this.state, []), redrawn = false;
|
|
6876
6886
|
update.flags |= changed;
|
|
6877
6887
|
if (!updated)
|
|
6878
6888
|
updated = update;
|
|
@@ -6896,28 +6906,28 @@ class EditorView {
|
|
|
6896
6906
|
logException(this.state, e);
|
|
6897
6907
|
}
|
|
6898
6908
|
}
|
|
6899
|
-
if (this.viewState.editorHeight) {
|
|
6900
|
-
if (this.viewState.scrollTarget) {
|
|
6901
|
-
this.docView.scrollIntoView(this.viewState.scrollTarget);
|
|
6902
|
-
this.viewState.scrollTarget = null;
|
|
6903
|
-
scrolled = true;
|
|
6904
|
-
}
|
|
6905
|
-
else if (scrollAnchorHeight > -1) {
|
|
6906
|
-
let newAnchorHeight = scrollAnchorPos < 0 ? this.viewState.heightMap.height :
|
|
6907
|
-
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
6908
|
-
let diff = newAnchorHeight - scrollAnchorHeight;
|
|
6909
|
-
if (diff > 1 || diff < -1) {
|
|
6910
|
-
sDOM.scrollTop = scrollTop + diff;
|
|
6911
|
-
scrolled = true;
|
|
6912
|
-
}
|
|
6913
|
-
}
|
|
6914
|
-
}
|
|
6915
6909
|
if (redrawn)
|
|
6916
6910
|
this.docView.updateSelection(true);
|
|
6917
|
-
if (
|
|
6918
|
-
|
|
6911
|
+
if (!update.viewportChanged && this.measureRequests.length == 0) {
|
|
6912
|
+
if (this.viewState.editorHeight) {
|
|
6913
|
+
if (this.viewState.scrollTarget) {
|
|
6914
|
+
this.docView.scrollIntoView(this.viewState.scrollTarget);
|
|
6915
|
+
this.viewState.scrollTarget = null;
|
|
6916
|
+
continue;
|
|
6917
|
+
}
|
|
6918
|
+
else {
|
|
6919
|
+
let newAnchorHeight = scrollAnchorPos < 0 ? this.viewState.heightMap.height :
|
|
6920
|
+
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
6921
|
+
let diff = newAnchorHeight - scrollAnchorHeight;
|
|
6922
|
+
if (diff > 1 || diff < -1) {
|
|
6923
|
+
scrollTop = sDOM.scrollTop = scrollTop + diff;
|
|
6924
|
+
scrollAnchorHeight = -1;
|
|
6925
|
+
continue;
|
|
6926
|
+
}
|
|
6927
|
+
}
|
|
6928
|
+
}
|
|
6919
6929
|
break;
|
|
6920
|
-
|
|
6930
|
+
}
|
|
6921
6931
|
}
|
|
6922
6932
|
}
|
|
6923
6933
|
finally {
|