@codemirror/view 6.5.1 → 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 +28 -0
- package/dist/index.cjs +312 -146
- package/dist/index.d.ts +108 -1
- package/dist/index.js +309 -147
- package/package.json +1 -1
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",
|
|
@@ -5313,14 +5316,13 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5313
5316
|
"&dark .cm-content": { caretColor: "white" },
|
|
5314
5317
|
".cm-line": {
|
|
5315
5318
|
display: "block",
|
|
5316
|
-
padding: "0 2px 0
|
|
5317
|
-
},
|
|
5318
|
-
".cm-selectionLayer": {
|
|
5319
|
-
zIndex: -1,
|
|
5320
|
-
contain: "size style"
|
|
5319
|
+
padding: "0 2px 0 6px"
|
|
5321
5320
|
},
|
|
5322
|
-
".cm-
|
|
5323
|
-
|
|
5321
|
+
".cm-layer": {
|
|
5322
|
+
contain: "size style",
|
|
5323
|
+
"& > *": {
|
|
5324
|
+
position: "absolute"
|
|
5325
|
+
}
|
|
5324
5326
|
},
|
|
5325
5327
|
"&light .cm-selectionBackground": {
|
|
5326
5328
|
background: "#d9d9d9"
|
|
@@ -5335,8 +5337,6 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5335
5337
|
background: "#233"
|
|
5336
5338
|
},
|
|
5337
5339
|
".cm-cursorLayer": {
|
|
5338
|
-
zIndex: 100,
|
|
5339
|
-
contain: "size style",
|
|
5340
5340
|
pointerEvents: "none"
|
|
5341
5341
|
},
|
|
5342
5342
|
"&.cm-focused .cm-cursorLayer": {
|
|
@@ -5348,7 +5348,6 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5348
5348
|
"@keyframes cm-blink": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
|
|
5349
5349
|
"@keyframes cm-blink2": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
|
|
5350
5350
|
".cm-cursor, .cm-dropCursor": {
|
|
5351
|
-
position: "absolute",
|
|
5352
5351
|
borderLeft: "1.2px solid black",
|
|
5353
5352
|
marginLeft: "-0.6px",
|
|
5354
5353
|
pointerEvents: "none",
|
|
@@ -5442,6 +5441,21 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
5442
5441
|
display: "inline-block",
|
|
5443
5442
|
verticalAlign: "top",
|
|
5444
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
|
+
},
|
|
5445
5459
|
".cm-button": {
|
|
5446
5460
|
verticalAlign: "middle",
|
|
5447
5461
|
color: "inherit",
|
|
@@ -5744,7 +5758,8 @@ class DOMObserver {
|
|
|
5744
5758
|
this.lastChange = 0;
|
|
5745
5759
|
this.scrollTargets = [];
|
|
5746
5760
|
this.intersection = null;
|
|
5747
|
-
this.
|
|
5761
|
+
this.resizeScroll = null;
|
|
5762
|
+
this.resizeContent = null;
|
|
5748
5763
|
this.intersecting = false;
|
|
5749
5764
|
this.gapIntersection = null;
|
|
5750
5765
|
this.gaps = [];
|
|
@@ -5782,12 +5797,14 @@ class DOMObserver {
|
|
|
5782
5797
|
this.onPrint = this.onPrint.bind(this);
|
|
5783
5798
|
this.onScroll = this.onScroll.bind(this);
|
|
5784
5799
|
if (typeof ResizeObserver == "function") {
|
|
5785
|
-
this.
|
|
5800
|
+
this.resizeScroll = new ResizeObserver(() => {
|
|
5786
5801
|
var _a;
|
|
5787
5802
|
if (((_a = this.view.docView) === null || _a === void 0 ? void 0 : _a.lastUpdate) < Date.now() - 75)
|
|
5788
5803
|
this.onResize();
|
|
5789
5804
|
});
|
|
5790
|
-
this.
|
|
5805
|
+
this.resizeScroll.observe(view.scrollDOM);
|
|
5806
|
+
this.resizeContent = new ResizeObserver(() => this.view.requestMeasure());
|
|
5807
|
+
this.resizeContent.observe(view.contentDOM);
|
|
5791
5808
|
}
|
|
5792
5809
|
this.addWindowListeners(this.win = view.win);
|
|
5793
5810
|
this.start();
|
|
@@ -6106,11 +6123,12 @@ class DOMObserver {
|
|
|
6106
6123
|
win.document.removeEventListener("selectionchange", this.onSelectionChange);
|
|
6107
6124
|
}
|
|
6108
6125
|
destroy() {
|
|
6109
|
-
var _a, _b, _c;
|
|
6126
|
+
var _a, _b, _c, _d;
|
|
6110
6127
|
this.stop();
|
|
6111
6128
|
(_a = this.intersection) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
6112
6129
|
(_b = this.gapIntersection) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
6113
|
-
(_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();
|
|
6114
6132
|
for (let dom of this.scrollTargets)
|
|
6115
6133
|
dom.removeEventListener("scroll", this.onScroll);
|
|
6116
6134
|
this.removeWindowListeners(this.win);
|
|
@@ -6209,7 +6227,7 @@ class EditorView {
|
|
|
6209
6227
|
this.scrollDOM.className = "cm-scroller";
|
|
6210
6228
|
this.scrollDOM.appendChild(this.contentDOM);
|
|
6211
6229
|
this.announceDOM = document.createElement("div");
|
|
6212
|
-
this.announceDOM.style.cssText = "position:
|
|
6230
|
+
this.announceDOM.style.cssText = "position: fixed; top: -10000px";
|
|
6213
6231
|
this.announceDOM.setAttribute("aria-live", "polite");
|
|
6214
6232
|
this.dom = document.createElement("div");
|
|
6215
6233
|
this.dom.appendChild(this.announceDOM);
|
|
@@ -7294,51 +7312,21 @@ function runHandlers(map, event, view, scope) {
|
|
|
7294
7312
|
return fallthrough;
|
|
7295
7313
|
}
|
|
7296
7314
|
|
|
7297
|
-
const CanHidePrimary = !browser.ios; // FIXME test IE
|
|
7298
|
-
const selectionConfig = state.Facet.define({
|
|
7299
|
-
combine(configs) {
|
|
7300
|
-
return state.combineConfig(configs, {
|
|
7301
|
-
cursorBlinkRate: 1200,
|
|
7302
|
-
drawRangeCursor: true
|
|
7303
|
-
}, {
|
|
7304
|
-
cursorBlinkRate: (a, b) => Math.min(a, b),
|
|
7305
|
-
drawRangeCursor: (a, b) => a || b
|
|
7306
|
-
});
|
|
7307
|
-
}
|
|
7308
|
-
});
|
|
7309
7315
|
/**
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
(with the `cm-selectionBackground` class), and the
|
|
7313
|
-
cursors with elements overlaid over the code (using
|
|
7314
|
-
`cm-cursor-primary` and `cm-cursor-secondary`).
|
|
7315
|
-
|
|
7316
|
-
This allows the editor to display secondary selection ranges, and
|
|
7317
|
-
tends to produce a type of selection more in line with that users
|
|
7318
|
-
expect in a text editor (the native selection styling will often
|
|
7319
|
-
leave gaps between lines and won't fill the horizontal space after
|
|
7320
|
-
a line when the selection continues past it).
|
|
7321
|
-
|
|
7322
|
-
It does have a performance cost, in that it requires an extra DOM
|
|
7323
|
-
layout cycle for many updates (the selection is drawn based on DOM
|
|
7324
|
-
layout information that's only available after laying out the
|
|
7325
|
-
content).
|
|
7316
|
+
Implementation of [`LayerMarker`](https://codemirror.net/6/docs/ref/#view.LayerMarker) that creates
|
|
7317
|
+
a rectangle at a given set of coordinates.
|
|
7326
7318
|
*/
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
}
|
|
7335
|
-
class Piece {
|
|
7336
|
-
constructor(left, top, width, height, className) {
|
|
7319
|
+
class RectangleMarker {
|
|
7320
|
+
/**
|
|
7321
|
+
Create a marker with the given class and dimensions. If `width`
|
|
7322
|
+
is null, the DOM element will get no width style.
|
|
7323
|
+
*/
|
|
7324
|
+
constructor(className, left, top, width, height) {
|
|
7325
|
+
this.className = className;
|
|
7337
7326
|
this.left = left;
|
|
7338
7327
|
this.top = top;
|
|
7339
7328
|
this.width = width;
|
|
7340
7329
|
this.height = height;
|
|
7341
|
-
this.className = className;
|
|
7342
7330
|
}
|
|
7343
7331
|
draw() {
|
|
7344
7332
|
let elt = document.createElement("div");
|
|
@@ -7346,10 +7334,16 @@ class Piece {
|
|
|
7346
7334
|
this.adjust(elt);
|
|
7347
7335
|
return elt;
|
|
7348
7336
|
}
|
|
7337
|
+
update(elt, prev) {
|
|
7338
|
+
if (prev.className != this.className)
|
|
7339
|
+
return false;
|
|
7340
|
+
this.adjust(elt);
|
|
7341
|
+
return true;
|
|
7342
|
+
}
|
|
7349
7343
|
adjust(elt) {
|
|
7350
7344
|
elt.style.left = this.left + "px";
|
|
7351
7345
|
elt.style.top = this.top + "px";
|
|
7352
|
-
if (this.width
|
|
7346
|
+
if (this.width != null)
|
|
7353
7347
|
elt.style.width = this.width + "px";
|
|
7354
7348
|
elt.style.height = this.height + "px";
|
|
7355
7349
|
}
|
|
@@ -7357,82 +7351,26 @@ class Piece {
|
|
|
7357
7351
|
return this.left == p.left && this.top == p.top && this.width == p.width && this.height == p.height &&
|
|
7358
7352
|
this.className == p.className;
|
|
7359
7353
|
}
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
this.setBlinkRate();
|
|
7375
|
-
}
|
|
7376
|
-
setBlinkRate() {
|
|
7377
|
-
this.cursorLayer.style.animationDuration = this.view.state.facet(selectionConfig).cursorBlinkRate + "ms";
|
|
7378
|
-
}
|
|
7379
|
-
update(update) {
|
|
7380
|
-
let confChanged = update.startState.facet(selectionConfig) != update.state.facet(selectionConfig);
|
|
7381
|
-
if (confChanged || update.selectionSet || update.geometryChanged || update.viewportChanged)
|
|
7382
|
-
this.view.requestMeasure(this.measureReq);
|
|
7383
|
-
if (update.transactions.some(tr => tr.scrollIntoView))
|
|
7384
|
-
this.cursorLayer.style.animationName = this.cursorLayer.style.animationName == "cm-blink" ? "cm-blink2" : "cm-blink";
|
|
7385
|
-
if (confChanged)
|
|
7386
|
-
this.setBlinkRate();
|
|
7387
|
-
}
|
|
7388
|
-
readPos() {
|
|
7389
|
-
let { state } = this.view, conf = state.facet(selectionConfig);
|
|
7390
|
-
let rangePieces = state.selection.ranges.map(r => r.empty ? [] : measureRange(this.view, r)).reduce((a, b) => a.concat(b));
|
|
7391
|
-
let cursors = [];
|
|
7392
|
-
for (let r of state.selection.ranges) {
|
|
7393
|
-
let prim = r == state.selection.main;
|
|
7394
|
-
if (r.empty ? !prim || CanHidePrimary : conf.drawRangeCursor) {
|
|
7395
|
-
let piece = measureCursor(this.view, r, prim);
|
|
7396
|
-
if (piece)
|
|
7397
|
-
cursors.push(piece);
|
|
7398
|
-
}
|
|
7399
|
-
}
|
|
7400
|
-
return { rangePieces, cursors };
|
|
7401
|
-
}
|
|
7402
|
-
drawSel({ rangePieces, cursors }) {
|
|
7403
|
-
if (rangePieces.length != this.rangePieces.length || rangePieces.some((p, i) => !p.eq(this.rangePieces[i]))) {
|
|
7404
|
-
this.selectionLayer.textContent = "";
|
|
7405
|
-
for (let p of rangePieces)
|
|
7406
|
-
this.selectionLayer.appendChild(p.draw());
|
|
7407
|
-
this.rangePieces = rangePieces;
|
|
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)];
|
|
7408
7368
|
}
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
if (oldCursors.length !== cursors.length) {
|
|
7412
|
-
this.cursorLayer.textContent = "";
|
|
7413
|
-
for (const c of cursors)
|
|
7414
|
-
this.cursorLayer.appendChild(c.draw());
|
|
7415
|
-
}
|
|
7416
|
-
else {
|
|
7417
|
-
cursors.forEach((c, idx) => c.adjust(oldCursors[idx]));
|
|
7418
|
-
}
|
|
7419
|
-
this.cursors = cursors;
|
|
7369
|
+
else {
|
|
7370
|
+
return rectanglesForRange(view, className, range);
|
|
7420
7371
|
}
|
|
7421
7372
|
}
|
|
7422
|
-
|
|
7423
|
-
this.selectionLayer.remove();
|
|
7424
|
-
this.cursorLayer.remove();
|
|
7425
|
-
}
|
|
7426
|
-
});
|
|
7427
|
-
const themeSpec = {
|
|
7428
|
-
".cm-line": {
|
|
7429
|
-
"& ::selection": { backgroundColor: "transparent !important" },
|
|
7430
|
-
"&::selection": { backgroundColor: "transparent !important" }
|
|
7431
|
-
}
|
|
7432
|
-
};
|
|
7433
|
-
if (CanHidePrimary)
|
|
7434
|
-
themeSpec[".cm-line"].caretColor = "transparent !important";
|
|
7435
|
-
const hideNativeSelection = state.Prec.highest(EditorView.theme(themeSpec));
|
|
7373
|
+
}
|
|
7436
7374
|
function getBase(view) {
|
|
7437
7375
|
let rect = view.scrollDOM.getBoundingClientRect();
|
|
7438
7376
|
let left = view.textDirection == exports.Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth;
|
|
@@ -7453,7 +7391,7 @@ function blockAt(view, pos) {
|
|
|
7453
7391
|
}
|
|
7454
7392
|
return line;
|
|
7455
7393
|
}
|
|
7456
|
-
function
|
|
7394
|
+
function rectanglesForRange(view, className, range) {
|
|
7457
7395
|
if (range.to <= view.viewport.from || range.from >= view.viewport.to)
|
|
7458
7396
|
return [];
|
|
7459
7397
|
let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
|
|
@@ -7485,7 +7423,7 @@ function measureRange(view, range) {
|
|
|
7485
7423
|
return pieces(top).concat(between).concat(pieces(bottom));
|
|
7486
7424
|
}
|
|
7487
7425
|
function piece(left, top, right, bottom) {
|
|
7488
|
-
return new
|
|
7426
|
+
return new RectangleMarker(className, left - base.left, top - base.top - 0.01 /* C.Epsilon */, right - left, bottom - top + 0.01 /* C.Epsilon */);
|
|
7489
7427
|
}
|
|
7490
7428
|
function pieces({ top, bottom, horizontal }) {
|
|
7491
7429
|
let pieces = [];
|
|
@@ -7537,14 +7475,175 @@ function measureRange(view, range) {
|
|
|
7537
7475
|
return { top: y, bottom: y, horizontal: [] };
|
|
7538
7476
|
}
|
|
7539
7477
|
}
|
|
7540
|
-
function
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7544
|
-
|
|
7545
|
-
|
|
7478
|
+
function sameMarker(a, b) {
|
|
7479
|
+
return a.constructor == b.constructor && a.eq(b);
|
|
7480
|
+
}
|
|
7481
|
+
class LayerView {
|
|
7482
|
+
constructor(view, layer) {
|
|
7483
|
+
this.view = view;
|
|
7484
|
+
this.layer = layer;
|
|
7485
|
+
this.drawn = [];
|
|
7486
|
+
this.measureReq = { read: this.measure.bind(this), write: this.draw.bind(this) };
|
|
7487
|
+
this.dom = view.scrollDOM.appendChild(document.createElement("div"));
|
|
7488
|
+
this.dom.classList.add("cm-layer");
|
|
7489
|
+
if (layer.above)
|
|
7490
|
+
this.dom.classList.add("cm-layer-above");
|
|
7491
|
+
if (layer.class)
|
|
7492
|
+
this.dom.classList.add(layer.class);
|
|
7493
|
+
this.dom.setAttribute("aria-hidden", "true");
|
|
7494
|
+
this.setOrder(view.state);
|
|
7495
|
+
view.requestMeasure(this.measureReq);
|
|
7496
|
+
if (layer.mount)
|
|
7497
|
+
layer.mount(this.dom, view);
|
|
7498
|
+
}
|
|
7499
|
+
update(update) {
|
|
7500
|
+
if (update.startState.facet(layerOrder) != update.state.facet(layerOrder))
|
|
7501
|
+
this.setOrder(update.state);
|
|
7502
|
+
if (this.layer.update(update, this.dom) || update.geometryChanged)
|
|
7503
|
+
update.view.requestMeasure(this.measureReq);
|
|
7504
|
+
}
|
|
7505
|
+
setOrder(state) {
|
|
7506
|
+
let pos = 0, order = state.facet(layerOrder);
|
|
7507
|
+
while (pos < order.length && order[pos] != this.layer)
|
|
7508
|
+
pos++;
|
|
7509
|
+
this.dom.style.zIndex = String((this.layer.above ? 150 : -1) - pos);
|
|
7510
|
+
}
|
|
7511
|
+
measure() {
|
|
7512
|
+
return this.layer.markers(this.view);
|
|
7513
|
+
}
|
|
7514
|
+
draw(markers) {
|
|
7515
|
+
if (markers.length != this.drawn.length || markers.some((p, i) => !sameMarker(p, this.drawn[i]))) {
|
|
7516
|
+
let old = this.dom.firstChild, oldI = 0;
|
|
7517
|
+
for (let marker of markers) {
|
|
7518
|
+
if (marker.update && old && marker.constructor && this.drawn[oldI].constructor &&
|
|
7519
|
+
marker.update(old, this.drawn[oldI])) {
|
|
7520
|
+
old = old.nextSibling;
|
|
7521
|
+
oldI++;
|
|
7522
|
+
}
|
|
7523
|
+
else {
|
|
7524
|
+
this.dom.insertBefore(marker.draw(), old);
|
|
7525
|
+
}
|
|
7526
|
+
}
|
|
7527
|
+
while (old) {
|
|
7528
|
+
let next = old.nextSibling;
|
|
7529
|
+
old.remove();
|
|
7530
|
+
old = next;
|
|
7531
|
+
}
|
|
7532
|
+
this.drawn = markers;
|
|
7533
|
+
}
|
|
7534
|
+
}
|
|
7535
|
+
destroy() {
|
|
7536
|
+
if (this.layer.destroy)
|
|
7537
|
+
this.layer.destroy(this.dom, this.view);
|
|
7538
|
+
this.dom.remove();
|
|
7539
|
+
}
|
|
7540
|
+
}
|
|
7541
|
+
const layerOrder = state.Facet.define();
|
|
7542
|
+
/**
|
|
7543
|
+
Define a layer.
|
|
7544
|
+
*/
|
|
7545
|
+
function layer(config) {
|
|
7546
|
+
return [
|
|
7547
|
+
ViewPlugin.define(v => new LayerView(v, config)),
|
|
7548
|
+
layerOrder.of(config)
|
|
7549
|
+
];
|
|
7546
7550
|
}
|
|
7547
7551
|
|
|
7552
|
+
const CanHidePrimary = !browser.ios; // FIXME test IE
|
|
7553
|
+
const selectionConfig = state.Facet.define({
|
|
7554
|
+
combine(configs) {
|
|
7555
|
+
return state.combineConfig(configs, {
|
|
7556
|
+
cursorBlinkRate: 1200,
|
|
7557
|
+
drawRangeCursor: true
|
|
7558
|
+
}, {
|
|
7559
|
+
cursorBlinkRate: (a, b) => Math.min(a, b),
|
|
7560
|
+
drawRangeCursor: (a, b) => a || b
|
|
7561
|
+
});
|
|
7562
|
+
}
|
|
7563
|
+
});
|
|
7564
|
+
/**
|
|
7565
|
+
Returns an extension that hides the browser's native selection and
|
|
7566
|
+
cursor, replacing the selection with a background behind the text
|
|
7567
|
+
(with the `cm-selectionBackground` class), and the
|
|
7568
|
+
cursors with elements overlaid over the code (using
|
|
7569
|
+
`cm-cursor-primary` and `cm-cursor-secondary`).
|
|
7570
|
+
|
|
7571
|
+
This allows the editor to display secondary selection ranges, and
|
|
7572
|
+
tends to produce a type of selection more in line with that users
|
|
7573
|
+
expect in a text editor (the native selection styling will often
|
|
7574
|
+
leave gaps between lines and won't fill the horizontal space after
|
|
7575
|
+
a line when the selection continues past it).
|
|
7576
|
+
|
|
7577
|
+
It does have a performance cost, in that it requires an extra DOM
|
|
7578
|
+
layout cycle for many updates (the selection is drawn based on DOM
|
|
7579
|
+
layout information that's only available after laying out the
|
|
7580
|
+
content).
|
|
7581
|
+
*/
|
|
7582
|
+
function drawSelection(config = {}) {
|
|
7583
|
+
return [
|
|
7584
|
+
selectionConfig.of(config),
|
|
7585
|
+
cursorLayer,
|
|
7586
|
+
selectionLayer,
|
|
7587
|
+
hideNativeSelection,
|
|
7588
|
+
nativeSelectionHidden.of(true)
|
|
7589
|
+
];
|
|
7590
|
+
}
|
|
7591
|
+
function configChanged(update) {
|
|
7592
|
+
return update.startState.facet(selectionConfig) != update.startState.facet(selectionConfig);
|
|
7593
|
+
}
|
|
7594
|
+
const cursorLayer = layer({
|
|
7595
|
+
above: true,
|
|
7596
|
+
markers(view) {
|
|
7597
|
+
let { state: state$1 } = view, conf = state$1.facet(selectionConfig);
|
|
7598
|
+
let cursors = [];
|
|
7599
|
+
for (let r of state$1.selection.ranges) {
|
|
7600
|
+
let prim = r == state$1.selection.main;
|
|
7601
|
+
if (r.empty ? !prim || CanHidePrimary : conf.drawRangeCursor) {
|
|
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))
|
|
7605
|
+
cursors.push(piece);
|
|
7606
|
+
}
|
|
7607
|
+
}
|
|
7608
|
+
return cursors;
|
|
7609
|
+
},
|
|
7610
|
+
update(update, dom) {
|
|
7611
|
+
if (update.transactions.some(tr => tr.scrollIntoView))
|
|
7612
|
+
dom.style.animationName = dom.style.animationName == "cm-blink" ? "cm-blink2" : "cm-blink";
|
|
7613
|
+
let confChange = configChanged(update);
|
|
7614
|
+
if (confChange)
|
|
7615
|
+
setBlinkRate(update.state, dom);
|
|
7616
|
+
return update.docChanged || update.selectionSet || confChange;
|
|
7617
|
+
},
|
|
7618
|
+
mount(dom, view) {
|
|
7619
|
+
setBlinkRate(view.state, dom);
|
|
7620
|
+
},
|
|
7621
|
+
class: "cm-cursorLayer"
|
|
7622
|
+
});
|
|
7623
|
+
function setBlinkRate(state, dom) {
|
|
7624
|
+
dom.style.animationDuration = state.facet(selectionConfig).cursorBlinkRate + "ms";
|
|
7625
|
+
}
|
|
7626
|
+
const selectionLayer = layer({
|
|
7627
|
+
above: false,
|
|
7628
|
+
markers(view) {
|
|
7629
|
+
return view.state.selection.ranges.map(r => r.empty ? [] : RectangleMarker.forRange(view, "cm-selectionBackground", r))
|
|
7630
|
+
.reduce((a, b) => a.concat(b));
|
|
7631
|
+
},
|
|
7632
|
+
update(update, dom) {
|
|
7633
|
+
return update.docChanged || update.selectionSet || update.viewportChanged || configChanged(update);
|
|
7634
|
+
},
|
|
7635
|
+
class: "cm-selectionLayer"
|
|
7636
|
+
});
|
|
7637
|
+
const themeSpec = {
|
|
7638
|
+
".cm-line": {
|
|
7639
|
+
"& ::selection": { backgroundColor: "transparent !important" },
|
|
7640
|
+
"&::selection": { backgroundColor: "transparent !important" }
|
|
7641
|
+
}
|
|
7642
|
+
};
|
|
7643
|
+
if (CanHidePrimary)
|
|
7644
|
+
themeSpec[".cm-line"].caretColor = "transparent !important";
|
|
7645
|
+
const hideNativeSelection = state.Prec.highest(EditorView.theme(themeSpec));
|
|
7646
|
+
|
|
7548
7647
|
const setDropCursorPos = state.StateEffect.define({
|
|
7549
7648
|
map(pos, mapping) { return pos == null ? null : mapping.mapPos(pos); }
|
|
7550
7649
|
});
|
|
@@ -8336,6 +8435,17 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
8336
8435
|
: pos.bottom + (size.bottom - size.top) + offset.y > space.bottom) &&
|
|
8337
8436
|
above == (space.bottom - pos.bottom > pos.top - space.top))
|
|
8338
8437
|
above = !above;
|
|
8438
|
+
let spaceVert = (above ? pos.top - space.top : space.bottom - pos.bottom) - arrowHeight;
|
|
8439
|
+
if (spaceVert < height && tView.resize !== false) {
|
|
8440
|
+
if (spaceVert < this.view.defaultLineHeight) {
|
|
8441
|
+
dom.style.top = Outside;
|
|
8442
|
+
continue;
|
|
8443
|
+
}
|
|
8444
|
+
dom.style.height = (height = spaceVert) + "px";
|
|
8445
|
+
}
|
|
8446
|
+
else if (dom.style.height) {
|
|
8447
|
+
dom.style.height = "";
|
|
8448
|
+
}
|
|
8339
8449
|
let top = above ? pos.top - height - arrowHeight - offset.y : pos.bottom + arrowHeight + offset.y;
|
|
8340
8450
|
let right = left + width;
|
|
8341
8451
|
if (tView.overlap !== true)
|
|
@@ -8379,7 +8489,8 @@ const tooltipPlugin = ViewPlugin.fromClass(class {
|
|
|
8379
8489
|
});
|
|
8380
8490
|
const baseTheme = EditorView.baseTheme({
|
|
8381
8491
|
".cm-tooltip": {
|
|
8382
|
-
zIndex: 100
|
|
8492
|
+
zIndex: 100,
|
|
8493
|
+
boxSizing: "border-box"
|
|
8383
8494
|
},
|
|
8384
8495
|
"&light .cm-tooltip": {
|
|
8385
8496
|
border: "1px solid #bbb",
|
|
@@ -9298,6 +9409,57 @@ function highlightActiveLineGutter() {
|
|
|
9298
9409
|
return activeLineGutterHighlighter;
|
|
9299
9410
|
}
|
|
9300
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
|
+
|
|
9301
9463
|
/**
|
|
9302
9464
|
@internal
|
|
9303
9465
|
*/
|
|
@@ -9309,6 +9471,7 @@ exports.Decoration = Decoration;
|
|
|
9309
9471
|
exports.EditorView = EditorView;
|
|
9310
9472
|
exports.GutterMarker = GutterMarker;
|
|
9311
9473
|
exports.MatchDecorator = MatchDecorator;
|
|
9474
|
+
exports.RectangleMarker = RectangleMarker;
|
|
9312
9475
|
exports.ViewPlugin = ViewPlugin;
|
|
9313
9476
|
exports.ViewUpdate = ViewUpdate;
|
|
9314
9477
|
exports.WidgetType = WidgetType;
|
|
@@ -9326,8 +9489,11 @@ exports.hasHoverTooltips = hasHoverTooltips;
|
|
|
9326
9489
|
exports.highlightActiveLine = highlightActiveLine;
|
|
9327
9490
|
exports.highlightActiveLineGutter = highlightActiveLineGutter;
|
|
9328
9491
|
exports.highlightSpecialChars = highlightSpecialChars;
|
|
9492
|
+
exports.highlightTrailingWhitespace = highlightTrailingWhitespace;
|
|
9493
|
+
exports.highlightWhitespace = highlightWhitespace;
|
|
9329
9494
|
exports.hoverTooltip = hoverTooltip;
|
|
9330
9495
|
exports.keymap = keymap;
|
|
9496
|
+
exports.layer = layer;
|
|
9331
9497
|
exports.lineNumberMarkers = lineNumberMarkers;
|
|
9332
9498
|
exports.lineNumbers = lineNumbers;
|
|
9333
9499
|
exports.logException = logException;
|