@codemirror/view 6.43.1 → 6.43.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 +18 -0
- package/dist/index.cjs +33 -20
- package/dist/index.js +33 -20
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## 6.43.3 (2026-06-25)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix a bug in the content DOM update code that could corrupt the editor state.
|
|
6
|
+
|
|
7
|
+
## 6.43.2 (2026-06-23)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Fix using select-all from the native context menu on Chrome Android.
|
|
12
|
+
|
|
13
|
+
On iOS when autocapitalize is enabled, ignore the shift modifier on virtual keyboard Enter or Backspace presses.
|
|
14
|
+
|
|
15
|
+
Work around an issue where Chrome Android scrolled the editor up when tapping an empty line to focus it.
|
|
16
|
+
|
|
17
|
+
Create undirectional selection ranges for double and triple clicks.
|
|
18
|
+
|
|
1
19
|
## 6.43.1 (2026-06-09)
|
|
2
20
|
|
|
3
21
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -2785,8 +2785,9 @@ class TileUpdate {
|
|
|
2785
2785
|
}
|
|
2786
2786
|
}
|
|
2787
2787
|
});
|
|
2788
|
-
b.addLineStartIfNotCovered(pendingLineAttrs);
|
|
2789
2788
|
this.openWidget = openEnd > markCount;
|
|
2789
|
+
if (!this.openWidget)
|
|
2790
|
+
b.addLineStartIfNotCovered(pendingLineAttrs);
|
|
2790
2791
|
this.openMarks = openEnd;
|
|
2791
2792
|
}
|
|
2792
2793
|
forward(from, to, side = 1) {
|
|
@@ -3611,7 +3612,7 @@ function groupAt(state$1, pos, bias = 1) {
|
|
|
3611
3612
|
break;
|
|
3612
3613
|
to = next;
|
|
3613
3614
|
}
|
|
3614
|
-
return state.EditorSelection.
|
|
3615
|
+
return state.EditorSelection.undirectionalRange(from + line.from, to + line.from);
|
|
3615
3616
|
}
|
|
3616
3617
|
function posAtCoordsImprecise(view, contentRect, block, x, y) {
|
|
3617
3618
|
let into = Math.round((x - contentRect.left) * view.defaultCharacterWidth);
|
|
@@ -3748,8 +3749,12 @@ function skipAtomsForSelection(atoms, sel) {
|
|
|
3748
3749
|
else {
|
|
3749
3750
|
let from = skipAtomicRanges(atoms, range.from, -1);
|
|
3750
3751
|
let to = skipAtomicRanges(atoms, range.to, 1);
|
|
3751
|
-
if (from != range.from || to != range.to)
|
|
3752
|
-
|
|
3752
|
+
if (from != range.from || to != range.to) {
|
|
3753
|
+
if (range.undirectional)
|
|
3754
|
+
updated = state.EditorSelection.undirectionalRange(range.from, range.to);
|
|
3755
|
+
else
|
|
3756
|
+
updated = state.EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to);
|
|
3757
|
+
}
|
|
3753
3758
|
}
|
|
3754
3759
|
if (updated) {
|
|
3755
3760
|
if (!ranges)
|
|
@@ -4155,7 +4160,8 @@ class DOMChange {
|
|
|
4155
4160
|
// Chrome will put the selection *inside* them, confusing
|
|
4156
4161
|
// posFromDOM
|
|
4157
4162
|
let vp = view.viewport;
|
|
4158
|
-
if ((browser.ios || browser.chrome) &&
|
|
4163
|
+
if ((browser.ios || browser.chrome) && head != anchor &&
|
|
4164
|
+
Math.min(head, anchor) <= curSel.main.from && Math.max(head, anchor) >= curSel.main.to &&
|
|
4159
4165
|
(vp.from > 0 || vp.to < view.state.doc.length)) {
|
|
4160
4166
|
let from = Math.min(head, anchor), to = Math.max(head, anchor);
|
|
4161
4167
|
let offFrom = vp.from - from, offTo = vp.to - to;
|
|
@@ -4476,13 +4482,11 @@ class InputState {
|
|
|
4476
4482
|
// (after which we retroactively handle them and reset the DOM) to
|
|
4477
4483
|
// avoid messing up the virtual keyboard state.
|
|
4478
4484
|
this.pendingIOSKey = undefined;
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
otherwise handled.
|
|
4485
|
-
*/
|
|
4485
|
+
// When enabled (>-1), tab presses are not given to key handlers,
|
|
4486
|
+
// leaving the browser's default behavior. If >0, the mode expires
|
|
4487
|
+
// at that timestamp, and any other keypress clears it.
|
|
4488
|
+
// Esc enables temporary tab focus mode for two seconds when not
|
|
4489
|
+
// otherwise handled.
|
|
4486
4490
|
this.tabFocusMode = -1;
|
|
4487
4491
|
this.lastSelectionOrigin = null;
|
|
4488
4492
|
this.lastSelectionTime = 0;
|
|
@@ -4590,11 +4594,16 @@ class InputState {
|
|
|
4590
4594
|
// state. So we let it go through, and then, in
|
|
4591
4595
|
// applyDOMChange, notify key handlers of it and reset to
|
|
4592
4596
|
// the state they produce.
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
((pending = PendingKeys.find(key => key.keyCode == event.keyCode)) && !event.ctrlKey ||
|
|
4597
|
+
if (browser.ios && !event.synthetic && !event.altKey && !event.metaKey &&
|
|
4598
|
+
(PendingKeys.some(key => key.keyCode == event.keyCode) && !event.ctrlKey ||
|
|
4596
4599
|
EmacsyPendingKeys.indexOf(event.key) > -1 && event.ctrlKey)) {
|
|
4597
|
-
|
|
4600
|
+
let mods = { ctrlKey: event.ctrlKey, altKey: event.altKey, metaKey: event.metaKey, shiftKey: event.shiftKey };
|
|
4601
|
+
// On iOS with autocapitalize, drop the shift modifier for these
|
|
4602
|
+
// keys, since it will be set at the start of every sentence.
|
|
4603
|
+
if (mods.shiftKey && browser.ios && !/^(off|none)$/.test(this.view.contentDOM.autocapitalize) &&
|
|
4604
|
+
iosVirtualKeyboardOpen(this.view.win))
|
|
4605
|
+
mods.shiftKey = false;
|
|
4606
|
+
this.pendingIOSKey = { key: event.key, keyCode: event.keyCode, mods };
|
|
4598
4607
|
setTimeout(() => this.flushIOSKey(), 250);
|
|
4599
4608
|
return true;
|
|
4600
4609
|
}
|
|
@@ -4610,7 +4619,7 @@ class InputState {
|
|
|
4610
4619
|
if (key.key == "Enter" && change && change.from < change.to && /^\S+$/.test(change.insert.toString()))
|
|
4611
4620
|
return false;
|
|
4612
4621
|
this.pendingIOSKey = undefined;
|
|
4613
|
-
return dispatchKey(this.view.contentDOM, key.key, key.keyCode, key
|
|
4622
|
+
return dispatchKey(this.view.contentDOM, key.key, key.keyCode, key.mods);
|
|
4614
4623
|
}
|
|
4615
4624
|
ignoreDuringComposition(event) {
|
|
4616
4625
|
if (!/^key/.test(event.type) || event.synthetic)
|
|
@@ -4648,6 +4657,11 @@ class InputState {
|
|
|
4648
4657
|
this.mouseSelection.destroy();
|
|
4649
4658
|
}
|
|
4650
4659
|
}
|
|
4660
|
+
function iosVirtualKeyboardOpen(win) {
|
|
4661
|
+
if (!win.visualViewport)
|
|
4662
|
+
return false;
|
|
4663
|
+
return win.visualViewport.height * win.visualViewport.scale / win.document.documentElement.clientHeight < 0.85;
|
|
4664
|
+
}
|
|
4651
4665
|
function bindHandler(plugin, handler) {
|
|
4652
4666
|
return (view, event) => {
|
|
4653
4667
|
try {
|
|
@@ -4967,7 +4981,7 @@ function rangeForClick(view, pos, bias, type) {
|
|
|
4967
4981
|
let from = visual ? visual.posAtStart : line.from, to = visual ? visual.posAtEnd : line.to;
|
|
4968
4982
|
if (to < view.state.doc.length && to == line.to)
|
|
4969
4983
|
to++;
|
|
4970
|
-
return state.EditorSelection.
|
|
4984
|
+
return state.EditorSelection.undirectionalRange(from, to);
|
|
4971
4985
|
}
|
|
4972
4986
|
}
|
|
4973
4987
|
const BadMouseDetail = browser.ie && browser.ie_version <= 11;
|
|
@@ -5025,7 +5039,7 @@ handlers.dragstart = (view, event) => {
|
|
|
5025
5039
|
if (tile && tile.isWidget()) {
|
|
5026
5040
|
let from = tile.posAtStart, to = from + tile.length;
|
|
5027
5041
|
if (from >= range.to || to <= range.from)
|
|
5028
|
-
range = state.EditorSelection.
|
|
5042
|
+
range = state.EditorSelection.undirectionalRange(from, to);
|
|
5029
5043
|
}
|
|
5030
5044
|
}
|
|
5031
5045
|
let { inputState } = view;
|
|
@@ -7651,7 +7665,6 @@ class EditContextManager {
|
|
|
7651
7665
|
for (let event in this.handlers)
|
|
7652
7666
|
context.addEventListener(event, this.handlers[event]);
|
|
7653
7667
|
this.measureReq = { read: view => {
|
|
7654
|
-
this.editContext.updateControlBounds(view.contentDOM.getBoundingClientRect());
|
|
7655
7668
|
let sel = getSelection(view.root);
|
|
7656
7669
|
if (sel && sel.rangeCount)
|
|
7657
7670
|
this.editContext.updateSelectionBounds(sel.getRangeAt(0).getBoundingClientRect());
|
package/dist/index.js
CHANGED
|
@@ -2781,8 +2781,9 @@ class TileUpdate {
|
|
|
2781
2781
|
}
|
|
2782
2782
|
}
|
|
2783
2783
|
});
|
|
2784
|
-
b.addLineStartIfNotCovered(pendingLineAttrs);
|
|
2785
2784
|
this.openWidget = openEnd > markCount;
|
|
2785
|
+
if (!this.openWidget)
|
|
2786
|
+
b.addLineStartIfNotCovered(pendingLineAttrs);
|
|
2786
2787
|
this.openMarks = openEnd;
|
|
2787
2788
|
}
|
|
2788
2789
|
forward(from, to, side = 1) {
|
|
@@ -3607,7 +3608,7 @@ function groupAt(state, pos, bias = 1) {
|
|
|
3607
3608
|
break;
|
|
3608
3609
|
to = next;
|
|
3609
3610
|
}
|
|
3610
|
-
return EditorSelection.
|
|
3611
|
+
return EditorSelection.undirectionalRange(from + line.from, to + line.from);
|
|
3611
3612
|
}
|
|
3612
3613
|
function posAtCoordsImprecise(view, contentRect, block, x, y) {
|
|
3613
3614
|
let into = Math.round((x - contentRect.left) * view.defaultCharacterWidth);
|
|
@@ -3744,8 +3745,12 @@ function skipAtomsForSelection(atoms, sel) {
|
|
|
3744
3745
|
else {
|
|
3745
3746
|
let from = skipAtomicRanges(atoms, range.from, -1);
|
|
3746
3747
|
let to = skipAtomicRanges(atoms, range.to, 1);
|
|
3747
|
-
if (from != range.from || to != range.to)
|
|
3748
|
-
|
|
3748
|
+
if (from != range.from || to != range.to) {
|
|
3749
|
+
if (range.undirectional)
|
|
3750
|
+
updated = EditorSelection.undirectionalRange(range.from, range.to);
|
|
3751
|
+
else
|
|
3752
|
+
updated = EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to);
|
|
3753
|
+
}
|
|
3749
3754
|
}
|
|
3750
3755
|
if (updated) {
|
|
3751
3756
|
if (!ranges)
|
|
@@ -4151,7 +4156,8 @@ class DOMChange {
|
|
|
4151
4156
|
// Chrome will put the selection *inside* them, confusing
|
|
4152
4157
|
// posFromDOM
|
|
4153
4158
|
let vp = view.viewport;
|
|
4154
|
-
if ((browser.ios || browser.chrome) &&
|
|
4159
|
+
if ((browser.ios || browser.chrome) && head != anchor &&
|
|
4160
|
+
Math.min(head, anchor) <= curSel.main.from && Math.max(head, anchor) >= curSel.main.to &&
|
|
4155
4161
|
(vp.from > 0 || vp.to < view.state.doc.length)) {
|
|
4156
4162
|
let from = Math.min(head, anchor), to = Math.max(head, anchor);
|
|
4157
4163
|
let offFrom = vp.from - from, offTo = vp.to - to;
|
|
@@ -4472,13 +4478,11 @@ class InputState {
|
|
|
4472
4478
|
// (after which we retroactively handle them and reset the DOM) to
|
|
4473
4479
|
// avoid messing up the virtual keyboard state.
|
|
4474
4480
|
this.pendingIOSKey = undefined;
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
otherwise handled.
|
|
4481
|
-
*/
|
|
4481
|
+
// When enabled (>-1), tab presses are not given to key handlers,
|
|
4482
|
+
// leaving the browser's default behavior. If >0, the mode expires
|
|
4483
|
+
// at that timestamp, and any other keypress clears it.
|
|
4484
|
+
// Esc enables temporary tab focus mode for two seconds when not
|
|
4485
|
+
// otherwise handled.
|
|
4482
4486
|
this.tabFocusMode = -1;
|
|
4483
4487
|
this.lastSelectionOrigin = null;
|
|
4484
4488
|
this.lastSelectionTime = 0;
|
|
@@ -4586,11 +4590,16 @@ class InputState {
|
|
|
4586
4590
|
// state. So we let it go through, and then, in
|
|
4587
4591
|
// applyDOMChange, notify key handlers of it and reset to
|
|
4588
4592
|
// the state they produce.
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
((pending = PendingKeys.find(key => key.keyCode == event.keyCode)) && !event.ctrlKey ||
|
|
4593
|
+
if (browser.ios && !event.synthetic && !event.altKey && !event.metaKey &&
|
|
4594
|
+
(PendingKeys.some(key => key.keyCode == event.keyCode) && !event.ctrlKey ||
|
|
4592
4595
|
EmacsyPendingKeys.indexOf(event.key) > -1 && event.ctrlKey)) {
|
|
4593
|
-
|
|
4596
|
+
let mods = { ctrlKey: event.ctrlKey, altKey: event.altKey, metaKey: event.metaKey, shiftKey: event.shiftKey };
|
|
4597
|
+
// On iOS with autocapitalize, drop the shift modifier for these
|
|
4598
|
+
// keys, since it will be set at the start of every sentence.
|
|
4599
|
+
if (mods.shiftKey && browser.ios && !/^(off|none)$/.test(this.view.contentDOM.autocapitalize) &&
|
|
4600
|
+
iosVirtualKeyboardOpen(this.view.win))
|
|
4601
|
+
mods.shiftKey = false;
|
|
4602
|
+
this.pendingIOSKey = { key: event.key, keyCode: event.keyCode, mods };
|
|
4594
4603
|
setTimeout(() => this.flushIOSKey(), 250);
|
|
4595
4604
|
return true;
|
|
4596
4605
|
}
|
|
@@ -4606,7 +4615,7 @@ class InputState {
|
|
|
4606
4615
|
if (key.key == "Enter" && change && change.from < change.to && /^\S+$/.test(change.insert.toString()))
|
|
4607
4616
|
return false;
|
|
4608
4617
|
this.pendingIOSKey = undefined;
|
|
4609
|
-
return dispatchKey(this.view.contentDOM, key.key, key.keyCode, key
|
|
4618
|
+
return dispatchKey(this.view.contentDOM, key.key, key.keyCode, key.mods);
|
|
4610
4619
|
}
|
|
4611
4620
|
ignoreDuringComposition(event) {
|
|
4612
4621
|
if (!/^key/.test(event.type) || event.synthetic)
|
|
@@ -4644,6 +4653,11 @@ class InputState {
|
|
|
4644
4653
|
this.mouseSelection.destroy();
|
|
4645
4654
|
}
|
|
4646
4655
|
}
|
|
4656
|
+
function iosVirtualKeyboardOpen(win) {
|
|
4657
|
+
if (!win.visualViewport)
|
|
4658
|
+
return false;
|
|
4659
|
+
return win.visualViewport.height * win.visualViewport.scale / win.document.documentElement.clientHeight < 0.85;
|
|
4660
|
+
}
|
|
4647
4661
|
function bindHandler(plugin, handler) {
|
|
4648
4662
|
return (view, event) => {
|
|
4649
4663
|
try {
|
|
@@ -4963,7 +4977,7 @@ function rangeForClick(view, pos, bias, type) {
|
|
|
4963
4977
|
let from = visual ? visual.posAtStart : line.from, to = visual ? visual.posAtEnd : line.to;
|
|
4964
4978
|
if (to < view.state.doc.length && to == line.to)
|
|
4965
4979
|
to++;
|
|
4966
|
-
return EditorSelection.
|
|
4980
|
+
return EditorSelection.undirectionalRange(from, to);
|
|
4967
4981
|
}
|
|
4968
4982
|
}
|
|
4969
4983
|
const BadMouseDetail = browser.ie && browser.ie_version <= 11;
|
|
@@ -5021,7 +5035,7 @@ handlers.dragstart = (view, event) => {
|
|
|
5021
5035
|
if (tile && tile.isWidget()) {
|
|
5022
5036
|
let from = tile.posAtStart, to = from + tile.length;
|
|
5023
5037
|
if (from >= range.to || to <= range.from)
|
|
5024
|
-
range = EditorSelection.
|
|
5038
|
+
range = EditorSelection.undirectionalRange(from, to);
|
|
5025
5039
|
}
|
|
5026
5040
|
}
|
|
5027
5041
|
let { inputState } = view;
|
|
@@ -7646,7 +7660,6 @@ class EditContextManager {
|
|
|
7646
7660
|
for (let event in this.handlers)
|
|
7647
7661
|
context.addEventListener(event, this.handlers[event]);
|
|
7648
7662
|
this.measureReq = { read: view => {
|
|
7649
|
-
this.editContext.updateControlBounds(view.contentDOM.getBoundingClientRect());
|
|
7650
7663
|
let sel = getSelection(view.root);
|
|
7651
7664
|
if (sel && sel.rangeCount)
|
|
7652
7665
|
this.editContext.updateSelectionBounds(sel.getRangeAt(0).getBoundingClientRect());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemirror/view",
|
|
3
|
-
"version": "6.43.
|
|
3
|
+
"version": "6.43.3",
|
|
4
4
|
"description": "DOM view component for the CodeMirror code editor",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "cm-runtests",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"sideEffects": false,
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@codemirror/state": "^6.
|
|
29
|
+
"@codemirror/state": "^6.7.0",
|
|
30
30
|
"crelt": "^1.0.6",
|
|
31
31
|
"style-mod": "^4.1.0",
|
|
32
32
|
"w3c-keyname": "^2.2.4"
|