@codemirror/view 6.38.2 → 6.38.3
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 +12 -0
- package/dist/index.cjs +33 -16
- package/dist/index.js +33 -16
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 6.38.3 (2025-09-22)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Work around a rendering bug in Mobile Safari by completely hiding empty layers.
|
|
6
|
+
|
|
7
|
+
Fix vertical cursor motion in Chrome around decorations with bottom borders or margins.
|
|
8
|
+
|
|
9
|
+
Fix an issue that caused mark decorations longer than 512 characters to needlessly be split.
|
|
10
|
+
|
|
11
|
+
Move the cursor out of atomic ranges when text input happens.
|
|
12
|
+
|
|
1
13
|
## 6.38.2 (2025-09-01)
|
|
2
14
|
|
|
3
15
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -1786,13 +1786,14 @@ class ContentBuilder {
|
|
|
1786
1786
|
this.textOff = 0;
|
|
1787
1787
|
}
|
|
1788
1788
|
}
|
|
1789
|
-
let
|
|
1789
|
+
let remaining = Math.min(this.text.length - this.textOff, length);
|
|
1790
|
+
let take = Math.min(remaining, 512 /* T.Chunk */);
|
|
1790
1791
|
this.flushBuffer(active.slice(active.length - openStart));
|
|
1791
1792
|
this.getLine().append(wrapMarks(new TextView(this.text.slice(this.textOff, this.textOff + take)), active), openStart);
|
|
1792
1793
|
this.atCursorPos = true;
|
|
1793
1794
|
this.textOff += take;
|
|
1794
1795
|
length -= take;
|
|
1795
|
-
openStart = 0;
|
|
1796
|
+
openStart = remaining <= take ? 0 : active.length;
|
|
1796
1797
|
}
|
|
1797
1798
|
}
|
|
1798
1799
|
span(from, to, active, openStart) {
|
|
@@ -3607,14 +3608,13 @@ function posAtCoords(view, coords, precise, bias = -1) {
|
|
|
3607
3608
|
}
|
|
3608
3609
|
else if (doc.caretRangeFromPoint) {
|
|
3609
3610
|
let range = doc.caretRangeFromPoint(x, y);
|
|
3610
|
-
if (range)
|
|
3611
|
+
if (range)
|
|
3611
3612
|
({ startContainer: node, startOffset: offset } = range);
|
|
3612
|
-
if (!view.contentDOM.contains(node) ||
|
|
3613
|
-
browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
|
|
3614
|
-
browser.chrome && isSuspiciousChromeCaretResult(node, offset, x))
|
|
3615
|
-
node = undefined;
|
|
3616
|
-
}
|
|
3617
3613
|
}
|
|
3614
|
+
if (node && (!view.contentDOM.contains(node) ||
|
|
3615
|
+
browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
|
|
3616
|
+
browser.chrome && isSuspiciousChromeCaretResult(node, offset, x)))
|
|
3617
|
+
node = undefined;
|
|
3618
3618
|
// Chrome will return offsets into <input> elements without child
|
|
3619
3619
|
// nodes, which will lead to a null deref below, so clip the
|
|
3620
3620
|
// offset to the node size.
|
|
@@ -3650,11 +3650,7 @@ function posAtCoordsImprecise(view, contentRect, block, x, y) {
|
|
|
3650
3650
|
let content = view.state.sliceDoc(block.from, block.to);
|
|
3651
3651
|
return block.from + state.findColumn(content, into, view.state.tabSize);
|
|
3652
3652
|
}
|
|
3653
|
-
|
|
3654
|
-
// the space between lines as belonging to the last character of the
|
|
3655
|
-
// line before. This is used to detect such a result so that it can be
|
|
3656
|
-
// ignored (issue #401).
|
|
3657
|
-
function isSuspiciousSafariCaretResult(node, offset, x) {
|
|
3653
|
+
function isEndOfLineBefore(node, offset, x) {
|
|
3658
3654
|
let len, scan = node;
|
|
3659
3655
|
if (node.nodeType != 3 || offset != (len = node.nodeValue.length))
|
|
3660
3656
|
return false;
|
|
@@ -3674,10 +3670,17 @@ function isSuspiciousSafariCaretResult(node, offset, x) {
|
|
|
3674
3670
|
}
|
|
3675
3671
|
return textRange(node, len - 1, len).getBoundingClientRect().right > x;
|
|
3676
3672
|
}
|
|
3673
|
+
// In case of a high line height, Safari's caretRangeFromPoint treats
|
|
3674
|
+
// the space between lines as belonging to the last character of the
|
|
3675
|
+
// line before. This is used to detect such a result so that it can be
|
|
3676
|
+
// ignored (issue #401).
|
|
3677
|
+
function isSuspiciousSafariCaretResult(node, offset, x) {
|
|
3678
|
+
return isEndOfLineBefore(node, offset, x);
|
|
3679
|
+
}
|
|
3677
3680
|
// Chrome will move positions between lines to the start of the next line
|
|
3678
3681
|
function isSuspiciousChromeCaretResult(node, offset, x) {
|
|
3679
3682
|
if (offset != 0)
|
|
3680
|
-
return
|
|
3683
|
+
return isEndOfLineBefore(node, offset, x);
|
|
3681
3684
|
for (let cur = node;;) {
|
|
3682
3685
|
let parent = cur.parentNode;
|
|
3683
3686
|
if (!parent || parent.nodeType != 1 || parent.firstChild != cur)
|
|
@@ -4103,8 +4106,20 @@ function applyDOMChangeInner(view, change, newSel, lastKey = -1) {
|
|
|
4103
4106
|
return true;
|
|
4104
4107
|
}
|
|
4105
4108
|
function applyDefaultInsert(view, change, newSel) {
|
|
4106
|
-
let tr, startState = view.state, sel = startState.selection.main;
|
|
4107
|
-
if (change.from
|
|
4109
|
+
let tr, startState = view.state, sel = startState.selection.main, inAtomic = -1;
|
|
4110
|
+
if (change.from == change.to && change.from < sel.from || change.from > sel.to) {
|
|
4111
|
+
let side = change.from < sel.from ? -1 : 1, pos = side < 0 ? sel.from : sel.to;
|
|
4112
|
+
let moved = skipAtomicRanges(startState.facet(atomicRanges).map(f => f(view)), pos, side);
|
|
4113
|
+
if (change.from == moved)
|
|
4114
|
+
inAtomic = moved;
|
|
4115
|
+
}
|
|
4116
|
+
if (inAtomic > -1) {
|
|
4117
|
+
tr = {
|
|
4118
|
+
changes: change,
|
|
4119
|
+
selection: state.EditorSelection.cursor(change.from + change.insert.length, -1)
|
|
4120
|
+
};
|
|
4121
|
+
}
|
|
4122
|
+
else if (change.from >= sel.from && change.to <= sel.to && change.to - change.from >= (sel.to - sel.from) / 3 &&
|
|
4108
4123
|
(!newSel || newSel.main.empty && newSel.main.from == change.from + change.insert.length) &&
|
|
4109
4124
|
view.inputState.composing < 0) {
|
|
4110
4125
|
let before = sel.from < change.from ? startState.sliceDoc(sel.from, change.from) : "";
|
|
@@ -9083,6 +9098,8 @@ class LayerView {
|
|
|
9083
9098
|
old = next;
|
|
9084
9099
|
}
|
|
9085
9100
|
this.drawn = markers;
|
|
9101
|
+
if (browser.ios) // Issue #1600
|
|
9102
|
+
this.dom.style.display = this.dom.firstChild ? "" : "none";
|
|
9086
9103
|
}
|
|
9087
9104
|
}
|
|
9088
9105
|
destroy() {
|
package/dist/index.js
CHANGED
|
@@ -1783,13 +1783,14 @@ class ContentBuilder {
|
|
|
1783
1783
|
this.textOff = 0;
|
|
1784
1784
|
}
|
|
1785
1785
|
}
|
|
1786
|
-
let
|
|
1786
|
+
let remaining = Math.min(this.text.length - this.textOff, length);
|
|
1787
|
+
let take = Math.min(remaining, 512 /* T.Chunk */);
|
|
1787
1788
|
this.flushBuffer(active.slice(active.length - openStart));
|
|
1788
1789
|
this.getLine().append(wrapMarks(new TextView(this.text.slice(this.textOff, this.textOff + take)), active), openStart);
|
|
1789
1790
|
this.atCursorPos = true;
|
|
1790
1791
|
this.textOff += take;
|
|
1791
1792
|
length -= take;
|
|
1792
|
-
openStart = 0;
|
|
1793
|
+
openStart = remaining <= take ? 0 : active.length;
|
|
1793
1794
|
}
|
|
1794
1795
|
}
|
|
1795
1796
|
span(from, to, active, openStart) {
|
|
@@ -3603,14 +3604,13 @@ function posAtCoords(view, coords, precise, bias = -1) {
|
|
|
3603
3604
|
}
|
|
3604
3605
|
else if (doc.caretRangeFromPoint) {
|
|
3605
3606
|
let range = doc.caretRangeFromPoint(x, y);
|
|
3606
|
-
if (range)
|
|
3607
|
+
if (range)
|
|
3607
3608
|
({ startContainer: node, startOffset: offset } = range);
|
|
3608
|
-
if (!view.contentDOM.contains(node) ||
|
|
3609
|
-
browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
|
|
3610
|
-
browser.chrome && isSuspiciousChromeCaretResult(node, offset, x))
|
|
3611
|
-
node = undefined;
|
|
3612
|
-
}
|
|
3613
3609
|
}
|
|
3610
|
+
if (node && (!view.contentDOM.contains(node) ||
|
|
3611
|
+
browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
|
|
3612
|
+
browser.chrome && isSuspiciousChromeCaretResult(node, offset, x)))
|
|
3613
|
+
node = undefined;
|
|
3614
3614
|
// Chrome will return offsets into <input> elements without child
|
|
3615
3615
|
// nodes, which will lead to a null deref below, so clip the
|
|
3616
3616
|
// offset to the node size.
|
|
@@ -3646,11 +3646,7 @@ function posAtCoordsImprecise(view, contentRect, block, x, y) {
|
|
|
3646
3646
|
let content = view.state.sliceDoc(block.from, block.to);
|
|
3647
3647
|
return block.from + findColumn(content, into, view.state.tabSize);
|
|
3648
3648
|
}
|
|
3649
|
-
|
|
3650
|
-
// the space between lines as belonging to the last character of the
|
|
3651
|
-
// line before. This is used to detect such a result so that it can be
|
|
3652
|
-
// ignored (issue #401).
|
|
3653
|
-
function isSuspiciousSafariCaretResult(node, offset, x) {
|
|
3649
|
+
function isEndOfLineBefore(node, offset, x) {
|
|
3654
3650
|
let len, scan = node;
|
|
3655
3651
|
if (node.nodeType != 3 || offset != (len = node.nodeValue.length))
|
|
3656
3652
|
return false;
|
|
@@ -3670,10 +3666,17 @@ function isSuspiciousSafariCaretResult(node, offset, x) {
|
|
|
3670
3666
|
}
|
|
3671
3667
|
return textRange(node, len - 1, len).getBoundingClientRect().right > x;
|
|
3672
3668
|
}
|
|
3669
|
+
// In case of a high line height, Safari's caretRangeFromPoint treats
|
|
3670
|
+
// the space between lines as belonging to the last character of the
|
|
3671
|
+
// line before. This is used to detect such a result so that it can be
|
|
3672
|
+
// ignored (issue #401).
|
|
3673
|
+
function isSuspiciousSafariCaretResult(node, offset, x) {
|
|
3674
|
+
return isEndOfLineBefore(node, offset, x);
|
|
3675
|
+
}
|
|
3673
3676
|
// Chrome will move positions between lines to the start of the next line
|
|
3674
3677
|
function isSuspiciousChromeCaretResult(node, offset, x) {
|
|
3675
3678
|
if (offset != 0)
|
|
3676
|
-
return
|
|
3679
|
+
return isEndOfLineBefore(node, offset, x);
|
|
3677
3680
|
for (let cur = node;;) {
|
|
3678
3681
|
let parent = cur.parentNode;
|
|
3679
3682
|
if (!parent || parent.nodeType != 1 || parent.firstChild != cur)
|
|
@@ -4099,8 +4102,20 @@ function applyDOMChangeInner(view, change, newSel, lastKey = -1) {
|
|
|
4099
4102
|
return true;
|
|
4100
4103
|
}
|
|
4101
4104
|
function applyDefaultInsert(view, change, newSel) {
|
|
4102
|
-
let tr, startState = view.state, sel = startState.selection.main;
|
|
4103
|
-
if (change.from
|
|
4105
|
+
let tr, startState = view.state, sel = startState.selection.main, inAtomic = -1;
|
|
4106
|
+
if (change.from == change.to && change.from < sel.from || change.from > sel.to) {
|
|
4107
|
+
let side = change.from < sel.from ? -1 : 1, pos = side < 0 ? sel.from : sel.to;
|
|
4108
|
+
let moved = skipAtomicRanges(startState.facet(atomicRanges).map(f => f(view)), pos, side);
|
|
4109
|
+
if (change.from == moved)
|
|
4110
|
+
inAtomic = moved;
|
|
4111
|
+
}
|
|
4112
|
+
if (inAtomic > -1) {
|
|
4113
|
+
tr = {
|
|
4114
|
+
changes: change,
|
|
4115
|
+
selection: EditorSelection.cursor(change.from + change.insert.length, -1)
|
|
4116
|
+
};
|
|
4117
|
+
}
|
|
4118
|
+
else if (change.from >= sel.from && change.to <= sel.to && change.to - change.from >= (sel.to - sel.from) / 3 &&
|
|
4104
4119
|
(!newSel || newSel.main.empty && newSel.main.from == change.from + change.insert.length) &&
|
|
4105
4120
|
view.inputState.composing < 0) {
|
|
4106
4121
|
let before = sel.from < change.from ? startState.sliceDoc(sel.from, change.from) : "";
|
|
@@ -9078,6 +9093,8 @@ class LayerView {
|
|
|
9078
9093
|
old = next;
|
|
9079
9094
|
}
|
|
9080
9095
|
this.drawn = markers;
|
|
9096
|
+
if (browser.ios) // Issue #1600
|
|
9097
|
+
this.dom.style.display = this.dom.firstChild ? "" : "none";
|
|
9081
9098
|
}
|
|
9082
9099
|
}
|
|
9083
9100
|
destroy() {
|