@codemirror/view 6.43.7 → 6.43.9
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 +42 -32
- package/dist/index.js +42 -32
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 6.43.9 (2026-08-16)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix an issue where the scroll position would incorrectly be moved up when a document scrolled to the bottom would lose height.
|
|
6
|
+
|
|
7
|
+
## 6.43.8 (2026-08-04)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Fix an issue that could cause identical `posAtCoords` queries to return different results.
|
|
12
|
+
|
|
13
|
+
Fix an issue where scrolling a position into view vertically on Android or iOS could cause horizontal scrolling motion.
|
|
14
|
+
|
|
1
15
|
## 6.43.7 (2026-07-27)
|
|
2
16
|
|
|
3
17
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -685,6 +685,22 @@ class DOMSelectionState {
|
|
|
685
685
|
this.focusOffset = focusOffset;
|
|
686
686
|
}
|
|
687
687
|
}
|
|
688
|
+
function getScrollStack(target) {
|
|
689
|
+
let stack = [];
|
|
690
|
+
for (let cur = target; cur; cur = cur.nodeType == 11 ? cur.host : cur.parentNode) {
|
|
691
|
+
if (cur.nodeType == 1)
|
|
692
|
+
stack.push({ node: cur, left: cur.scrollLeft, top: cur.scrollTop });
|
|
693
|
+
}
|
|
694
|
+
return stack;
|
|
695
|
+
}
|
|
696
|
+
function restoreScrollStack(stack, vert = true) {
|
|
697
|
+
for (let { node, left, top } of stack) {
|
|
698
|
+
if (vert && node.scrollTop != top)
|
|
699
|
+
node.scrollTop = top;
|
|
700
|
+
if (node.scrollLeft != left)
|
|
701
|
+
node.scrollLeft = left;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
688
704
|
let preventScrollSupported = null;
|
|
689
705
|
// Safari 26 breaks preventScroll support
|
|
690
706
|
if (browser.safari && browser.safari_version >= 26)
|
|
@@ -696,12 +712,7 @@ function focusPreventScroll(dom) {
|
|
|
696
712
|
return dom.setActive(); // in IE
|
|
697
713
|
if (preventScrollSupported)
|
|
698
714
|
return dom.focus(preventScrollSupported);
|
|
699
|
-
let stack =
|
|
700
|
-
for (let cur = dom; cur; cur = cur.parentNode) {
|
|
701
|
-
stack.push(cur, cur.scrollTop, cur.scrollLeft);
|
|
702
|
-
if (cur == cur.ownerDocument)
|
|
703
|
-
break;
|
|
704
|
-
}
|
|
715
|
+
let stack = getScrollStack(dom);
|
|
705
716
|
dom.focus(preventScrollSupported == null ? {
|
|
706
717
|
get preventScroll() {
|
|
707
718
|
preventScrollSupported = { preventScroll: true };
|
|
@@ -710,13 +721,7 @@ function focusPreventScroll(dom) {
|
|
|
710
721
|
} : undefined);
|
|
711
722
|
if (!preventScrollSupported) {
|
|
712
723
|
preventScrollSupported = false;
|
|
713
|
-
|
|
714
|
-
let elt = stack[i++], top = stack[i++], left = stack[i++];
|
|
715
|
-
if (elt.scrollTop != top)
|
|
716
|
-
elt.scrollTop = top;
|
|
717
|
-
if (elt.scrollLeft != left)
|
|
718
|
-
elt.scrollLeft = left;
|
|
719
|
-
}
|
|
724
|
+
restoreScrollStack(stack);
|
|
720
725
|
}
|
|
721
726
|
}
|
|
722
727
|
let scratchRange;
|
|
@@ -3462,11 +3467,14 @@ class DocView {
|
|
|
3462
3467
|
// can affect it. So this tries to kludge around the problem by
|
|
3463
3468
|
// calling scrollIntoView on the scroll target's line.
|
|
3464
3469
|
if (window.visualViewport && window.innerHeight - window.visualViewport.height > 1 &&
|
|
3465
|
-
(rect.top > window.
|
|
3466
|
-
rect.bottom < window.
|
|
3470
|
+
(rect.top > window.visualViewport.offsetTop + window.visualViewport.height ||
|
|
3471
|
+
rect.bottom < window.visualViewport.offsetTop)) {
|
|
3467
3472
|
let line = this.view.docView.lineAt(range.head, 1);
|
|
3468
|
-
if (line)
|
|
3473
|
+
if (line) {
|
|
3474
|
+
let stack = getScrollStack(line.dom);
|
|
3469
3475
|
line.dom.scrollIntoView({ block: "nearest" });
|
|
3476
|
+
restoreScrollStack(stack, false);
|
|
3477
|
+
}
|
|
3470
3478
|
}
|
|
3471
3479
|
}
|
|
3472
3480
|
lineHasWidget(pos) {
|
|
@@ -3888,23 +3896,22 @@ class InlineCoordsScan {
|
|
|
3888
3896
|
search: while (lo < hi) {
|
|
3889
3897
|
let dist = hi - lo, mid = (lo + hi) >> 1;
|
|
3890
3898
|
adjust: if (seen.has(mid)) {
|
|
3891
|
-
let
|
|
3892
|
-
|
|
3899
|
+
for (let i = 1; i < dist; i++) {
|
|
3900
|
+
let scan = mid + i;
|
|
3901
|
+
if (scan >= hi)
|
|
3902
|
+
scan -= dist;
|
|
3893
3903
|
if (!seen.has(scan)) {
|
|
3894
3904
|
mid = scan;
|
|
3895
3905
|
break adjust;
|
|
3896
3906
|
}
|
|
3897
|
-
scan++;
|
|
3898
|
-
if (scan == hi)
|
|
3899
|
-
scan = lo; // Wrap around
|
|
3900
3907
|
}
|
|
3901
3908
|
break search; // No index found, we're done
|
|
3902
3909
|
}
|
|
3903
3910
|
seen.add(mid);
|
|
3904
|
-
let rects = getRects(mid);
|
|
3911
|
+
let rects = getRects(mid), side = 0;
|
|
3905
3912
|
if (rects)
|
|
3906
3913
|
for (let i = 0; i < rects.length; i++) {
|
|
3907
|
-
let rect = rects[i]
|
|
3914
|
+
let rect = rects[i];
|
|
3908
3915
|
// Ignore empty rectangles when there are other rectangles
|
|
3909
3916
|
if (rect.width == 0 && rects.length > 1)
|
|
3910
3917
|
continue;
|
|
@@ -3929,12 +3936,12 @@ class InlineCoordsScan {
|
|
|
3929
3936
|
if (off)
|
|
3930
3937
|
side = (off < 0) == (this.baseDir == exports.Direction.LTR) ? -1 : 1;
|
|
3931
3938
|
}
|
|
3932
|
-
// Narrow binary search when it is safe to do so
|
|
3933
|
-
if (side == -1 && (!bidi || this.baseDirAt(positions[mid], 1)))
|
|
3934
|
-
hi = mid;
|
|
3935
|
-
else if (side == 1 && (!bidi || this.baseDirAt(positions[mid + 1], -1)))
|
|
3936
|
-
lo = mid + 1;
|
|
3937
3939
|
}
|
|
3940
|
+
// Narrow binary search when it is safe to do so
|
|
3941
|
+
if (side == -1 && (!bidi || this.baseDirAt(positions[mid], 1)))
|
|
3942
|
+
hi = mid;
|
|
3943
|
+
else if (side == 1 && (!bidi || this.baseDirAt(positions[mid + 1], -1)))
|
|
3944
|
+
lo = mid + 1;
|
|
3938
3945
|
}
|
|
3939
3946
|
// If no element with y overlap is found, find the nearest element
|
|
3940
3947
|
// on the y axis, move this.y into it, and retry the scan.
|
|
@@ -8229,10 +8236,12 @@ class EditorView {
|
|
|
8229
8236
|
(scroll == this.scrollDOM || this.hasFocus ||
|
|
8230
8237
|
Math.max(this.inputState.lastWheelEvent, this.inputState.lastTouchTime) > Date.now() - 100)) {
|
|
8231
8238
|
scrollOffset = scrollOffset + diff;
|
|
8232
|
-
if (scroll)
|
|
8233
|
-
scroll.scrollTop += diff;
|
|
8234
|
-
else
|
|
8239
|
+
if (!scroll)
|
|
8235
8240
|
this.win.scrollBy(0, diff);
|
|
8241
|
+
else if (scrollAnchorPos < 0)
|
|
8242
|
+
scroll.scrollTop = scroll.scrollHeight;
|
|
8243
|
+
else
|
|
8244
|
+
scroll.scrollTop += diff;
|
|
8236
8245
|
scrollAnchorHeight = -1;
|
|
8237
8246
|
continue;
|
|
8238
8247
|
}
|
|
@@ -9597,7 +9606,8 @@ const selectionLayer = layer({
|
|
|
9597
9606
|
},
|
|
9598
9607
|
class: "cm-selectionLayer"
|
|
9599
9608
|
});
|
|
9600
|
-
|
|
9609
|
+
// https://discuss.codemirror.net/t/firefox-153-ignores-transparent-selection-styling/9838
|
|
9610
|
+
const selectionBg = browser.gecko && browser.gecko_version == 153 ? "#ffffff01" : "transparent";
|
|
9601
9611
|
const hideNativeSelection = state.Prec.highest(EditorView.theme({
|
|
9602
9612
|
".cm-line": {
|
|
9603
9613
|
"& ::selection, &::selection": { backgroundColor: `${selectionBg} !important` },
|
package/dist/index.js
CHANGED
|
@@ -682,6 +682,22 @@ class DOMSelectionState {
|
|
|
682
682
|
this.focusOffset = focusOffset;
|
|
683
683
|
}
|
|
684
684
|
}
|
|
685
|
+
function getScrollStack(target) {
|
|
686
|
+
let stack = [];
|
|
687
|
+
for (let cur = target; cur; cur = cur.nodeType == 11 ? cur.host : cur.parentNode) {
|
|
688
|
+
if (cur.nodeType == 1)
|
|
689
|
+
stack.push({ node: cur, left: cur.scrollLeft, top: cur.scrollTop });
|
|
690
|
+
}
|
|
691
|
+
return stack;
|
|
692
|
+
}
|
|
693
|
+
function restoreScrollStack(stack, vert = true) {
|
|
694
|
+
for (let { node, left, top } of stack) {
|
|
695
|
+
if (vert && node.scrollTop != top)
|
|
696
|
+
node.scrollTop = top;
|
|
697
|
+
if (node.scrollLeft != left)
|
|
698
|
+
node.scrollLeft = left;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
685
701
|
let preventScrollSupported = null;
|
|
686
702
|
// Safari 26 breaks preventScroll support
|
|
687
703
|
if (browser.safari && browser.safari_version >= 26)
|
|
@@ -693,12 +709,7 @@ function focusPreventScroll(dom) {
|
|
|
693
709
|
return dom.setActive(); // in IE
|
|
694
710
|
if (preventScrollSupported)
|
|
695
711
|
return dom.focus(preventScrollSupported);
|
|
696
|
-
let stack =
|
|
697
|
-
for (let cur = dom; cur; cur = cur.parentNode) {
|
|
698
|
-
stack.push(cur, cur.scrollTop, cur.scrollLeft);
|
|
699
|
-
if (cur == cur.ownerDocument)
|
|
700
|
-
break;
|
|
701
|
-
}
|
|
712
|
+
let stack = getScrollStack(dom);
|
|
702
713
|
dom.focus(preventScrollSupported == null ? {
|
|
703
714
|
get preventScroll() {
|
|
704
715
|
preventScrollSupported = { preventScroll: true };
|
|
@@ -707,13 +718,7 @@ function focusPreventScroll(dom) {
|
|
|
707
718
|
} : undefined);
|
|
708
719
|
if (!preventScrollSupported) {
|
|
709
720
|
preventScrollSupported = false;
|
|
710
|
-
|
|
711
|
-
let elt = stack[i++], top = stack[i++], left = stack[i++];
|
|
712
|
-
if (elt.scrollTop != top)
|
|
713
|
-
elt.scrollTop = top;
|
|
714
|
-
if (elt.scrollLeft != left)
|
|
715
|
-
elt.scrollLeft = left;
|
|
716
|
-
}
|
|
721
|
+
restoreScrollStack(stack);
|
|
717
722
|
}
|
|
718
723
|
}
|
|
719
724
|
let scratchRange;
|
|
@@ -3458,11 +3463,14 @@ class DocView {
|
|
|
3458
3463
|
// can affect it. So this tries to kludge around the problem by
|
|
3459
3464
|
// calling scrollIntoView on the scroll target's line.
|
|
3460
3465
|
if (window.visualViewport && window.innerHeight - window.visualViewport.height > 1 &&
|
|
3461
|
-
(rect.top > window.
|
|
3462
|
-
rect.bottom < window.
|
|
3466
|
+
(rect.top > window.visualViewport.offsetTop + window.visualViewport.height ||
|
|
3467
|
+
rect.bottom < window.visualViewport.offsetTop)) {
|
|
3463
3468
|
let line = this.view.docView.lineAt(range.head, 1);
|
|
3464
|
-
if (line)
|
|
3469
|
+
if (line) {
|
|
3470
|
+
let stack = getScrollStack(line.dom);
|
|
3465
3471
|
line.dom.scrollIntoView({ block: "nearest" });
|
|
3472
|
+
restoreScrollStack(stack, false);
|
|
3473
|
+
}
|
|
3466
3474
|
}
|
|
3467
3475
|
}
|
|
3468
3476
|
lineHasWidget(pos) {
|
|
@@ -3884,23 +3892,22 @@ class InlineCoordsScan {
|
|
|
3884
3892
|
search: while (lo < hi) {
|
|
3885
3893
|
let dist = hi - lo, mid = (lo + hi) >> 1;
|
|
3886
3894
|
adjust: if (seen.has(mid)) {
|
|
3887
|
-
let
|
|
3888
|
-
|
|
3895
|
+
for (let i = 1; i < dist; i++) {
|
|
3896
|
+
let scan = mid + i;
|
|
3897
|
+
if (scan >= hi)
|
|
3898
|
+
scan -= dist;
|
|
3889
3899
|
if (!seen.has(scan)) {
|
|
3890
3900
|
mid = scan;
|
|
3891
3901
|
break adjust;
|
|
3892
3902
|
}
|
|
3893
|
-
scan++;
|
|
3894
|
-
if (scan == hi)
|
|
3895
|
-
scan = lo; // Wrap around
|
|
3896
3903
|
}
|
|
3897
3904
|
break search; // No index found, we're done
|
|
3898
3905
|
}
|
|
3899
3906
|
seen.add(mid);
|
|
3900
|
-
let rects = getRects(mid);
|
|
3907
|
+
let rects = getRects(mid), side = 0;
|
|
3901
3908
|
if (rects)
|
|
3902
3909
|
for (let i = 0; i < rects.length; i++) {
|
|
3903
|
-
let rect = rects[i]
|
|
3910
|
+
let rect = rects[i];
|
|
3904
3911
|
// Ignore empty rectangles when there are other rectangles
|
|
3905
3912
|
if (rect.width == 0 && rects.length > 1)
|
|
3906
3913
|
continue;
|
|
@@ -3925,12 +3932,12 @@ class InlineCoordsScan {
|
|
|
3925
3932
|
if (off)
|
|
3926
3933
|
side = (off < 0) == (this.baseDir == Direction.LTR) ? -1 : 1;
|
|
3927
3934
|
}
|
|
3928
|
-
// Narrow binary search when it is safe to do so
|
|
3929
|
-
if (side == -1 && (!bidi || this.baseDirAt(positions[mid], 1)))
|
|
3930
|
-
hi = mid;
|
|
3931
|
-
else if (side == 1 && (!bidi || this.baseDirAt(positions[mid + 1], -1)))
|
|
3932
|
-
lo = mid + 1;
|
|
3933
3935
|
}
|
|
3936
|
+
// Narrow binary search when it is safe to do so
|
|
3937
|
+
if (side == -1 && (!bidi || this.baseDirAt(positions[mid], 1)))
|
|
3938
|
+
hi = mid;
|
|
3939
|
+
else if (side == 1 && (!bidi || this.baseDirAt(positions[mid + 1], -1)))
|
|
3940
|
+
lo = mid + 1;
|
|
3934
3941
|
}
|
|
3935
3942
|
// If no element with y overlap is found, find the nearest element
|
|
3936
3943
|
// on the y axis, move this.y into it, and retry the scan.
|
|
@@ -8224,10 +8231,12 @@ class EditorView {
|
|
|
8224
8231
|
(scroll == this.scrollDOM || this.hasFocus ||
|
|
8225
8232
|
Math.max(this.inputState.lastWheelEvent, this.inputState.lastTouchTime) > Date.now() - 100)) {
|
|
8226
8233
|
scrollOffset = scrollOffset + diff;
|
|
8227
|
-
if (scroll)
|
|
8228
|
-
scroll.scrollTop += diff;
|
|
8229
|
-
else
|
|
8234
|
+
if (!scroll)
|
|
8230
8235
|
this.win.scrollBy(0, diff);
|
|
8236
|
+
else if (scrollAnchorPos < 0)
|
|
8237
|
+
scroll.scrollTop = scroll.scrollHeight;
|
|
8238
|
+
else
|
|
8239
|
+
scroll.scrollTop += diff;
|
|
8231
8240
|
scrollAnchorHeight = -1;
|
|
8232
8241
|
continue;
|
|
8233
8242
|
}
|
|
@@ -9592,7 +9601,8 @@ const selectionLayer = /*@__PURE__*/layer({
|
|
|
9592
9601
|
},
|
|
9593
9602
|
class: "cm-selectionLayer"
|
|
9594
9603
|
});
|
|
9595
|
-
|
|
9604
|
+
// https://discuss.codemirror.net/t/firefox-153-ignores-transparent-selection-styling/9838
|
|
9605
|
+
const selectionBg = browser.gecko && browser.gecko_version == 153 ? "#ffffff01" : "transparent";
|
|
9596
9606
|
const hideNativeSelection = /*@__PURE__*/Prec.highest(/*@__PURE__*/EditorView.theme({
|
|
9597
9607
|
".cm-line": {
|
|
9598
9608
|
"& ::selection, &::selection": { backgroundColor: `${selectionBg} !important` },
|