@codemirror/view 6.6.0 → 6.7.1
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 +28 -0
- package/dist/index.cjs +308 -155
- package/dist/index.d.ts +30 -3
- package/dist/index.js +304 -153
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -191,6 +191,26 @@ function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
+
function scrollableParent(dom) {
|
|
195
|
+
let doc = dom.ownerDocument;
|
|
196
|
+
for (let cur = dom.parentNode; cur;) {
|
|
197
|
+
if (cur == doc.body) {
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
else if (cur.nodeType == 1) {
|
|
201
|
+
if (cur.scrollHeight > cur.clientHeight || cur.scrollWidth > cur.clientWidth)
|
|
202
|
+
return cur;
|
|
203
|
+
cur = cur.assignedSlot || cur.parentNode;
|
|
204
|
+
}
|
|
205
|
+
else if (cur.nodeType == 11) {
|
|
206
|
+
cur = cur.host;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
194
214
|
class DOMSelectionState {
|
|
195
215
|
constructor() {
|
|
196
216
|
this.anchorNode = null;
|
|
@@ -1603,6 +1623,7 @@ class ContentBuilder {
|
|
|
1603
1623
|
this.curLine = null;
|
|
1604
1624
|
this.breakAtStart = 0;
|
|
1605
1625
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1626
|
+
this.bufferMarks = [];
|
|
1606
1627
|
// Set to false directly after a widget that covers the position after it
|
|
1607
1628
|
this.atCursorPos = true;
|
|
1608
1629
|
this.openStart = -1;
|
|
@@ -1625,20 +1646,20 @@ class ContentBuilder {
|
|
|
1625
1646
|
}
|
|
1626
1647
|
return this.curLine;
|
|
1627
1648
|
}
|
|
1628
|
-
flushBuffer(active) {
|
|
1649
|
+
flushBuffer(active = this.bufferMarks) {
|
|
1629
1650
|
if (this.pendingBuffer) {
|
|
1630
1651
|
this.curLine.append(wrapMarks(new WidgetBufferView(-1), active), active.length);
|
|
1631
1652
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1632
1653
|
}
|
|
1633
1654
|
}
|
|
1634
1655
|
addBlockWidget(view) {
|
|
1635
|
-
this.flushBuffer(
|
|
1656
|
+
this.flushBuffer();
|
|
1636
1657
|
this.curLine = null;
|
|
1637
1658
|
this.content.push(view);
|
|
1638
1659
|
}
|
|
1639
1660
|
finish(openEnd) {
|
|
1640
|
-
if (
|
|
1641
|
-
this.flushBuffer(
|
|
1661
|
+
if (this.pendingBuffer && openEnd <= this.bufferMarks.length)
|
|
1662
|
+
this.flushBuffer();
|
|
1642
1663
|
else
|
|
1643
1664
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1644
1665
|
if (!this.posCovered())
|
|
@@ -1658,8 +1679,9 @@ class ContentBuilder {
|
|
|
1658
1679
|
this.content[this.content.length - 1].breakAfter = 1;
|
|
1659
1680
|
else
|
|
1660
1681
|
this.breakAtStart = 1;
|
|
1661
|
-
this.flushBuffer(
|
|
1682
|
+
this.flushBuffer();
|
|
1662
1683
|
this.curLine = null;
|
|
1684
|
+
this.atCursorPos = true;
|
|
1663
1685
|
length--;
|
|
1664
1686
|
continue;
|
|
1665
1687
|
}
|
|
@@ -1701,7 +1723,7 @@ class ContentBuilder {
|
|
|
1701
1723
|
else {
|
|
1702
1724
|
let view = WidgetView.create(deco.widget || new NullWidget("span"), len, len ? 0 : deco.startSide);
|
|
1703
1725
|
let cursorBefore = this.atCursorPos && !view.isEditable && openStart <= active.length && (from < to || deco.startSide > 0);
|
|
1704
|
-
let cursorAfter = !view.isEditable && (from < to || deco.startSide <= 0);
|
|
1726
|
+
let cursorAfter = !view.isEditable && (from < to || openStart > active.length || deco.startSide <= 0);
|
|
1705
1727
|
let line = this.getLine();
|
|
1706
1728
|
if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore)
|
|
1707
1729
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
@@ -1712,7 +1734,9 @@ class ContentBuilder {
|
|
|
1712
1734
|
}
|
|
1713
1735
|
line.append(wrapMarks(view, active), openStart);
|
|
1714
1736
|
this.atCursorPos = cursorAfter;
|
|
1715
|
-
this.pendingBuffer = !cursorAfter ? 0 /* Buf.No */ : from < to ? 1 /* Buf.Yes */ : 2 /* Buf.IfCursor */;
|
|
1737
|
+
this.pendingBuffer = !cursorAfter ? 0 /* Buf.No */ : from < to || openStart > active.length ? 1 /* Buf.Yes */ : 2 /* Buf.IfCursor */;
|
|
1738
|
+
if (this.pendingBuffer)
|
|
1739
|
+
this.bufferMarks = active.slice();
|
|
1716
1740
|
}
|
|
1717
1741
|
}
|
|
1718
1742
|
else if (this.doc.lineAt(this.pos).from == this.pos) { // Line decoration
|
|
@@ -3387,22 +3411,30 @@ class InputState {
|
|
|
3387
3411
|
this.compositionFirstChange = null;
|
|
3388
3412
|
this.compositionEndedAt = 0;
|
|
3389
3413
|
this.mouseSelection = null;
|
|
3414
|
+
let handleEvent = (handler, event) => {
|
|
3415
|
+
if (this.ignoreDuringComposition(event))
|
|
3416
|
+
return;
|
|
3417
|
+
if (event.type == "keydown" && this.keydown(view, event))
|
|
3418
|
+
return;
|
|
3419
|
+
if (this.mustFlushObserver(event))
|
|
3420
|
+
view.observer.forceFlush();
|
|
3421
|
+
if (this.runCustomHandlers(event.type, view, event))
|
|
3422
|
+
event.preventDefault();
|
|
3423
|
+
else
|
|
3424
|
+
handler(view, event);
|
|
3425
|
+
};
|
|
3390
3426
|
for (let type in handlers) {
|
|
3391
3427
|
let handler = handlers[type];
|
|
3392
|
-
view.contentDOM.addEventListener(type,
|
|
3393
|
-
if (
|
|
3394
|
-
|
|
3395
|
-
if (type == "keydown" && this.keydown(view, event))
|
|
3396
|
-
return;
|
|
3397
|
-
if (this.mustFlushObserver(event))
|
|
3398
|
-
view.observer.forceFlush();
|
|
3399
|
-
if (this.runCustomHandlers(type, view, event))
|
|
3400
|
-
event.preventDefault();
|
|
3401
|
-
else
|
|
3402
|
-
handler(view, event);
|
|
3428
|
+
view.contentDOM.addEventListener(type, event => {
|
|
3429
|
+
if (eventBelongsToEditor(view, event))
|
|
3430
|
+
handleEvent(handler, event);
|
|
3403
3431
|
}, handlerOptions[type]);
|
|
3404
3432
|
this.registeredEvents.push(type);
|
|
3405
3433
|
}
|
|
3434
|
+
view.scrollDOM.addEventListener("mousedown", (event) => {
|
|
3435
|
+
if (event.target == view.scrollDOM)
|
|
3436
|
+
handleEvent(handlers.mousedown, event);
|
|
3437
|
+
});
|
|
3406
3438
|
if (browser.chrome && browser.chrome_version == 102) { // FIXME remove at some point
|
|
3407
3439
|
// On Chrome 102, viewport updates somehow stop wheel-based
|
|
3408
3440
|
// scrolling. Turning off pointer events during the scroll seems
|
|
@@ -3559,12 +3591,18 @@ const PendingKeys = [
|
|
|
3559
3591
|
const EmacsyPendingKeys = "dthko";
|
|
3560
3592
|
// Key codes for modifier keys
|
|
3561
3593
|
const modifierCodes = [16, 17, 18, 20, 91, 92, 224, 225];
|
|
3594
|
+
function dragScrollSpeed(dist) {
|
|
3595
|
+
return dist * 0.7 + 8;
|
|
3596
|
+
}
|
|
3562
3597
|
class MouseSelection {
|
|
3563
3598
|
constructor(view, startEvent, style, mustSelect) {
|
|
3564
3599
|
this.view = view;
|
|
3565
3600
|
this.style = style;
|
|
3566
3601
|
this.mustSelect = mustSelect;
|
|
3602
|
+
this.scrollSpeed = { x: 0, y: 0 };
|
|
3603
|
+
this.scrolling = -1;
|
|
3567
3604
|
this.lastEvent = startEvent;
|
|
3605
|
+
this.scrollParent = scrollableParent(view.contentDOM);
|
|
3568
3606
|
let doc = view.contentDOM.ownerDocument;
|
|
3569
3607
|
doc.addEventListener("mousemove", this.move = this.move.bind(this));
|
|
3570
3608
|
doc.addEventListener("mouseup", this.up = this.up.bind(this));
|
|
@@ -3580,11 +3618,24 @@ class MouseSelection {
|
|
|
3580
3618
|
}
|
|
3581
3619
|
}
|
|
3582
3620
|
move(event) {
|
|
3621
|
+
var _a;
|
|
3583
3622
|
if (event.buttons == 0)
|
|
3584
3623
|
return this.destroy();
|
|
3585
3624
|
if (this.dragging !== false)
|
|
3586
3625
|
return;
|
|
3587
3626
|
this.select(this.lastEvent = event);
|
|
3627
|
+
let sx = 0, sy = 0;
|
|
3628
|
+
let rect = ((_a = this.scrollParent) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect())
|
|
3629
|
+
|| { left: 0, top: 0, right: this.view.win.innerWidth, bottom: this.view.win.innerHeight };
|
|
3630
|
+
if (event.clientX <= rect.left)
|
|
3631
|
+
sx = -dragScrollSpeed(rect.left - event.clientX);
|
|
3632
|
+
else if (event.clientX >= rect.right)
|
|
3633
|
+
sx = dragScrollSpeed(event.clientX - rect.right);
|
|
3634
|
+
if (event.clientY <= rect.top)
|
|
3635
|
+
sy = -dragScrollSpeed(rect.top - event.clientY);
|
|
3636
|
+
else if (event.clientY >= rect.bottom)
|
|
3637
|
+
sy = dragScrollSpeed(event.clientY - rect.bottom);
|
|
3638
|
+
this.setScrollSpeed(sx, sy);
|
|
3588
3639
|
}
|
|
3589
3640
|
up(event) {
|
|
3590
3641
|
if (this.dragging == null)
|
|
@@ -3594,19 +3645,41 @@ class MouseSelection {
|
|
|
3594
3645
|
this.destroy();
|
|
3595
3646
|
}
|
|
3596
3647
|
destroy() {
|
|
3648
|
+
this.setScrollSpeed(0, 0);
|
|
3597
3649
|
let doc = this.view.contentDOM.ownerDocument;
|
|
3598
3650
|
doc.removeEventListener("mousemove", this.move);
|
|
3599
3651
|
doc.removeEventListener("mouseup", this.up);
|
|
3600
3652
|
this.view.inputState.mouseSelection = null;
|
|
3601
3653
|
}
|
|
3654
|
+
setScrollSpeed(sx, sy) {
|
|
3655
|
+
this.scrollSpeed = { x: sx, y: sy };
|
|
3656
|
+
if (sx || sy) {
|
|
3657
|
+
if (this.scrolling < 0)
|
|
3658
|
+
this.scrolling = setInterval(() => this.scroll(), 50);
|
|
3659
|
+
}
|
|
3660
|
+
else if (this.scrolling > -1) {
|
|
3661
|
+
clearInterval(this.scrolling);
|
|
3662
|
+
this.scrolling = -1;
|
|
3663
|
+
}
|
|
3664
|
+
}
|
|
3665
|
+
scroll() {
|
|
3666
|
+
if (this.scrollParent) {
|
|
3667
|
+
this.scrollParent.scrollLeft += this.scrollSpeed.x;
|
|
3668
|
+
this.scrollParent.scrollTop += this.scrollSpeed.y;
|
|
3669
|
+
}
|
|
3670
|
+
else {
|
|
3671
|
+
this.view.win.scrollBy(this.scrollSpeed.x, this.scrollSpeed.y);
|
|
3672
|
+
}
|
|
3673
|
+
if (this.dragging === false)
|
|
3674
|
+
this.select(this.lastEvent);
|
|
3675
|
+
}
|
|
3602
3676
|
select(event) {
|
|
3603
3677
|
let selection = this.style.get(event, this.extend, this.multiple);
|
|
3604
3678
|
if (this.mustSelect || !selection.eq(this.view.state.selection) ||
|
|
3605
3679
|
selection.main.assoc != this.view.state.selection.main.assoc)
|
|
3606
3680
|
this.view.dispatch({
|
|
3607
3681
|
selection,
|
|
3608
|
-
userEvent: "select.pointer"
|
|
3609
|
-
scrollIntoView: true
|
|
3682
|
+
userEvent: "select.pointer"
|
|
3610
3683
|
});
|
|
3611
3684
|
this.mustSelect = false;
|
|
3612
3685
|
}
|
|
@@ -3797,23 +3870,15 @@ function getClickType(event) {
|
|
|
3797
3870
|
function basicMouseSelection(view, event) {
|
|
3798
3871
|
let start = queryPos(view, event), type = getClickType(event);
|
|
3799
3872
|
let startSel = view.state.selection;
|
|
3800
|
-
let last = start, lastEvent = event;
|
|
3801
3873
|
return {
|
|
3802
3874
|
update(update) {
|
|
3803
3875
|
if (update.docChanged) {
|
|
3804
3876
|
start.pos = update.changes.mapPos(start.pos);
|
|
3805
3877
|
startSel = startSel.map(update.changes);
|
|
3806
|
-
lastEvent = null;
|
|
3807
3878
|
}
|
|
3808
3879
|
},
|
|
3809
3880
|
get(event, extend, multiple) {
|
|
3810
|
-
let cur;
|
|
3811
|
-
if (lastEvent && event.clientX == lastEvent.clientX && event.clientY == lastEvent.clientY)
|
|
3812
|
-
cur = last;
|
|
3813
|
-
else {
|
|
3814
|
-
cur = last = queryPos(view, event);
|
|
3815
|
-
lastEvent = event;
|
|
3816
|
-
}
|
|
3881
|
+
let cur = queryPos(view, event);
|
|
3817
3882
|
let range = rangeForClick(view, cur.pos, cur.bias, type);
|
|
3818
3883
|
if (start.pos != cur.pos && !extend) {
|
|
3819
3884
|
let startRange = rangeForClick(view, start.pos, start.bias, type);
|
|
@@ -5291,7 +5356,6 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5291
5356
|
margin: 0,
|
|
5292
5357
|
flexGrow: 2,
|
|
5293
5358
|
flexShrink: 0,
|
|
5294
|
-
minHeight: "100%",
|
|
5295
5359
|
display: "block",
|
|
5296
5360
|
whiteSpace: "pre",
|
|
5297
5361
|
wordWrap: "normal",
|
|
@@ -5438,6 +5502,21 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5438
5502
|
display: "inline-block",
|
|
5439
5503
|
verticalAlign: "top",
|
|
5440
5504
|
},
|
|
5505
|
+
".cm-highlightSpace:before": {
|
|
5506
|
+
content: "attr(data-display)",
|
|
5507
|
+
position: "absolute",
|
|
5508
|
+
pointerEvents: "none",
|
|
5509
|
+
color: "#888"
|
|
5510
|
+
},
|
|
5511
|
+
".cm-highlightTab": {
|
|
5512
|
+
backgroundImage: `url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="200" height="20"><path stroke="%23888" stroke-width="1" fill="none" d="M1 10H196L190 5M190 15L196 10M197 4L197 16"/></svg>')`,
|
|
5513
|
+
backgroundSize: "auto 100%",
|
|
5514
|
+
backgroundPosition: "right 90%",
|
|
5515
|
+
backgroundRepeat: "no-repeat"
|
|
5516
|
+
},
|
|
5517
|
+
".cm-trailingSpace": {
|
|
5518
|
+
backgroundColor: "#ff332255"
|
|
5519
|
+
},
|
|
5441
5520
|
".cm-button": {
|
|
5442
5521
|
verticalAlign: "middle",
|
|
5443
5522
|
color: "inherit",
|
|
@@ -5740,7 +5819,8 @@ class DOMObserver {
|
|
|
5740
5819
|
this.lastChange = 0;
|
|
5741
5820
|
this.scrollTargets = [];
|
|
5742
5821
|
this.intersection = null;
|
|
5743
|
-
this.
|
|
5822
|
+
this.resizeScroll = null;
|
|
5823
|
+
this.resizeContent = null;
|
|
5744
5824
|
this.intersecting = false;
|
|
5745
5825
|
this.gapIntersection = null;
|
|
5746
5826
|
this.gaps = [];
|
|
@@ -5778,12 +5858,14 @@ class DOMObserver {
|
|
|
5778
5858
|
this.onPrint = this.onPrint.bind(this);
|
|
5779
5859
|
this.onScroll = this.onScroll.bind(this);
|
|
5780
5860
|
if (typeof ResizeObserver == "function") {
|
|
5781
|
-
this.
|
|
5861
|
+
this.resizeScroll = new ResizeObserver(() => {
|
|
5782
5862
|
var _a;
|
|
5783
5863
|
if (((_a = this.view.docView) === null || _a === void 0 ? void 0 : _a.lastUpdate) < Date.now() - 75)
|
|
5784
5864
|
this.onResize();
|
|
5785
5865
|
});
|
|
5786
|
-
this.
|
|
5866
|
+
this.resizeScroll.observe(view.scrollDOM);
|
|
5867
|
+
this.resizeContent = new ResizeObserver(() => this.view.requestMeasure());
|
|
5868
|
+
this.resizeContent.observe(view.contentDOM);
|
|
5787
5869
|
}
|
|
5788
5870
|
this.addWindowListeners(this.win = view.win);
|
|
5789
5871
|
this.start();
|
|
@@ -6102,11 +6184,12 @@ class DOMObserver {
|
|
|
6102
6184
|
win.document.removeEventListener("selectionchange", this.onSelectionChange);
|
|
6103
6185
|
}
|
|
6104
6186
|
destroy() {
|
|
6105
|
-
var _a, _b, _c;
|
|
6187
|
+
var _a, _b, _c, _d;
|
|
6106
6188
|
this.stop();
|
|
6107
6189
|
(_a = this.intersection) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
6108
6190
|
(_b = this.gapIntersection) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
6109
|
-
(_c = this.
|
|
6191
|
+
(_c = this.resizeScroll) === null || _c === void 0 ? void 0 : _c.disconnect();
|
|
6192
|
+
(_d = this.resizeContent) === null || _d === void 0 ? void 0 : _d.disconnect();
|
|
6110
6193
|
for (let dom of this.scrollTargets)
|
|
6111
6194
|
dom.removeEventListener("scroll", this.onScroll);
|
|
6112
6195
|
this.removeWindowListeners(this.win);
|
|
@@ -6205,7 +6288,7 @@ class EditorView {
|
|
|
6205
6288
|
this.scrollDOM.className = "cm-scroller";
|
|
6206
6289
|
this.scrollDOM.appendChild(this.contentDOM);
|
|
6207
6290
|
this.announceDOM = document.createElement("div");
|
|
6208
|
-
this.announceDOM.style.cssText = "position:
|
|
6291
|
+
this.announceDOM.style.cssText = "position: fixed; top: -10000px";
|
|
6209
6292
|
this.announceDOM.setAttribute("aria-live", "polite");
|
|
6210
6293
|
this.dom = document.createElement("div");
|
|
6211
6294
|
this.dom.appendChild(this.announceDOM);
|
|
@@ -7296,7 +7379,8 @@ a rectangle at a given set of coordinates.
|
|
|
7296
7379
|
*/
|
|
7297
7380
|
class RectangleMarker {
|
|
7298
7381
|
/**
|
|
7299
|
-
Create a marker with the given class and dimensions.
|
|
7382
|
+
Create a marker with the given class and dimensions. If `width`
|
|
7383
|
+
is null, the DOM element will get no width style.
|
|
7300
7384
|
*/
|
|
7301
7385
|
constructor(className, left, top, width, height) {
|
|
7302
7386
|
this.className = className;
|
|
@@ -7320,7 +7404,7 @@ class RectangleMarker {
|
|
|
7320
7404
|
adjust(elt) {
|
|
7321
7405
|
elt.style.left = this.left + "px";
|
|
7322
7406
|
elt.style.top = this.top + "px";
|
|
7323
|
-
if (this.width
|
|
7407
|
+
if (this.width != null)
|
|
7324
7408
|
elt.style.width = this.width + "px";
|
|
7325
7409
|
elt.style.height = this.height + "px";
|
|
7326
7410
|
}
|
|
@@ -7328,6 +7412,129 @@ class RectangleMarker {
|
|
|
7328
7412
|
return this.left == p.left && this.top == p.top && this.width == p.width && this.height == p.height &&
|
|
7329
7413
|
this.className == p.className;
|
|
7330
7414
|
}
|
|
7415
|
+
/**
|
|
7416
|
+
Create a set of rectangles for the given selection range,
|
|
7417
|
+
assigning them theclass`className`. Will create a single
|
|
7418
|
+
rectangle for empty ranges, and a set of selection-style
|
|
7419
|
+
rectangles covering the range's content (in a bidi-aware
|
|
7420
|
+
way) for non-empty ones.
|
|
7421
|
+
*/
|
|
7422
|
+
static forRange(view, className, range) {
|
|
7423
|
+
if (range.empty) {
|
|
7424
|
+
let pos = view.coordsAtPos(range.head, range.assoc || 1);
|
|
7425
|
+
if (!pos)
|
|
7426
|
+
return [];
|
|
7427
|
+
let base = getBase(view);
|
|
7428
|
+
return [new RectangleMarker(className, pos.left - base.left, pos.top - base.top, null, pos.bottom - pos.top)];
|
|
7429
|
+
}
|
|
7430
|
+
else {
|
|
7431
|
+
return rectanglesForRange(view, className, range);
|
|
7432
|
+
}
|
|
7433
|
+
}
|
|
7434
|
+
}
|
|
7435
|
+
function getBase(view) {
|
|
7436
|
+
let rect = view.scrollDOM.getBoundingClientRect();
|
|
7437
|
+
let left = view.textDirection == exports.Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth;
|
|
7438
|
+
return { left: left - view.scrollDOM.scrollLeft, top: rect.top - view.scrollDOM.scrollTop };
|
|
7439
|
+
}
|
|
7440
|
+
function wrappedLine(view, pos, inside) {
|
|
7441
|
+
let range = state.EditorSelection.cursor(pos);
|
|
7442
|
+
return { from: Math.max(inside.from, view.moveToLineBoundary(range, false, true).from),
|
|
7443
|
+
to: Math.min(inside.to, view.moveToLineBoundary(range, true, true).from),
|
|
7444
|
+
type: exports.BlockType.Text };
|
|
7445
|
+
}
|
|
7446
|
+
function blockAt(view, pos) {
|
|
7447
|
+
let line = view.lineBlockAt(pos);
|
|
7448
|
+
if (Array.isArray(line.type))
|
|
7449
|
+
for (let l of line.type) {
|
|
7450
|
+
if (l.to > pos || l.to == pos && (l.to == line.to || l.type == exports.BlockType.Text))
|
|
7451
|
+
return l;
|
|
7452
|
+
}
|
|
7453
|
+
return line;
|
|
7454
|
+
}
|
|
7455
|
+
function rectanglesForRange(view, className, range) {
|
|
7456
|
+
if (range.to <= view.viewport.from || range.from >= view.viewport.to)
|
|
7457
|
+
return [];
|
|
7458
|
+
let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
|
|
7459
|
+
let ltr = view.textDirection == exports.Direction.LTR;
|
|
7460
|
+
let content = view.contentDOM, contentRect = content.getBoundingClientRect(), base = getBase(view);
|
|
7461
|
+
let lineStyle = window.getComputedStyle(content.firstChild);
|
|
7462
|
+
let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent));
|
|
7463
|
+
let rightSide = contentRect.right - parseInt(lineStyle.paddingRight);
|
|
7464
|
+
let startBlock = blockAt(view, from), endBlock = blockAt(view, to);
|
|
7465
|
+
let visualStart = startBlock.type == exports.BlockType.Text ? startBlock : null;
|
|
7466
|
+
let visualEnd = endBlock.type == exports.BlockType.Text ? endBlock : null;
|
|
7467
|
+
if (view.lineWrapping) {
|
|
7468
|
+
if (visualStart)
|
|
7469
|
+
visualStart = wrappedLine(view, from, visualStart);
|
|
7470
|
+
if (visualEnd)
|
|
7471
|
+
visualEnd = wrappedLine(view, to, visualEnd);
|
|
7472
|
+
}
|
|
7473
|
+
if (visualStart && visualEnd && visualStart.from == visualEnd.from) {
|
|
7474
|
+
return pieces(drawForLine(range.from, range.to, visualStart));
|
|
7475
|
+
}
|
|
7476
|
+
else {
|
|
7477
|
+
let top = visualStart ? drawForLine(range.from, null, visualStart) : drawForWidget(startBlock, false);
|
|
7478
|
+
let bottom = visualEnd ? drawForLine(null, range.to, visualEnd) : drawForWidget(endBlock, true);
|
|
7479
|
+
let between = [];
|
|
7480
|
+
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - 1)
|
|
7481
|
+
between.push(piece(leftSide, top.bottom, rightSide, bottom.top));
|
|
7482
|
+
else if (top.bottom < bottom.top && view.elementAtHeight((top.bottom + bottom.top) / 2).type == exports.BlockType.Text)
|
|
7483
|
+
top.bottom = bottom.top = (top.bottom + bottom.top) / 2;
|
|
7484
|
+
return pieces(top).concat(between).concat(pieces(bottom));
|
|
7485
|
+
}
|
|
7486
|
+
function piece(left, top, right, bottom) {
|
|
7487
|
+
return new RectangleMarker(className, left - base.left, top - base.top - 0.01 /* C.Epsilon */, right - left, bottom - top + 0.01 /* C.Epsilon */);
|
|
7488
|
+
}
|
|
7489
|
+
function pieces({ top, bottom, horizontal }) {
|
|
7490
|
+
let pieces = [];
|
|
7491
|
+
for (let i = 0; i < horizontal.length; i += 2)
|
|
7492
|
+
pieces.push(piece(horizontal[i], top, horizontal[i + 1], bottom));
|
|
7493
|
+
return pieces;
|
|
7494
|
+
}
|
|
7495
|
+
// Gets passed from/to in line-local positions
|
|
7496
|
+
function drawForLine(from, to, line) {
|
|
7497
|
+
let top = 1e9, bottom = -1e9, horizontal = [];
|
|
7498
|
+
function addSpan(from, fromOpen, to, toOpen, dir) {
|
|
7499
|
+
// Passing 2/-2 is a kludge to force the view to return
|
|
7500
|
+
// coordinates on the proper side of block widgets, since
|
|
7501
|
+
// normalizing the side there, though appropriate for most
|
|
7502
|
+
// coordsAtPos queries, would break selection drawing.
|
|
7503
|
+
let fromCoords = view.coordsAtPos(from, (from == line.to ? -2 : 2));
|
|
7504
|
+
let toCoords = view.coordsAtPos(to, (to == line.from ? 2 : -2));
|
|
7505
|
+
top = Math.min(fromCoords.top, toCoords.top, top);
|
|
7506
|
+
bottom = Math.max(fromCoords.bottom, toCoords.bottom, bottom);
|
|
7507
|
+
if (dir == exports.Direction.LTR)
|
|
7508
|
+
horizontal.push(ltr && fromOpen ? leftSide : fromCoords.left, ltr && toOpen ? rightSide : toCoords.right);
|
|
7509
|
+
else
|
|
7510
|
+
horizontal.push(!ltr && toOpen ? leftSide : toCoords.left, !ltr && fromOpen ? rightSide : fromCoords.right);
|
|
7511
|
+
}
|
|
7512
|
+
let start = from !== null && from !== void 0 ? from : line.from, end = to !== null && to !== void 0 ? to : line.to;
|
|
7513
|
+
// Split the range by visible range and document line
|
|
7514
|
+
for (let r of view.visibleRanges)
|
|
7515
|
+
if (r.to > start && r.from < end) {
|
|
7516
|
+
for (let pos = Math.max(r.from, start), endPos = Math.min(r.to, end);;) {
|
|
7517
|
+
let docLine = view.state.doc.lineAt(pos);
|
|
7518
|
+
for (let span of view.bidiSpans(docLine)) {
|
|
7519
|
+
let spanFrom = span.from + docLine.from, spanTo = span.to + docLine.from;
|
|
7520
|
+
if (spanFrom >= endPos)
|
|
7521
|
+
break;
|
|
7522
|
+
if (spanTo > pos)
|
|
7523
|
+
addSpan(Math.max(spanFrom, pos), from == null && spanFrom <= start, Math.min(spanTo, endPos), to == null && spanTo >= end, span.dir);
|
|
7524
|
+
}
|
|
7525
|
+
pos = docLine.to + 1;
|
|
7526
|
+
if (pos >= endPos)
|
|
7527
|
+
break;
|
|
7528
|
+
}
|
|
7529
|
+
}
|
|
7530
|
+
if (horizontal.length == 0)
|
|
7531
|
+
addSpan(start, from == null, end, to == null, view.textDirection);
|
|
7532
|
+
return { top, bottom, horizontal };
|
|
7533
|
+
}
|
|
7534
|
+
function drawForWidget(block, top) {
|
|
7535
|
+
let y = contentRect.top + (top ? block.top : block.bottom);
|
|
7536
|
+
return { top: y, bottom: y, horizontal: [] };
|
|
7537
|
+
}
|
|
7331
7538
|
}
|
|
7332
7539
|
function sameMarker(a, b) {
|
|
7333
7540
|
return a.constructor == b.constructor && a.eq(b);
|
|
@@ -7387,6 +7594,8 @@ class LayerView {
|
|
|
7387
7594
|
}
|
|
7388
7595
|
}
|
|
7389
7596
|
destroy() {
|
|
7597
|
+
if (this.layer.destroy)
|
|
7598
|
+
this.layer.destroy(this.dom, this.view);
|
|
7390
7599
|
this.dom.remove();
|
|
7391
7600
|
}
|
|
7392
7601
|
}
|
|
@@ -7446,13 +7655,14 @@ function configChanged(update) {
|
|
|
7446
7655
|
const cursorLayer = layer({
|
|
7447
7656
|
above: true,
|
|
7448
7657
|
markers(view) {
|
|
7449
|
-
let { state } = view, conf = state.facet(selectionConfig);
|
|
7658
|
+
let { state: state$1 } = view, conf = state$1.facet(selectionConfig);
|
|
7450
7659
|
let cursors = [];
|
|
7451
|
-
for (let r of state.selection.ranges) {
|
|
7452
|
-
let prim = r == state.selection.main;
|
|
7660
|
+
for (let r of state$1.selection.ranges) {
|
|
7661
|
+
let prim = r == state$1.selection.main;
|
|
7453
7662
|
if (r.empty ? !prim || CanHidePrimary : conf.drawRangeCursor) {
|
|
7454
|
-
let
|
|
7455
|
-
|
|
7663
|
+
let className = prim ? "cm-cursor cm-cursor-primary" : "cm-cursor cm-cursor-secondary";
|
|
7664
|
+
let cursor = r.empty ? r : state.EditorSelection.cursor(r.head, r.head > r.anchor ? -1 : 1);
|
|
7665
|
+
for (let piece of RectangleMarker.forRange(view, className, cursor))
|
|
7456
7666
|
cursors.push(piece);
|
|
7457
7667
|
}
|
|
7458
7668
|
}
|
|
@@ -7477,7 +7687,8 @@ function setBlinkRate(state, dom) {
|
|
|
7477
7687
|
const selectionLayer = layer({
|
|
7478
7688
|
above: false,
|
|
7479
7689
|
markers(view) {
|
|
7480
|
-
return view.state.selection.ranges.map(r => r.empty ? [] :
|
|
7690
|
+
return view.state.selection.ranges.map(r => r.empty ? [] : RectangleMarker.forRange(view, "cm-selectionBackground", r))
|
|
7691
|
+
.reduce((a, b) => a.concat(b));
|
|
7481
7692
|
},
|
|
7482
7693
|
update(update, dom) {
|
|
7483
7694
|
return update.docChanged || update.selectionSet || update.viewportChanged || configChanged(update);
|
|
@@ -7493,117 +7704,6 @@ const themeSpec = {
|
|
|
7493
7704
|
if (CanHidePrimary)
|
|
7494
7705
|
themeSpec[".cm-line"].caretColor = "transparent !important";
|
|
7495
7706
|
const hideNativeSelection = state.Prec.highest(EditorView.theme(themeSpec));
|
|
7496
|
-
function getBase(view) {
|
|
7497
|
-
let rect = view.scrollDOM.getBoundingClientRect();
|
|
7498
|
-
let left = view.textDirection == exports.Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth;
|
|
7499
|
-
return { left: left - view.scrollDOM.scrollLeft, top: rect.top - view.scrollDOM.scrollTop };
|
|
7500
|
-
}
|
|
7501
|
-
function wrappedLine(view, pos, inside) {
|
|
7502
|
-
let range = state.EditorSelection.cursor(pos);
|
|
7503
|
-
return { from: Math.max(inside.from, view.moveToLineBoundary(range, false, true).from),
|
|
7504
|
-
to: Math.min(inside.to, view.moveToLineBoundary(range, true, true).from),
|
|
7505
|
-
type: exports.BlockType.Text };
|
|
7506
|
-
}
|
|
7507
|
-
function blockAt(view, pos) {
|
|
7508
|
-
let line = view.lineBlockAt(pos);
|
|
7509
|
-
if (Array.isArray(line.type))
|
|
7510
|
-
for (let l of line.type) {
|
|
7511
|
-
if (l.to > pos || l.to == pos && (l.to == line.to || l.type == exports.BlockType.Text))
|
|
7512
|
-
return l;
|
|
7513
|
-
}
|
|
7514
|
-
return line;
|
|
7515
|
-
}
|
|
7516
|
-
function measureRange(view, range) {
|
|
7517
|
-
if (range.to <= view.viewport.from || range.from >= view.viewport.to)
|
|
7518
|
-
return [];
|
|
7519
|
-
let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
|
|
7520
|
-
let ltr = view.textDirection == exports.Direction.LTR;
|
|
7521
|
-
let content = view.contentDOM, contentRect = content.getBoundingClientRect(), base = getBase(view);
|
|
7522
|
-
let lineStyle = window.getComputedStyle(content.firstChild);
|
|
7523
|
-
let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent));
|
|
7524
|
-
let rightSide = contentRect.right - parseInt(lineStyle.paddingRight);
|
|
7525
|
-
let startBlock = blockAt(view, from), endBlock = blockAt(view, to);
|
|
7526
|
-
let visualStart = startBlock.type == exports.BlockType.Text ? startBlock : null;
|
|
7527
|
-
let visualEnd = endBlock.type == exports.BlockType.Text ? endBlock : null;
|
|
7528
|
-
if (view.lineWrapping) {
|
|
7529
|
-
if (visualStart)
|
|
7530
|
-
visualStart = wrappedLine(view, from, visualStart);
|
|
7531
|
-
if (visualEnd)
|
|
7532
|
-
visualEnd = wrappedLine(view, to, visualEnd);
|
|
7533
|
-
}
|
|
7534
|
-
if (visualStart && visualEnd && visualStart.from == visualEnd.from) {
|
|
7535
|
-
return pieces(drawForLine(range.from, range.to, visualStart));
|
|
7536
|
-
}
|
|
7537
|
-
else {
|
|
7538
|
-
let top = visualStart ? drawForLine(range.from, null, visualStart) : drawForWidget(startBlock, false);
|
|
7539
|
-
let bottom = visualEnd ? drawForLine(null, range.to, visualEnd) : drawForWidget(endBlock, true);
|
|
7540
|
-
let between = [];
|
|
7541
|
-
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - 1)
|
|
7542
|
-
between.push(piece(leftSide, top.bottom, rightSide, bottom.top));
|
|
7543
|
-
else if (top.bottom < bottom.top && view.elementAtHeight((top.bottom + bottom.top) / 2).type == exports.BlockType.Text)
|
|
7544
|
-
top.bottom = bottom.top = (top.bottom + bottom.top) / 2;
|
|
7545
|
-
return pieces(top).concat(between).concat(pieces(bottom));
|
|
7546
|
-
}
|
|
7547
|
-
function piece(left, top, right, bottom) {
|
|
7548
|
-
return new RectangleMarker("cm-selectionBackground", left - base.left, top - base.top - 0.01 /* C.Epsilon */, right - left, bottom - top + 0.01 /* C.Epsilon */);
|
|
7549
|
-
}
|
|
7550
|
-
function pieces({ top, bottom, horizontal }) {
|
|
7551
|
-
let pieces = [];
|
|
7552
|
-
for (let i = 0; i < horizontal.length; i += 2)
|
|
7553
|
-
pieces.push(piece(horizontal[i], top, horizontal[i + 1], bottom));
|
|
7554
|
-
return pieces;
|
|
7555
|
-
}
|
|
7556
|
-
// Gets passed from/to in line-local positions
|
|
7557
|
-
function drawForLine(from, to, line) {
|
|
7558
|
-
let top = 1e9, bottom = -1e9, horizontal = [];
|
|
7559
|
-
function addSpan(from, fromOpen, to, toOpen, dir) {
|
|
7560
|
-
// Passing 2/-2 is a kludge to force the view to return
|
|
7561
|
-
// coordinates on the proper side of block widgets, since
|
|
7562
|
-
// normalizing the side there, though appropriate for most
|
|
7563
|
-
// coordsAtPos queries, would break selection drawing.
|
|
7564
|
-
let fromCoords = view.coordsAtPos(from, (from == line.to ? -2 : 2));
|
|
7565
|
-
let toCoords = view.coordsAtPos(to, (to == line.from ? 2 : -2));
|
|
7566
|
-
top = Math.min(fromCoords.top, toCoords.top, top);
|
|
7567
|
-
bottom = Math.max(fromCoords.bottom, toCoords.bottom, bottom);
|
|
7568
|
-
if (dir == exports.Direction.LTR)
|
|
7569
|
-
horizontal.push(ltr && fromOpen ? leftSide : fromCoords.left, ltr && toOpen ? rightSide : toCoords.right);
|
|
7570
|
-
else
|
|
7571
|
-
horizontal.push(!ltr && toOpen ? leftSide : toCoords.left, !ltr && fromOpen ? rightSide : fromCoords.right);
|
|
7572
|
-
}
|
|
7573
|
-
let start = from !== null && from !== void 0 ? from : line.from, end = to !== null && to !== void 0 ? to : line.to;
|
|
7574
|
-
// Split the range by visible range and document line
|
|
7575
|
-
for (let r of view.visibleRanges)
|
|
7576
|
-
if (r.to > start && r.from < end) {
|
|
7577
|
-
for (let pos = Math.max(r.from, start), endPos = Math.min(r.to, end);;) {
|
|
7578
|
-
let docLine = view.state.doc.lineAt(pos);
|
|
7579
|
-
for (let span of view.bidiSpans(docLine)) {
|
|
7580
|
-
let spanFrom = span.from + docLine.from, spanTo = span.to + docLine.from;
|
|
7581
|
-
if (spanFrom >= endPos)
|
|
7582
|
-
break;
|
|
7583
|
-
if (spanTo > pos)
|
|
7584
|
-
addSpan(Math.max(spanFrom, pos), from == null && spanFrom <= start, Math.min(spanTo, endPos), to == null && spanTo >= end, span.dir);
|
|
7585
|
-
}
|
|
7586
|
-
pos = docLine.to + 1;
|
|
7587
|
-
if (pos >= endPos)
|
|
7588
|
-
break;
|
|
7589
|
-
}
|
|
7590
|
-
}
|
|
7591
|
-
if (horizontal.length == 0)
|
|
7592
|
-
addSpan(start, from == null, end, to == null, view.textDirection);
|
|
7593
|
-
return { top, bottom, horizontal };
|
|
7594
|
-
}
|
|
7595
|
-
function drawForWidget(block, top) {
|
|
7596
|
-
let y = contentRect.top + (top ? block.top : block.bottom);
|
|
7597
|
-
return { top: y, bottom: y, horizontal: [] };
|
|
7598
|
-
}
|
|
7599
|
-
}
|
|
7600
|
-
function measureCursor(view, cursor, primary) {
|
|
7601
|
-
let pos = view.coordsAtPos(cursor.head, cursor.assoc || 1);
|
|
7602
|
-
if (!pos)
|
|
7603
|
-
return null;
|
|
7604
|
-
let base = getBase(view);
|
|
7605
|
-
return new RectangleMarker(primary ? "cm-cursor cm-cursor-primary" : "cm-cursor cm-cursor-secondary", pos.left - base.left, pos.top - base.top, -1, pos.bottom - pos.top);
|
|
7606
|
-
}
|
|
7607
7707
|
|
|
7608
7708
|
const setDropCursorPos = state.StateEffect.define({
|
|
7609
7709
|
map(pos, mapping) { return pos == null ? null : mapping.mapPos(pos); }
|
|
@@ -9370,6 +9470,57 @@ function highlightActiveLineGutter() {
|
|
|
9370
9470
|
return activeLineGutterHighlighter;
|
|
9371
9471
|
}
|
|
9372
9472
|
|
|
9473
|
+
const WhitespaceDeco = new Map();
|
|
9474
|
+
function getWhitespaceDeco(space) {
|
|
9475
|
+
let deco = WhitespaceDeco.get(space);
|
|
9476
|
+
if (!deco)
|
|
9477
|
+
WhitespaceDeco.set(space, deco = Decoration.mark({
|
|
9478
|
+
attributes: space === "\t" ? {
|
|
9479
|
+
class: "cm-highlightTab",
|
|
9480
|
+
} : {
|
|
9481
|
+
class: "cm-highlightSpace",
|
|
9482
|
+
"data-display": space.replace(/ /g, "·")
|
|
9483
|
+
}
|
|
9484
|
+
}));
|
|
9485
|
+
return deco;
|
|
9486
|
+
}
|
|
9487
|
+
function matcher(decorator) {
|
|
9488
|
+
return ViewPlugin.define(view => ({
|
|
9489
|
+
decorations: decorator.createDeco(view),
|
|
9490
|
+
update(u) {
|
|
9491
|
+
this.decorations = decorator.updateDeco(u, this.decorations);
|
|
9492
|
+
},
|
|
9493
|
+
}), {
|
|
9494
|
+
decorations: v => v.decorations
|
|
9495
|
+
});
|
|
9496
|
+
}
|
|
9497
|
+
const whitespaceHighlighter = matcher(new MatchDecorator({
|
|
9498
|
+
regexp: /\t| +/g,
|
|
9499
|
+
decoration: match => getWhitespaceDeco(match[0]),
|
|
9500
|
+
boundary: /\S/,
|
|
9501
|
+
}));
|
|
9502
|
+
/**
|
|
9503
|
+
Returns an extension that highlights whitespace, adding a
|
|
9504
|
+
`cm-highlightSpace` class to stretches of spaces, and a
|
|
9505
|
+
`cm-highlightTab` class to individual tab characters. By default,
|
|
9506
|
+
the former are shown as faint dots, and the latter as arrows.
|
|
9507
|
+
*/
|
|
9508
|
+
function highlightWhitespace() {
|
|
9509
|
+
return whitespaceHighlighter;
|
|
9510
|
+
}
|
|
9511
|
+
const trailingHighlighter = matcher(new MatchDecorator({
|
|
9512
|
+
regexp: /\s+$/g,
|
|
9513
|
+
decoration: Decoration.mark({ class: "cm-trailingSpace" }),
|
|
9514
|
+
boundary: /\S/,
|
|
9515
|
+
}));
|
|
9516
|
+
/**
|
|
9517
|
+
Returns an extension that adds a `cm-trailingSpace` class to all
|
|
9518
|
+
trailing whitespace.
|
|
9519
|
+
*/
|
|
9520
|
+
function highlightTrailingWhitespace() {
|
|
9521
|
+
return trailingHighlighter;
|
|
9522
|
+
}
|
|
9523
|
+
|
|
9373
9524
|
/**
|
|
9374
9525
|
@internal
|
|
9375
9526
|
*/
|
|
@@ -9399,6 +9550,8 @@ exports.hasHoverTooltips = hasHoverTooltips;
|
|
|
9399
9550
|
exports.highlightActiveLine = highlightActiveLine;
|
|
9400
9551
|
exports.highlightActiveLineGutter = highlightActiveLineGutter;
|
|
9401
9552
|
exports.highlightSpecialChars = highlightSpecialChars;
|
|
9553
|
+
exports.highlightTrailingWhitespace = highlightTrailingWhitespace;
|
|
9554
|
+
exports.highlightWhitespace = highlightWhitespace;
|
|
9402
9555
|
exports.hoverTooltip = hoverTooltip;
|
|
9403
9556
|
exports.keymap = keymap;
|
|
9404
9557
|
exports.layer = layer;
|