@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.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",
|
|
@@ -5306,14 +5309,13 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5306
5309
|
"&dark .cm-content": { caretColor: "white" },
|
|
5307
5310
|
".cm-line": {
|
|
5308
5311
|
display: "block",
|
|
5309
|
-
padding: "0 2px 0
|
|
5310
|
-
},
|
|
5311
|
-
".cm-selectionLayer": {
|
|
5312
|
-
zIndex: -1,
|
|
5313
|
-
contain: "size style"
|
|
5312
|
+
padding: "0 2px 0 6px"
|
|
5314
5313
|
},
|
|
5315
|
-
".cm-
|
|
5316
|
-
|
|
5314
|
+
".cm-layer": {
|
|
5315
|
+
contain: "size style",
|
|
5316
|
+
"& > *": {
|
|
5317
|
+
position: "absolute"
|
|
5318
|
+
}
|
|
5317
5319
|
},
|
|
5318
5320
|
"&light .cm-selectionBackground": {
|
|
5319
5321
|
background: "#d9d9d9"
|
|
@@ -5328,8 +5330,6 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5328
5330
|
background: "#233"
|
|
5329
5331
|
},
|
|
5330
5332
|
".cm-cursorLayer": {
|
|
5331
|
-
zIndex: 100,
|
|
5332
|
-
contain: "size style",
|
|
5333
5333
|
pointerEvents: "none"
|
|
5334
5334
|
},
|
|
5335
5335
|
"&.cm-focused .cm-cursorLayer": {
|
|
@@ -5341,7 +5341,6 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5341
5341
|
"@keyframes cm-blink": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
|
|
5342
5342
|
"@keyframes cm-blink2": { "0%": {}, "50%": { opacity: 0 }, "100%": {} },
|
|
5343
5343
|
".cm-cursor, .cm-dropCursor": {
|
|
5344
|
-
position: "absolute",
|
|
5345
5344
|
borderLeft: "1.2px solid black",
|
|
5346
5345
|
marginLeft: "-0.6px",
|
|
5347
5346
|
pointerEvents: "none",
|
|
@@ -5435,6 +5434,21 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5435
5434
|
display: "inline-block",
|
|
5436
5435
|
verticalAlign: "top",
|
|
5437
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
|
+
},
|
|
5438
5452
|
".cm-button": {
|
|
5439
5453
|
verticalAlign: "middle",
|
|
5440
5454
|
color: "inherit",
|
|
@@ -5737,7 +5751,8 @@ class DOMObserver {
|
|
|
5737
5751
|
this.lastChange = 0;
|
|
5738
5752
|
this.scrollTargets = [];
|
|
5739
5753
|
this.intersection = null;
|
|
5740
|
-
this.
|
|
5754
|
+
this.resizeScroll = null;
|
|
5755
|
+
this.resizeContent = null;
|
|
5741
5756
|
this.intersecting = false;
|
|
5742
5757
|
this.gapIntersection = null;
|
|
5743
5758
|
this.gaps = [];
|
|
@@ -5775,12 +5790,14 @@ class DOMObserver {
|
|
|
5775
5790
|
this.onPrint = this.onPrint.bind(this);
|
|
5776
5791
|
this.onScroll = this.onScroll.bind(this);
|
|
5777
5792
|
if (typeof ResizeObserver == "function") {
|
|
5778
|
-
this.
|
|
5793
|
+
this.resizeScroll = new ResizeObserver(() => {
|
|
5779
5794
|
var _a;
|
|
5780
5795
|
if (((_a = this.view.docView) === null || _a === void 0 ? void 0 : _a.lastUpdate) < Date.now() - 75)
|
|
5781
5796
|
this.onResize();
|
|
5782
5797
|
});
|
|
5783
|
-
this.
|
|
5798
|
+
this.resizeScroll.observe(view.scrollDOM);
|
|
5799
|
+
this.resizeContent = new ResizeObserver(() => this.view.requestMeasure());
|
|
5800
|
+
this.resizeContent.observe(view.contentDOM);
|
|
5784
5801
|
}
|
|
5785
5802
|
this.addWindowListeners(this.win = view.win);
|
|
5786
5803
|
this.start();
|
|
@@ -6099,11 +6116,12 @@ class DOMObserver {
|
|
|
6099
6116
|
win.document.removeEventListener("selectionchange", this.onSelectionChange);
|
|
6100
6117
|
}
|
|
6101
6118
|
destroy() {
|
|
6102
|
-
var _a, _b, _c;
|
|
6119
|
+
var _a, _b, _c, _d;
|
|
6103
6120
|
this.stop();
|
|
6104
6121
|
(_a = this.intersection) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
6105
6122
|
(_b = this.gapIntersection) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
6106
|
-
(_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();
|
|
6107
6125
|
for (let dom of this.scrollTargets)
|
|
6108
6126
|
dom.removeEventListener("scroll", this.onScroll);
|
|
6109
6127
|
this.removeWindowListeners(this.win);
|
|
@@ -6202,7 +6220,7 @@ class EditorView {
|
|
|
6202
6220
|
this.scrollDOM.className = "cm-scroller";
|
|
6203
6221
|
this.scrollDOM.appendChild(this.contentDOM);
|
|
6204
6222
|
this.announceDOM = document.createElement("div");
|
|
6205
|
-
this.announceDOM.style.cssText = "position:
|
|
6223
|
+
this.announceDOM.style.cssText = "position: fixed; top: -10000px";
|
|
6206
6224
|
this.announceDOM.setAttribute("aria-live", "polite");
|
|
6207
6225
|
this.dom = document.createElement("div");
|
|
6208
6226
|
this.dom.appendChild(this.announceDOM);
|
|
@@ -7287,51 +7305,21 @@ function runHandlers(map, event, view, scope) {
|
|
|
7287
7305
|
return fallthrough;
|
|
7288
7306
|
}
|
|
7289
7307
|
|
|
7290
|
-
const CanHidePrimary = !browser.ios; // FIXME test IE
|
|
7291
|
-
const selectionConfig = /*@__PURE__*/Facet.define({
|
|
7292
|
-
combine(configs) {
|
|
7293
|
-
return combineConfig(configs, {
|
|
7294
|
-
cursorBlinkRate: 1200,
|
|
7295
|
-
drawRangeCursor: true
|
|
7296
|
-
}, {
|
|
7297
|
-
cursorBlinkRate: (a, b) => Math.min(a, b),
|
|
7298
|
-
drawRangeCursor: (a, b) => a || b
|
|
7299
|
-
});
|
|
7300
|
-
}
|
|
7301
|
-
});
|
|
7302
7308
|
/**
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
(with the `cm-selectionBackground` class), and the
|
|
7306
|
-
cursors with elements overlaid over the code (using
|
|
7307
|
-
`cm-cursor-primary` and `cm-cursor-secondary`).
|
|
7308
|
-
|
|
7309
|
-
This allows the editor to display secondary selection ranges, and
|
|
7310
|
-
tends to produce a type of selection more in line with that users
|
|
7311
|
-
expect in a text editor (the native selection styling will often
|
|
7312
|
-
leave gaps between lines and won't fill the horizontal space after
|
|
7313
|
-
a line when the selection continues past it).
|
|
7314
|
-
|
|
7315
|
-
It does have a performance cost, in that it requires an extra DOM
|
|
7316
|
-
layout cycle for many updates (the selection is drawn based on DOM
|
|
7317
|
-
layout information that's only available after laying out the
|
|
7318
|
-
content).
|
|
7309
|
+
Implementation of [`LayerMarker`](https://codemirror.net/6/docs/ref/#view.LayerMarker) that creates
|
|
7310
|
+
a rectangle at a given set of coordinates.
|
|
7319
7311
|
*/
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
}
|
|
7328
|
-
class Piece {
|
|
7329
|
-
constructor(left, top, width, height, className) {
|
|
7312
|
+
class RectangleMarker {
|
|
7313
|
+
/**
|
|
7314
|
+
Create a marker with the given class and dimensions. If `width`
|
|
7315
|
+
is null, the DOM element will get no width style.
|
|
7316
|
+
*/
|
|
7317
|
+
constructor(className, left, top, width, height) {
|
|
7318
|
+
this.className = className;
|
|
7330
7319
|
this.left = left;
|
|
7331
7320
|
this.top = top;
|
|
7332
7321
|
this.width = width;
|
|
7333
7322
|
this.height = height;
|
|
7334
|
-
this.className = className;
|
|
7335
7323
|
}
|
|
7336
7324
|
draw() {
|
|
7337
7325
|
let elt = document.createElement("div");
|
|
@@ -7339,10 +7327,16 @@ class Piece {
|
|
|
7339
7327
|
this.adjust(elt);
|
|
7340
7328
|
return elt;
|
|
7341
7329
|
}
|
|
7330
|
+
update(elt, prev) {
|
|
7331
|
+
if (prev.className != this.className)
|
|
7332
|
+
return false;
|
|
7333
|
+
this.adjust(elt);
|
|
7334
|
+
return true;
|
|
7335
|
+
}
|
|
7342
7336
|
adjust(elt) {
|
|
7343
7337
|
elt.style.left = this.left + "px";
|
|
7344
7338
|
elt.style.top = this.top + "px";
|
|
7345
|
-
if (this.width
|
|
7339
|
+
if (this.width != null)
|
|
7346
7340
|
elt.style.width = this.width + "px";
|
|
7347
7341
|
elt.style.height = this.height + "px";
|
|
7348
7342
|
}
|
|
@@ -7350,82 +7344,26 @@ class Piece {
|
|
|
7350
7344
|
return this.left == p.left && this.top == p.top && this.width == p.width && this.height == p.height &&
|
|
7351
7345
|
this.className == p.className;
|
|
7352
7346
|
}
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
this.setBlinkRate();
|
|
7368
|
-
}
|
|
7369
|
-
setBlinkRate() {
|
|
7370
|
-
this.cursorLayer.style.animationDuration = this.view.state.facet(selectionConfig).cursorBlinkRate + "ms";
|
|
7371
|
-
}
|
|
7372
|
-
update(update) {
|
|
7373
|
-
let confChanged = update.startState.facet(selectionConfig) != update.state.facet(selectionConfig);
|
|
7374
|
-
if (confChanged || update.selectionSet || update.geometryChanged || update.viewportChanged)
|
|
7375
|
-
this.view.requestMeasure(this.measureReq);
|
|
7376
|
-
if (update.transactions.some(tr => tr.scrollIntoView))
|
|
7377
|
-
this.cursorLayer.style.animationName = this.cursorLayer.style.animationName == "cm-blink" ? "cm-blink2" : "cm-blink";
|
|
7378
|
-
if (confChanged)
|
|
7379
|
-
this.setBlinkRate();
|
|
7380
|
-
}
|
|
7381
|
-
readPos() {
|
|
7382
|
-
let { state } = this.view, conf = state.facet(selectionConfig);
|
|
7383
|
-
let rangePieces = state.selection.ranges.map(r => r.empty ? [] : measureRange(this.view, r)).reduce((a, b) => a.concat(b));
|
|
7384
|
-
let cursors = [];
|
|
7385
|
-
for (let r of state.selection.ranges) {
|
|
7386
|
-
let prim = r == state.selection.main;
|
|
7387
|
-
if (r.empty ? !prim || CanHidePrimary : conf.drawRangeCursor) {
|
|
7388
|
-
let piece = measureCursor(this.view, r, prim);
|
|
7389
|
-
if (piece)
|
|
7390
|
-
cursors.push(piece);
|
|
7391
|
-
}
|
|
7392
|
-
}
|
|
7393
|
-
return { rangePieces, cursors };
|
|
7394
|
-
}
|
|
7395
|
-
drawSel({ rangePieces, cursors }) {
|
|
7396
|
-
if (rangePieces.length != this.rangePieces.length || rangePieces.some((p, i) => !p.eq(this.rangePieces[i]))) {
|
|
7397
|
-
this.selectionLayer.textContent = "";
|
|
7398
|
-
for (let p of rangePieces)
|
|
7399
|
-
this.selectionLayer.appendChild(p.draw());
|
|
7400
|
-
this.rangePieces = rangePieces;
|
|
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)];
|
|
7401
7361
|
}
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
if (oldCursors.length !== cursors.length) {
|
|
7405
|
-
this.cursorLayer.textContent = "";
|
|
7406
|
-
for (const c of cursors)
|
|
7407
|
-
this.cursorLayer.appendChild(c.draw());
|
|
7408
|
-
}
|
|
7409
|
-
else {
|
|
7410
|
-
cursors.forEach((c, idx) => c.adjust(oldCursors[idx]));
|
|
7411
|
-
}
|
|
7412
|
-
this.cursors = cursors;
|
|
7362
|
+
else {
|
|
7363
|
+
return rectanglesForRange(view, className, range);
|
|
7413
7364
|
}
|
|
7414
7365
|
}
|
|
7415
|
-
|
|
7416
|
-
this.selectionLayer.remove();
|
|
7417
|
-
this.cursorLayer.remove();
|
|
7418
|
-
}
|
|
7419
|
-
});
|
|
7420
|
-
const themeSpec = {
|
|
7421
|
-
".cm-line": {
|
|
7422
|
-
"& ::selection": { backgroundColor: "transparent !important" },
|
|
7423
|
-
"&::selection": { backgroundColor: "transparent !important" }
|
|
7424
|
-
}
|
|
7425
|
-
};
|
|
7426
|
-
if (CanHidePrimary)
|
|
7427
|
-
themeSpec[".cm-line"].caretColor = "transparent !important";
|
|
7428
|
-
const hideNativeSelection = /*@__PURE__*/Prec.highest(/*@__PURE__*/EditorView.theme(themeSpec));
|
|
7366
|
+
}
|
|
7429
7367
|
function getBase(view) {
|
|
7430
7368
|
let rect = view.scrollDOM.getBoundingClientRect();
|
|
7431
7369
|
let left = view.textDirection == Direction.LTR ? rect.left : rect.right - view.scrollDOM.clientWidth;
|
|
@@ -7446,7 +7384,7 @@ function blockAt(view, pos) {
|
|
|
7446
7384
|
}
|
|
7447
7385
|
return line;
|
|
7448
7386
|
}
|
|
7449
|
-
function
|
|
7387
|
+
function rectanglesForRange(view, className, range) {
|
|
7450
7388
|
if (range.to <= view.viewport.from || range.from >= view.viewport.to)
|
|
7451
7389
|
return [];
|
|
7452
7390
|
let from = Math.max(range.from, view.viewport.from), to = Math.min(range.to, view.viewport.to);
|
|
@@ -7478,7 +7416,7 @@ function measureRange(view, range) {
|
|
|
7478
7416
|
return pieces(top).concat(between).concat(pieces(bottom));
|
|
7479
7417
|
}
|
|
7480
7418
|
function piece(left, top, right, bottom) {
|
|
7481
|
-
return new
|
|
7419
|
+
return new RectangleMarker(className, left - base.left, top - base.top - 0.01 /* C.Epsilon */, right - left, bottom - top + 0.01 /* C.Epsilon */);
|
|
7482
7420
|
}
|
|
7483
7421
|
function pieces({ top, bottom, horizontal }) {
|
|
7484
7422
|
let pieces = [];
|
|
@@ -7530,13 +7468,174 @@ function measureRange(view, range) {
|
|
|
7530
7468
|
return { top: y, bottom: y, horizontal: [] };
|
|
7531
7469
|
}
|
|
7532
7470
|
}
|
|
7533
|
-
function
|
|
7534
|
-
|
|
7535
|
-
if (!pos)
|
|
7536
|
-
return null;
|
|
7537
|
-
let base = getBase(view);
|
|
7538
|
-
return new Piece(pos.left - base.left, pos.top - base.top, -1, pos.bottom - pos.top, primary ? "cm-cursor cm-cursor-primary" : "cm-cursor cm-cursor-secondary");
|
|
7471
|
+
function sameMarker(a, b) {
|
|
7472
|
+
return a.constructor == b.constructor && a.eq(b);
|
|
7539
7473
|
}
|
|
7474
|
+
class LayerView {
|
|
7475
|
+
constructor(view, layer) {
|
|
7476
|
+
this.view = view;
|
|
7477
|
+
this.layer = layer;
|
|
7478
|
+
this.drawn = [];
|
|
7479
|
+
this.measureReq = { read: this.measure.bind(this), write: this.draw.bind(this) };
|
|
7480
|
+
this.dom = view.scrollDOM.appendChild(document.createElement("div"));
|
|
7481
|
+
this.dom.classList.add("cm-layer");
|
|
7482
|
+
if (layer.above)
|
|
7483
|
+
this.dom.classList.add("cm-layer-above");
|
|
7484
|
+
if (layer.class)
|
|
7485
|
+
this.dom.classList.add(layer.class);
|
|
7486
|
+
this.dom.setAttribute("aria-hidden", "true");
|
|
7487
|
+
this.setOrder(view.state);
|
|
7488
|
+
view.requestMeasure(this.measureReq);
|
|
7489
|
+
if (layer.mount)
|
|
7490
|
+
layer.mount(this.dom, view);
|
|
7491
|
+
}
|
|
7492
|
+
update(update) {
|
|
7493
|
+
if (update.startState.facet(layerOrder) != update.state.facet(layerOrder))
|
|
7494
|
+
this.setOrder(update.state);
|
|
7495
|
+
if (this.layer.update(update, this.dom) || update.geometryChanged)
|
|
7496
|
+
update.view.requestMeasure(this.measureReq);
|
|
7497
|
+
}
|
|
7498
|
+
setOrder(state) {
|
|
7499
|
+
let pos = 0, order = state.facet(layerOrder);
|
|
7500
|
+
while (pos < order.length && order[pos] != this.layer)
|
|
7501
|
+
pos++;
|
|
7502
|
+
this.dom.style.zIndex = String((this.layer.above ? 150 : -1) - pos);
|
|
7503
|
+
}
|
|
7504
|
+
measure() {
|
|
7505
|
+
return this.layer.markers(this.view);
|
|
7506
|
+
}
|
|
7507
|
+
draw(markers) {
|
|
7508
|
+
if (markers.length != this.drawn.length || markers.some((p, i) => !sameMarker(p, this.drawn[i]))) {
|
|
7509
|
+
let old = this.dom.firstChild, oldI = 0;
|
|
7510
|
+
for (let marker of markers) {
|
|
7511
|
+
if (marker.update && old && marker.constructor && this.drawn[oldI].constructor &&
|
|
7512
|
+
marker.update(old, this.drawn[oldI])) {
|
|
7513
|
+
old = old.nextSibling;
|
|
7514
|
+
oldI++;
|
|
7515
|
+
}
|
|
7516
|
+
else {
|
|
7517
|
+
this.dom.insertBefore(marker.draw(), old);
|
|
7518
|
+
}
|
|
7519
|
+
}
|
|
7520
|
+
while (old) {
|
|
7521
|
+
let next = old.nextSibling;
|
|
7522
|
+
old.remove();
|
|
7523
|
+
old = next;
|
|
7524
|
+
}
|
|
7525
|
+
this.drawn = markers;
|
|
7526
|
+
}
|
|
7527
|
+
}
|
|
7528
|
+
destroy() {
|
|
7529
|
+
if (this.layer.destroy)
|
|
7530
|
+
this.layer.destroy(this.dom, this.view);
|
|
7531
|
+
this.dom.remove();
|
|
7532
|
+
}
|
|
7533
|
+
}
|
|
7534
|
+
const layerOrder = /*@__PURE__*/Facet.define();
|
|
7535
|
+
/**
|
|
7536
|
+
Define a layer.
|
|
7537
|
+
*/
|
|
7538
|
+
function layer(config) {
|
|
7539
|
+
return [
|
|
7540
|
+
ViewPlugin.define(v => new LayerView(v, config)),
|
|
7541
|
+
layerOrder.of(config)
|
|
7542
|
+
];
|
|
7543
|
+
}
|
|
7544
|
+
|
|
7545
|
+
const CanHidePrimary = !browser.ios; // FIXME test IE
|
|
7546
|
+
const selectionConfig = /*@__PURE__*/Facet.define({
|
|
7547
|
+
combine(configs) {
|
|
7548
|
+
return combineConfig(configs, {
|
|
7549
|
+
cursorBlinkRate: 1200,
|
|
7550
|
+
drawRangeCursor: true
|
|
7551
|
+
}, {
|
|
7552
|
+
cursorBlinkRate: (a, b) => Math.min(a, b),
|
|
7553
|
+
drawRangeCursor: (a, b) => a || b
|
|
7554
|
+
});
|
|
7555
|
+
}
|
|
7556
|
+
});
|
|
7557
|
+
/**
|
|
7558
|
+
Returns an extension that hides the browser's native selection and
|
|
7559
|
+
cursor, replacing the selection with a background behind the text
|
|
7560
|
+
(with the `cm-selectionBackground` class), and the
|
|
7561
|
+
cursors with elements overlaid over the code (using
|
|
7562
|
+
`cm-cursor-primary` and `cm-cursor-secondary`).
|
|
7563
|
+
|
|
7564
|
+
This allows the editor to display secondary selection ranges, and
|
|
7565
|
+
tends to produce a type of selection more in line with that users
|
|
7566
|
+
expect in a text editor (the native selection styling will often
|
|
7567
|
+
leave gaps between lines and won't fill the horizontal space after
|
|
7568
|
+
a line when the selection continues past it).
|
|
7569
|
+
|
|
7570
|
+
It does have a performance cost, in that it requires an extra DOM
|
|
7571
|
+
layout cycle for many updates (the selection is drawn based on DOM
|
|
7572
|
+
layout information that's only available after laying out the
|
|
7573
|
+
content).
|
|
7574
|
+
*/
|
|
7575
|
+
function drawSelection(config = {}) {
|
|
7576
|
+
return [
|
|
7577
|
+
selectionConfig.of(config),
|
|
7578
|
+
cursorLayer,
|
|
7579
|
+
selectionLayer,
|
|
7580
|
+
hideNativeSelection,
|
|
7581
|
+
nativeSelectionHidden.of(true)
|
|
7582
|
+
];
|
|
7583
|
+
}
|
|
7584
|
+
function configChanged(update) {
|
|
7585
|
+
return update.startState.facet(selectionConfig) != update.startState.facet(selectionConfig);
|
|
7586
|
+
}
|
|
7587
|
+
const cursorLayer = /*@__PURE__*/layer({
|
|
7588
|
+
above: true,
|
|
7589
|
+
markers(view) {
|
|
7590
|
+
let { state } = view, conf = state.facet(selectionConfig);
|
|
7591
|
+
let cursors = [];
|
|
7592
|
+
for (let r of state.selection.ranges) {
|
|
7593
|
+
let prim = r == state.selection.main;
|
|
7594
|
+
if (r.empty ? !prim || CanHidePrimary : conf.drawRangeCursor) {
|
|
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))
|
|
7598
|
+
cursors.push(piece);
|
|
7599
|
+
}
|
|
7600
|
+
}
|
|
7601
|
+
return cursors;
|
|
7602
|
+
},
|
|
7603
|
+
update(update, dom) {
|
|
7604
|
+
if (update.transactions.some(tr => tr.scrollIntoView))
|
|
7605
|
+
dom.style.animationName = dom.style.animationName == "cm-blink" ? "cm-blink2" : "cm-blink";
|
|
7606
|
+
let confChange = configChanged(update);
|
|
7607
|
+
if (confChange)
|
|
7608
|
+
setBlinkRate(update.state, dom);
|
|
7609
|
+
return update.docChanged || update.selectionSet || confChange;
|
|
7610
|
+
},
|
|
7611
|
+
mount(dom, view) {
|
|
7612
|
+
setBlinkRate(view.state, dom);
|
|
7613
|
+
},
|
|
7614
|
+
class: "cm-cursorLayer"
|
|
7615
|
+
});
|
|
7616
|
+
function setBlinkRate(state, dom) {
|
|
7617
|
+
dom.style.animationDuration = state.facet(selectionConfig).cursorBlinkRate + "ms";
|
|
7618
|
+
}
|
|
7619
|
+
const selectionLayer = /*@__PURE__*/layer({
|
|
7620
|
+
above: false,
|
|
7621
|
+
markers(view) {
|
|
7622
|
+
return view.state.selection.ranges.map(r => r.empty ? [] : RectangleMarker.forRange(view, "cm-selectionBackground", r))
|
|
7623
|
+
.reduce((a, b) => a.concat(b));
|
|
7624
|
+
},
|
|
7625
|
+
update(update, dom) {
|
|
7626
|
+
return update.docChanged || update.selectionSet || update.viewportChanged || configChanged(update);
|
|
7627
|
+
},
|
|
7628
|
+
class: "cm-selectionLayer"
|
|
7629
|
+
});
|
|
7630
|
+
const themeSpec = {
|
|
7631
|
+
".cm-line": {
|
|
7632
|
+
"& ::selection": { backgroundColor: "transparent !important" },
|
|
7633
|
+
"&::selection": { backgroundColor: "transparent !important" }
|
|
7634
|
+
}
|
|
7635
|
+
};
|
|
7636
|
+
if (CanHidePrimary)
|
|
7637
|
+
themeSpec[".cm-line"].caretColor = "transparent !important";
|
|
7638
|
+
const hideNativeSelection = /*@__PURE__*/Prec.highest(/*@__PURE__*/EditorView.theme(themeSpec));
|
|
7540
7639
|
|
|
7541
7640
|
const setDropCursorPos = /*@__PURE__*/StateEffect.define({
|
|
7542
7641
|
map(pos, mapping) { return pos == null ? null : mapping.mapPos(pos); }
|
|
@@ -8329,6 +8428,17 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
8329
8428
|
: pos.bottom + (size.bottom - size.top) + offset.y > space.bottom) &&
|
|
8330
8429
|
above == (space.bottom - pos.bottom > pos.top - space.top))
|
|
8331
8430
|
above = !above;
|
|
8431
|
+
let spaceVert = (above ? pos.top - space.top : space.bottom - pos.bottom) - arrowHeight;
|
|
8432
|
+
if (spaceVert < height && tView.resize !== false) {
|
|
8433
|
+
if (spaceVert < this.view.defaultLineHeight) {
|
|
8434
|
+
dom.style.top = Outside;
|
|
8435
|
+
continue;
|
|
8436
|
+
}
|
|
8437
|
+
dom.style.height = (height = spaceVert) + "px";
|
|
8438
|
+
}
|
|
8439
|
+
else if (dom.style.height) {
|
|
8440
|
+
dom.style.height = "";
|
|
8441
|
+
}
|
|
8332
8442
|
let top = above ? pos.top - height - arrowHeight - offset.y : pos.bottom + arrowHeight + offset.y;
|
|
8333
8443
|
let right = left + width;
|
|
8334
8444
|
if (tView.overlap !== true)
|
|
@@ -8372,7 +8482,8 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
8372
8482
|
});
|
|
8373
8483
|
const baseTheme = /*@__PURE__*/EditorView.baseTheme({
|
|
8374
8484
|
".cm-tooltip": {
|
|
8375
|
-
zIndex: 100
|
|
8485
|
+
zIndex: 100,
|
|
8486
|
+
boxSizing: "border-box"
|
|
8376
8487
|
},
|
|
8377
8488
|
"&light .cm-tooltip": {
|
|
8378
8489
|
border: "1px solid #bbb",
|
|
@@ -9291,9 +9402,60 @@ function highlightActiveLineGutter() {
|
|
|
9291
9402
|
return activeLineGutterHighlighter;
|
|
9292
9403
|
}
|
|
9293
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
|
+
|
|
9294
9456
|
/**
|
|
9295
9457
|
@internal
|
|
9296
9458
|
*/
|
|
9297
9459
|
const __test = { HeightMap, HeightOracle, MeasuredHeights, QueryType, ChangedRange, computeOrder, moveVisually };
|
|
9298
9460
|
|
|
9299
|
-
export { BidiSpan, BlockInfo, BlockType, Decoration, Direction, EditorView, GutterMarker, MatchDecorator, ViewPlugin, ViewUpdate, WidgetType, __test, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getPanel, getTooltip, gutter, gutterLineClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, hoverTooltip, keymap, 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 };
|