@codemirror/view 6.6.0 → 6.7.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 +20 -0
- package/dist/index.cjs +225 -133
- package/dist/index.d.ts +30 -3
- package/dist/index.js +221 -131
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## 6.7.0 (2022-12-07)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Make the editor notice widget height changes to automatically adjust its height information.
|
|
6
|
+
|
|
7
|
+
Fix an issue where widget buffers could be incorrectly omitted after empty lines.
|
|
8
|
+
|
|
9
|
+
Fix an issue in content redrawing that could cause `coordsAtPos` to return incorrect results.
|
|
10
|
+
|
|
11
|
+
### New features
|
|
12
|
+
|
|
13
|
+
The static `RectangleMarker.forRange` method exposes the logic used by the editor to draw rectangles covering a selection range.
|
|
14
|
+
|
|
15
|
+
Layers can now provide a `destroy` function to be called when the layer is removed.
|
|
16
|
+
|
|
17
|
+
The new `highlightWhitespace` extension makes spaces and tabs in the editor visible.
|
|
18
|
+
|
|
19
|
+
The `highlightTrailingWhitespace` extension can be used to make trailing whitespace stand out.
|
|
20
|
+
|
|
1
21
|
## 6.6.0 (2022-11-24)
|
|
2
22
|
|
|
3
23
|
### New features
|
package/dist/index.cjs
CHANGED
|
@@ -1603,6 +1603,7 @@ class ContentBuilder {
|
|
|
1603
1603
|
this.curLine = null;
|
|
1604
1604
|
this.breakAtStart = 0;
|
|
1605
1605
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1606
|
+
this.bufferMarks = [];
|
|
1606
1607
|
// Set to false directly after a widget that covers the position after it
|
|
1607
1608
|
this.atCursorPos = true;
|
|
1608
1609
|
this.openStart = -1;
|
|
@@ -1625,20 +1626,20 @@ class ContentBuilder {
|
|
|
1625
1626
|
}
|
|
1626
1627
|
return this.curLine;
|
|
1627
1628
|
}
|
|
1628
|
-
flushBuffer(active) {
|
|
1629
|
+
flushBuffer(active = this.bufferMarks) {
|
|
1629
1630
|
if (this.pendingBuffer) {
|
|
1630
1631
|
this.curLine.append(wrapMarks(new WidgetBufferView(-1), active), active.length);
|
|
1631
1632
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1632
1633
|
}
|
|
1633
1634
|
}
|
|
1634
1635
|
addBlockWidget(view) {
|
|
1635
|
-
this.flushBuffer(
|
|
1636
|
+
this.flushBuffer();
|
|
1636
1637
|
this.curLine = null;
|
|
1637
1638
|
this.content.push(view);
|
|
1638
1639
|
}
|
|
1639
1640
|
finish(openEnd) {
|
|
1640
|
-
if (
|
|
1641
|
-
this.flushBuffer(
|
|
1641
|
+
if (this.pendingBuffer && openEnd <= this.bufferMarks.length)
|
|
1642
|
+
this.flushBuffer();
|
|
1642
1643
|
else
|
|
1643
1644
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1644
1645
|
if (!this.posCovered())
|
|
@@ -1658,8 +1659,9 @@ class ContentBuilder {
|
|
|
1658
1659
|
this.content[this.content.length - 1].breakAfter = 1;
|
|
1659
1660
|
else
|
|
1660
1661
|
this.breakAtStart = 1;
|
|
1661
|
-
this.flushBuffer(
|
|
1662
|
+
this.flushBuffer();
|
|
1662
1663
|
this.curLine = null;
|
|
1664
|
+
this.atCursorPos = true;
|
|
1663
1665
|
length--;
|
|
1664
1666
|
continue;
|
|
1665
1667
|
}
|
|
@@ -1701,7 +1703,7 @@ class ContentBuilder {
|
|
|
1701
1703
|
else {
|
|
1702
1704
|
let view = WidgetView.create(deco.widget || new NullWidget("span"), len, len ? 0 : deco.startSide);
|
|
1703
1705
|
let cursorBefore = this.atCursorPos && !view.isEditable && openStart <= active.length && (from < to || deco.startSide > 0);
|
|
1704
|
-
let cursorAfter = !view.isEditable && (from < to || deco.startSide <= 0);
|
|
1706
|
+
let cursorAfter = !view.isEditable && (from < to || openStart > active.length || deco.startSide <= 0);
|
|
1705
1707
|
let line = this.getLine();
|
|
1706
1708
|
if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore)
|
|
1707
1709
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
@@ -1712,7 +1714,9 @@ class ContentBuilder {
|
|
|
1712
1714
|
}
|
|
1713
1715
|
line.append(wrapMarks(view, active), openStart);
|
|
1714
1716
|
this.atCursorPos = cursorAfter;
|
|
1715
|
-
this.pendingBuffer = !cursorAfter ? 0 /* Buf.No */ : from < to ? 1 /* Buf.Yes */ : 2 /* Buf.IfCursor */;
|
|
1717
|
+
this.pendingBuffer = !cursorAfter ? 0 /* Buf.No */ : from < to || openStart > active.length ? 1 /* Buf.Yes */ : 2 /* Buf.IfCursor */;
|
|
1718
|
+
if (this.pendingBuffer)
|
|
1719
|
+
this.bufferMarks = active.slice();
|
|
1716
1720
|
}
|
|
1717
1721
|
}
|
|
1718
1722
|
else if (this.doc.lineAt(this.pos).from == this.pos) { // Line decoration
|
|
@@ -5291,7 +5295,6 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5291
5295
|
margin: 0,
|
|
5292
5296
|
flexGrow: 2,
|
|
5293
5297
|
flexShrink: 0,
|
|
5294
|
-
minHeight: "100%",
|
|
5295
5298
|
display: "block",
|
|
5296
5299
|
whiteSpace: "pre",
|
|
5297
5300
|
wordWrap: "normal",
|
|
@@ -5438,6 +5441,21 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5438
5441
|
display: "inline-block",
|
|
5439
5442
|
verticalAlign: "top",
|
|
5440
5443
|
},
|
|
5444
|
+
".cm-highlightSpace:before": {
|
|
5445
|
+
content: "attr(data-display)",
|
|
5446
|
+
position: "absolute",
|
|
5447
|
+
pointerEvents: "none",
|
|
5448
|
+
color: "#888"
|
|
5449
|
+
},
|
|
5450
|
+
".cm-highlightTab": {
|
|
5451
|
+
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>')`,
|
|
5452
|
+
backgroundSize: "auto 100%",
|
|
5453
|
+
backgroundPosition: "right 90%",
|
|
5454
|
+
backgroundRepeat: "no-repeat"
|
|
5455
|
+
},
|
|
5456
|
+
".cm-trailingSpace": {
|
|
5457
|
+
backgroundColor: "#ff332255"
|
|
5458
|
+
},
|
|
5441
5459
|
".cm-button": {
|
|
5442
5460
|
verticalAlign: "middle",
|
|
5443
5461
|
color: "inherit",
|
|
@@ -5740,7 +5758,8 @@ class DOMObserver {
|
|
|
5740
5758
|
this.lastChange = 0;
|
|
5741
5759
|
this.scrollTargets = [];
|
|
5742
5760
|
this.intersection = null;
|
|
5743
|
-
this.
|
|
5761
|
+
this.resizeScroll = null;
|
|
5762
|
+
this.resizeContent = null;
|
|
5744
5763
|
this.intersecting = false;
|
|
5745
5764
|
this.gapIntersection = null;
|
|
5746
5765
|
this.gaps = [];
|
|
@@ -5778,12 +5797,14 @@ class DOMObserver {
|
|
|
5778
5797
|
this.onPrint = this.onPrint.bind(this);
|
|
5779
5798
|
this.onScroll = this.onScroll.bind(this);
|
|
5780
5799
|
if (typeof ResizeObserver == "function") {
|
|
5781
|
-
this.
|
|
5800
|
+
this.resizeScroll = new ResizeObserver(() => {
|
|
5782
5801
|
var _a;
|
|
5783
5802
|
if (((_a = this.view.docView) === null || _a === void 0 ? void 0 : _a.lastUpdate) < Date.now() - 75)
|
|
5784
5803
|
this.onResize();
|
|
5785
5804
|
});
|
|
5786
|
-
this.
|
|
5805
|
+
this.resizeScroll.observe(view.scrollDOM);
|
|
5806
|
+
this.resizeContent = new ResizeObserver(() => this.view.requestMeasure());
|
|
5807
|
+
this.resizeContent.observe(view.contentDOM);
|
|
5787
5808
|
}
|
|
5788
5809
|
this.addWindowListeners(this.win = view.win);
|
|
5789
5810
|
this.start();
|
|
@@ -6102,11 +6123,12 @@ class DOMObserver {
|
|
|
6102
6123
|
win.document.removeEventListener("selectionchange", this.onSelectionChange);
|
|
6103
6124
|
}
|
|
6104
6125
|
destroy() {
|
|
6105
|
-
var _a, _b, _c;
|
|
6126
|
+
var _a, _b, _c, _d;
|
|
6106
6127
|
this.stop();
|
|
6107
6128
|
(_a = this.intersection) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
6108
6129
|
(_b = this.gapIntersection) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
6109
|
-
(_c = this.
|
|
6130
|
+
(_c = this.resizeScroll) === null || _c === void 0 ? void 0 : _c.disconnect();
|
|
6131
|
+
(_d = this.resizeContent) === null || _d === void 0 ? void 0 : _d.disconnect();
|
|
6110
6132
|
for (let dom of this.scrollTargets)
|
|
6111
6133
|
dom.removeEventListener("scroll", this.onScroll);
|
|
6112
6134
|
this.removeWindowListeners(this.win);
|
|
@@ -6205,7 +6227,7 @@ class EditorView {
|
|
|
6205
6227
|
this.scrollDOM.className = "cm-scroller";
|
|
6206
6228
|
this.scrollDOM.appendChild(this.contentDOM);
|
|
6207
6229
|
this.announceDOM = document.createElement("div");
|
|
6208
|
-
this.announceDOM.style.cssText = "position:
|
|
6230
|
+
this.announceDOM.style.cssText = "position: fixed; top: -10000px";
|
|
6209
6231
|
this.announceDOM.setAttribute("aria-live", "polite");
|
|
6210
6232
|
this.dom = document.createElement("div");
|
|
6211
6233
|
this.dom.appendChild(this.announceDOM);
|
|
@@ -7296,7 +7318,8 @@ a rectangle at a given set of coordinates.
|
|
|
7296
7318
|
*/
|
|
7297
7319
|
class RectangleMarker {
|
|
7298
7320
|
/**
|
|
7299
|
-
Create a marker with the given class and dimensions.
|
|
7321
|
+
Create a marker with the given class and dimensions. If `width`
|
|
7322
|
+
is null, the DOM element will get no width style.
|
|
7300
7323
|
*/
|
|
7301
7324
|
constructor(className, left, top, width, height) {
|
|
7302
7325
|
this.className = className;
|
|
@@ -7320,7 +7343,7 @@ class RectangleMarker {
|
|
|
7320
7343
|
adjust(elt) {
|
|
7321
7344
|
elt.style.left = this.left + "px";
|
|
7322
7345
|
elt.style.top = this.top + "px";
|
|
7323
|
-
if (this.width
|
|
7346
|
+
if (this.width != null)
|
|
7324
7347
|
elt.style.width = this.width + "px";
|
|
7325
7348
|
elt.style.height = this.height + "px";
|
|
7326
7349
|
}
|
|
@@ -7328,6 +7351,129 @@ class RectangleMarker {
|
|
|
7328
7351
|
return this.left == p.left && this.top == p.top && this.width == p.width && this.height == p.height &&
|
|
7329
7352
|
this.className == p.className;
|
|
7330
7353
|
}
|
|
7354
|
+
/**
|
|
7355
|
+
Create a set of rectangles for the given selection range,
|
|
7356
|
+
assigning them theclass`className`. Will create a single
|
|
7357
|
+
rectangle for empty ranges, and a set of selection-style
|
|
7358
|
+
rectangles covering the range's content (in a bidi-aware
|
|
7359
|
+
way) for non-empty ones.
|
|
7360
|
+
*/
|
|
7361
|
+
static forRange(view, className, range) {
|
|
7362
|
+
if (range.empty) {
|
|
7363
|
+
let pos = view.coordsAtPos(range.head, range.assoc || 1);
|
|
7364
|
+
if (!pos)
|
|
7365
|
+
return [];
|
|
7366
|
+
let base = getBase(view);
|
|
7367
|
+
return [new RectangleMarker(className, pos.left - base.left, pos.top - base.top, null, pos.bottom - pos.top)];
|
|
7368
|
+
}
|
|
7369
|
+
else {
|
|
7370
|
+
return rectanglesForRange(view, className, range);
|
|
7371
|
+
}
|
|
7372
|
+
}
|
|
7373
|
+
}
|
|
7374
|
+
function getBase(view) {
|
|
7375
|
+
let rect = view.scrollDOM.getBoundingClientRect();
|
|
7376
|
+
let left = view.textDirection == exports.Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth;
|
|
7377
|
+
return { left: left - view.scrollDOM.scrollLeft, top: rect.top - view.scrollDOM.scrollTop };
|
|
7378
|
+
}
|
|
7379
|
+
function wrappedLine(view, pos, inside) {
|
|
7380
|
+
let range = state.EditorSelection.cursor(pos);
|
|
7381
|
+
return { from: Math.max(inside.from, view.moveToLineBoundary(range, false, true).from),
|
|
7382
|
+
to: Math.min(inside.to, view.moveToLineBoundary(range, true, true).from),
|
|
7383
|
+
type: exports.BlockType.Text };
|
|
7384
|
+
}
|
|
7385
|
+
function blockAt(view, pos) {
|
|
7386
|
+
let line = view.lineBlockAt(pos);
|
|
7387
|
+
if (Array.isArray(line.type))
|
|
7388
|
+
for (let l of line.type) {
|
|
7389
|
+
if (l.to > pos || l.to == pos && (l.to == line.to || l.type == exports.BlockType.Text))
|
|
7390
|
+
return l;
|
|
7391
|
+
}
|
|
7392
|
+
return line;
|
|
7393
|
+
}
|
|
7394
|
+
function rectanglesForRange(view, className, range) {
|
|
7395
|
+
if (range.to <= view.viewport.from || range.from >= view.viewport.to)
|
|
7396
|
+
return [];
|
|
7397
|
+
let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
|
|
7398
|
+
let ltr = view.textDirection == exports.Direction.LTR;
|
|
7399
|
+
let content = view.contentDOM, contentRect = content.getBoundingClientRect(), base = getBase(view);
|
|
7400
|
+
let lineStyle = window.getComputedStyle(content.firstChild);
|
|
7401
|
+
let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent));
|
|
7402
|
+
let rightSide = contentRect.right - parseInt(lineStyle.paddingRight);
|
|
7403
|
+
let startBlock = blockAt(view, from), endBlock = blockAt(view, to);
|
|
7404
|
+
let visualStart = startBlock.type == exports.BlockType.Text ? startBlock : null;
|
|
7405
|
+
let visualEnd = endBlock.type == exports.BlockType.Text ? endBlock : null;
|
|
7406
|
+
if (view.lineWrapping) {
|
|
7407
|
+
if (visualStart)
|
|
7408
|
+
visualStart = wrappedLine(view, from, visualStart);
|
|
7409
|
+
if (visualEnd)
|
|
7410
|
+
visualEnd = wrappedLine(view, to, visualEnd);
|
|
7411
|
+
}
|
|
7412
|
+
if (visualStart && visualEnd && visualStart.from == visualEnd.from) {
|
|
7413
|
+
return pieces(drawForLine(range.from, range.to, visualStart));
|
|
7414
|
+
}
|
|
7415
|
+
else {
|
|
7416
|
+
let top = visualStart ? drawForLine(range.from, null, visualStart) : drawForWidget(startBlock, false);
|
|
7417
|
+
let bottom = visualEnd ? drawForLine(null, range.to, visualEnd) : drawForWidget(endBlock, true);
|
|
7418
|
+
let between = [];
|
|
7419
|
+
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - 1)
|
|
7420
|
+
between.push(piece(leftSide, top.bottom, rightSide, bottom.top));
|
|
7421
|
+
else if (top.bottom < bottom.top && view.elementAtHeight((top.bottom + bottom.top) / 2).type == exports.BlockType.Text)
|
|
7422
|
+
top.bottom = bottom.top = (top.bottom + bottom.top) / 2;
|
|
7423
|
+
return pieces(top).concat(between).concat(pieces(bottom));
|
|
7424
|
+
}
|
|
7425
|
+
function piece(left, top, right, bottom) {
|
|
7426
|
+
return new RectangleMarker(className, left - base.left, top - base.top - 0.01 /* C.Epsilon */, right - left, bottom - top + 0.01 /* C.Epsilon */);
|
|
7427
|
+
}
|
|
7428
|
+
function pieces({ top, bottom, horizontal }) {
|
|
7429
|
+
let pieces = [];
|
|
7430
|
+
for (let i = 0; i < horizontal.length; i += 2)
|
|
7431
|
+
pieces.push(piece(horizontal[i], top, horizontal[i + 1], bottom));
|
|
7432
|
+
return pieces;
|
|
7433
|
+
}
|
|
7434
|
+
// Gets passed from/to in line-local positions
|
|
7435
|
+
function drawForLine(from, to, line) {
|
|
7436
|
+
let top = 1e9, bottom = -1e9, horizontal = [];
|
|
7437
|
+
function addSpan(from, fromOpen, to, toOpen, dir) {
|
|
7438
|
+
// Passing 2/-2 is a kludge to force the view to return
|
|
7439
|
+
// coordinates on the proper side of block widgets, since
|
|
7440
|
+
// normalizing the side there, though appropriate for most
|
|
7441
|
+
// coordsAtPos queries, would break selection drawing.
|
|
7442
|
+
let fromCoords = view.coordsAtPos(from, (from == line.to ? -2 : 2));
|
|
7443
|
+
let toCoords = view.coordsAtPos(to, (to == line.from ? 2 : -2));
|
|
7444
|
+
top = Math.min(fromCoords.top, toCoords.top, top);
|
|
7445
|
+
bottom = Math.max(fromCoords.bottom, toCoords.bottom, bottom);
|
|
7446
|
+
if (dir == exports.Direction.LTR)
|
|
7447
|
+
horizontal.push(ltr && fromOpen ? leftSide : fromCoords.left, ltr && toOpen ? rightSide : toCoords.right);
|
|
7448
|
+
else
|
|
7449
|
+
horizontal.push(!ltr && toOpen ? leftSide : toCoords.left, !ltr && fromOpen ? rightSide : fromCoords.right);
|
|
7450
|
+
}
|
|
7451
|
+
let start = from !== null && from !== void 0 ? from : line.from, end = to !== null && to !== void 0 ? to : line.to;
|
|
7452
|
+
// Split the range by visible range and document line
|
|
7453
|
+
for (let r of view.visibleRanges)
|
|
7454
|
+
if (r.to > start && r.from < end) {
|
|
7455
|
+
for (let pos = Math.max(r.from, start), endPos = Math.min(r.to, end);;) {
|
|
7456
|
+
let docLine = view.state.doc.lineAt(pos);
|
|
7457
|
+
for (let span of view.bidiSpans(docLine)) {
|
|
7458
|
+
let spanFrom = span.from + docLine.from, spanTo = span.to + docLine.from;
|
|
7459
|
+
if (spanFrom >= endPos)
|
|
7460
|
+
break;
|
|
7461
|
+
if (spanTo > pos)
|
|
7462
|
+
addSpan(Math.max(spanFrom, pos), from == null && spanFrom <= start, Math.min(spanTo, endPos), to == null && spanTo >= end, span.dir);
|
|
7463
|
+
}
|
|
7464
|
+
pos = docLine.to + 1;
|
|
7465
|
+
if (pos >= endPos)
|
|
7466
|
+
break;
|
|
7467
|
+
}
|
|
7468
|
+
}
|
|
7469
|
+
if (horizontal.length == 0)
|
|
7470
|
+
addSpan(start, from == null, end, to == null, view.textDirection);
|
|
7471
|
+
return { top, bottom, horizontal };
|
|
7472
|
+
}
|
|
7473
|
+
function drawForWidget(block, top) {
|
|
7474
|
+
let y = contentRect.top + (top ? block.top : block.bottom);
|
|
7475
|
+
return { top: y, bottom: y, horizontal: [] };
|
|
7476
|
+
}
|
|
7331
7477
|
}
|
|
7332
7478
|
function sameMarker(a, b) {
|
|
7333
7479
|
return a.constructor == b.constructor && a.eq(b);
|
|
@@ -7387,6 +7533,8 @@ class LayerView {
|
|
|
7387
7533
|
}
|
|
7388
7534
|
}
|
|
7389
7535
|
destroy() {
|
|
7536
|
+
if (this.layer.destroy)
|
|
7537
|
+
this.layer.destroy(this.dom, this.view);
|
|
7390
7538
|
this.dom.remove();
|
|
7391
7539
|
}
|
|
7392
7540
|
}
|
|
@@ -7446,13 +7594,14 @@ function configChanged(update) {
|
|
|
7446
7594
|
const cursorLayer = layer({
|
|
7447
7595
|
above: true,
|
|
7448
7596
|
markers(view) {
|
|
7449
|
-
let { state } = view, conf = state.facet(selectionConfig);
|
|
7597
|
+
let { state: state$1 } = view, conf = state$1.facet(selectionConfig);
|
|
7450
7598
|
let cursors = [];
|
|
7451
|
-
for (let r of state.selection.ranges) {
|
|
7452
|
-
let prim = r == state.selection.main;
|
|
7599
|
+
for (let r of state$1.selection.ranges) {
|
|
7600
|
+
let prim = r == state$1.selection.main;
|
|
7453
7601
|
if (r.empty ? !prim || CanHidePrimary : conf.drawRangeCursor) {
|
|
7454
|
-
let
|
|
7455
|
-
|
|
7602
|
+
let className = prim ? "cm-cursor cm-cursor-primary" : "cm-cursor cm-cursor-secondary";
|
|
7603
|
+
let cursor = r.empty ? r : state.EditorSelection.cursor(r.head, r.head > r.anchor ? -1 : 1);
|
|
7604
|
+
for (let piece of RectangleMarker.forRange(view, className, cursor))
|
|
7456
7605
|
cursors.push(piece);
|
|
7457
7606
|
}
|
|
7458
7607
|
}
|
|
@@ -7477,7 +7626,8 @@ function setBlinkRate(state, dom) {
|
|
|
7477
7626
|
const selectionLayer = layer({
|
|
7478
7627
|
above: false,
|
|
7479
7628
|
markers(view) {
|
|
7480
|
-
return view.state.selection.ranges.map(r => r.empty ? [] :
|
|
7629
|
+
return view.state.selection.ranges.map(r => r.empty ? [] : RectangleMarker.forRange(view, "cm-selectionBackground", r))
|
|
7630
|
+
.reduce((a, b) => a.concat(b));
|
|
7481
7631
|
},
|
|
7482
7632
|
update(update, dom) {
|
|
7483
7633
|
return update.docChanged || update.selectionSet || update.viewportChanged || configChanged(update);
|
|
@@ -7493,117 +7643,6 @@ const themeSpec = {
|
|
|
7493
7643
|
if (CanHidePrimary)
|
|
7494
7644
|
themeSpec[".cm-line"].caretColor = "transparent !important";
|
|
7495
7645
|
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
7646
|
|
|
7608
7647
|
const setDropCursorPos = state.StateEffect.define({
|
|
7609
7648
|
map(pos, mapping) { return pos == null ? null : mapping.mapPos(pos); }
|
|
@@ -9370,6 +9409,57 @@ function highlightActiveLineGutter() {
|
|
|
9370
9409
|
return activeLineGutterHighlighter;
|
|
9371
9410
|
}
|
|
9372
9411
|
|
|
9412
|
+
const WhitespaceDeco = new Map();
|
|
9413
|
+
function getWhitespaceDeco(space) {
|
|
9414
|
+
let deco = WhitespaceDeco.get(space);
|
|
9415
|
+
if (!deco)
|
|
9416
|
+
WhitespaceDeco.set(space, deco = Decoration.mark({
|
|
9417
|
+
attributes: space === "\t" ? {
|
|
9418
|
+
class: "cm-highlightTab",
|
|
9419
|
+
} : {
|
|
9420
|
+
class: "cm-highlightSpace",
|
|
9421
|
+
"data-display": space.replace(/ /g, "·")
|
|
9422
|
+
}
|
|
9423
|
+
}));
|
|
9424
|
+
return deco;
|
|
9425
|
+
}
|
|
9426
|
+
function matcher(decorator) {
|
|
9427
|
+
return ViewPlugin.define(view => ({
|
|
9428
|
+
decorations: decorator.createDeco(view),
|
|
9429
|
+
update(u) {
|
|
9430
|
+
this.decorations = decorator.updateDeco(u, this.decorations);
|
|
9431
|
+
},
|
|
9432
|
+
}), {
|
|
9433
|
+
decorations: v => v.decorations
|
|
9434
|
+
});
|
|
9435
|
+
}
|
|
9436
|
+
const whitespaceHighlighter = matcher(new MatchDecorator({
|
|
9437
|
+
regexp: /\t| +/g,
|
|
9438
|
+
decoration: match => getWhitespaceDeco(match[0]),
|
|
9439
|
+
boundary: /\S/,
|
|
9440
|
+
}));
|
|
9441
|
+
/**
|
|
9442
|
+
Returns an extension that highlights whitespace, adding a
|
|
9443
|
+
`cm-highlightSpace` class to stretches of spaces, and a
|
|
9444
|
+
`cm-highlightTab` class to individual tab characters. By default,
|
|
9445
|
+
the former are shown as faint dots, and the latter as arrows.
|
|
9446
|
+
*/
|
|
9447
|
+
function highlightWhitespace() {
|
|
9448
|
+
return whitespaceHighlighter;
|
|
9449
|
+
}
|
|
9450
|
+
const trailingHighlighter = matcher(new MatchDecorator({
|
|
9451
|
+
regexp: /\s+$/g,
|
|
9452
|
+
decoration: Decoration.mark({ class: "cm-trailingSpace" }),
|
|
9453
|
+
boundary: /\S/,
|
|
9454
|
+
}));
|
|
9455
|
+
/**
|
|
9456
|
+
Returns an extension that adds a `cm-trailingSpace` class to all
|
|
9457
|
+
trailing whitespace.
|
|
9458
|
+
*/
|
|
9459
|
+
function highlightTrailingWhitespace() {
|
|
9460
|
+
return trailingHighlighter;
|
|
9461
|
+
}
|
|
9462
|
+
|
|
9373
9463
|
/**
|
|
9374
9464
|
@internal
|
|
9375
9465
|
*/
|
|
@@ -9399,6 +9489,8 @@ exports.hasHoverTooltips = hasHoverTooltips;
|
|
|
9399
9489
|
exports.highlightActiveLine = highlightActiveLine;
|
|
9400
9490
|
exports.highlightActiveLineGutter = highlightActiveLineGutter;
|
|
9401
9491
|
exports.highlightSpecialChars = highlightSpecialChars;
|
|
9492
|
+
exports.highlightTrailingWhitespace = highlightTrailingWhitespace;
|
|
9493
|
+
exports.highlightWhitespace = highlightWhitespace;
|
|
9402
9494
|
exports.hoverTooltip = hoverTooltip;
|
|
9403
9495
|
exports.keymap = keymap;
|
|
9404
9496
|
exports.layer = layer;
|
package/dist/index.d.ts
CHANGED
|
@@ -1402,13 +1402,22 @@ declare class RectangleMarker implements LayerMarker {
|
|
|
1402
1402
|
private width;
|
|
1403
1403
|
private height;
|
|
1404
1404
|
/**
|
|
1405
|
-
Create a marker with the given class and dimensions.
|
|
1405
|
+
Create a marker with the given class and dimensions. If `width`
|
|
1406
|
+
is null, the DOM element will get no width style.
|
|
1406
1407
|
*/
|
|
1407
|
-
constructor(className: string, left: number, top: number, width: number, height: number);
|
|
1408
|
+
constructor(className: string, left: number, top: number, width: number | null, height: number);
|
|
1408
1409
|
draw(): HTMLDivElement;
|
|
1409
1410
|
update(elt: HTMLElement, prev: RectangleMarker): boolean;
|
|
1410
1411
|
private adjust;
|
|
1411
1412
|
eq(p: RectangleMarker): boolean;
|
|
1413
|
+
/**
|
|
1414
|
+
Create a set of rectangles for the given selection range,
|
|
1415
|
+
assigning them theclass`className`. Will create a single
|
|
1416
|
+
rectangle for empty ranges, and a set of selection-style
|
|
1417
|
+
rectangles covering the range's content (in a bidi-aware
|
|
1418
|
+
way) for non-empty ones.
|
|
1419
|
+
*/
|
|
1420
|
+
static forRange(view: EditorView, className: string, range: SelectionRange): readonly RectangleMarker[];
|
|
1412
1421
|
}
|
|
1413
1422
|
interface LayerConfig {
|
|
1414
1423
|
/**
|
|
@@ -1434,6 +1443,11 @@ interface LayerConfig {
|
|
|
1434
1443
|
If given, this is called when the layer is created.
|
|
1435
1444
|
*/
|
|
1436
1445
|
mount?(layer: HTMLElement, view: EditorView): void;
|
|
1446
|
+
/**
|
|
1447
|
+
If given, called when the layer is removed from the editor or
|
|
1448
|
+
the entire editor is destroyed.
|
|
1449
|
+
*/
|
|
1450
|
+
destroy?(layer: HTMLElement, view: EditorView): void;
|
|
1437
1451
|
}
|
|
1438
1452
|
/**
|
|
1439
1453
|
Define a layer.
|
|
@@ -1900,4 +1914,17 @@ line](https://codemirror.net/6/docs/ref/#view.highlightActiveLine).
|
|
|
1900
1914
|
*/
|
|
1901
1915
|
declare function highlightActiveLineGutter(): Extension;
|
|
1902
1916
|
|
|
1903
|
-
|
|
1917
|
+
/**
|
|
1918
|
+
Returns an extension that highlights whitespace, adding a
|
|
1919
|
+
`cm-highlightSpace` class to stretches of spaces, and a
|
|
1920
|
+
`cm-highlightTab` class to individual tab characters. By default,
|
|
1921
|
+
the former are shown as faint dots, and the latter as arrows.
|
|
1922
|
+
*/
|
|
1923
|
+
declare function highlightWhitespace(): Extension;
|
|
1924
|
+
/**
|
|
1925
|
+
Returns an extension that adds a `cm-trailingSpace` class to all
|
|
1926
|
+
trailing whitespace.
|
|
1927
|
+
*/
|
|
1928
|
+
declare function highlightTrailingWhitespace(): Extension;
|
|
1929
|
+
|
|
1930
|
+
export { BidiSpan, BlockInfo, BlockType, Command, DOMEventHandlers, DOMEventMap, Decoration, DecorationSet, Direction, EditorView, EditorViewConfig, GutterMarker, KeyBinding, LayerMarker, MatchDecorator, MouseSelectionStyle, Panel, PanelConstructor, PluginSpec, PluginValue, Rect, RectangleMarker, Tooltip, TooltipView, ViewPlugin, ViewUpdate, WidgetType, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getPanel, getTooltip, gutter, gutterLineClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, highlightWhitespace, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showPanel, showTooltip, tooltips };
|
package/dist/index.js
CHANGED
|
@@ -1598,6 +1598,7 @@ class ContentBuilder {
|
|
|
1598
1598
|
this.curLine = null;
|
|
1599
1599
|
this.breakAtStart = 0;
|
|
1600
1600
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1601
|
+
this.bufferMarks = [];
|
|
1601
1602
|
// Set to false directly after a widget that covers the position after it
|
|
1602
1603
|
this.atCursorPos = true;
|
|
1603
1604
|
this.openStart = -1;
|
|
@@ -1620,20 +1621,20 @@ class ContentBuilder {
|
|
|
1620
1621
|
}
|
|
1621
1622
|
return this.curLine;
|
|
1622
1623
|
}
|
|
1623
|
-
flushBuffer(active) {
|
|
1624
|
+
flushBuffer(active = this.bufferMarks) {
|
|
1624
1625
|
if (this.pendingBuffer) {
|
|
1625
1626
|
this.curLine.append(wrapMarks(new WidgetBufferView(-1), active), active.length);
|
|
1626
1627
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1627
1628
|
}
|
|
1628
1629
|
}
|
|
1629
1630
|
addBlockWidget(view) {
|
|
1630
|
-
this.flushBuffer(
|
|
1631
|
+
this.flushBuffer();
|
|
1631
1632
|
this.curLine = null;
|
|
1632
1633
|
this.content.push(view);
|
|
1633
1634
|
}
|
|
1634
1635
|
finish(openEnd) {
|
|
1635
|
-
if (
|
|
1636
|
-
this.flushBuffer(
|
|
1636
|
+
if (this.pendingBuffer && openEnd <= this.bufferMarks.length)
|
|
1637
|
+
this.flushBuffer();
|
|
1637
1638
|
else
|
|
1638
1639
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1639
1640
|
if (!this.posCovered())
|
|
@@ -1653,8 +1654,9 @@ class ContentBuilder {
|
|
|
1653
1654
|
this.content[this.content.length - 1].breakAfter = 1;
|
|
1654
1655
|
else
|
|
1655
1656
|
this.breakAtStart = 1;
|
|
1656
|
-
this.flushBuffer(
|
|
1657
|
+
this.flushBuffer();
|
|
1657
1658
|
this.curLine = null;
|
|
1659
|
+
this.atCursorPos = true;
|
|
1658
1660
|
length--;
|
|
1659
1661
|
continue;
|
|
1660
1662
|
}
|
|
@@ -1696,7 +1698,7 @@ class ContentBuilder {
|
|
|
1696
1698
|
else {
|
|
1697
1699
|
let view = WidgetView.create(deco.widget || new NullWidget("span"), len, len ? 0 : deco.startSide);
|
|
1698
1700
|
let cursorBefore = this.atCursorPos && !view.isEditable && openStart <= active.length && (from < to || deco.startSide > 0);
|
|
1699
|
-
let cursorAfter = !view.isEditable && (from < to || deco.startSide <= 0);
|
|
1701
|
+
let cursorAfter = !view.isEditable && (from < to || openStart > active.length || deco.startSide <= 0);
|
|
1700
1702
|
let line = this.getLine();
|
|
1701
1703
|
if (this.pendingBuffer == 2 /* Buf.IfCursor */ && !cursorBefore)
|
|
1702
1704
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
@@ -1707,7 +1709,9 @@ class ContentBuilder {
|
|
|
1707
1709
|
}
|
|
1708
1710
|
line.append(wrapMarks(view, active), openStart);
|
|
1709
1711
|
this.atCursorPos = cursorAfter;
|
|
1710
|
-
this.pendingBuffer = !cursorAfter ? 0 /* Buf.No */ : from < to ? 1 /* Buf.Yes */ : 2 /* Buf.IfCursor */;
|
|
1712
|
+
this.pendingBuffer = !cursorAfter ? 0 /* Buf.No */ : from < to || openStart > active.length ? 1 /* Buf.Yes */ : 2 /* Buf.IfCursor */;
|
|
1713
|
+
if (this.pendingBuffer)
|
|
1714
|
+
this.bufferMarks = active.slice();
|
|
1711
1715
|
}
|
|
1712
1716
|
}
|
|
1713
1717
|
else if (this.doc.lineAt(this.pos).from == this.pos) { // Line decoration
|
|
@@ -5284,7 +5288,6 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5284
5288
|
margin: 0,
|
|
5285
5289
|
flexGrow: 2,
|
|
5286
5290
|
flexShrink: 0,
|
|
5287
|
-
minHeight: "100%",
|
|
5288
5291
|
display: "block",
|
|
5289
5292
|
whiteSpace: "pre",
|
|
5290
5293
|
wordWrap: "normal",
|
|
@@ -5431,6 +5434,21 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5431
5434
|
display: "inline-block",
|
|
5432
5435
|
verticalAlign: "top",
|
|
5433
5436
|
},
|
|
5437
|
+
".cm-highlightSpace:before": {
|
|
5438
|
+
content: "attr(data-display)",
|
|
5439
|
+
position: "absolute",
|
|
5440
|
+
pointerEvents: "none",
|
|
5441
|
+
color: "#888"
|
|
5442
|
+
},
|
|
5443
|
+
".cm-highlightTab": {
|
|
5444
|
+
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>')`,
|
|
5445
|
+
backgroundSize: "auto 100%",
|
|
5446
|
+
backgroundPosition: "right 90%",
|
|
5447
|
+
backgroundRepeat: "no-repeat"
|
|
5448
|
+
},
|
|
5449
|
+
".cm-trailingSpace": {
|
|
5450
|
+
backgroundColor: "#ff332255"
|
|
5451
|
+
},
|
|
5434
5452
|
".cm-button": {
|
|
5435
5453
|
verticalAlign: "middle",
|
|
5436
5454
|
color: "inherit",
|
|
@@ -5733,7 +5751,8 @@ class DOMObserver {
|
|
|
5733
5751
|
this.lastChange = 0;
|
|
5734
5752
|
this.scrollTargets = [];
|
|
5735
5753
|
this.intersection = null;
|
|
5736
|
-
this.
|
|
5754
|
+
this.resizeScroll = null;
|
|
5755
|
+
this.resizeContent = null;
|
|
5737
5756
|
this.intersecting = false;
|
|
5738
5757
|
this.gapIntersection = null;
|
|
5739
5758
|
this.gaps = [];
|
|
@@ -5771,12 +5790,14 @@ class DOMObserver {
|
|
|
5771
5790
|
this.onPrint = this.onPrint.bind(this);
|
|
5772
5791
|
this.onScroll = this.onScroll.bind(this);
|
|
5773
5792
|
if (typeof ResizeObserver == "function") {
|
|
5774
|
-
this.
|
|
5793
|
+
this.resizeScroll = new ResizeObserver(() => {
|
|
5775
5794
|
var _a;
|
|
5776
5795
|
if (((_a = this.view.docView) === null || _a === void 0 ? void 0 : _a.lastUpdate) < Date.now() - 75)
|
|
5777
5796
|
this.onResize();
|
|
5778
5797
|
});
|
|
5779
|
-
this.
|
|
5798
|
+
this.resizeScroll.observe(view.scrollDOM);
|
|
5799
|
+
this.resizeContent = new ResizeObserver(() => this.view.requestMeasure());
|
|
5800
|
+
this.resizeContent.observe(view.contentDOM);
|
|
5780
5801
|
}
|
|
5781
5802
|
this.addWindowListeners(this.win = view.win);
|
|
5782
5803
|
this.start();
|
|
@@ -6095,11 +6116,12 @@ class DOMObserver {
|
|
|
6095
6116
|
win.document.removeEventListener("selectionchange", this.onSelectionChange);
|
|
6096
6117
|
}
|
|
6097
6118
|
destroy() {
|
|
6098
|
-
var _a, _b, _c;
|
|
6119
|
+
var _a, _b, _c, _d;
|
|
6099
6120
|
this.stop();
|
|
6100
6121
|
(_a = this.intersection) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
6101
6122
|
(_b = this.gapIntersection) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
6102
|
-
(_c = this.
|
|
6123
|
+
(_c = this.resizeScroll) === null || _c === void 0 ? void 0 : _c.disconnect();
|
|
6124
|
+
(_d = this.resizeContent) === null || _d === void 0 ? void 0 : _d.disconnect();
|
|
6103
6125
|
for (let dom of this.scrollTargets)
|
|
6104
6126
|
dom.removeEventListener("scroll", this.onScroll);
|
|
6105
6127
|
this.removeWindowListeners(this.win);
|
|
@@ -6198,7 +6220,7 @@ class EditorView {
|
|
|
6198
6220
|
this.scrollDOM.className = "cm-scroller";
|
|
6199
6221
|
this.scrollDOM.appendChild(this.contentDOM);
|
|
6200
6222
|
this.announceDOM = document.createElement("div");
|
|
6201
|
-
this.announceDOM.style.cssText = "position:
|
|
6223
|
+
this.announceDOM.style.cssText = "position: fixed; top: -10000px";
|
|
6202
6224
|
this.announceDOM.setAttribute("aria-live", "polite");
|
|
6203
6225
|
this.dom = document.createElement("div");
|
|
6204
6226
|
this.dom.appendChild(this.announceDOM);
|
|
@@ -7289,7 +7311,8 @@ a rectangle at a given set of coordinates.
|
|
|
7289
7311
|
*/
|
|
7290
7312
|
class RectangleMarker {
|
|
7291
7313
|
/**
|
|
7292
|
-
Create a marker with the given class and dimensions.
|
|
7314
|
+
Create a marker with the given class and dimensions. If `width`
|
|
7315
|
+
is null, the DOM element will get no width style.
|
|
7293
7316
|
*/
|
|
7294
7317
|
constructor(className, left, top, width, height) {
|
|
7295
7318
|
this.className = className;
|
|
@@ -7313,7 +7336,7 @@ class RectangleMarker {
|
|
|
7313
7336
|
adjust(elt) {
|
|
7314
7337
|
elt.style.left = this.left + "px";
|
|
7315
7338
|
elt.style.top = this.top + "px";
|
|
7316
|
-
if (this.width
|
|
7339
|
+
if (this.width != null)
|
|
7317
7340
|
elt.style.width = this.width + "px";
|
|
7318
7341
|
elt.style.height = this.height + "px";
|
|
7319
7342
|
}
|
|
@@ -7321,6 +7344,129 @@ class RectangleMarker {
|
|
|
7321
7344
|
return this.left == p.left && this.top == p.top && this.width == p.width && this.height == p.height &&
|
|
7322
7345
|
this.className == p.className;
|
|
7323
7346
|
}
|
|
7347
|
+
/**
|
|
7348
|
+
Create a set of rectangles for the given selection range,
|
|
7349
|
+
assigning them theclass`className`. Will create a single
|
|
7350
|
+
rectangle for empty ranges, and a set of selection-style
|
|
7351
|
+
rectangles covering the range's content (in a bidi-aware
|
|
7352
|
+
way) for non-empty ones.
|
|
7353
|
+
*/
|
|
7354
|
+
static forRange(view, className, range) {
|
|
7355
|
+
if (range.empty) {
|
|
7356
|
+
let pos = view.coordsAtPos(range.head, range.assoc || 1);
|
|
7357
|
+
if (!pos)
|
|
7358
|
+
return [];
|
|
7359
|
+
let base = getBase(view);
|
|
7360
|
+
return [new RectangleMarker(className, pos.left - base.left, pos.top - base.top, null, pos.bottom - pos.top)];
|
|
7361
|
+
}
|
|
7362
|
+
else {
|
|
7363
|
+
return rectanglesForRange(view, className, range);
|
|
7364
|
+
}
|
|
7365
|
+
}
|
|
7366
|
+
}
|
|
7367
|
+
function getBase(view) {
|
|
7368
|
+
let rect = view.scrollDOM.getBoundingClientRect();
|
|
7369
|
+
let left = view.textDirection == Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth;
|
|
7370
|
+
return { left: left - view.scrollDOM.scrollLeft, top: rect.top - view.scrollDOM.scrollTop };
|
|
7371
|
+
}
|
|
7372
|
+
function wrappedLine(view, pos, inside) {
|
|
7373
|
+
let range = EditorSelection.cursor(pos);
|
|
7374
|
+
return { from: Math.max(inside.from, view.moveToLineBoundary(range, false, true).from),
|
|
7375
|
+
to: Math.min(inside.to, view.moveToLineBoundary(range, true, true).from),
|
|
7376
|
+
type: BlockType.Text };
|
|
7377
|
+
}
|
|
7378
|
+
function blockAt(view, pos) {
|
|
7379
|
+
let line = view.lineBlockAt(pos);
|
|
7380
|
+
if (Array.isArray(line.type))
|
|
7381
|
+
for (let l of line.type) {
|
|
7382
|
+
if (l.to > pos || l.to == pos && (l.to == line.to || l.type == BlockType.Text))
|
|
7383
|
+
return l;
|
|
7384
|
+
}
|
|
7385
|
+
return line;
|
|
7386
|
+
}
|
|
7387
|
+
function rectanglesForRange(view, className, range) {
|
|
7388
|
+
if (range.to <= view.viewport.from || range.from >= view.viewport.to)
|
|
7389
|
+
return [];
|
|
7390
|
+
let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
|
|
7391
|
+
let ltr = view.textDirection == Direction.LTR;
|
|
7392
|
+
let content = view.contentDOM, contentRect = content.getBoundingClientRect(), base = getBase(view);
|
|
7393
|
+
let lineStyle = window.getComputedStyle(content.firstChild);
|
|
7394
|
+
let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent));
|
|
7395
|
+
let rightSide = contentRect.right - parseInt(lineStyle.paddingRight);
|
|
7396
|
+
let startBlock = blockAt(view, from), endBlock = blockAt(view, to);
|
|
7397
|
+
let visualStart = startBlock.type == BlockType.Text ? startBlock : null;
|
|
7398
|
+
let visualEnd = endBlock.type == BlockType.Text ? endBlock : null;
|
|
7399
|
+
if (view.lineWrapping) {
|
|
7400
|
+
if (visualStart)
|
|
7401
|
+
visualStart = wrappedLine(view, from, visualStart);
|
|
7402
|
+
if (visualEnd)
|
|
7403
|
+
visualEnd = wrappedLine(view, to, visualEnd);
|
|
7404
|
+
}
|
|
7405
|
+
if (visualStart && visualEnd && visualStart.from == visualEnd.from) {
|
|
7406
|
+
return pieces(drawForLine(range.from, range.to, visualStart));
|
|
7407
|
+
}
|
|
7408
|
+
else {
|
|
7409
|
+
let top = visualStart ? drawForLine(range.from, null, visualStart) : drawForWidget(startBlock, false);
|
|
7410
|
+
let bottom = visualEnd ? drawForLine(null, range.to, visualEnd) : drawForWidget(endBlock, true);
|
|
7411
|
+
let between = [];
|
|
7412
|
+
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - 1)
|
|
7413
|
+
between.push(piece(leftSide, top.bottom, rightSide, bottom.top));
|
|
7414
|
+
else if (top.bottom < bottom.top && view.elementAtHeight((top.bottom + bottom.top) / 2).type == BlockType.Text)
|
|
7415
|
+
top.bottom = bottom.top = (top.bottom + bottom.top) / 2;
|
|
7416
|
+
return pieces(top).concat(between).concat(pieces(bottom));
|
|
7417
|
+
}
|
|
7418
|
+
function piece(left, top, right, bottom) {
|
|
7419
|
+
return new RectangleMarker(className, left - base.left, top - base.top - 0.01 /* C.Epsilon */, right - left, bottom - top + 0.01 /* C.Epsilon */);
|
|
7420
|
+
}
|
|
7421
|
+
function pieces({ top, bottom, horizontal }) {
|
|
7422
|
+
let pieces = [];
|
|
7423
|
+
for (let i = 0; i < horizontal.length; i += 2)
|
|
7424
|
+
pieces.push(piece(horizontal[i], top, horizontal[i + 1], bottom));
|
|
7425
|
+
return pieces;
|
|
7426
|
+
}
|
|
7427
|
+
// Gets passed from/to in line-local positions
|
|
7428
|
+
function drawForLine(from, to, line) {
|
|
7429
|
+
let top = 1e9, bottom = -1e9, horizontal = [];
|
|
7430
|
+
function addSpan(from, fromOpen, to, toOpen, dir) {
|
|
7431
|
+
// Passing 2/-2 is a kludge to force the view to return
|
|
7432
|
+
// coordinates on the proper side of block widgets, since
|
|
7433
|
+
// normalizing the side there, though appropriate for most
|
|
7434
|
+
// coordsAtPos queries, would break selection drawing.
|
|
7435
|
+
let fromCoords = view.coordsAtPos(from, (from == line.to ? -2 : 2));
|
|
7436
|
+
let toCoords = view.coordsAtPos(to, (to == line.from ? 2 : -2));
|
|
7437
|
+
top = Math.min(fromCoords.top, toCoords.top, top);
|
|
7438
|
+
bottom = Math.max(fromCoords.bottom, toCoords.bottom, bottom);
|
|
7439
|
+
if (dir == Direction.LTR)
|
|
7440
|
+
horizontal.push(ltr && fromOpen ? leftSide : fromCoords.left, ltr && toOpen ? rightSide : toCoords.right);
|
|
7441
|
+
else
|
|
7442
|
+
horizontal.push(!ltr && toOpen ? leftSide : toCoords.left, !ltr && fromOpen ? rightSide : fromCoords.right);
|
|
7443
|
+
}
|
|
7444
|
+
let start = from !== null && from !== void 0 ? from : line.from, end = to !== null && to !== void 0 ? to : line.to;
|
|
7445
|
+
// Split the range by visible range and document line
|
|
7446
|
+
for (let r of view.visibleRanges)
|
|
7447
|
+
if (r.to > start && r.from < end) {
|
|
7448
|
+
for (let pos = Math.max(r.from, start), endPos = Math.min(r.to, end);;) {
|
|
7449
|
+
let docLine = view.state.doc.lineAt(pos);
|
|
7450
|
+
for (let span of view.bidiSpans(docLine)) {
|
|
7451
|
+
let spanFrom = span.from + docLine.from, spanTo = span.to + docLine.from;
|
|
7452
|
+
if (spanFrom >= endPos)
|
|
7453
|
+
break;
|
|
7454
|
+
if (spanTo > pos)
|
|
7455
|
+
addSpan(Math.max(spanFrom, pos), from == null && spanFrom <= start, Math.min(spanTo, endPos), to == null && spanTo >= end, span.dir);
|
|
7456
|
+
}
|
|
7457
|
+
pos = docLine.to + 1;
|
|
7458
|
+
if (pos >= endPos)
|
|
7459
|
+
break;
|
|
7460
|
+
}
|
|
7461
|
+
}
|
|
7462
|
+
if (horizontal.length == 0)
|
|
7463
|
+
addSpan(start, from == null, end, to == null, view.textDirection);
|
|
7464
|
+
return { top, bottom, horizontal };
|
|
7465
|
+
}
|
|
7466
|
+
function drawForWidget(block, top) {
|
|
7467
|
+
let y = contentRect.top + (top ? block.top : block.bottom);
|
|
7468
|
+
return { top: y, bottom: y, horizontal: [] };
|
|
7469
|
+
}
|
|
7324
7470
|
}
|
|
7325
7471
|
function sameMarker(a, b) {
|
|
7326
7472
|
return a.constructor == b.constructor && a.eq(b);
|
|
@@ -7380,6 +7526,8 @@ class LayerView {
|
|
|
7380
7526
|
}
|
|
7381
7527
|
}
|
|
7382
7528
|
destroy() {
|
|
7529
|
+
if (this.layer.destroy)
|
|
7530
|
+
this.layer.destroy(this.dom, this.view);
|
|
7383
7531
|
this.dom.remove();
|
|
7384
7532
|
}
|
|
7385
7533
|
}
|
|
@@ -7444,8 +7592,9 @@ const cursorLayer = /*@__PURE__*/layer({
|
|
|
7444
7592
|
for (let r of state.selection.ranges) {
|
|
7445
7593
|
let prim = r == state.selection.main;
|
|
7446
7594
|
if (r.empty ? !prim || CanHidePrimary : conf.drawRangeCursor) {
|
|
7447
|
-
let
|
|
7448
|
-
|
|
7595
|
+
let className = prim ? "cm-cursor cm-cursor-primary" : "cm-cursor cm-cursor-secondary";
|
|
7596
|
+
let cursor = r.empty ? r : EditorSelection.cursor(r.head, r.head > r.anchor ? -1 : 1);
|
|
7597
|
+
for (let piece of RectangleMarker.forRange(view, className, cursor))
|
|
7449
7598
|
cursors.push(piece);
|
|
7450
7599
|
}
|
|
7451
7600
|
}
|
|
@@ -7470,7 +7619,8 @@ function setBlinkRate(state, dom) {
|
|
|
7470
7619
|
const selectionLayer = /*@__PURE__*/layer({
|
|
7471
7620
|
above: false,
|
|
7472
7621
|
markers(view) {
|
|
7473
|
-
return view.state.selection.ranges.map(r => r.empty ? [] :
|
|
7622
|
+
return view.state.selection.ranges.map(r => r.empty ? [] : RectangleMarker.forRange(view, "cm-selectionBackground", r))
|
|
7623
|
+
.reduce((a, b) => a.concat(b));
|
|
7474
7624
|
},
|
|
7475
7625
|
update(update, dom) {
|
|
7476
7626
|
return update.docChanged || update.selectionSet || update.viewportChanged || configChanged(update);
|
|
@@ -7486,117 +7636,6 @@ const themeSpec = {
|
|
|
7486
7636
|
if (CanHidePrimary)
|
|
7487
7637
|
themeSpec[".cm-line"].caretColor = "transparent !important";
|
|
7488
7638
|
const hideNativeSelection = /*@__PURE__*/Prec.highest(/*@__PURE__*/EditorView.theme(themeSpec));
|
|
7489
|
-
function getBase(view) {
|
|
7490
|
-
let rect = view.scrollDOM.getBoundingClientRect();
|
|
7491
|
-
let left = view.textDirection == Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth;
|
|
7492
|
-
return { left: left - view.scrollDOM.scrollLeft, top: rect.top - view.scrollDOM.scrollTop };
|
|
7493
|
-
}
|
|
7494
|
-
function wrappedLine(view, pos, inside) {
|
|
7495
|
-
let range = EditorSelection.cursor(pos);
|
|
7496
|
-
return { from: Math.max(inside.from, view.moveToLineBoundary(range, false, true).from),
|
|
7497
|
-
to: Math.min(inside.to, view.moveToLineBoundary(range, true, true).from),
|
|
7498
|
-
type: BlockType.Text };
|
|
7499
|
-
}
|
|
7500
|
-
function blockAt(view, pos) {
|
|
7501
|
-
let line = view.lineBlockAt(pos);
|
|
7502
|
-
if (Array.isArray(line.type))
|
|
7503
|
-
for (let l of line.type) {
|
|
7504
|
-
if (l.to > pos || l.to == pos && (l.to == line.to || l.type == BlockType.Text))
|
|
7505
|
-
return l;
|
|
7506
|
-
}
|
|
7507
|
-
return line;
|
|
7508
|
-
}
|
|
7509
|
-
function measureRange(view, range) {
|
|
7510
|
-
if (range.to <= view.viewport.from || range.from >= view.viewport.to)
|
|
7511
|
-
return [];
|
|
7512
|
-
let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
|
|
7513
|
-
let ltr = view.textDirection == Direction.LTR;
|
|
7514
|
-
let content = view.contentDOM, contentRect = content.getBoundingClientRect(), base = getBase(view);
|
|
7515
|
-
let lineStyle = window.getComputedStyle(content.firstChild);
|
|
7516
|
-
let leftSide = contentRect.left + parseInt(lineStyle.paddingLeft) + Math.min(0, parseInt(lineStyle.textIndent));
|
|
7517
|
-
let rightSide = contentRect.right - parseInt(lineStyle.paddingRight);
|
|
7518
|
-
let startBlock = blockAt(view, from), endBlock = blockAt(view, to);
|
|
7519
|
-
let visualStart = startBlock.type == BlockType.Text ? startBlock : null;
|
|
7520
|
-
let visualEnd = endBlock.type == BlockType.Text ? endBlock : null;
|
|
7521
|
-
if (view.lineWrapping) {
|
|
7522
|
-
if (visualStart)
|
|
7523
|
-
visualStart = wrappedLine(view, from, visualStart);
|
|
7524
|
-
if (visualEnd)
|
|
7525
|
-
visualEnd = wrappedLine(view, to, visualEnd);
|
|
7526
|
-
}
|
|
7527
|
-
if (visualStart && visualEnd && visualStart.from == visualEnd.from) {
|
|
7528
|
-
return pieces(drawForLine(range.from, range.to, visualStart));
|
|
7529
|
-
}
|
|
7530
|
-
else {
|
|
7531
|
-
let top = visualStart ? drawForLine(range.from, null, visualStart) : drawForWidget(startBlock, false);
|
|
7532
|
-
let bottom = visualEnd ? drawForLine(null, range.to, visualEnd) : drawForWidget(endBlock, true);
|
|
7533
|
-
let between = [];
|
|
7534
|
-
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - 1)
|
|
7535
|
-
between.push(piece(leftSide, top.bottom, rightSide, bottom.top));
|
|
7536
|
-
else if (top.bottom < bottom.top && view.elementAtHeight((top.bottom + bottom.top) / 2).type == BlockType.Text)
|
|
7537
|
-
top.bottom = bottom.top = (top.bottom + bottom.top) / 2;
|
|
7538
|
-
return pieces(top).concat(between).concat(pieces(bottom));
|
|
7539
|
-
}
|
|
7540
|
-
function piece(left, top, right, bottom) {
|
|
7541
|
-
return new RectangleMarker("cm-selectionBackground", left - base.left, top - base.top - 0.01 /* C.Epsilon */, right - left, bottom - top + 0.01 /* C.Epsilon */);
|
|
7542
|
-
}
|
|
7543
|
-
function pieces({ top, bottom, horizontal }) {
|
|
7544
|
-
let pieces = [];
|
|
7545
|
-
for (let i = 0; i < horizontal.length; i += 2)
|
|
7546
|
-
pieces.push(piece(horizontal[i], top, horizontal[i + 1], bottom));
|
|
7547
|
-
return pieces;
|
|
7548
|
-
}
|
|
7549
|
-
// Gets passed from/to in line-local positions
|
|
7550
|
-
function drawForLine(from, to, line) {
|
|
7551
|
-
let top = 1e9, bottom = -1e9, horizontal = [];
|
|
7552
|
-
function addSpan(from, fromOpen, to, toOpen, dir) {
|
|
7553
|
-
// Passing 2/-2 is a kludge to force the view to return
|
|
7554
|
-
// coordinates on the proper side of block widgets, since
|
|
7555
|
-
// normalizing the side there, though appropriate for most
|
|
7556
|
-
// coordsAtPos queries, would break selection drawing.
|
|
7557
|
-
let fromCoords = view.coordsAtPos(from, (from == line.to ? -2 : 2));
|
|
7558
|
-
let toCoords = view.coordsAtPos(to, (to == line.from ? 2 : -2));
|
|
7559
|
-
top = Math.min(fromCoords.top, toCoords.top, top);
|
|
7560
|
-
bottom = Math.max(fromCoords.bottom, toCoords.bottom, bottom);
|
|
7561
|
-
if (dir == Direction.LTR)
|
|
7562
|
-
horizontal.push(ltr && fromOpen ? leftSide : fromCoords.left, ltr && toOpen ? rightSide : toCoords.right);
|
|
7563
|
-
else
|
|
7564
|
-
horizontal.push(!ltr && toOpen ? leftSide : toCoords.left, !ltr && fromOpen ? rightSide : fromCoords.right);
|
|
7565
|
-
}
|
|
7566
|
-
let start = from !== null && from !== void 0 ? from : line.from, end = to !== null && to !== void 0 ? to : line.to;
|
|
7567
|
-
// Split the range by visible range and document line
|
|
7568
|
-
for (let r of view.visibleRanges)
|
|
7569
|
-
if (r.to > start && r.from < end) {
|
|
7570
|
-
for (let pos = Math.max(r.from, start), endPos = Math.min(r.to, end);;) {
|
|
7571
|
-
let docLine = view.state.doc.lineAt(pos);
|
|
7572
|
-
for (let span of view.bidiSpans(docLine)) {
|
|
7573
|
-
let spanFrom = span.from + docLine.from, spanTo = span.to + docLine.from;
|
|
7574
|
-
if (spanFrom >= endPos)
|
|
7575
|
-
break;
|
|
7576
|
-
if (spanTo > pos)
|
|
7577
|
-
addSpan(Math.max(spanFrom, pos), from == null && spanFrom <= start, Math.min(spanTo, endPos), to == null && spanTo >= end, span.dir);
|
|
7578
|
-
}
|
|
7579
|
-
pos = docLine.to + 1;
|
|
7580
|
-
if (pos >= endPos)
|
|
7581
|
-
break;
|
|
7582
|
-
}
|
|
7583
|
-
}
|
|
7584
|
-
if (horizontal.length == 0)
|
|
7585
|
-
addSpan(start, from == null, end, to == null, view.textDirection);
|
|
7586
|
-
return { top, bottom, horizontal };
|
|
7587
|
-
}
|
|
7588
|
-
function drawForWidget(block, top) {
|
|
7589
|
-
let y = contentRect.top + (top ? block.top : block.bottom);
|
|
7590
|
-
return { top: y, bottom: y, horizontal: [] };
|
|
7591
|
-
}
|
|
7592
|
-
}
|
|
7593
|
-
function measureCursor(view, cursor, primary) {
|
|
7594
|
-
let pos = view.coordsAtPos(cursor.head, cursor.assoc || 1);
|
|
7595
|
-
if (!pos)
|
|
7596
|
-
return null;
|
|
7597
|
-
let base = getBase(view);
|
|
7598
|
-
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);
|
|
7599
|
-
}
|
|
7600
7639
|
|
|
7601
7640
|
const setDropCursorPos = /*@__PURE__*/StateEffect.define({
|
|
7602
7641
|
map(pos, mapping) { return pos == null ? null : mapping.mapPos(pos); }
|
|
@@ -9363,9 +9402,60 @@ function highlightActiveLineGutter() {
|
|
|
9363
9402
|
return activeLineGutterHighlighter;
|
|
9364
9403
|
}
|
|
9365
9404
|
|
|
9405
|
+
const WhitespaceDeco = /*@__PURE__*/new Map();
|
|
9406
|
+
function getWhitespaceDeco(space) {
|
|
9407
|
+
let deco = WhitespaceDeco.get(space);
|
|
9408
|
+
if (!deco)
|
|
9409
|
+
WhitespaceDeco.set(space, deco = Decoration.mark({
|
|
9410
|
+
attributes: space === "\t" ? {
|
|
9411
|
+
class: "cm-highlightTab",
|
|
9412
|
+
} : {
|
|
9413
|
+
class: "cm-highlightSpace",
|
|
9414
|
+
"data-display": space.replace(/ /g, "·")
|
|
9415
|
+
}
|
|
9416
|
+
}));
|
|
9417
|
+
return deco;
|
|
9418
|
+
}
|
|
9419
|
+
function matcher(decorator) {
|
|
9420
|
+
return ViewPlugin.define(view => ({
|
|
9421
|
+
decorations: decorator.createDeco(view),
|
|
9422
|
+
update(u) {
|
|
9423
|
+
this.decorations = decorator.updateDeco(u, this.decorations);
|
|
9424
|
+
},
|
|
9425
|
+
}), {
|
|
9426
|
+
decorations: v => v.decorations
|
|
9427
|
+
});
|
|
9428
|
+
}
|
|
9429
|
+
const whitespaceHighlighter = /*@__PURE__*/matcher(/*@__PURE__*/new MatchDecorator({
|
|
9430
|
+
regexp: /\t| +/g,
|
|
9431
|
+
decoration: match => getWhitespaceDeco(match[0]),
|
|
9432
|
+
boundary: /\S/,
|
|
9433
|
+
}));
|
|
9434
|
+
/**
|
|
9435
|
+
Returns an extension that highlights whitespace, adding a
|
|
9436
|
+
`cm-highlightSpace` class to stretches of spaces, and a
|
|
9437
|
+
`cm-highlightTab` class to individual tab characters. By default,
|
|
9438
|
+
the former are shown as faint dots, and the latter as arrows.
|
|
9439
|
+
*/
|
|
9440
|
+
function highlightWhitespace() {
|
|
9441
|
+
return whitespaceHighlighter;
|
|
9442
|
+
}
|
|
9443
|
+
const trailingHighlighter = /*@__PURE__*/matcher(/*@__PURE__*/new MatchDecorator({
|
|
9444
|
+
regexp: /\s+$/g,
|
|
9445
|
+
decoration: /*@__PURE__*/Decoration.mark({ class: "cm-trailingSpace" }),
|
|
9446
|
+
boundary: /\S/,
|
|
9447
|
+
}));
|
|
9448
|
+
/**
|
|
9449
|
+
Returns an extension that adds a `cm-trailingSpace` class to all
|
|
9450
|
+
trailing whitespace.
|
|
9451
|
+
*/
|
|
9452
|
+
function highlightTrailingWhitespace() {
|
|
9453
|
+
return trailingHighlighter;
|
|
9454
|
+
}
|
|
9455
|
+
|
|
9366
9456
|
/**
|
|
9367
9457
|
@internal
|
|
9368
9458
|
*/
|
|
9369
9459
|
const __test = { HeightMap, HeightOracle, MeasuredHeights, QueryType, ChangedRange, computeOrder, moveVisually };
|
|
9370
9460
|
|
|
9371
|
-
export { BidiSpan, BlockInfo, BlockType, Decoration, Direction, EditorView, GutterMarker, MatchDecorator, RectangleMarker, ViewPlugin, ViewUpdate, WidgetType, __test, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getPanel, getTooltip, gutter, gutterLineClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showPanel, showTooltip, tooltips };
|
|
9461
|
+
export { BidiSpan, BlockInfo, BlockType, Decoration, Direction, EditorView, GutterMarker, MatchDecorator, RectangleMarker, ViewPlugin, ViewUpdate, WidgetType, __test, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getPanel, getTooltip, gutter, gutterLineClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, highlightWhitespace, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showPanel, showTooltip, tooltips };
|