@codemirror/view 0.19.31 → 0.19.35
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 +46 -0
- package/dist/index.cjs +149 -86
- package/dist/index.d.ts +42 -3
- package/dist/index.js +149 -86
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,49 @@
|
|
|
1
|
+
## 0.19.35 (2021-12-20)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
The editor will now handle double-taps as if they are double-clicks, rather than letting the browser's native behavior happen (because the latter often does the wrong thing).
|
|
6
|
+
|
|
7
|
+
Fix an issue where backspacing out a selection on Chrome Android would sometimes only delete the last character due to event order issues.
|
|
8
|
+
|
|
9
|
+
`posAtCoords`, without second argument, will no longer return null for positions below or above the document.
|
|
10
|
+
|
|
11
|
+
## 0.19.34 (2021-12-17)
|
|
12
|
+
|
|
13
|
+
### Bug fixes
|
|
14
|
+
|
|
15
|
+
Fix a bug where content line elements would in some cases lose their `cm-line` class. Move test to scrollIntoView
|
|
16
|
+
|
|
17
|
+
## 0.19.33 (2021-12-16)
|
|
18
|
+
|
|
19
|
+
### Breaking changes
|
|
20
|
+
|
|
21
|
+
`EditorView.scrollTo` and `EditorView.centerOn` are deprecated in favor of `EditorView.scrollIntoView`, and will be removed in the next breaking release.
|
|
22
|
+
|
|
23
|
+
### Bug fixes
|
|
24
|
+
|
|
25
|
+
Fix an issue that could cause the editor to unnecessarily interfere with composition (especially visible on macOS Chrome).
|
|
26
|
+
|
|
27
|
+
A composition started with multiple lines selected will no longer be interruptd by the editor.
|
|
28
|
+
|
|
29
|
+
### New features
|
|
30
|
+
|
|
31
|
+
The new `EditorView.scrollIntoView` function allows you to do more fine-grained scrolling.
|
|
32
|
+
|
|
33
|
+
## 0.19.32 (2021-12-15)
|
|
34
|
+
|
|
35
|
+
### Bug fixes
|
|
36
|
+
|
|
37
|
+
Fix a bug where CodeMirror's own event handers would run even after a user-supplied handler called `preventDefault` on an event.
|
|
38
|
+
|
|
39
|
+
Properly draw selections when negative text-indent is used for soft wrapping.
|
|
40
|
+
|
|
41
|
+
Fix an issue where `viewportLineBlocks` could hold inaccurate height information when the vertical scaling changed.
|
|
42
|
+
|
|
43
|
+
Fixes drop cursor positioning when the document is scrolled. Force a content measure when the editor comes into view
|
|
44
|
+
|
|
45
|
+
Fix a bug that could cause the editor to not measure its layout the first time it came into view.
|
|
46
|
+
|
|
1
47
|
## 0.19.31 (2021-12-13)
|
|
2
48
|
|
|
3
49
|
### New features
|
package/dist/index.cjs
CHANGED
|
@@ -101,8 +101,7 @@ function windowRect(win) {
|
|
|
101
101
|
return { left: 0, right: win.innerWidth,
|
|
102
102
|
top: 0, bottom: win.innerHeight };
|
|
103
103
|
}
|
|
104
|
-
|
|
105
|
-
function scrollRectIntoView(dom, rect, side, center) {
|
|
104
|
+
function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
106
105
|
let doc = dom.ownerDocument, win = doc.defaultView;
|
|
107
106
|
for (let cur = dom; cur;) {
|
|
108
107
|
if (cur.nodeType == 1) { // Element
|
|
@@ -121,38 +120,42 @@ function scrollRectIntoView(dom, rect, side, center) {
|
|
|
121
120
|
top: rect.top, bottom: rect.top + cur.clientHeight };
|
|
122
121
|
}
|
|
123
122
|
let moveX = 0, moveY = 0;
|
|
124
|
-
if (
|
|
123
|
+
if (y == "nearest") {
|
|
124
|
+
if (rect.top < bounding.top) {
|
|
125
|
+
moveY = -(bounding.top - rect.top + yMargin);
|
|
126
|
+
if (side > 0 && rect.bottom > bounding.bottom + moveY)
|
|
127
|
+
moveY = rect.bottom - bounding.bottom + moveY + yMargin;
|
|
128
|
+
}
|
|
129
|
+
else if (rect.bottom > bounding.bottom) {
|
|
130
|
+
moveY = rect.bottom - bounding.bottom + yMargin;
|
|
131
|
+
if (side < 0 && (rect.top - moveY) < bounding.top)
|
|
132
|
+
moveY = -(bounding.top + moveY - rect.top + yMargin);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
125
136
|
let rectHeight = rect.bottom - rect.top, boundingHeight = bounding.bottom - bounding.top;
|
|
126
|
-
let targetTop
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
else if (side < 0)
|
|
130
|
-
targetTop = rect.top - ScrollSpace;
|
|
131
|
-
else
|
|
132
|
-
targetTop = rect.bottom + ScrollSpace - boundingHeight;
|
|
137
|
+
let targetTop = y == "center" && rectHeight <= boundingHeight ? rect.top + rectHeight / 2 - boundingHeight / 2 :
|
|
138
|
+
y == "start" || y == "center" && side < 0 ? rect.top - yMargin :
|
|
139
|
+
rect.bottom - boundingHeight + yMargin;
|
|
133
140
|
moveY = targetTop - bounding.top;
|
|
134
|
-
if (Math.abs(moveY) <= 1)
|
|
135
|
-
moveY = 0;
|
|
136
|
-
}
|
|
137
|
-
else if (rect.top < bounding.top) {
|
|
138
|
-
moveY = -(bounding.top - rect.top + ScrollSpace);
|
|
139
|
-
if (side > 0 && rect.bottom > bounding.bottom + moveY)
|
|
140
|
-
moveY = rect.bottom - bounding.bottom + moveY + ScrollSpace;
|
|
141
|
-
}
|
|
142
|
-
else if (rect.bottom > bounding.bottom) {
|
|
143
|
-
moveY = rect.bottom - bounding.bottom + ScrollSpace;
|
|
144
|
-
if (side < 0 && (rect.top - moveY) < bounding.top)
|
|
145
|
-
moveY = -(bounding.top + moveY - rect.top + ScrollSpace);
|
|
146
141
|
}
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
142
|
+
if (x == "nearest") {
|
|
143
|
+
if (rect.left < bounding.left) {
|
|
144
|
+
moveX = -(bounding.left - rect.left + xMargin);
|
|
145
|
+
if (side > 0 && rect.right > bounding.right + moveX)
|
|
146
|
+
moveX = rect.right - bounding.right + moveX + xMargin;
|
|
147
|
+
}
|
|
148
|
+
else if (rect.right > bounding.right) {
|
|
149
|
+
moveX = rect.right - bounding.right + xMargin;
|
|
150
|
+
if (side < 0 && rect.left < bounding.left + moveX)
|
|
151
|
+
moveX = -(bounding.left + moveX - rect.left + xMargin);
|
|
152
|
+
}
|
|
151
153
|
}
|
|
152
|
-
else
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
else {
|
|
155
|
+
let targetLeft = x == "center" ? rect.left + (rect.right - rect.left) / 2 - (bounding.right - bounding.left) / 2 :
|
|
156
|
+
(x == "start") == ltr ? rect.left - xMargin :
|
|
157
|
+
rect.right - (bounding.right - bounding.left) + xMargin;
|
|
158
|
+
moveX = targetLeft - bounding.left;
|
|
156
159
|
}
|
|
157
160
|
if (moveX || moveY) {
|
|
158
161
|
if (top) {
|
|
@@ -176,7 +179,7 @@ function scrollRectIntoView(dom, rect, side, center) {
|
|
|
176
179
|
if (top)
|
|
177
180
|
break;
|
|
178
181
|
cur = cur.assignedSlot || cur.parentNode;
|
|
179
|
-
|
|
182
|
+
x = y = "nearest";
|
|
180
183
|
}
|
|
181
184
|
else if (cur.nodeType == 11) { // A shadow root
|
|
182
185
|
cur = cur.host;
|
|
@@ -263,6 +266,10 @@ function getRoot(node) {
|
|
|
263
266
|
}
|
|
264
267
|
return null;
|
|
265
268
|
}
|
|
269
|
+
function clearAttributes(node) {
|
|
270
|
+
while (node.attributes.length)
|
|
271
|
+
node.removeAttributeNode(node.attributes[0]);
|
|
272
|
+
}
|
|
266
273
|
|
|
267
274
|
class DOMPos {
|
|
268
275
|
constructor(node, offset, precise = true) {
|
|
@@ -309,14 +316,16 @@ class ContentView {
|
|
|
309
316
|
// given position.
|
|
310
317
|
coordsAt(_pos, _side) { return null; }
|
|
311
318
|
sync(track) {
|
|
312
|
-
var _a;
|
|
313
319
|
if (this.dirty & 2 /* Node */) {
|
|
314
320
|
let parent = this.dom;
|
|
315
321
|
let pos = parent.firstChild;
|
|
316
322
|
for (let child of this.children) {
|
|
317
323
|
if (child.dirty) {
|
|
318
|
-
if (!child.dom && pos
|
|
319
|
-
|
|
324
|
+
if (!child.dom && pos) {
|
|
325
|
+
let contentView = ContentView.get(pos);
|
|
326
|
+
if (!contentView || !contentView.parent && contentView.constructor == child.constructor)
|
|
327
|
+
child.reuseDOM(pos);
|
|
328
|
+
}
|
|
320
329
|
child.sync(track);
|
|
321
330
|
child.dirty = 0 /* Not */;
|
|
322
331
|
}
|
|
@@ -344,7 +353,7 @@ class ContentView {
|
|
|
344
353
|
}
|
|
345
354
|
}
|
|
346
355
|
}
|
|
347
|
-
reuseDOM(_dom) {
|
|
356
|
+
reuseDOM(_dom) { }
|
|
348
357
|
localPosFromDOM(node, offset) {
|
|
349
358
|
let after;
|
|
350
359
|
if (node == this.dom) {
|
|
@@ -643,10 +652,8 @@ class TextView extends ContentView {
|
|
|
643
652
|
}
|
|
644
653
|
}
|
|
645
654
|
reuseDOM(dom) {
|
|
646
|
-
if (dom.nodeType
|
|
647
|
-
|
|
648
|
-
this.createDOM(dom);
|
|
649
|
-
return true;
|
|
655
|
+
if (dom.nodeType == 3)
|
|
656
|
+
this.createDOM(dom);
|
|
650
657
|
}
|
|
651
658
|
merge(from, to, source) {
|
|
652
659
|
if (source && (!(source instanceof TextView) || this.length - (to - from) + source.length > MaxJoinLen))
|
|
@@ -681,18 +688,26 @@ class MarkView extends ContentView {
|
|
|
681
688
|
for (let ch of children)
|
|
682
689
|
ch.setParent(this);
|
|
683
690
|
}
|
|
684
|
-
|
|
685
|
-
|
|
691
|
+
setAttrs(dom) {
|
|
692
|
+
clearAttributes(dom);
|
|
686
693
|
if (this.mark.class)
|
|
687
694
|
dom.className = this.mark.class;
|
|
688
695
|
if (this.mark.attrs)
|
|
689
696
|
for (let name in this.mark.attrs)
|
|
690
697
|
dom.setAttribute(name, this.mark.attrs[name]);
|
|
691
|
-
|
|
698
|
+
return dom;
|
|
699
|
+
}
|
|
700
|
+
reuseDOM(node) {
|
|
701
|
+
if (node.nodeName == this.mark.tagName.toUpperCase()) {
|
|
702
|
+
this.setDOM(node);
|
|
703
|
+
this.dirty |= 4 /* Attrs */ | 2 /* Node */;
|
|
704
|
+
}
|
|
692
705
|
}
|
|
693
706
|
sync(track) {
|
|
694
|
-
if (!this.dom
|
|
695
|
-
this.
|
|
707
|
+
if (!this.dom)
|
|
708
|
+
this.setDOM(this.setAttrs(document.createElement(this.mark.tagName)));
|
|
709
|
+
else if (this.dirty & 4 /* Attrs */)
|
|
710
|
+
this.setAttrs(this.dom);
|
|
696
711
|
super.sync(track);
|
|
697
712
|
}
|
|
698
713
|
merge(from, to, source, _hasStart, openStart, openEnd) {
|
|
@@ -836,8 +851,7 @@ class WidgetView extends ContentView {
|
|
|
836
851
|
}
|
|
837
852
|
class CompositionView extends WidgetView {
|
|
838
853
|
domAtPos(pos) { return new DOMPos(this.widget.text, pos); }
|
|
839
|
-
sync() {
|
|
840
|
-
this.setDOM(this.widget.toDOM()); }
|
|
854
|
+
sync() { this.setDOM(this.widget.toDOM()); }
|
|
841
855
|
localPosFromDOM(node, offset) {
|
|
842
856
|
return !offset ? 0 : node.nodeType == 3 ? Math.min(offset, this.length) : this.length;
|
|
843
857
|
}
|
|
@@ -1302,13 +1316,24 @@ class LineView extends ContentView {
|
|
|
1302
1316
|
domAtPos(pos) {
|
|
1303
1317
|
return inlineDOMAtPos(this.dom, this.children, pos);
|
|
1304
1318
|
}
|
|
1319
|
+
reuseDOM(node) {
|
|
1320
|
+
if (node.nodeName == "DIV") {
|
|
1321
|
+
this.setDOM(node);
|
|
1322
|
+
this.dirty |= 4 /* Attrs */ | 2 /* Node */;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1305
1325
|
sync(track) {
|
|
1306
1326
|
var _a;
|
|
1307
|
-
if (!this.dom
|
|
1327
|
+
if (!this.dom) {
|
|
1308
1328
|
this.setDOM(document.createElement("div"));
|
|
1309
1329
|
this.dom.className = "cm-line";
|
|
1310
1330
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
1311
1331
|
}
|
|
1332
|
+
else if (this.dirty & 4 /* Attrs */) {
|
|
1333
|
+
clearAttributes(this.dom);
|
|
1334
|
+
this.dom.className = "cm-line";
|
|
1335
|
+
this.prevAttrs = this.attrs ? null : undefined;
|
|
1336
|
+
}
|
|
1312
1337
|
if (this.prevAttrs !== undefined) {
|
|
1313
1338
|
updateAttrs(this.dom, this.prevAttrs, this.attrs);
|
|
1314
1339
|
this.dom.classList.add("cm-line");
|
|
@@ -1580,12 +1605,27 @@ const mouseSelectionStyle = state.Facet.define();
|
|
|
1580
1605
|
const exceptionSink = state.Facet.define();
|
|
1581
1606
|
const updateListener = state.Facet.define();
|
|
1582
1607
|
const inputHandler = state.Facet.define();
|
|
1608
|
+
// FIXME remove
|
|
1583
1609
|
const scrollTo = state.StateEffect.define({
|
|
1584
1610
|
map: (range, changes) => range.map(changes)
|
|
1585
1611
|
});
|
|
1612
|
+
// FIXME remove
|
|
1586
1613
|
const centerOn = state.StateEffect.define({
|
|
1587
1614
|
map: (range, changes) => range.map(changes)
|
|
1588
1615
|
});
|
|
1616
|
+
class ScrollTarget {
|
|
1617
|
+
constructor(range, y = "nearest", x = "nearest", yMargin = 5, xMargin = 5) {
|
|
1618
|
+
this.range = range;
|
|
1619
|
+
this.y = y;
|
|
1620
|
+
this.x = x;
|
|
1621
|
+
this.yMargin = yMargin;
|
|
1622
|
+
this.xMargin = xMargin;
|
|
1623
|
+
}
|
|
1624
|
+
map(changes) {
|
|
1625
|
+
return changes.empty ? this : new ScrollTarget(this.range.map(changes), this.y, this.x, this.yMargin, this.xMargin);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
const scrollIntoView = state.StateEffect.define({ map: (t, ch) => t.map(ch) });
|
|
1589
1629
|
/**
|
|
1590
1630
|
Log or report an unhandled exception in client code. Should
|
|
1591
1631
|
probably only be used by extension code that allows client code to
|
|
@@ -2664,7 +2704,8 @@ class DocView extends ContentView {
|
|
|
2664
2704
|
this.view.viewState.lineGapDeco
|
|
2665
2705
|
];
|
|
2666
2706
|
}
|
|
2667
|
-
scrollIntoView(
|
|
2707
|
+
scrollIntoView(target) {
|
|
2708
|
+
let { range } = target;
|
|
2668
2709
|
let rect = this.coordsAt(range.head, range.empty ? range.assoc : range.head > range.anchor ? -1 : 1), other;
|
|
2669
2710
|
if (!rect)
|
|
2670
2711
|
return;
|
|
@@ -2684,10 +2725,11 @@ class DocView extends ContentView {
|
|
|
2684
2725
|
if (bottom != null)
|
|
2685
2726
|
mBottom = Math.max(mBottom, bottom);
|
|
2686
2727
|
}
|
|
2687
|
-
|
|
2728
|
+
let targetRect = {
|
|
2688
2729
|
left: rect.left - mLeft, top: rect.top - mTop,
|
|
2689
2730
|
right: rect.right + mRight, bottom: rect.bottom + mBottom
|
|
2690
|
-
}
|
|
2731
|
+
};
|
|
2732
|
+
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);
|
|
2691
2733
|
}
|
|
2692
2734
|
}
|
|
2693
2735
|
function betweenUneditable(pos) {
|
|
@@ -2948,12 +2990,8 @@ function domPosInText(node, x, y) {
|
|
|
2948
2990
|
function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
2949
2991
|
var _a;
|
|
2950
2992
|
let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
|
|
2951
|
-
let block,
|
|
2952
|
-
|
|
2953
|
-
if (precise)
|
|
2954
|
-
return null;
|
|
2955
|
-
yOffset = yOffset < 0 ? 0 : docHeight;
|
|
2956
|
-
}
|
|
2993
|
+
let block, { docHeight } = view.viewState;
|
|
2994
|
+
let yOffset = Math.max(0, Math.min(y - docTop, docHeight));
|
|
2957
2995
|
// Scan for a text block near the queried y position
|
|
2958
2996
|
for (let halfLine = view.defaultLineHeight / 2, bounced = false;;) {
|
|
2959
2997
|
block = view.elementAtHeight(yOffset);
|
|
@@ -2974,20 +3012,29 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
2974
3012
|
}
|
|
2975
3013
|
y = docTop + yOffset;
|
|
2976
3014
|
let lineStart = block.from;
|
|
2977
|
-
// Clip x to the viewport sides
|
|
2978
|
-
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
2979
3015
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
2980
3016
|
if (lineStart < view.viewport.from)
|
|
2981
|
-
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
3017
|
+
return view.viewport.from == 0 ? 0 : precise ? posAtCoordsImprecise(view, content, block, x, y) : null;
|
|
2982
3018
|
if (lineStart > view.viewport.to)
|
|
2983
|
-
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3019
|
+
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3020
|
+
precise ? posAtCoordsImprecise(view, content, block, x, y) : null;
|
|
2984
3021
|
// Prefer ShadowRootOrDocument.elementFromPoint if present, fall back to document if not
|
|
2985
3022
|
let doc = view.dom.ownerDocument;
|
|
2986
|
-
let
|
|
3023
|
+
let root = view.root.elementFromPoint ? view.root : doc;
|
|
3024
|
+
let element = root.elementFromPoint(x, y);
|
|
3025
|
+
if (element && !view.contentDOM.contains(element))
|
|
3026
|
+
element = null;
|
|
3027
|
+
// If the element is unexpected, clip x at the sides of the content area and try again
|
|
3028
|
+
if (!element) {
|
|
3029
|
+
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
3030
|
+
element = root.elementFromPoint(x, y);
|
|
3031
|
+
if (element && !view.contentDOM.contains(element))
|
|
3032
|
+
element = null;
|
|
3033
|
+
}
|
|
2987
3034
|
// There's visible editor content under the point, so we can try
|
|
2988
3035
|
// using caret(Position|Range)FromPoint as a shortcut
|
|
2989
3036
|
let node, offset = -1;
|
|
2990
|
-
if (element &&
|
|
3037
|
+
if (element && ((_a = view.docView.nearest(element)) === null || _a === void 0 ? void 0 : _a.isEditable) != false) {
|
|
2991
3038
|
if (doc.caretPositionFromPoint) {
|
|
2992
3039
|
let pos = doc.caretPositionFromPoint(x, y);
|
|
2993
3040
|
if (pos)
|
|
@@ -3199,7 +3246,7 @@ class InputState {
|
|
|
3199
3246
|
let handler = set.handlers[type];
|
|
3200
3247
|
if (handler) {
|
|
3201
3248
|
try {
|
|
3202
|
-
if (handler.call(set.plugin, event, view))
|
|
3249
|
+
if (handler.call(set.plugin, event, view) || event.defaultPrevented)
|
|
3203
3250
|
return true;
|
|
3204
3251
|
}
|
|
3205
3252
|
catch (e) {
|
|
@@ -3468,7 +3515,7 @@ handlers.touchmove = view => {
|
|
|
3468
3515
|
};
|
|
3469
3516
|
handlers.mousedown = (view, event) => {
|
|
3470
3517
|
view.observer.flush();
|
|
3471
|
-
if (lastTouch > Date.now() - 2000)
|
|
3518
|
+
if (lastTouch > Date.now() - 2000 && getClickType(event) == 1)
|
|
3472
3519
|
return; // Ignore touch interaction
|
|
3473
3520
|
let style = null;
|
|
3474
3521
|
for (let makeStyle of view.state.facet(mouseSelectionStyle)) {
|
|
@@ -3590,9 +3637,9 @@ handlers.dragstart = (view, event) => {
|
|
|
3590
3637
|
}
|
|
3591
3638
|
};
|
|
3592
3639
|
function dropText(view, event, text, direct) {
|
|
3593
|
-
|
|
3594
|
-
if (dropPos == null || !text)
|
|
3640
|
+
if (!text)
|
|
3595
3641
|
return;
|
|
3642
|
+
let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
3596
3643
|
event.preventDefault();
|
|
3597
3644
|
let { mouseSelection } = view.inputState;
|
|
3598
3645
|
let del = direct && mouseSelection && mouseSelection.dragging && mouseSelection.dragMove ?
|
|
@@ -4521,15 +4568,6 @@ class LineGapWidget extends WidgetType {
|
|
|
4521
4568
|
}
|
|
4522
4569
|
get estimatedHeight() { return this.vertical ? this.size : -1; }
|
|
4523
4570
|
}
|
|
4524
|
-
class ScrollTarget {
|
|
4525
|
-
constructor(range, center = false) {
|
|
4526
|
-
this.range = range;
|
|
4527
|
-
this.center = center;
|
|
4528
|
-
}
|
|
4529
|
-
map(changes) {
|
|
4530
|
-
return changes.empty ? this : new ScrollTarget(this.range.map(changes), this.center);
|
|
4531
|
-
}
|
|
4532
|
-
}
|
|
4533
4571
|
class ViewState {
|
|
4534
4572
|
constructor(state) {
|
|
4535
4573
|
this.state = state;
|
|
@@ -4604,9 +4642,9 @@ class ViewState {
|
|
|
4604
4642
|
let updateLines = !update.changes.empty || (update.flags & 2 /* Height */) ||
|
|
4605
4643
|
viewport.from != this.viewport.from || viewport.to != this.viewport.to;
|
|
4606
4644
|
this.viewport = viewport;
|
|
4645
|
+
this.updateForViewport();
|
|
4607
4646
|
if (updateLines)
|
|
4608
4647
|
this.updateViewportLines();
|
|
4609
|
-
this.updateForViewport();
|
|
4610
4648
|
if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
|
|
4611
4649
|
this.updateLineGaps(this.ensureLineGaps(this.mapLineGaps(this.lineGaps, update.changes)));
|
|
4612
4650
|
update.flags |= this.computeVisibleRanges();
|
|
@@ -4638,7 +4676,12 @@ class ViewState {
|
|
|
4638
4676
|
let pixelViewport = this.printing ? { top: -1e8, bottom: 1e8, left: -1e8, right: 1e8 } : visiblePixelRange(dom, this.paddingTop);
|
|
4639
4677
|
let dTop = pixelViewport.top - this.pixelViewport.top, dBottom = pixelViewport.bottom - this.pixelViewport.bottom;
|
|
4640
4678
|
this.pixelViewport = pixelViewport;
|
|
4641
|
-
|
|
4679
|
+
let inView = this.pixelViewport.bottom > this.pixelViewport.top && this.pixelViewport.right > this.pixelViewport.left;
|
|
4680
|
+
if (inView != this.inView) {
|
|
4681
|
+
this.inView = inView;
|
|
4682
|
+
if (inView)
|
|
4683
|
+
measureContent = true;
|
|
4684
|
+
}
|
|
4642
4685
|
if (!this.inView)
|
|
4643
4686
|
return 0;
|
|
4644
4687
|
if (measureContent) {
|
|
@@ -4675,9 +4718,9 @@ class ViewState {
|
|
|
4675
4718
|
this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from || this.scrollTarget.range.head > this.viewport.to);
|
|
4676
4719
|
if (viewportChange)
|
|
4677
4720
|
this.viewport = this.getViewport(bias, this.scrollTarget);
|
|
4721
|
+
this.updateForViewport();
|
|
4678
4722
|
if ((result & 2 /* Height */) || viewportChange)
|
|
4679
4723
|
this.updateViewportLines();
|
|
4680
|
-
this.updateForViewport();
|
|
4681
4724
|
if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
|
|
4682
4725
|
this.updateLineGaps(this.ensureLineGaps(refresh ? [] : this.lineGaps));
|
|
4683
4726
|
result |= this.computeVisibleRanges();
|
|
@@ -4705,9 +4748,9 @@ class ViewState {
|
|
|
4705
4748
|
let { head } = scrollTarget.range, viewHeight = this.editorHeight;
|
|
4706
4749
|
if (head < viewport.from || head > viewport.to) {
|
|
4707
4750
|
let block = map.lineAt(head, QueryType.ByPos, doc, 0, 0), topPos;
|
|
4708
|
-
if (scrollTarget.center)
|
|
4751
|
+
if (scrollTarget.y == "center")
|
|
4709
4752
|
topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
|
|
4710
|
-
else if (head < viewport.from)
|
|
4753
|
+
else if (scrollTarget.y == "start" || scrollTarget.y == "nearest" && head < viewport.from)
|
|
4711
4754
|
topPos = block.top;
|
|
4712
4755
|
else
|
|
4713
4756
|
topPos = block.bottom - viewHeight;
|
|
@@ -5213,7 +5256,7 @@ class DOMObserver {
|
|
|
5213
5256
|
this.intersection = new IntersectionObserver(entries => {
|
|
5214
5257
|
if (this.parentCheck < 0)
|
|
5215
5258
|
this.parentCheck = setTimeout(this.listenForScroll.bind(this), 1000);
|
|
5216
|
-
if (entries.length > 0 && entries[entries.length - 1].intersectionRatio > 0 != this.intersecting) {
|
|
5259
|
+
if (entries.length > 0 && (entries[entries.length - 1].intersectionRatio > 0) != this.intersecting) {
|
|
5217
5260
|
this.intersecting = !this.intersecting;
|
|
5218
5261
|
if (this.intersecting != this.view.inView)
|
|
5219
5262
|
this.onScrollChanged(document.createEvent("Event"));
|
|
@@ -5254,8 +5297,10 @@ class DOMObserver {
|
|
|
5254
5297
|
// Deletions on IE11 fire their events in the wrong order, giving
|
|
5255
5298
|
// us a selection change event before the DOM changes are
|
|
5256
5299
|
// reported.
|
|
5257
|
-
//
|
|
5258
|
-
|
|
5300
|
+
// Chrome Android has a similar issue when backspacing out a
|
|
5301
|
+
// selection (#645).
|
|
5302
|
+
if ((browser.ie && browser.ie_version <= 11 || browser.android && browser.chrome) && !view.state.selection.main.empty &&
|
|
5303
|
+
// (Selection.isCollapsed isn't reliable on IE)
|
|
5259
5304
|
sel.focusNode && isEquivalentPosition(sel.focusNode, sel.focusOffset, sel.anchorNode, sel.anchorOffset))
|
|
5260
5305
|
this.flushSoon();
|
|
5261
5306
|
else
|
|
@@ -5813,7 +5858,9 @@ class EditorView {
|
|
|
5813
5858
|
if (e.is(scrollTo))
|
|
5814
5859
|
scrollTarget = new ScrollTarget(e.value);
|
|
5815
5860
|
else if (e.is(centerOn))
|
|
5816
|
-
scrollTarget = new ScrollTarget(e.value,
|
|
5861
|
+
scrollTarget = new ScrollTarget(e.value, "center");
|
|
5862
|
+
else if (e.is(scrollIntoView))
|
|
5863
|
+
scrollTarget = e.value;
|
|
5817
5864
|
}
|
|
5818
5865
|
}
|
|
5819
5866
|
this.viewState.update(update, scrollTarget);
|
|
@@ -6381,6 +6428,14 @@ class EditorView {
|
|
|
6381
6428
|
this.destroyed = true;
|
|
6382
6429
|
}
|
|
6383
6430
|
/**
|
|
6431
|
+
Returns an effect that can be
|
|
6432
|
+
[added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a transaction to
|
|
6433
|
+
cause it to scroll the given position or range into view.
|
|
6434
|
+
*/
|
|
6435
|
+
static scrollIntoView(pos, options = {}) {
|
|
6436
|
+
return scrollIntoView.of(new ScrollTarget(typeof pos == "number" ? state.EditorSelection.cursor(pos) : pos, options.y, options.x, options.yMargin, options.xMargin));
|
|
6437
|
+
}
|
|
6438
|
+
/**
|
|
6384
6439
|
Facet that can be used to add DOM event handlers. The value
|
|
6385
6440
|
should be an object mapping event names to handler functions. The
|
|
6386
6441
|
first such function to return true will be assumed to have handled
|
|
@@ -6434,11 +6489,15 @@ class EditorView {
|
|
|
6434
6489
|
/**
|
|
6435
6490
|
Effect that can be [added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a
|
|
6436
6491
|
transaction to make it scroll the given range into view.
|
|
6492
|
+
|
|
6493
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
6437
6494
|
*/
|
|
6438
6495
|
EditorView.scrollTo = scrollTo;
|
|
6439
6496
|
/**
|
|
6440
6497
|
Effect that makes the editor scroll the given range to the
|
|
6441
6498
|
center of the visible view.
|
|
6499
|
+
|
|
6500
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
6442
6501
|
*/
|
|
6443
6502
|
EditorView.centerOn = centerOn;
|
|
6444
6503
|
/**
|
|
@@ -6907,7 +6966,7 @@ function measureRange(view, range) {
|
|
|
6907
6966
|
let ltr = view.textDirection == exports.Direction.LTR;
|
|
6908
6967
|
let content = view.contentDOM, contentRect = content.getBoundingClientRect(), base = getBase(view);
|
|
6909
6968
|
let lineStyle = window.getComputedStyle(content.firstChild);
|
|
6910
|
-
let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft);
|
|
6969
|
+
let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent));
|
|
6911
6970
|
let rightSide = contentRect.right - parseInt(lineStyle.paddingRight);
|
|
6912
6971
|
let startBlock = blockAt(view, from), endBlock = blockAt(view, to);
|
|
6913
6972
|
let visualStart = startBlock.type == exports.BlockType.Text ? startBlock : null;
|
|
@@ -7033,7 +7092,11 @@ const drawDropCursor = ViewPlugin.fromClass(class {
|
|
|
7033
7092
|
if (!rect)
|
|
7034
7093
|
return null;
|
|
7035
7094
|
let outer = this.view.scrollDOM.getBoundingClientRect();
|
|
7036
|
-
return {
|
|
7095
|
+
return {
|
|
7096
|
+
left: rect.left - outer.left + this.view.scrollDOM.scrollLeft,
|
|
7097
|
+
top: rect.top - outer.top + this.view.scrollDOM.scrollTop,
|
|
7098
|
+
height: rect.bottom - rect.top
|
|
7099
|
+
};
|
|
7037
7100
|
}
|
|
7038
7101
|
drawCursor(pos) {
|
|
7039
7102
|
if (this.cursor) {
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as _codemirror_rangeset from '@codemirror/rangeset';
|
|
|
2
2
|
import { RangeSet, RangeValue, Range } from '@codemirror/rangeset';
|
|
3
3
|
export { Range } from '@codemirror/rangeset';
|
|
4
4
|
import * as _codemirror_state from '@codemirror/state';
|
|
5
|
-
import { EditorState, Extension, Transaction, ChangeSet, EditorSelection, TransactionSpec, SelectionRange, Facet } from '@codemirror/state';
|
|
5
|
+
import { EditorState, Extension, Transaction, ChangeSet, EditorSelection, TransactionSpec, SelectionRange, StateEffect, Facet } from '@codemirror/state';
|
|
6
6
|
import { Line } from '@codemirror/text';
|
|
7
7
|
import { StyleModule, StyleSpec } from 'style-mod';
|
|
8
8
|
|
|
@@ -264,6 +264,7 @@ interface Rect {
|
|
|
264
264
|
readonly top: number;
|
|
265
265
|
readonly bottom: number;
|
|
266
266
|
}
|
|
267
|
+
declare type ScrollStrategy = "nearest" | "start" | "end" | "center";
|
|
267
268
|
|
|
268
269
|
/**
|
|
269
270
|
Command functions are used in key bindings and other types of user
|
|
@@ -936,8 +937,11 @@ declare class EditorView {
|
|
|
936
937
|
*/
|
|
937
938
|
posAtDOM(node: Node, offset?: number): number;
|
|
938
939
|
/**
|
|
939
|
-
Get the document position at the given screen coordinates.
|
|
940
|
-
|
|
940
|
+
Get the document position at the given screen coordinates. For
|
|
941
|
+
positions not covered by the visible viewport's DOM structure,
|
|
942
|
+
this will return null, unless `false` is passed as second
|
|
943
|
+
argument, in which case it'll return an estimated position that
|
|
944
|
+
would be near the coordinates if it were rendered.
|
|
941
945
|
*/
|
|
942
946
|
posAtCoords(coords: {
|
|
943
947
|
x: number;
|
|
@@ -1006,14 +1010,49 @@ declare class EditorView {
|
|
|
1006
1010
|
/**
|
|
1007
1011
|
Effect that can be [added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a
|
|
1008
1012
|
transaction to make it scroll the given range into view.
|
|
1013
|
+
|
|
1014
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
1009
1015
|
*/
|
|
1010
1016
|
static scrollTo: _codemirror_state.StateEffectType<SelectionRange>;
|
|
1011
1017
|
/**
|
|
1012
1018
|
Effect that makes the editor scroll the given range to the
|
|
1013
1019
|
center of the visible view.
|
|
1020
|
+
|
|
1021
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
1014
1022
|
*/
|
|
1015
1023
|
static centerOn: _codemirror_state.StateEffectType<SelectionRange>;
|
|
1016
1024
|
/**
|
|
1025
|
+
Returns an effect that can be
|
|
1026
|
+
[added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a transaction to
|
|
1027
|
+
cause it to scroll the given position or range into view.
|
|
1028
|
+
*/
|
|
1029
|
+
static scrollIntoView(pos: number | SelectionRange, options?: {
|
|
1030
|
+
/**
|
|
1031
|
+
By default (`"nearest"`) the position will be vertically
|
|
1032
|
+
scrolled only the minimal amount required to move the given
|
|
1033
|
+
position into view. You can set this to `"start"` to move it
|
|
1034
|
+
to the top of the view, `"end"` to move it to the bottom, or
|
|
1035
|
+
`"center"` to move it to the center.
|
|
1036
|
+
*/
|
|
1037
|
+
y?: ScrollStrategy;
|
|
1038
|
+
/**
|
|
1039
|
+
Effect similar to
|
|
1040
|
+
[`y`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView^options.y), but for the
|
|
1041
|
+
horizontal scroll position.
|
|
1042
|
+
*/
|
|
1043
|
+
x?: ScrollStrategy;
|
|
1044
|
+
/**
|
|
1045
|
+
Extra vertical distance to add when moving something into
|
|
1046
|
+
view. Not used with the `"center"` strategy. Defaults to 5.
|
|
1047
|
+
*/
|
|
1048
|
+
yMargin?: number;
|
|
1049
|
+
/**
|
|
1050
|
+
Extra horizontal distance to add. Not used with the `"center"`
|
|
1051
|
+
strategy. Defaults to 5.
|
|
1052
|
+
*/
|
|
1053
|
+
xMargin?: number;
|
|
1054
|
+
}): StateEffect<unknown>;
|
|
1055
|
+
/**
|
|
1017
1056
|
Facet to add a [style
|
|
1018
1057
|
module](https://github.com/marijnh/style-mod#documentation) to
|
|
1019
1058
|
an editor view. The view will ensure that the module is
|
package/dist/index.js
CHANGED
|
@@ -98,8 +98,7 @@ function windowRect(win) {
|
|
|
98
98
|
return { left: 0, right: win.innerWidth,
|
|
99
99
|
top: 0, bottom: win.innerHeight };
|
|
100
100
|
}
|
|
101
|
-
|
|
102
|
-
function scrollRectIntoView(dom, rect, side, center) {
|
|
101
|
+
function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
103
102
|
let doc = dom.ownerDocument, win = doc.defaultView;
|
|
104
103
|
for (let cur = dom; cur;) {
|
|
105
104
|
if (cur.nodeType == 1) { // Element
|
|
@@ -118,38 +117,42 @@ function scrollRectIntoView(dom, rect, side, center) {
|
|
|
118
117
|
top: rect.top, bottom: rect.top + cur.clientHeight };
|
|
119
118
|
}
|
|
120
119
|
let moveX = 0, moveY = 0;
|
|
121
|
-
if (
|
|
120
|
+
if (y == "nearest") {
|
|
121
|
+
if (rect.top < bounding.top) {
|
|
122
|
+
moveY = -(bounding.top - rect.top + yMargin);
|
|
123
|
+
if (side > 0 && rect.bottom > bounding.bottom + moveY)
|
|
124
|
+
moveY = rect.bottom - bounding.bottom + moveY + yMargin;
|
|
125
|
+
}
|
|
126
|
+
else if (rect.bottom > bounding.bottom) {
|
|
127
|
+
moveY = rect.bottom - bounding.bottom + yMargin;
|
|
128
|
+
if (side < 0 && (rect.top - moveY) < bounding.top)
|
|
129
|
+
moveY = -(bounding.top + moveY - rect.top + yMargin);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
122
133
|
let rectHeight = rect.bottom - rect.top, boundingHeight = bounding.bottom - bounding.top;
|
|
123
|
-
let targetTop
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
else if (side < 0)
|
|
127
|
-
targetTop = rect.top - ScrollSpace;
|
|
128
|
-
else
|
|
129
|
-
targetTop = rect.bottom + ScrollSpace - boundingHeight;
|
|
134
|
+
let targetTop = y == "center" && rectHeight <= boundingHeight ? rect.top + rectHeight / 2 - boundingHeight / 2 :
|
|
135
|
+
y == "start" || y == "center" && side < 0 ? rect.top - yMargin :
|
|
136
|
+
rect.bottom - boundingHeight + yMargin;
|
|
130
137
|
moveY = targetTop - bounding.top;
|
|
131
|
-
if (Math.abs(moveY) <= 1)
|
|
132
|
-
moveY = 0;
|
|
133
|
-
}
|
|
134
|
-
else if (rect.top < bounding.top) {
|
|
135
|
-
moveY = -(bounding.top - rect.top + ScrollSpace);
|
|
136
|
-
if (side > 0 && rect.bottom > bounding.bottom + moveY)
|
|
137
|
-
moveY = rect.bottom - bounding.bottom + moveY + ScrollSpace;
|
|
138
|
-
}
|
|
139
|
-
else if (rect.bottom > bounding.bottom) {
|
|
140
|
-
moveY = rect.bottom - bounding.bottom + ScrollSpace;
|
|
141
|
-
if (side < 0 && (rect.top - moveY) < bounding.top)
|
|
142
|
-
moveY = -(bounding.top + moveY - rect.top + ScrollSpace);
|
|
143
138
|
}
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
139
|
+
if (x == "nearest") {
|
|
140
|
+
if (rect.left < bounding.left) {
|
|
141
|
+
moveX = -(bounding.left - rect.left + xMargin);
|
|
142
|
+
if (side > 0 && rect.right > bounding.right + moveX)
|
|
143
|
+
moveX = rect.right - bounding.right + moveX + xMargin;
|
|
144
|
+
}
|
|
145
|
+
else if (rect.right > bounding.right) {
|
|
146
|
+
moveX = rect.right - bounding.right + xMargin;
|
|
147
|
+
if (side < 0 && rect.left < bounding.left + moveX)
|
|
148
|
+
moveX = -(bounding.left + moveX - rect.left + xMargin);
|
|
149
|
+
}
|
|
148
150
|
}
|
|
149
|
-
else
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
else {
|
|
152
|
+
let targetLeft = x == "center" ? rect.left + (rect.right - rect.left) / 2 - (bounding.right - bounding.left) / 2 :
|
|
153
|
+
(x == "start") == ltr ? rect.left - xMargin :
|
|
154
|
+
rect.right - (bounding.right - bounding.left) + xMargin;
|
|
155
|
+
moveX = targetLeft - bounding.left;
|
|
153
156
|
}
|
|
154
157
|
if (moveX || moveY) {
|
|
155
158
|
if (top) {
|
|
@@ -173,7 +176,7 @@ function scrollRectIntoView(dom, rect, side, center) {
|
|
|
173
176
|
if (top)
|
|
174
177
|
break;
|
|
175
178
|
cur = cur.assignedSlot || cur.parentNode;
|
|
176
|
-
|
|
179
|
+
x = y = "nearest";
|
|
177
180
|
}
|
|
178
181
|
else if (cur.nodeType == 11) { // A shadow root
|
|
179
182
|
cur = cur.host;
|
|
@@ -260,6 +263,10 @@ function getRoot(node) {
|
|
|
260
263
|
}
|
|
261
264
|
return null;
|
|
262
265
|
}
|
|
266
|
+
function clearAttributes(node) {
|
|
267
|
+
while (node.attributes.length)
|
|
268
|
+
node.removeAttributeNode(node.attributes[0]);
|
|
269
|
+
}
|
|
263
270
|
|
|
264
271
|
class DOMPos {
|
|
265
272
|
constructor(node, offset, precise = true) {
|
|
@@ -306,14 +313,16 @@ class ContentView {
|
|
|
306
313
|
// given position.
|
|
307
314
|
coordsAt(_pos, _side) { return null; }
|
|
308
315
|
sync(track) {
|
|
309
|
-
var _a;
|
|
310
316
|
if (this.dirty & 2 /* Node */) {
|
|
311
317
|
let parent = this.dom;
|
|
312
318
|
let pos = parent.firstChild;
|
|
313
319
|
for (let child of this.children) {
|
|
314
320
|
if (child.dirty) {
|
|
315
|
-
if (!child.dom && pos
|
|
316
|
-
|
|
321
|
+
if (!child.dom && pos) {
|
|
322
|
+
let contentView = ContentView.get(pos);
|
|
323
|
+
if (!contentView || !contentView.parent && contentView.constructor == child.constructor)
|
|
324
|
+
child.reuseDOM(pos);
|
|
325
|
+
}
|
|
317
326
|
child.sync(track);
|
|
318
327
|
child.dirty = 0 /* Not */;
|
|
319
328
|
}
|
|
@@ -341,7 +350,7 @@ class ContentView {
|
|
|
341
350
|
}
|
|
342
351
|
}
|
|
343
352
|
}
|
|
344
|
-
reuseDOM(_dom) {
|
|
353
|
+
reuseDOM(_dom) { }
|
|
345
354
|
localPosFromDOM(node, offset) {
|
|
346
355
|
let after;
|
|
347
356
|
if (node == this.dom) {
|
|
@@ -640,10 +649,8 @@ class TextView extends ContentView {
|
|
|
640
649
|
}
|
|
641
650
|
}
|
|
642
651
|
reuseDOM(dom) {
|
|
643
|
-
if (dom.nodeType
|
|
644
|
-
|
|
645
|
-
this.createDOM(dom);
|
|
646
|
-
return true;
|
|
652
|
+
if (dom.nodeType == 3)
|
|
653
|
+
this.createDOM(dom);
|
|
647
654
|
}
|
|
648
655
|
merge(from, to, source) {
|
|
649
656
|
if (source && (!(source instanceof TextView) || this.length - (to - from) + source.length > MaxJoinLen))
|
|
@@ -678,18 +685,26 @@ class MarkView extends ContentView {
|
|
|
678
685
|
for (let ch of children)
|
|
679
686
|
ch.setParent(this);
|
|
680
687
|
}
|
|
681
|
-
|
|
682
|
-
|
|
688
|
+
setAttrs(dom) {
|
|
689
|
+
clearAttributes(dom);
|
|
683
690
|
if (this.mark.class)
|
|
684
691
|
dom.className = this.mark.class;
|
|
685
692
|
if (this.mark.attrs)
|
|
686
693
|
for (let name in this.mark.attrs)
|
|
687
694
|
dom.setAttribute(name, this.mark.attrs[name]);
|
|
688
|
-
|
|
695
|
+
return dom;
|
|
696
|
+
}
|
|
697
|
+
reuseDOM(node) {
|
|
698
|
+
if (node.nodeName == this.mark.tagName.toUpperCase()) {
|
|
699
|
+
this.setDOM(node);
|
|
700
|
+
this.dirty |= 4 /* Attrs */ | 2 /* Node */;
|
|
701
|
+
}
|
|
689
702
|
}
|
|
690
703
|
sync(track) {
|
|
691
|
-
if (!this.dom
|
|
692
|
-
this.
|
|
704
|
+
if (!this.dom)
|
|
705
|
+
this.setDOM(this.setAttrs(document.createElement(this.mark.tagName)));
|
|
706
|
+
else if (this.dirty & 4 /* Attrs */)
|
|
707
|
+
this.setAttrs(this.dom);
|
|
693
708
|
super.sync(track);
|
|
694
709
|
}
|
|
695
710
|
merge(from, to, source, _hasStart, openStart, openEnd) {
|
|
@@ -833,8 +848,7 @@ class WidgetView extends ContentView {
|
|
|
833
848
|
}
|
|
834
849
|
class CompositionView extends WidgetView {
|
|
835
850
|
domAtPos(pos) { return new DOMPos(this.widget.text, pos); }
|
|
836
|
-
sync() {
|
|
837
|
-
this.setDOM(this.widget.toDOM()); }
|
|
851
|
+
sync() { this.setDOM(this.widget.toDOM()); }
|
|
838
852
|
localPosFromDOM(node, offset) {
|
|
839
853
|
return !offset ? 0 : node.nodeType == 3 ? Math.min(offset, this.length) : this.length;
|
|
840
854
|
}
|
|
@@ -1298,13 +1312,24 @@ class LineView extends ContentView {
|
|
|
1298
1312
|
domAtPos(pos) {
|
|
1299
1313
|
return inlineDOMAtPos(this.dom, this.children, pos);
|
|
1300
1314
|
}
|
|
1315
|
+
reuseDOM(node) {
|
|
1316
|
+
if (node.nodeName == "DIV") {
|
|
1317
|
+
this.setDOM(node);
|
|
1318
|
+
this.dirty |= 4 /* Attrs */ | 2 /* Node */;
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1301
1321
|
sync(track) {
|
|
1302
1322
|
var _a;
|
|
1303
|
-
if (!this.dom
|
|
1323
|
+
if (!this.dom) {
|
|
1304
1324
|
this.setDOM(document.createElement("div"));
|
|
1305
1325
|
this.dom.className = "cm-line";
|
|
1306
1326
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
1307
1327
|
}
|
|
1328
|
+
else if (this.dirty & 4 /* Attrs */) {
|
|
1329
|
+
clearAttributes(this.dom);
|
|
1330
|
+
this.dom.className = "cm-line";
|
|
1331
|
+
this.prevAttrs = this.attrs ? null : undefined;
|
|
1332
|
+
}
|
|
1308
1333
|
if (this.prevAttrs !== undefined) {
|
|
1309
1334
|
updateAttrs(this.dom, this.prevAttrs, this.attrs);
|
|
1310
1335
|
this.dom.classList.add("cm-line");
|
|
@@ -1576,12 +1601,27 @@ const mouseSelectionStyle = /*@__PURE__*/Facet.define();
|
|
|
1576
1601
|
const exceptionSink = /*@__PURE__*/Facet.define();
|
|
1577
1602
|
const updateListener = /*@__PURE__*/Facet.define();
|
|
1578
1603
|
const inputHandler = /*@__PURE__*/Facet.define();
|
|
1604
|
+
// FIXME remove
|
|
1579
1605
|
const scrollTo = /*@__PURE__*/StateEffect.define({
|
|
1580
1606
|
map: (range, changes) => range.map(changes)
|
|
1581
1607
|
});
|
|
1608
|
+
// FIXME remove
|
|
1582
1609
|
const centerOn = /*@__PURE__*/StateEffect.define({
|
|
1583
1610
|
map: (range, changes) => range.map(changes)
|
|
1584
1611
|
});
|
|
1612
|
+
class ScrollTarget {
|
|
1613
|
+
constructor(range, y = "nearest", x = "nearest", yMargin = 5, xMargin = 5) {
|
|
1614
|
+
this.range = range;
|
|
1615
|
+
this.y = y;
|
|
1616
|
+
this.x = x;
|
|
1617
|
+
this.yMargin = yMargin;
|
|
1618
|
+
this.xMargin = xMargin;
|
|
1619
|
+
}
|
|
1620
|
+
map(changes) {
|
|
1621
|
+
return changes.empty ? this : new ScrollTarget(this.range.map(changes), this.y, this.x, this.yMargin, this.xMargin);
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
const scrollIntoView = /*@__PURE__*/StateEffect.define({ map: (t, ch) => t.map(ch) });
|
|
1585
1625
|
/**
|
|
1586
1626
|
Log or report an unhandled exception in client code. Should
|
|
1587
1627
|
probably only be used by extension code that allows client code to
|
|
@@ -2659,7 +2699,8 @@ class DocView extends ContentView {
|
|
|
2659
2699
|
this.view.viewState.lineGapDeco
|
|
2660
2700
|
];
|
|
2661
2701
|
}
|
|
2662
|
-
scrollIntoView(
|
|
2702
|
+
scrollIntoView(target) {
|
|
2703
|
+
let { range } = target;
|
|
2663
2704
|
let rect = this.coordsAt(range.head, range.empty ? range.assoc : range.head > range.anchor ? -1 : 1), other;
|
|
2664
2705
|
if (!rect)
|
|
2665
2706
|
return;
|
|
@@ -2679,10 +2720,11 @@ class DocView extends ContentView {
|
|
|
2679
2720
|
if (bottom != null)
|
|
2680
2721
|
mBottom = Math.max(mBottom, bottom);
|
|
2681
2722
|
}
|
|
2682
|
-
|
|
2723
|
+
let targetRect = {
|
|
2683
2724
|
left: rect.left - mLeft, top: rect.top - mTop,
|
|
2684
2725
|
right: rect.right + mRight, bottom: rect.bottom + mBottom
|
|
2685
|
-
}
|
|
2726
|
+
};
|
|
2727
|
+
scrollRectIntoView(this.view.scrollDOM, targetRect, range.head < range.anchor ? -1 : 1, target.x, target.y, target.xMargin, target.yMargin, this.view.textDirection == Direction.LTR);
|
|
2686
2728
|
}
|
|
2687
2729
|
}
|
|
2688
2730
|
function betweenUneditable(pos) {
|
|
@@ -2943,12 +2985,8 @@ function domPosInText(node, x, y) {
|
|
|
2943
2985
|
function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
2944
2986
|
var _a;
|
|
2945
2987
|
let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
|
|
2946
|
-
let block,
|
|
2947
|
-
|
|
2948
|
-
if (precise)
|
|
2949
|
-
return null;
|
|
2950
|
-
yOffset = yOffset < 0 ? 0 : docHeight;
|
|
2951
|
-
}
|
|
2988
|
+
let block, { docHeight } = view.viewState;
|
|
2989
|
+
let yOffset = Math.max(0, Math.min(y - docTop, docHeight));
|
|
2952
2990
|
// Scan for a text block near the queried y position
|
|
2953
2991
|
for (let halfLine = view.defaultLineHeight / 2, bounced = false;;) {
|
|
2954
2992
|
block = view.elementAtHeight(yOffset);
|
|
@@ -2969,20 +3007,29 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
2969
3007
|
}
|
|
2970
3008
|
y = docTop + yOffset;
|
|
2971
3009
|
let lineStart = block.from;
|
|
2972
|
-
// Clip x to the viewport sides
|
|
2973
|
-
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
2974
3010
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
2975
3011
|
if (lineStart < view.viewport.from)
|
|
2976
|
-
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
3012
|
+
return view.viewport.from == 0 ? 0 : precise ? posAtCoordsImprecise(view, content, block, x, y) : null;
|
|
2977
3013
|
if (lineStart > view.viewport.to)
|
|
2978
|
-
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3014
|
+
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3015
|
+
precise ? posAtCoordsImprecise(view, content, block, x, y) : null;
|
|
2979
3016
|
// Prefer ShadowRootOrDocument.elementFromPoint if present, fall back to document if not
|
|
2980
3017
|
let doc = view.dom.ownerDocument;
|
|
2981
|
-
let
|
|
3018
|
+
let root = view.root.elementFromPoint ? view.root : doc;
|
|
3019
|
+
let element = root.elementFromPoint(x, y);
|
|
3020
|
+
if (element && !view.contentDOM.contains(element))
|
|
3021
|
+
element = null;
|
|
3022
|
+
// If the element is unexpected, clip x at the sides of the content area and try again
|
|
3023
|
+
if (!element) {
|
|
3024
|
+
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
3025
|
+
element = root.elementFromPoint(x, y);
|
|
3026
|
+
if (element && !view.contentDOM.contains(element))
|
|
3027
|
+
element = null;
|
|
3028
|
+
}
|
|
2982
3029
|
// There's visible editor content under the point, so we can try
|
|
2983
3030
|
// using caret(Position|Range)FromPoint as a shortcut
|
|
2984
3031
|
let node, offset = -1;
|
|
2985
|
-
if (element &&
|
|
3032
|
+
if (element && ((_a = view.docView.nearest(element)) === null || _a === void 0 ? void 0 : _a.isEditable) != false) {
|
|
2986
3033
|
if (doc.caretPositionFromPoint) {
|
|
2987
3034
|
let pos = doc.caretPositionFromPoint(x, y);
|
|
2988
3035
|
if (pos)
|
|
@@ -3194,7 +3241,7 @@ class InputState {
|
|
|
3194
3241
|
let handler = set.handlers[type];
|
|
3195
3242
|
if (handler) {
|
|
3196
3243
|
try {
|
|
3197
|
-
if (handler.call(set.plugin, event, view))
|
|
3244
|
+
if (handler.call(set.plugin, event, view) || event.defaultPrevented)
|
|
3198
3245
|
return true;
|
|
3199
3246
|
}
|
|
3200
3247
|
catch (e) {
|
|
@@ -3463,7 +3510,7 @@ handlers.touchmove = view => {
|
|
|
3463
3510
|
};
|
|
3464
3511
|
handlers.mousedown = (view, event) => {
|
|
3465
3512
|
view.observer.flush();
|
|
3466
|
-
if (lastTouch > Date.now() - 2000)
|
|
3513
|
+
if (lastTouch > Date.now() - 2000 && getClickType(event) == 1)
|
|
3467
3514
|
return; // Ignore touch interaction
|
|
3468
3515
|
let style = null;
|
|
3469
3516
|
for (let makeStyle of view.state.facet(mouseSelectionStyle)) {
|
|
@@ -3585,9 +3632,9 @@ handlers.dragstart = (view, event) => {
|
|
|
3585
3632
|
}
|
|
3586
3633
|
};
|
|
3587
3634
|
function dropText(view, event, text, direct) {
|
|
3588
|
-
|
|
3589
|
-
if (dropPos == null || !text)
|
|
3635
|
+
if (!text)
|
|
3590
3636
|
return;
|
|
3637
|
+
let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
3591
3638
|
event.preventDefault();
|
|
3592
3639
|
let { mouseSelection } = view.inputState;
|
|
3593
3640
|
let del = direct && mouseSelection && mouseSelection.dragging && mouseSelection.dragMove ?
|
|
@@ -4515,15 +4562,6 @@ class LineGapWidget extends WidgetType {
|
|
|
4515
4562
|
}
|
|
4516
4563
|
get estimatedHeight() { return this.vertical ? this.size : -1; }
|
|
4517
4564
|
}
|
|
4518
|
-
class ScrollTarget {
|
|
4519
|
-
constructor(range, center = false) {
|
|
4520
|
-
this.range = range;
|
|
4521
|
-
this.center = center;
|
|
4522
|
-
}
|
|
4523
|
-
map(changes) {
|
|
4524
|
-
return changes.empty ? this : new ScrollTarget(this.range.map(changes), this.center);
|
|
4525
|
-
}
|
|
4526
|
-
}
|
|
4527
4565
|
class ViewState {
|
|
4528
4566
|
constructor(state) {
|
|
4529
4567
|
this.state = state;
|
|
@@ -4598,9 +4636,9 @@ class ViewState {
|
|
|
4598
4636
|
let updateLines = !update.changes.empty || (update.flags & 2 /* Height */) ||
|
|
4599
4637
|
viewport.from != this.viewport.from || viewport.to != this.viewport.to;
|
|
4600
4638
|
this.viewport = viewport;
|
|
4639
|
+
this.updateForViewport();
|
|
4601
4640
|
if (updateLines)
|
|
4602
4641
|
this.updateViewportLines();
|
|
4603
|
-
this.updateForViewport();
|
|
4604
4642
|
if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
|
|
4605
4643
|
this.updateLineGaps(this.ensureLineGaps(this.mapLineGaps(this.lineGaps, update.changes)));
|
|
4606
4644
|
update.flags |= this.computeVisibleRanges();
|
|
@@ -4632,7 +4670,12 @@ class ViewState {
|
|
|
4632
4670
|
let pixelViewport = this.printing ? { top: -1e8, bottom: 1e8, left: -1e8, right: 1e8 } : visiblePixelRange(dom, this.paddingTop);
|
|
4633
4671
|
let dTop = pixelViewport.top - this.pixelViewport.top, dBottom = pixelViewport.bottom - this.pixelViewport.bottom;
|
|
4634
4672
|
this.pixelViewport = pixelViewport;
|
|
4635
|
-
|
|
4673
|
+
let inView = this.pixelViewport.bottom > this.pixelViewport.top && this.pixelViewport.right > this.pixelViewport.left;
|
|
4674
|
+
if (inView != this.inView) {
|
|
4675
|
+
this.inView = inView;
|
|
4676
|
+
if (inView)
|
|
4677
|
+
measureContent = true;
|
|
4678
|
+
}
|
|
4636
4679
|
if (!this.inView)
|
|
4637
4680
|
return 0;
|
|
4638
4681
|
if (measureContent) {
|
|
@@ -4669,9 +4712,9 @@ class ViewState {
|
|
|
4669
4712
|
this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from || this.scrollTarget.range.head > this.viewport.to);
|
|
4670
4713
|
if (viewportChange)
|
|
4671
4714
|
this.viewport = this.getViewport(bias, this.scrollTarget);
|
|
4715
|
+
this.updateForViewport();
|
|
4672
4716
|
if ((result & 2 /* Height */) || viewportChange)
|
|
4673
4717
|
this.updateViewportLines();
|
|
4674
|
-
this.updateForViewport();
|
|
4675
4718
|
if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
|
|
4676
4719
|
this.updateLineGaps(this.ensureLineGaps(refresh ? [] : this.lineGaps));
|
|
4677
4720
|
result |= this.computeVisibleRanges();
|
|
@@ -4699,9 +4742,9 @@ class ViewState {
|
|
|
4699
4742
|
let { head } = scrollTarget.range, viewHeight = this.editorHeight;
|
|
4700
4743
|
if (head < viewport.from || head > viewport.to) {
|
|
4701
4744
|
let block = map.lineAt(head, QueryType.ByPos, doc, 0, 0), topPos;
|
|
4702
|
-
if (scrollTarget.center)
|
|
4745
|
+
if (scrollTarget.y == "center")
|
|
4703
4746
|
topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
|
|
4704
|
-
else if (head < viewport.from)
|
|
4747
|
+
else if (scrollTarget.y == "start" || scrollTarget.y == "nearest" && head < viewport.from)
|
|
4705
4748
|
topPos = block.top;
|
|
4706
4749
|
else
|
|
4707
4750
|
topPos = block.bottom - viewHeight;
|
|
@@ -5207,7 +5250,7 @@ class DOMObserver {
|
|
|
5207
5250
|
this.intersection = new IntersectionObserver(entries => {
|
|
5208
5251
|
if (this.parentCheck < 0)
|
|
5209
5252
|
this.parentCheck = setTimeout(this.listenForScroll.bind(this), 1000);
|
|
5210
|
-
if (entries.length > 0 && entries[entries.length - 1].intersectionRatio > 0 != this.intersecting) {
|
|
5253
|
+
if (entries.length > 0 && (entries[entries.length - 1].intersectionRatio > 0) != this.intersecting) {
|
|
5211
5254
|
this.intersecting = !this.intersecting;
|
|
5212
5255
|
if (this.intersecting != this.view.inView)
|
|
5213
5256
|
this.onScrollChanged(document.createEvent("Event"));
|
|
@@ -5248,8 +5291,10 @@ class DOMObserver {
|
|
|
5248
5291
|
// Deletions on IE11 fire their events in the wrong order, giving
|
|
5249
5292
|
// us a selection change event before the DOM changes are
|
|
5250
5293
|
// reported.
|
|
5251
|
-
//
|
|
5252
|
-
|
|
5294
|
+
// Chrome Android has a similar issue when backspacing out a
|
|
5295
|
+
// selection (#645).
|
|
5296
|
+
if ((browser.ie && browser.ie_version <= 11 || browser.android && browser.chrome) && !view.state.selection.main.empty &&
|
|
5297
|
+
// (Selection.isCollapsed isn't reliable on IE)
|
|
5253
5298
|
sel.focusNode && isEquivalentPosition(sel.focusNode, sel.focusOffset, sel.anchorNode, sel.anchorOffset))
|
|
5254
5299
|
this.flushSoon();
|
|
5255
5300
|
else
|
|
@@ -5807,7 +5852,9 @@ class EditorView {
|
|
|
5807
5852
|
if (e.is(scrollTo))
|
|
5808
5853
|
scrollTarget = new ScrollTarget(e.value);
|
|
5809
5854
|
else if (e.is(centerOn))
|
|
5810
|
-
scrollTarget = new ScrollTarget(e.value,
|
|
5855
|
+
scrollTarget = new ScrollTarget(e.value, "center");
|
|
5856
|
+
else if (e.is(scrollIntoView))
|
|
5857
|
+
scrollTarget = e.value;
|
|
5811
5858
|
}
|
|
5812
5859
|
}
|
|
5813
5860
|
this.viewState.update(update, scrollTarget);
|
|
@@ -6375,6 +6422,14 @@ class EditorView {
|
|
|
6375
6422
|
this.destroyed = true;
|
|
6376
6423
|
}
|
|
6377
6424
|
/**
|
|
6425
|
+
Returns an effect that can be
|
|
6426
|
+
[added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a transaction to
|
|
6427
|
+
cause it to scroll the given position or range into view.
|
|
6428
|
+
*/
|
|
6429
|
+
static scrollIntoView(pos, options = {}) {
|
|
6430
|
+
return scrollIntoView.of(new ScrollTarget(typeof pos == "number" ? EditorSelection.cursor(pos) : pos, options.y, options.x, options.yMargin, options.xMargin));
|
|
6431
|
+
}
|
|
6432
|
+
/**
|
|
6378
6433
|
Facet that can be used to add DOM event handlers. The value
|
|
6379
6434
|
should be an object mapping event names to handler functions. The
|
|
6380
6435
|
first such function to return true will be assumed to have handled
|
|
@@ -6428,11 +6483,15 @@ class EditorView {
|
|
|
6428
6483
|
/**
|
|
6429
6484
|
Effect that can be [added](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) to a
|
|
6430
6485
|
transaction to make it scroll the given range into view.
|
|
6486
|
+
|
|
6487
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
6431
6488
|
*/
|
|
6432
6489
|
EditorView.scrollTo = scrollTo;
|
|
6433
6490
|
/**
|
|
6434
6491
|
Effect that makes the editor scroll the given range to the
|
|
6435
6492
|
center of the visible view.
|
|
6493
|
+
|
|
6494
|
+
*Deprecated*. Use [`scrollIntoView`](https://codemirror.net/6/docs/ref/#view.EditorView^scrollIntoView) instead.
|
|
6436
6495
|
*/
|
|
6437
6496
|
EditorView.centerOn = centerOn;
|
|
6438
6497
|
/**
|
|
@@ -6901,7 +6960,7 @@ function measureRange(view, range) {
|
|
|
6901
6960
|
let ltr = view.textDirection == Direction.LTR;
|
|
6902
6961
|
let content = view.contentDOM, contentRect = content.getBoundingClientRect(), base = getBase(view);
|
|
6903
6962
|
let lineStyle = window.getComputedStyle(content.firstChild);
|
|
6904
|
-
let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft);
|
|
6963
|
+
let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent));
|
|
6905
6964
|
let rightSide = contentRect.right - parseInt(lineStyle.paddingRight);
|
|
6906
6965
|
let startBlock = blockAt(view, from), endBlock = blockAt(view, to);
|
|
6907
6966
|
let visualStart = startBlock.type == BlockType.Text ? startBlock : null;
|
|
@@ -7027,7 +7086,11 @@ const drawDropCursor = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
7027
7086
|
if (!rect)
|
|
7028
7087
|
return null;
|
|
7029
7088
|
let outer = this.view.scrollDOM.getBoundingClientRect();
|
|
7030
|
-
return {
|
|
7089
|
+
return {
|
|
7090
|
+
left: rect.left - outer.left + this.view.scrollDOM.scrollLeft,
|
|
7091
|
+
top: rect.top - outer.top + this.view.scrollDOM.scrollTop,
|
|
7092
|
+
height: rect.bottom - rect.top
|
|
7093
|
+
};
|
|
7031
7094
|
}
|
|
7032
7095
|
drawCursor(pos) {
|
|
7033
7096
|
if (this.cursor) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemirror/view",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.35",
|
|
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/rangeset": "^0.19.
|
|
29
|
+
"@codemirror/rangeset": "^0.19.4",
|
|
30
30
|
"@codemirror/state": "^0.19.3",
|
|
31
31
|
"@codemirror/text": "^0.19.0",
|
|
32
32
|
"style-mod": "^4.0.0",
|