@codemirror/view 6.11.1 → 6.11.2
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 +43 -29
- package/dist/index.js +43 -29
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 6.11.2 (2023-05-13)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix a bug where the `crosshairCursor` extension could, when non-native key events were fired, trigger disruptive and needless view updates.
|
|
6
|
+
|
|
7
|
+
Fix an Android issue where backspacing at the front of a line with widget decorations could replace those decorations with their text content.
|
|
8
|
+
|
|
9
|
+
Respect scroll margins when scrolling the target of drag-selection into view.
|
|
10
|
+
|
|
11
|
+
Validate selection offsets reported by the browser, to work around Safari giving us invalid values in some cases.
|
|
12
|
+
|
|
1
13
|
## 6.11.1 (2023-05-09)
|
|
2
14
|
|
|
3
15
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -222,7 +222,9 @@ class DOMSelectionState {
|
|
|
222
222
|
this.focusNode == domSel.focusNode && this.focusOffset == domSel.focusOffset;
|
|
223
223
|
}
|
|
224
224
|
setRange(range) {
|
|
225
|
-
|
|
225
|
+
let { anchorNode, focusNode } = range;
|
|
226
|
+
// Clip offsets to node size to avoid crashes when Safari reports bogus offsets (#1152)
|
|
227
|
+
this.set(anchorNode, Math.min(range.anchorOffset, anchorNode ? maxOffset(anchorNode) : 0), focusNode, Math.min(range.focusOffset, focusNode ? maxOffset(focusNode) : 0));
|
|
226
228
|
}
|
|
227
229
|
set(anchorNode, anchorOffset, focusNode, focusOffset) {
|
|
228
230
|
this.anchorNode = anchorNode;
|
|
@@ -295,6 +297,8 @@ function atElementStart(doc, selection) {
|
|
|
295
297
|
let node = selection.focusNode, offset = selection.focusOffset;
|
|
296
298
|
if (!node || selection.anchorNode != node || selection.anchorOffset != offset)
|
|
297
299
|
return false;
|
|
300
|
+
// Safari can report bogus offsets (#1152)
|
|
301
|
+
offset = Math.min(offset, maxOffset(node));
|
|
298
302
|
for (;;) {
|
|
299
303
|
if (offset) {
|
|
300
304
|
if (node.nodeType != 1)
|
|
@@ -2007,6 +2011,23 @@ const contentAttributes = state.Facet.define();
|
|
|
2007
2011
|
const decorations = state.Facet.define();
|
|
2008
2012
|
const atomicRanges = state.Facet.define();
|
|
2009
2013
|
const scrollMargins = state.Facet.define();
|
|
2014
|
+
function getScrollMargins(view) {
|
|
2015
|
+
let left = 0, right = 0, top = 0, bottom = 0;
|
|
2016
|
+
for (let source of view.state.facet(scrollMargins)) {
|
|
2017
|
+
let m = source(view);
|
|
2018
|
+
if (m) {
|
|
2019
|
+
if (m.left != null)
|
|
2020
|
+
left = Math.max(left, m.left);
|
|
2021
|
+
if (m.right != null)
|
|
2022
|
+
right = Math.max(right, m.right);
|
|
2023
|
+
if (m.top != null)
|
|
2024
|
+
top = Math.max(top, m.top);
|
|
2025
|
+
if (m.bottom != null)
|
|
2026
|
+
bottom = Math.max(bottom, m.bottom);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
return { left, right, top, bottom };
|
|
2030
|
+
}
|
|
2010
2031
|
const styleModule = state.Facet.define();
|
|
2011
2032
|
class ChangedRange {
|
|
2012
2033
|
constructor(fromA, toA, fromB, toB) {
|
|
@@ -2938,22 +2959,10 @@ class DocView extends ContentView {
|
|
|
2938
2959
|
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
2939
2960
|
rect = { left: Math.min(rect.left, other.left), top: Math.min(rect.top, other.top),
|
|
2940
2961
|
right: Math.max(rect.right, other.right), bottom: Math.max(rect.bottom, other.bottom) };
|
|
2941
|
-
let
|
|
2942
|
-
for (let margins of this.view.state.facet(scrollMargins).map(f => f(this.view)))
|
|
2943
|
-
if (margins) {
|
|
2944
|
-
let { left, right, top, bottom } = margins;
|
|
2945
|
-
if (left != null)
|
|
2946
|
-
mLeft = Math.max(mLeft, left);
|
|
2947
|
-
if (right != null)
|
|
2948
|
-
mRight = Math.max(mRight, right);
|
|
2949
|
-
if (top != null)
|
|
2950
|
-
mTop = Math.max(mTop, top);
|
|
2951
|
-
if (bottom != null)
|
|
2952
|
-
mBottom = Math.max(mBottom, bottom);
|
|
2953
|
-
}
|
|
2962
|
+
let margins = getScrollMargins(this.view);
|
|
2954
2963
|
let targetRect = {
|
|
2955
|
-
left: rect.left -
|
|
2956
|
-
right: rect.right +
|
|
2964
|
+
left: rect.left - margins.left, top: rect.top - margins.top,
|
|
2965
|
+
right: rect.right + margins.right, bottom: rect.bottom + margins.bottom
|
|
2957
2966
|
};
|
|
2958
2967
|
scrollRectIntoView(this.view.scrollDOM, targetRect, range.head < range.anchor ? -1 : 1, target.x, target.y, target.xMargin, target.yMargin, this.view.textDirection == exports.Direction.LTR);
|
|
2959
2968
|
}
|
|
@@ -3733,13 +3742,14 @@ class MouseSelection {
|
|
|
3733
3742
|
let sx = 0, sy = 0;
|
|
3734
3743
|
let rect = ((_a = this.scrollParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect())
|
|
3735
3744
|
|| { left: 0, top: 0, right: this.view.win.innerWidth, bottom: this.view.win.innerHeight };
|
|
3736
|
-
|
|
3745
|
+
let margins = getScrollMargins(this.view);
|
|
3746
|
+
if (event.clientX - margins.left <= rect.left + dragScrollMargin)
|
|
3737
3747
|
sx = -dragScrollSpeed(rect.left - event.clientX);
|
|
3738
|
-
else if (event.clientX >= rect.right - dragScrollMargin)
|
|
3748
|
+
else if (event.clientX + margins.right >= rect.right - dragScrollMargin)
|
|
3739
3749
|
sx = dragScrollSpeed(event.clientX - rect.right);
|
|
3740
|
-
if (event.clientY <= rect.top + dragScrollMargin)
|
|
3750
|
+
if (event.clientY - margins.top <= rect.top + dragScrollMargin)
|
|
3741
3751
|
sy = -dragScrollSpeed(rect.top - event.clientY);
|
|
3742
|
-
else if (event.clientY >= rect.bottom - dragScrollMargin)
|
|
3752
|
+
else if (event.clientY + margins.bottom >= rect.bottom - dragScrollMargin)
|
|
3743
3753
|
sy = dragScrollSpeed(event.clientY - rect.bottom);
|
|
3744
3754
|
this.setScrollSpeed(sx, sy);
|
|
3745
3755
|
}
|
|
@@ -5781,13 +5791,13 @@ class DOMChange {
|
|
|
5781
5791
|
function applyDOMChange(view, domChange) {
|
|
5782
5792
|
let change;
|
|
5783
5793
|
let { newSel } = domChange, sel = view.state.selection.main;
|
|
5794
|
+
let lastKey = view.inputState.lastKeyTime > Date.now() - 100 ? view.inputState.lastKeyCode : -1;
|
|
5784
5795
|
if (domChange.bounds) {
|
|
5785
5796
|
let { from, to } = domChange.bounds;
|
|
5786
5797
|
let preferredPos = sel.from, preferredSide = null;
|
|
5787
5798
|
// Prefer anchoring to end when Backspace is pressed (or, on
|
|
5788
5799
|
// Android, when something was deleted)
|
|
5789
|
-
if (
|
|
5790
|
-
browser.android && domChange.text.length < to - from) {
|
|
5800
|
+
if (lastKey === 8 || browser.android && domChange.text.length < to - from) {
|
|
5791
5801
|
preferredPos = sel.to;
|
|
5792
5802
|
preferredSide = "end";
|
|
5793
5803
|
}
|
|
@@ -5795,7 +5805,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5795
5805
|
if (diff) {
|
|
5796
5806
|
// Chrome inserts two newlines when pressing shift-enter at the
|
|
5797
5807
|
// end of a line. DomChange drops one of those.
|
|
5798
|
-
if (browser.chrome &&
|
|
5808
|
+
if (browser.chrome && lastKey == 13 &&
|
|
5799
5809
|
diff.toB == diff.from + 2 && domChange.text.slice(diff.from, diff.toB) == LineBreakPlaceholder + LineBreakPlaceholder)
|
|
5800
5810
|
diff.toB--;
|
|
5801
5811
|
change = { from: from + diff.from, to: from + diff.toA,
|
|
@@ -5853,7 +5863,8 @@ function applyDOMChange(view, domChange) {
|
|
|
5853
5863
|
((change.from == sel.from && change.to == sel.to &&
|
|
5854
5864
|
change.insert.length == 1 && change.insert.lines == 2 &&
|
|
5855
5865
|
dispatchKey(view.contentDOM, "Enter", 13)) ||
|
|
5856
|
-
(change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0
|
|
5866
|
+
((change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0 ||
|
|
5867
|
+
lastKey == 8 && change.insert.length < change.to - change.from) &&
|
|
5857
5868
|
dispatchKey(view.contentDOM, "Backspace", 8)) ||
|
|
5858
5869
|
(change.from == sel.from && change.to == sel.to + 1 && change.insert.length == 0 &&
|
|
5859
5870
|
dispatchKey(view.contentDOM, "Delete", 46))))
|
|
@@ -6251,7 +6262,10 @@ class DOMObserver {
|
|
|
6251
6262
|
let key = this.delayedAndroidKey;
|
|
6252
6263
|
if (key) {
|
|
6253
6264
|
this.clearDelayedAndroidKey();
|
|
6254
|
-
|
|
6265
|
+
this.view.inputState.lastKeyCode = key.keyCode;
|
|
6266
|
+
this.view.inputState.lastKeyTime = Date.now();
|
|
6267
|
+
let flushed = this.flush();
|
|
6268
|
+
if (!flushed && key.force)
|
|
6255
6269
|
dispatchKey(this.dom, key.key, key.keyCode);
|
|
6256
6270
|
}
|
|
6257
6271
|
};
|
|
@@ -8480,10 +8494,10 @@ function rectangularSelection(options) {
|
|
|
8480
8494
|
return EditorView.mouseSelectionStyle.of((view, event) => filter(event) ? rectangleSelectionStyle(view, event) : null);
|
|
8481
8495
|
}
|
|
8482
8496
|
const keys = {
|
|
8483
|
-
Alt: [18, e => e.altKey],
|
|
8484
|
-
Control: [17, e => e.ctrlKey],
|
|
8485
|
-
Shift: [16, e => e.shiftKey],
|
|
8486
|
-
Meta: [91, e => e.metaKey]
|
|
8497
|
+
Alt: [18, e => !!e.altKey],
|
|
8498
|
+
Control: [17, e => !!e.ctrlKey],
|
|
8499
|
+
Shift: [16, e => !!e.shiftKey],
|
|
8500
|
+
Meta: [91, e => !!e.metaKey]
|
|
8487
8501
|
};
|
|
8488
8502
|
const showCrosshair = { style: "cursor: crosshair" };
|
|
8489
8503
|
/**
|
package/dist/index.js
CHANGED
|
@@ -218,7 +218,9 @@ class DOMSelectionState {
|
|
|
218
218
|
this.focusNode == domSel.focusNode && this.focusOffset == domSel.focusOffset;
|
|
219
219
|
}
|
|
220
220
|
setRange(range) {
|
|
221
|
-
|
|
221
|
+
let { anchorNode, focusNode } = range;
|
|
222
|
+
// Clip offsets to node size to avoid crashes when Safari reports bogus offsets (#1152)
|
|
223
|
+
this.set(anchorNode, Math.min(range.anchorOffset, anchorNode ? maxOffset(anchorNode) : 0), focusNode, Math.min(range.focusOffset, focusNode ? maxOffset(focusNode) : 0));
|
|
222
224
|
}
|
|
223
225
|
set(anchorNode, anchorOffset, focusNode, focusOffset) {
|
|
224
226
|
this.anchorNode = anchorNode;
|
|
@@ -291,6 +293,8 @@ function atElementStart(doc, selection) {
|
|
|
291
293
|
let node = selection.focusNode, offset = selection.focusOffset;
|
|
292
294
|
if (!node || selection.anchorNode != node || selection.anchorOffset != offset)
|
|
293
295
|
return false;
|
|
296
|
+
// Safari can report bogus offsets (#1152)
|
|
297
|
+
offset = Math.min(offset, maxOffset(node));
|
|
294
298
|
for (;;) {
|
|
295
299
|
if (offset) {
|
|
296
300
|
if (node.nodeType != 1)
|
|
@@ -2002,6 +2006,23 @@ const contentAttributes = /*@__PURE__*/Facet.define();
|
|
|
2002
2006
|
const decorations = /*@__PURE__*/Facet.define();
|
|
2003
2007
|
const atomicRanges = /*@__PURE__*/Facet.define();
|
|
2004
2008
|
const scrollMargins = /*@__PURE__*/Facet.define();
|
|
2009
|
+
function getScrollMargins(view) {
|
|
2010
|
+
let left = 0, right = 0, top = 0, bottom = 0;
|
|
2011
|
+
for (let source of view.state.facet(scrollMargins)) {
|
|
2012
|
+
let m = source(view);
|
|
2013
|
+
if (m) {
|
|
2014
|
+
if (m.left != null)
|
|
2015
|
+
left = Math.max(left, m.left);
|
|
2016
|
+
if (m.right != null)
|
|
2017
|
+
right = Math.max(right, m.right);
|
|
2018
|
+
if (m.top != null)
|
|
2019
|
+
top = Math.max(top, m.top);
|
|
2020
|
+
if (m.bottom != null)
|
|
2021
|
+
bottom = Math.max(bottom, m.bottom);
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
return { left, right, top, bottom };
|
|
2025
|
+
}
|
|
2005
2026
|
const styleModule = /*@__PURE__*/Facet.define();
|
|
2006
2027
|
class ChangedRange {
|
|
2007
2028
|
constructor(fromA, toA, fromB, toB) {
|
|
@@ -2932,22 +2953,10 @@ class DocView extends ContentView {
|
|
|
2932
2953
|
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
2933
2954
|
rect = { left: Math.min(rect.left, other.left), top: Math.min(rect.top, other.top),
|
|
2934
2955
|
right: Math.max(rect.right, other.right), bottom: Math.max(rect.bottom, other.bottom) };
|
|
2935
|
-
let
|
|
2936
|
-
for (let margins of this.view.state.facet(scrollMargins).map(f => f(this.view)))
|
|
2937
|
-
if (margins) {
|
|
2938
|
-
let { left, right, top, bottom } = margins;
|
|
2939
|
-
if (left != null)
|
|
2940
|
-
mLeft = Math.max(mLeft, left);
|
|
2941
|
-
if (right != null)
|
|
2942
|
-
mRight = Math.max(mRight, right);
|
|
2943
|
-
if (top != null)
|
|
2944
|
-
mTop = Math.max(mTop, top);
|
|
2945
|
-
if (bottom != null)
|
|
2946
|
-
mBottom = Math.max(mBottom, bottom);
|
|
2947
|
-
}
|
|
2956
|
+
let margins = getScrollMargins(this.view);
|
|
2948
2957
|
let targetRect = {
|
|
2949
|
-
left: rect.left -
|
|
2950
|
-
right: rect.right +
|
|
2958
|
+
left: rect.left - margins.left, top: rect.top - margins.top,
|
|
2959
|
+
right: rect.right + margins.right, bottom: rect.bottom + margins.bottom
|
|
2951
2960
|
};
|
|
2952
2961
|
scrollRectIntoView(this.view.scrollDOM, targetRect, range.head < range.anchor ? -1 : 1, target.x, target.y, target.xMargin, target.yMargin, this.view.textDirection == Direction.LTR);
|
|
2953
2962
|
}
|
|
@@ -3727,13 +3736,14 @@ class MouseSelection {
|
|
|
3727
3736
|
let sx = 0, sy = 0;
|
|
3728
3737
|
let rect = ((_a = this.scrollParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect())
|
|
3729
3738
|
|| { left: 0, top: 0, right: this.view.win.innerWidth, bottom: this.view.win.innerHeight };
|
|
3730
|
-
|
|
3739
|
+
let margins = getScrollMargins(this.view);
|
|
3740
|
+
if (event.clientX - margins.left <= rect.left + dragScrollMargin)
|
|
3731
3741
|
sx = -dragScrollSpeed(rect.left - event.clientX);
|
|
3732
|
-
else if (event.clientX >= rect.right - dragScrollMargin)
|
|
3742
|
+
else if (event.clientX + margins.right >= rect.right - dragScrollMargin)
|
|
3733
3743
|
sx = dragScrollSpeed(event.clientX - rect.right);
|
|
3734
|
-
if (event.clientY <= rect.top + dragScrollMargin)
|
|
3744
|
+
if (event.clientY - margins.top <= rect.top + dragScrollMargin)
|
|
3735
3745
|
sy = -dragScrollSpeed(rect.top - event.clientY);
|
|
3736
|
-
else if (event.clientY >= rect.bottom - dragScrollMargin)
|
|
3746
|
+
else if (event.clientY + margins.bottom >= rect.bottom - dragScrollMargin)
|
|
3737
3747
|
sy = dragScrollSpeed(event.clientY - rect.bottom);
|
|
3738
3748
|
this.setScrollSpeed(sx, sy);
|
|
3739
3749
|
}
|
|
@@ -5774,13 +5784,13 @@ class DOMChange {
|
|
|
5774
5784
|
function applyDOMChange(view, domChange) {
|
|
5775
5785
|
let change;
|
|
5776
5786
|
let { newSel } = domChange, sel = view.state.selection.main;
|
|
5787
|
+
let lastKey = view.inputState.lastKeyTime > Date.now() - 100 ? view.inputState.lastKeyCode : -1;
|
|
5777
5788
|
if (domChange.bounds) {
|
|
5778
5789
|
let { from, to } = domChange.bounds;
|
|
5779
5790
|
let preferredPos = sel.from, preferredSide = null;
|
|
5780
5791
|
// Prefer anchoring to end when Backspace is pressed (or, on
|
|
5781
5792
|
// Android, when something was deleted)
|
|
5782
|
-
if (
|
|
5783
|
-
browser.android && domChange.text.length < to - from) {
|
|
5793
|
+
if (lastKey === 8 || browser.android && domChange.text.length < to - from) {
|
|
5784
5794
|
preferredPos = sel.to;
|
|
5785
5795
|
preferredSide = "end";
|
|
5786
5796
|
}
|
|
@@ -5788,7 +5798,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5788
5798
|
if (diff) {
|
|
5789
5799
|
// Chrome inserts two newlines when pressing shift-enter at the
|
|
5790
5800
|
// end of a line. DomChange drops one of those.
|
|
5791
|
-
if (browser.chrome &&
|
|
5801
|
+
if (browser.chrome && lastKey == 13 &&
|
|
5792
5802
|
diff.toB == diff.from + 2 && domChange.text.slice(diff.from, diff.toB) == LineBreakPlaceholder + LineBreakPlaceholder)
|
|
5793
5803
|
diff.toB--;
|
|
5794
5804
|
change = { from: from + diff.from, to: from + diff.toA,
|
|
@@ -5846,7 +5856,8 @@ function applyDOMChange(view, domChange) {
|
|
|
5846
5856
|
((change.from == sel.from && change.to == sel.to &&
|
|
5847
5857
|
change.insert.length == 1 && change.insert.lines == 2 &&
|
|
5848
5858
|
dispatchKey(view.contentDOM, "Enter", 13)) ||
|
|
5849
|
-
(change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0
|
|
5859
|
+
((change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0 ||
|
|
5860
|
+
lastKey == 8 && change.insert.length < change.to - change.from) &&
|
|
5850
5861
|
dispatchKey(view.contentDOM, "Backspace", 8)) ||
|
|
5851
5862
|
(change.from == sel.from && change.to == sel.to + 1 && change.insert.length == 0 &&
|
|
5852
5863
|
dispatchKey(view.contentDOM, "Delete", 46))))
|
|
@@ -6244,7 +6255,10 @@ class DOMObserver {
|
|
|
6244
6255
|
let key = this.delayedAndroidKey;
|
|
6245
6256
|
if (key) {
|
|
6246
6257
|
this.clearDelayedAndroidKey();
|
|
6247
|
-
|
|
6258
|
+
this.view.inputState.lastKeyCode = key.keyCode;
|
|
6259
|
+
this.view.inputState.lastKeyTime = Date.now();
|
|
6260
|
+
let flushed = this.flush();
|
|
6261
|
+
if (!flushed && key.force)
|
|
6248
6262
|
dispatchKey(this.dom, key.key, key.keyCode);
|
|
6249
6263
|
}
|
|
6250
6264
|
};
|
|
@@ -8473,10 +8487,10 @@ function rectangularSelection(options) {
|
|
|
8473
8487
|
return EditorView.mouseSelectionStyle.of((view, event) => filter(event) ? rectangleSelectionStyle(view, event) : null);
|
|
8474
8488
|
}
|
|
8475
8489
|
const keys = {
|
|
8476
|
-
Alt: [18, e => e.altKey],
|
|
8477
|
-
Control: [17, e => e.ctrlKey],
|
|
8478
|
-
Shift: [16, e => e.shiftKey],
|
|
8479
|
-
Meta: [91, e => e.metaKey]
|
|
8490
|
+
Alt: [18, e => !!e.altKey],
|
|
8491
|
+
Control: [17, e => !!e.ctrlKey],
|
|
8492
|
+
Shift: [16, e => !!e.shiftKey],
|
|
8493
|
+
Meta: [91, e => !!e.metaKey]
|
|
8480
8494
|
};
|
|
8481
8495
|
const showCrosshair = { style: "cursor: crosshair" };
|
|
8482
8496
|
/**
|