@codemirror/view 6.1.2 → 6.2.0
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 +24 -0
- package/dist/index.cjs +71 -23
- package/dist/index.d.ts +10 -3
- package/dist/index.js +71 -23
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
## 6.2.0 (2022-08-05)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix a bug where `posAtCoords` would return the wrong results for positions to the right of wrapped lines.
|
|
6
|
+
|
|
7
|
+
### New features
|
|
8
|
+
|
|
9
|
+
The new `EditorView.setRoot` method can be used when an editor view is moved to a new document or shadow root.
|
|
10
|
+
|
|
11
|
+
## 6.1.4 (2022-08-04)
|
|
12
|
+
|
|
13
|
+
### Bug fixes
|
|
14
|
+
|
|
15
|
+
Make selection-restoration on focus more reliable.
|
|
16
|
+
|
|
17
|
+
## 6.1.3 (2022-08-03)
|
|
18
|
+
|
|
19
|
+
### Bug fixes
|
|
20
|
+
|
|
21
|
+
Fix a bug where a document that contains only non-printing characters would lead to bogus text measurements (and, from those, to crashing).
|
|
22
|
+
|
|
23
|
+
Make sure differences between estimated and actual block heights don't cause visible scroll glitches.
|
|
24
|
+
|
|
1
25
|
## 6.1.2 (2022-07-27)
|
|
2
26
|
|
|
3
27
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -1473,15 +1473,17 @@ class LineView extends ContentView {
|
|
|
1473
1473
|
return null;
|
|
1474
1474
|
let totalWidth = 0;
|
|
1475
1475
|
for (let child of this.children) {
|
|
1476
|
-
if (!(child instanceof TextView))
|
|
1476
|
+
if (!(child instanceof TextView) || /[^ -~]/.test(child.text))
|
|
1477
1477
|
return null;
|
|
1478
1478
|
let rects = clientRectsFor(child.dom);
|
|
1479
1479
|
if (rects.length != 1)
|
|
1480
1480
|
return null;
|
|
1481
1481
|
totalWidth += rects[0].width;
|
|
1482
1482
|
}
|
|
1483
|
-
return
|
|
1484
|
-
|
|
1483
|
+
return !totalWidth ? null : {
|
|
1484
|
+
lineHeight: this.dom.getBoundingClientRect().height,
|
|
1485
|
+
charWidth: totalWidth / this.length
|
|
1486
|
+
};
|
|
1485
1487
|
}
|
|
1486
1488
|
coordsAt(pos, side) {
|
|
1487
1489
|
return coordsInChildren(this, pos, side);
|
|
@@ -2481,7 +2483,6 @@ class DocView extends ContentView {
|
|
|
2481
2483
|
this.updateDeco();
|
|
2482
2484
|
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
|
|
2483
2485
|
}
|
|
2484
|
-
get root() { return this.view.root; }
|
|
2485
2486
|
get editorView() { return this.view; }
|
|
2486
2487
|
get length() { return this.view.state.doc.length; }
|
|
2487
2488
|
// Update the document view to a given state. scrollIntoView can be
|
|
@@ -2604,7 +2605,7 @@ class DocView extends ContentView {
|
|
|
2604
2605
|
this.dom.blur();
|
|
2605
2606
|
this.dom.focus({ preventScroll: true });
|
|
2606
2607
|
}
|
|
2607
|
-
let rawSel = getSelection(this.root);
|
|
2608
|
+
let rawSel = getSelection(this.view.root);
|
|
2608
2609
|
if (!rawSel) ;
|
|
2609
2610
|
else if (main.empty) {
|
|
2610
2611
|
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=1612076
|
|
@@ -2647,7 +2648,7 @@ class DocView extends ContentView {
|
|
|
2647
2648
|
if (this.compositionDeco.size)
|
|
2648
2649
|
return;
|
|
2649
2650
|
let cursor = this.view.state.selection.main;
|
|
2650
|
-
let sel = getSelection(this.root);
|
|
2651
|
+
let sel = getSelection(this.view.root);
|
|
2651
2652
|
if (!sel || !cursor.empty || !cursor.assoc || !sel.modify)
|
|
2652
2653
|
return;
|
|
2653
2654
|
let line = LineView.find(this, cursor.head);
|
|
@@ -2664,7 +2665,7 @@ class DocView extends ContentView {
|
|
|
2664
2665
|
sel.modify("move", cursor.assoc < 0 ? "forward" : "backward", "lineboundary");
|
|
2665
2666
|
}
|
|
2666
2667
|
mayControlSelection() {
|
|
2667
|
-
let active = this.root.activeElement;
|
|
2668
|
+
let active = this.view.root.activeElement;
|
|
2668
2669
|
return active == this.dom ||
|
|
2669
2670
|
hasSelection(this.dom, this.view.observer.selectionRange) && !(active && this.dom.contains(active));
|
|
2670
2671
|
}
|
|
@@ -3017,7 +3018,7 @@ function upBot(rect, bottom) {
|
|
|
3017
3018
|
return bottom > rect.bottom ? { top: rect.top, left: rect.left, right: rect.right, bottom } : rect;
|
|
3018
3019
|
}
|
|
3019
3020
|
function domPosAtCoords(parent, x, y) {
|
|
3020
|
-
let closest, closestRect, closestX, closestY;
|
|
3021
|
+
let closest, closestRect, closestX, closestY, closestOverlap = false;
|
|
3021
3022
|
let above, below, aboveRect, belowRect;
|
|
3022
3023
|
for (let child = parent.firstChild; child; child = child.nextSibling) {
|
|
3023
3024
|
let rects = clientRectsFor(child);
|
|
@@ -3033,6 +3034,7 @@ function domPosAtCoords(parent, x, y) {
|
|
|
3033
3034
|
closestRect = rect;
|
|
3034
3035
|
closestX = dx;
|
|
3035
3036
|
closestY = dy;
|
|
3037
|
+
closestOverlap = !dx || (dx > 0 ? i < rects.length - 1 : i > 0);
|
|
3036
3038
|
}
|
|
3037
3039
|
if (dx == 0) {
|
|
3038
3040
|
if (y > rect.bottom && (!aboveRect || aboveRect.bottom < rect.bottom)) {
|
|
@@ -3065,7 +3067,7 @@ function domPosAtCoords(parent, x, y) {
|
|
|
3065
3067
|
let clipX = Math.max(closestRect.left, Math.min(closestRect.right, x));
|
|
3066
3068
|
if (closest.nodeType == 3)
|
|
3067
3069
|
return domPosInText(closest, clipX, y);
|
|
3068
|
-
if (
|
|
3070
|
+
if (closestOverlap && closest.contentEditable != "false")
|
|
3069
3071
|
return domPosAtCoords(closest, clipX, y);
|
|
3070
3072
|
let offset = Array.prototype.indexOf.call(parent.childNodes, closest) +
|
|
3071
3073
|
(x >= (closestRect.left + closestRect.right) / 2 ? 1 : 0);
|
|
@@ -3162,7 +3164,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3162
3164
|
let range = doc.caretRangeFromPoint(x, y);
|
|
3163
3165
|
if (range) {
|
|
3164
3166
|
({ startContainer: node, startOffset: offset } = range);
|
|
3165
|
-
if (
|
|
3167
|
+
if (!view.contentDOM.contains(node) ||
|
|
3168
|
+
browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
|
|
3166
3169
|
browser.chrome && isSuspiciousChromeCaretResult(node, offset, x))
|
|
3167
3170
|
node = undefined;
|
|
3168
3171
|
}
|
|
@@ -4675,7 +4678,7 @@ function visiblePixelRange(dom, paddingTop) {
|
|
|
4675
4678
|
left = Math.max(left, parentRect.left);
|
|
4676
4679
|
right = Math.min(right, parentRect.right);
|
|
4677
4680
|
top = Math.max(top, parentRect.top);
|
|
4678
|
-
bottom = Math.min(bottom, parentRect.bottom);
|
|
4681
|
+
bottom = parent == dom.parentNode ? parentRect.bottom : Math.min(bottom, parentRect.bottom);
|
|
4679
4682
|
}
|
|
4680
4683
|
parent = style.position == "absolute" || style.position == "fixed" ? elt.offsetParent : elt.parentNode;
|
|
4681
4684
|
}
|
|
@@ -5376,6 +5379,7 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5376
5379
|
".cm-widgetBuffer": {
|
|
5377
5380
|
verticalAlign: "text-top",
|
|
5378
5381
|
height: "1em",
|
|
5382
|
+
width: 0,
|
|
5379
5383
|
display: "inline"
|
|
5380
5384
|
},
|
|
5381
5385
|
".cm-placeholder": {
|
|
@@ -5485,7 +5489,9 @@ class DOMObserver {
|
|
|
5485
5489
|
this.flushSoon();
|
|
5486
5490
|
};
|
|
5487
5491
|
this.onSelectionChange = this.onSelectionChange.bind(this);
|
|
5488
|
-
|
|
5492
|
+
this.onResize = this.onResize.bind(this);
|
|
5493
|
+
this.onPrint = this.onPrint.bind(this);
|
|
5494
|
+
this.onScroll = this.onScroll.bind(this);
|
|
5489
5495
|
if (typeof ResizeObserver == "function") {
|
|
5490
5496
|
this.resize = new ResizeObserver(() => {
|
|
5491
5497
|
if (this.view.docView.lastUpdate < Date.now() - 75)
|
|
@@ -5493,9 +5499,9 @@ class DOMObserver {
|
|
|
5493
5499
|
});
|
|
5494
5500
|
this.resize.observe(view.scrollDOM);
|
|
5495
5501
|
}
|
|
5496
|
-
|
|
5502
|
+
this.win = view.dom.ownerDocument.defaultView;
|
|
5503
|
+
this.addWindowListeners(this.win);
|
|
5497
5504
|
this.start();
|
|
5498
|
-
window.addEventListener("scroll", this.onScroll = this.onScroll.bind(this));
|
|
5499
5505
|
if (typeof IntersectionObserver == "function") {
|
|
5500
5506
|
this.intersection = new IntersectionObserver(entries => {
|
|
5501
5507
|
if (this.parentCheck < 0)
|
|
@@ -5514,7 +5520,6 @@ class DOMObserver {
|
|
|
5514
5520
|
}
|
|
5515
5521
|
this.listenForScroll();
|
|
5516
5522
|
this.readSelectionRange();
|
|
5517
|
-
this.dom.ownerDocument.addEventListener("selectionchange", this.onSelectionChange);
|
|
5518
5523
|
}
|
|
5519
5524
|
onScroll(e) {
|
|
5520
5525
|
if (this.intersecting)
|
|
@@ -5577,10 +5582,11 @@ class DOMObserver {
|
|
|
5577
5582
|
// Detect the situation where the browser has, on focus, moved the
|
|
5578
5583
|
// selection to the start of the content element. Reset it to the
|
|
5579
5584
|
// position from the editor state.
|
|
5580
|
-
if (local && !this.selectionChanged &&
|
|
5585
|
+
if (local && !this.selectionChanged &&
|
|
5581
5586
|
view.inputState.lastFocusTime > Date.now() - 200 &&
|
|
5582
5587
|
view.inputState.lastTouchTime < Date.now() - 300 &&
|
|
5583
5588
|
atElementStart(this.dom, range)) {
|
|
5589
|
+
this.view.inputState.lastFocusTime = 0;
|
|
5584
5590
|
view.docView.updateSelection();
|
|
5585
5591
|
return false;
|
|
5586
5592
|
}
|
|
@@ -5757,6 +5763,25 @@ class DOMObserver {
|
|
|
5757
5763
|
return null;
|
|
5758
5764
|
}
|
|
5759
5765
|
}
|
|
5766
|
+
setWindow(win) {
|
|
5767
|
+
if (win != this.win) {
|
|
5768
|
+
this.removeWindowListeners(this.win);
|
|
5769
|
+
this.win = win;
|
|
5770
|
+
this.addWindowListeners(this.win);
|
|
5771
|
+
}
|
|
5772
|
+
}
|
|
5773
|
+
addWindowListeners(win) {
|
|
5774
|
+
win.addEventListener("resize", this.onResize);
|
|
5775
|
+
win.addEventListener("beforeprint", this.onPrint);
|
|
5776
|
+
win.addEventListener("scroll", this.onScroll);
|
|
5777
|
+
win.document.addEventListener("selectionchange", this.onSelectionChange);
|
|
5778
|
+
}
|
|
5779
|
+
removeWindowListeners(win) {
|
|
5780
|
+
win.removeEventListener("scroll", this.onScroll);
|
|
5781
|
+
win.removeEventListener("resize", this.onResize);
|
|
5782
|
+
win.removeEventListener("beforeprint", this.onPrint);
|
|
5783
|
+
win.document.removeEventListener("selectionchange", this.onSelectionChange);
|
|
5784
|
+
}
|
|
5760
5785
|
destroy() {
|
|
5761
5786
|
var _a, _b, _c;
|
|
5762
5787
|
this.stop();
|
|
@@ -5765,10 +5790,7 @@ class DOMObserver {
|
|
|
5765
5790
|
(_c = this.resize) === null || _c === void 0 ? void 0 : _c.disconnect();
|
|
5766
5791
|
for (let dom of this.scrollTargets)
|
|
5767
5792
|
dom.removeEventListener("scroll", this.onScroll);
|
|
5768
|
-
|
|
5769
|
-
window.removeEventListener("resize", this.onResize);
|
|
5770
|
-
window.removeEventListener("beforeprint", this.onPrint);
|
|
5771
|
-
this.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange);
|
|
5793
|
+
this.removeWindowListeners(this.win);
|
|
5772
5794
|
clearTimeout(this.parentCheck);
|
|
5773
5795
|
clearTimeout(this.resizeTimeout);
|
|
5774
5796
|
}
|
|
@@ -6076,7 +6098,7 @@ class EditorView {
|
|
|
6076
6098
|
this.dom.appendChild(this.scrollDOM);
|
|
6077
6099
|
this._dispatch = config.dispatch || ((tr) => this.update([tr]));
|
|
6078
6100
|
this.dispatch = this.dispatch.bind(this);
|
|
6079
|
-
this.
|
|
6101
|
+
this._root = (config.root || getRoot(config.parent) || document);
|
|
6080
6102
|
this.viewState = new ViewState(config.state || state.EditorState.create(config));
|
|
6081
6103
|
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
6082
6104
|
for (let plugin of this.plugins)
|
|
@@ -6137,6 +6159,10 @@ class EditorView {
|
|
|
6137
6159
|
composition there.
|
|
6138
6160
|
*/
|
|
6139
6161
|
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
6162
|
+
/**
|
|
6163
|
+
The document or shadow root that the view lives in.
|
|
6164
|
+
*/
|
|
6165
|
+
get root() { return this._root; }
|
|
6140
6166
|
dispatch(...input) {
|
|
6141
6167
|
this._dispatch(input.length == 1 && input[0] instanceof state.Transaction ? input[0]
|
|
6142
6168
|
: this.state.update(...input));
|
|
@@ -6284,10 +6310,13 @@ class EditorView {
|
|
|
6284
6310
|
if (flush)
|
|
6285
6311
|
this.observer.forceFlush();
|
|
6286
6312
|
let updated = null;
|
|
6313
|
+
let { scrollHeight, scrollTop, clientHeight } = this.scrollDOM;
|
|
6314
|
+
let refHeight = scrollTop > scrollHeight - clientHeight - 4 ? scrollHeight : scrollTop;
|
|
6287
6315
|
try {
|
|
6288
6316
|
for (let i = 0;; i++) {
|
|
6289
6317
|
this.updateState = 1 /* Measuring */;
|
|
6290
6318
|
let oldViewport = this.viewport;
|
|
6319
|
+
let refBlock = this.viewState.lineBlockAtHeight(refHeight);
|
|
6291
6320
|
let changed = this.viewState.measure(this);
|
|
6292
6321
|
if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null)
|
|
6293
6322
|
break;
|
|
@@ -6339,6 +6368,13 @@ class EditorView {
|
|
|
6339
6368
|
this.viewState.scrollTarget = null;
|
|
6340
6369
|
scrolled = true;
|
|
6341
6370
|
}
|
|
6371
|
+
else {
|
|
6372
|
+
let diff = this.viewState.lineBlockAt(refBlock.from).top - refBlock.top;
|
|
6373
|
+
if (diff > 1 || diff < -1) {
|
|
6374
|
+
this.scrollDOM.scrollTop += diff;
|
|
6375
|
+
scrolled = true;
|
|
6376
|
+
}
|
|
6377
|
+
}
|
|
6342
6378
|
if (redrawn)
|
|
6343
6379
|
this.docView.updateSelection(true);
|
|
6344
6380
|
if (this.viewport.from == oldViewport.from && this.viewport.to == oldViewport.to &&
|
|
@@ -6462,7 +6498,7 @@ class EditorView {
|
|
|
6462
6498
|
/**
|
|
6463
6499
|
Find the text line or block widget at the given vertical
|
|
6464
6500
|
position (which is interpreted as relative to the [top of the
|
|
6465
|
-
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)
|
|
6501
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)).
|
|
6466
6502
|
*/
|
|
6467
6503
|
elementAtHeight(height) {
|
|
6468
6504
|
this.readMeasured();
|
|
@@ -6471,7 +6507,8 @@ class EditorView {
|
|
|
6471
6507
|
/**
|
|
6472
6508
|
Find the line block (see
|
|
6473
6509
|
[`lineBlockAt`](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) at the given
|
|
6474
|
-
height
|
|
6510
|
+
height, again interpreted relative to the [top of the
|
|
6511
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop).
|
|
6475
6512
|
*/
|
|
6476
6513
|
lineBlockAtHeight(height) {
|
|
6477
6514
|
this.readMeasured();
|
|
@@ -6678,6 +6715,17 @@ class EditorView {
|
|
|
6678
6715
|
});
|
|
6679
6716
|
}
|
|
6680
6717
|
/**
|
|
6718
|
+
Update the [root](https://codemirror.net/6/docs/ref/##view.EditorViewConfig.root) in which the editor lives. This is only
|
|
6719
|
+
necessary when moving the editor's existing DOM to a new window or shadow root.
|
|
6720
|
+
*/
|
|
6721
|
+
setRoot(root) {
|
|
6722
|
+
if (this._root != root) {
|
|
6723
|
+
this._root = root;
|
|
6724
|
+
this.observer.setWindow((root.nodeType == 9 ? root : root.ownerDocument).defaultView);
|
|
6725
|
+
this.mountStyles();
|
|
6726
|
+
}
|
|
6727
|
+
}
|
|
6728
|
+
/**
|
|
6681
6729
|
Clean up this editor view, removing its element from the
|
|
6682
6730
|
document, unregistering event handlers, and notifying
|
|
6683
6731
|
plugins. The view instance can no longer be used after
|
package/dist/index.d.ts
CHANGED
|
@@ -647,10 +647,11 @@ declare class EditorView {
|
|
|
647
647
|
*/
|
|
648
648
|
get compositionStarted(): boolean;
|
|
649
649
|
private _dispatch;
|
|
650
|
+
private _root;
|
|
650
651
|
/**
|
|
651
652
|
The document or shadow root that the view lives in.
|
|
652
653
|
*/
|
|
653
|
-
|
|
654
|
+
get root(): DocumentOrShadowRoot;
|
|
654
655
|
/**
|
|
655
656
|
The DOM element that wraps the entire editor view.
|
|
656
657
|
*/
|
|
@@ -752,13 +753,14 @@ declare class EditorView {
|
|
|
752
753
|
/**
|
|
753
754
|
Find the text line or block widget at the given vertical
|
|
754
755
|
position (which is interpreted as relative to the [top of the
|
|
755
|
-
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)
|
|
756
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)).
|
|
756
757
|
*/
|
|
757
758
|
elementAtHeight(height: number): BlockInfo;
|
|
758
759
|
/**
|
|
759
760
|
Find the line block (see
|
|
760
761
|
[`lineBlockAt`](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) at the given
|
|
761
|
-
height
|
|
762
|
+
height, again interpreted relative to the [top of the
|
|
763
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop).
|
|
762
764
|
*/
|
|
763
765
|
lineBlockAtHeight(height: number): BlockInfo;
|
|
764
766
|
/**
|
|
@@ -921,6 +923,11 @@ declare class EditorView {
|
|
|
921
923
|
*/
|
|
922
924
|
focus(): void;
|
|
923
925
|
/**
|
|
926
|
+
Update the [root](https://codemirror.net/6/docs/ref/##view.EditorViewConfig.root) in which the editor lives. This is only
|
|
927
|
+
necessary when moving the editor's existing DOM to a new window or shadow root.
|
|
928
|
+
*/
|
|
929
|
+
setRoot(root: Document | ShadowRoot): void;
|
|
930
|
+
/**
|
|
924
931
|
Clean up this editor view, removing its element from the
|
|
925
932
|
document, unregistering event handlers, and notifying
|
|
926
933
|
plugins. The view instance can no longer be used after
|
package/dist/index.js
CHANGED
|
@@ -1468,15 +1468,17 @@ class LineView extends ContentView {
|
|
|
1468
1468
|
return null;
|
|
1469
1469
|
let totalWidth = 0;
|
|
1470
1470
|
for (let child of this.children) {
|
|
1471
|
-
if (!(child instanceof TextView))
|
|
1471
|
+
if (!(child instanceof TextView) || /[^ -~]/.test(child.text))
|
|
1472
1472
|
return null;
|
|
1473
1473
|
let rects = clientRectsFor(child.dom);
|
|
1474
1474
|
if (rects.length != 1)
|
|
1475
1475
|
return null;
|
|
1476
1476
|
totalWidth += rects[0].width;
|
|
1477
1477
|
}
|
|
1478
|
-
return
|
|
1479
|
-
|
|
1478
|
+
return !totalWidth ? null : {
|
|
1479
|
+
lineHeight: this.dom.getBoundingClientRect().height,
|
|
1480
|
+
charWidth: totalWidth / this.length
|
|
1481
|
+
};
|
|
1480
1482
|
}
|
|
1481
1483
|
coordsAt(pos, side) {
|
|
1482
1484
|
return coordsInChildren(this, pos, side);
|
|
@@ -2475,7 +2477,6 @@ class DocView extends ContentView {
|
|
|
2475
2477
|
this.updateDeco();
|
|
2476
2478
|
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
|
|
2477
2479
|
}
|
|
2478
|
-
get root() { return this.view.root; }
|
|
2479
2480
|
get editorView() { return this.view; }
|
|
2480
2481
|
get length() { return this.view.state.doc.length; }
|
|
2481
2482
|
// Update the document view to a given state. scrollIntoView can be
|
|
@@ -2598,7 +2599,7 @@ class DocView extends ContentView {
|
|
|
2598
2599
|
this.dom.blur();
|
|
2599
2600
|
this.dom.focus({ preventScroll: true });
|
|
2600
2601
|
}
|
|
2601
|
-
let rawSel = getSelection(this.root);
|
|
2602
|
+
let rawSel = getSelection(this.view.root);
|
|
2602
2603
|
if (!rawSel) ;
|
|
2603
2604
|
else if (main.empty) {
|
|
2604
2605
|
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=1612076
|
|
@@ -2641,7 +2642,7 @@ class DocView extends ContentView {
|
|
|
2641
2642
|
if (this.compositionDeco.size)
|
|
2642
2643
|
return;
|
|
2643
2644
|
let cursor = this.view.state.selection.main;
|
|
2644
|
-
let sel = getSelection(this.root);
|
|
2645
|
+
let sel = getSelection(this.view.root);
|
|
2645
2646
|
if (!sel || !cursor.empty || !cursor.assoc || !sel.modify)
|
|
2646
2647
|
return;
|
|
2647
2648
|
let line = LineView.find(this, cursor.head);
|
|
@@ -2658,7 +2659,7 @@ class DocView extends ContentView {
|
|
|
2658
2659
|
sel.modify("move", cursor.assoc < 0 ? "forward" : "backward", "lineboundary");
|
|
2659
2660
|
}
|
|
2660
2661
|
mayControlSelection() {
|
|
2661
|
-
let active = this.root.activeElement;
|
|
2662
|
+
let active = this.view.root.activeElement;
|
|
2662
2663
|
return active == this.dom ||
|
|
2663
2664
|
hasSelection(this.dom, this.view.observer.selectionRange) && !(active && this.dom.contains(active));
|
|
2664
2665
|
}
|
|
@@ -3011,7 +3012,7 @@ function upBot(rect, bottom) {
|
|
|
3011
3012
|
return bottom > rect.bottom ? { top: rect.top, left: rect.left, right: rect.right, bottom } : rect;
|
|
3012
3013
|
}
|
|
3013
3014
|
function domPosAtCoords(parent, x, y) {
|
|
3014
|
-
let closest, closestRect, closestX, closestY;
|
|
3015
|
+
let closest, closestRect, closestX, closestY, closestOverlap = false;
|
|
3015
3016
|
let above, below, aboveRect, belowRect;
|
|
3016
3017
|
for (let child = parent.firstChild; child; child = child.nextSibling) {
|
|
3017
3018
|
let rects = clientRectsFor(child);
|
|
@@ -3027,6 +3028,7 @@ function domPosAtCoords(parent, x, y) {
|
|
|
3027
3028
|
closestRect = rect;
|
|
3028
3029
|
closestX = dx;
|
|
3029
3030
|
closestY = dy;
|
|
3031
|
+
closestOverlap = !dx || (dx > 0 ? i < rects.length - 1 : i > 0);
|
|
3030
3032
|
}
|
|
3031
3033
|
if (dx == 0) {
|
|
3032
3034
|
if (y > rect.bottom && (!aboveRect || aboveRect.bottom < rect.bottom)) {
|
|
@@ -3059,7 +3061,7 @@ function domPosAtCoords(parent, x, y) {
|
|
|
3059
3061
|
let clipX = Math.max(closestRect.left, Math.min(closestRect.right, x));
|
|
3060
3062
|
if (closest.nodeType == 3)
|
|
3061
3063
|
return domPosInText(closest, clipX, y);
|
|
3062
|
-
if (
|
|
3064
|
+
if (closestOverlap && closest.contentEditable != "false")
|
|
3063
3065
|
return domPosAtCoords(closest, clipX, y);
|
|
3064
3066
|
let offset = Array.prototype.indexOf.call(parent.childNodes, closest) +
|
|
3065
3067
|
(x >= (closestRect.left + closestRect.right) / 2 ? 1 : 0);
|
|
@@ -3156,7 +3158,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3156
3158
|
let range = doc.caretRangeFromPoint(x, y);
|
|
3157
3159
|
if (range) {
|
|
3158
3160
|
({ startContainer: node, startOffset: offset } = range);
|
|
3159
|
-
if (
|
|
3161
|
+
if (!view.contentDOM.contains(node) ||
|
|
3162
|
+
browser.safari && isSuspiciousSafariCaretResult(node, offset, x) ||
|
|
3160
3163
|
browser.chrome && isSuspiciousChromeCaretResult(node, offset, x))
|
|
3161
3164
|
node = undefined;
|
|
3162
3165
|
}
|
|
@@ -4668,7 +4671,7 @@ function visiblePixelRange(dom, paddingTop) {
|
|
|
4668
4671
|
left = Math.max(left, parentRect.left);
|
|
4669
4672
|
right = Math.min(right, parentRect.right);
|
|
4670
4673
|
top = Math.max(top, parentRect.top);
|
|
4671
|
-
bottom = Math.min(bottom, parentRect.bottom);
|
|
4674
|
+
bottom = parent == dom.parentNode ? parentRect.bottom : Math.min(bottom, parentRect.bottom);
|
|
4672
4675
|
}
|
|
4673
4676
|
parent = style.position == "absolute" || style.position == "fixed" ? elt.offsetParent : elt.parentNode;
|
|
4674
4677
|
}
|
|
@@ -5369,6 +5372,7 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5369
5372
|
".cm-widgetBuffer": {
|
|
5370
5373
|
verticalAlign: "text-top",
|
|
5371
5374
|
height: "1em",
|
|
5375
|
+
width: 0,
|
|
5372
5376
|
display: "inline"
|
|
5373
5377
|
},
|
|
5374
5378
|
".cm-placeholder": {
|
|
@@ -5478,7 +5482,9 @@ class DOMObserver {
|
|
|
5478
5482
|
this.flushSoon();
|
|
5479
5483
|
};
|
|
5480
5484
|
this.onSelectionChange = this.onSelectionChange.bind(this);
|
|
5481
|
-
|
|
5485
|
+
this.onResize = this.onResize.bind(this);
|
|
5486
|
+
this.onPrint = this.onPrint.bind(this);
|
|
5487
|
+
this.onScroll = this.onScroll.bind(this);
|
|
5482
5488
|
if (typeof ResizeObserver == "function") {
|
|
5483
5489
|
this.resize = new ResizeObserver(() => {
|
|
5484
5490
|
if (this.view.docView.lastUpdate < Date.now() - 75)
|
|
@@ -5486,9 +5492,9 @@ class DOMObserver {
|
|
|
5486
5492
|
});
|
|
5487
5493
|
this.resize.observe(view.scrollDOM);
|
|
5488
5494
|
}
|
|
5489
|
-
|
|
5495
|
+
this.win = view.dom.ownerDocument.defaultView;
|
|
5496
|
+
this.addWindowListeners(this.win);
|
|
5490
5497
|
this.start();
|
|
5491
|
-
window.addEventListener("scroll", this.onScroll = this.onScroll.bind(this));
|
|
5492
5498
|
if (typeof IntersectionObserver == "function") {
|
|
5493
5499
|
this.intersection = new IntersectionObserver(entries => {
|
|
5494
5500
|
if (this.parentCheck < 0)
|
|
@@ -5507,7 +5513,6 @@ class DOMObserver {
|
|
|
5507
5513
|
}
|
|
5508
5514
|
this.listenForScroll();
|
|
5509
5515
|
this.readSelectionRange();
|
|
5510
|
-
this.dom.ownerDocument.addEventListener("selectionchange", this.onSelectionChange);
|
|
5511
5516
|
}
|
|
5512
5517
|
onScroll(e) {
|
|
5513
5518
|
if (this.intersecting)
|
|
@@ -5570,10 +5575,11 @@ class DOMObserver {
|
|
|
5570
5575
|
// Detect the situation where the browser has, on focus, moved the
|
|
5571
5576
|
// selection to the start of the content element. Reset it to the
|
|
5572
5577
|
// position from the editor state.
|
|
5573
|
-
if (local && !this.selectionChanged &&
|
|
5578
|
+
if (local && !this.selectionChanged &&
|
|
5574
5579
|
view.inputState.lastFocusTime > Date.now() - 200 &&
|
|
5575
5580
|
view.inputState.lastTouchTime < Date.now() - 300 &&
|
|
5576
5581
|
atElementStart(this.dom, range)) {
|
|
5582
|
+
this.view.inputState.lastFocusTime = 0;
|
|
5577
5583
|
view.docView.updateSelection();
|
|
5578
5584
|
return false;
|
|
5579
5585
|
}
|
|
@@ -5750,6 +5756,25 @@ class DOMObserver {
|
|
|
5750
5756
|
return null;
|
|
5751
5757
|
}
|
|
5752
5758
|
}
|
|
5759
|
+
setWindow(win) {
|
|
5760
|
+
if (win != this.win) {
|
|
5761
|
+
this.removeWindowListeners(this.win);
|
|
5762
|
+
this.win = win;
|
|
5763
|
+
this.addWindowListeners(this.win);
|
|
5764
|
+
}
|
|
5765
|
+
}
|
|
5766
|
+
addWindowListeners(win) {
|
|
5767
|
+
win.addEventListener("resize", this.onResize);
|
|
5768
|
+
win.addEventListener("beforeprint", this.onPrint);
|
|
5769
|
+
win.addEventListener("scroll", this.onScroll);
|
|
5770
|
+
win.document.addEventListener("selectionchange", this.onSelectionChange);
|
|
5771
|
+
}
|
|
5772
|
+
removeWindowListeners(win) {
|
|
5773
|
+
win.removeEventListener("scroll", this.onScroll);
|
|
5774
|
+
win.removeEventListener("resize", this.onResize);
|
|
5775
|
+
win.removeEventListener("beforeprint", this.onPrint);
|
|
5776
|
+
win.document.removeEventListener("selectionchange", this.onSelectionChange);
|
|
5777
|
+
}
|
|
5753
5778
|
destroy() {
|
|
5754
5779
|
var _a, _b, _c;
|
|
5755
5780
|
this.stop();
|
|
@@ -5758,10 +5783,7 @@ class DOMObserver {
|
|
|
5758
5783
|
(_c = this.resize) === null || _c === void 0 ? void 0 : _c.disconnect();
|
|
5759
5784
|
for (let dom of this.scrollTargets)
|
|
5760
5785
|
dom.removeEventListener("scroll", this.onScroll);
|
|
5761
|
-
|
|
5762
|
-
window.removeEventListener("resize", this.onResize);
|
|
5763
|
-
window.removeEventListener("beforeprint", this.onPrint);
|
|
5764
|
-
this.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange);
|
|
5786
|
+
this.removeWindowListeners(this.win);
|
|
5765
5787
|
clearTimeout(this.parentCheck);
|
|
5766
5788
|
clearTimeout(this.resizeTimeout);
|
|
5767
5789
|
}
|
|
@@ -6069,7 +6091,7 @@ class EditorView {
|
|
|
6069
6091
|
this.dom.appendChild(this.scrollDOM);
|
|
6070
6092
|
this._dispatch = config.dispatch || ((tr) => this.update([tr]));
|
|
6071
6093
|
this.dispatch = this.dispatch.bind(this);
|
|
6072
|
-
this.
|
|
6094
|
+
this._root = (config.root || getRoot(config.parent) || document);
|
|
6073
6095
|
this.viewState = new ViewState(config.state || EditorState.create(config));
|
|
6074
6096
|
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
6075
6097
|
for (let plugin of this.plugins)
|
|
@@ -6130,6 +6152,10 @@ class EditorView {
|
|
|
6130
6152
|
composition there.
|
|
6131
6153
|
*/
|
|
6132
6154
|
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
6155
|
+
/**
|
|
6156
|
+
The document or shadow root that the view lives in.
|
|
6157
|
+
*/
|
|
6158
|
+
get root() { return this._root; }
|
|
6133
6159
|
dispatch(...input) {
|
|
6134
6160
|
this._dispatch(input.length == 1 && input[0] instanceof Transaction ? input[0]
|
|
6135
6161
|
: this.state.update(...input));
|
|
@@ -6277,10 +6303,13 @@ class EditorView {
|
|
|
6277
6303
|
if (flush)
|
|
6278
6304
|
this.observer.forceFlush();
|
|
6279
6305
|
let updated = null;
|
|
6306
|
+
let { scrollHeight, scrollTop, clientHeight } = this.scrollDOM;
|
|
6307
|
+
let refHeight = scrollTop > scrollHeight - clientHeight - 4 ? scrollHeight : scrollTop;
|
|
6280
6308
|
try {
|
|
6281
6309
|
for (let i = 0;; i++) {
|
|
6282
6310
|
this.updateState = 1 /* Measuring */;
|
|
6283
6311
|
let oldViewport = this.viewport;
|
|
6312
|
+
let refBlock = this.viewState.lineBlockAtHeight(refHeight);
|
|
6284
6313
|
let changed = this.viewState.measure(this);
|
|
6285
6314
|
if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null)
|
|
6286
6315
|
break;
|
|
@@ -6332,6 +6361,13 @@ class EditorView {
|
|
|
6332
6361
|
this.viewState.scrollTarget = null;
|
|
6333
6362
|
scrolled = true;
|
|
6334
6363
|
}
|
|
6364
|
+
else {
|
|
6365
|
+
let diff = this.viewState.lineBlockAt(refBlock.from).top - refBlock.top;
|
|
6366
|
+
if (diff > 1 || diff < -1) {
|
|
6367
|
+
this.scrollDOM.scrollTop += diff;
|
|
6368
|
+
scrolled = true;
|
|
6369
|
+
}
|
|
6370
|
+
}
|
|
6335
6371
|
if (redrawn)
|
|
6336
6372
|
this.docView.updateSelection(true);
|
|
6337
6373
|
if (this.viewport.from == oldViewport.from && this.viewport.to == oldViewport.to &&
|
|
@@ -6455,7 +6491,7 @@ class EditorView {
|
|
|
6455
6491
|
/**
|
|
6456
6492
|
Find the text line or block widget at the given vertical
|
|
6457
6493
|
position (which is interpreted as relative to the [top of the
|
|
6458
|
-
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)
|
|
6494
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)).
|
|
6459
6495
|
*/
|
|
6460
6496
|
elementAtHeight(height) {
|
|
6461
6497
|
this.readMeasured();
|
|
@@ -6464,7 +6500,8 @@ class EditorView {
|
|
|
6464
6500
|
/**
|
|
6465
6501
|
Find the line block (see
|
|
6466
6502
|
[`lineBlockAt`](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) at the given
|
|
6467
|
-
height
|
|
6503
|
+
height, again interpreted relative to the [top of the
|
|
6504
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop).
|
|
6468
6505
|
*/
|
|
6469
6506
|
lineBlockAtHeight(height) {
|
|
6470
6507
|
this.readMeasured();
|
|
@@ -6671,6 +6708,17 @@ class EditorView {
|
|
|
6671
6708
|
});
|
|
6672
6709
|
}
|
|
6673
6710
|
/**
|
|
6711
|
+
Update the [root](https://codemirror.net/6/docs/ref/##view.EditorViewConfig.root) in which the editor lives. This is only
|
|
6712
|
+
necessary when moving the editor's existing DOM to a new window or shadow root.
|
|
6713
|
+
*/
|
|
6714
|
+
setRoot(root) {
|
|
6715
|
+
if (this._root != root) {
|
|
6716
|
+
this._root = root;
|
|
6717
|
+
this.observer.setWindow((root.nodeType == 9 ? root : root.ownerDocument).defaultView);
|
|
6718
|
+
this.mountStyles();
|
|
6719
|
+
}
|
|
6720
|
+
}
|
|
6721
|
+
/**
|
|
6674
6722
|
Clean up this editor view, removing its element from the
|
|
6675
6723
|
document, unregistering event handlers, and notifying
|
|
6676
6724
|
plugins. The view instance can no longer be used after
|