@codemirror/view 6.32.0 → 6.34.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 +46 -37
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +46 -37
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## 6.34.0 (2024-09-25)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix an issue where the dots past the wrapping point were displayed incorrectly when using `highlightWhitespace` with a wrapped sequence of spaces.
|
|
6
|
+
|
|
7
|
+
Improve performance of documents displaying lots of highlighted spaces by using a CSS background instead of pseudo-element.
|
|
8
|
+
|
|
9
|
+
### New features
|
|
10
|
+
|
|
11
|
+
`placeholder` now allows a function that constructs the placedholder DOM to be passed in, and uses `cloneNode` when a raw element is passed in, to prevent adding the same element to multiple editors.
|
|
12
|
+
|
|
13
|
+
## 6.33.1 (2024-08-30)
|
|
14
|
+
|
|
15
|
+
### Bug fixes
|
|
16
|
+
|
|
17
|
+
Work around odd behavior in Chrome's newly supported `caretPositionFromPoint` method, which could cause CodeMirror to crash with a null dereference.
|
|
18
|
+
|
|
19
|
+
## 6.33.0 (2024-08-24)
|
|
20
|
+
|
|
21
|
+
### Bug fixes
|
|
22
|
+
|
|
23
|
+
Make it easier to move the pointer over a hover tooltip with an arrow by not closing the tooltip when the pointer is moving over the gap for the arrow.
|
|
24
|
+
|
|
25
|
+
### New features
|
|
26
|
+
|
|
27
|
+
The new `EditorView.clipboardInputFilter` and `clipboardOutputFilter` facets allow you to register filter functions that change text taken from or sent to the clipboard.
|
|
28
|
+
|
|
1
29
|
## 6.32.0 (2024-08-12)
|
|
2
30
|
|
|
3
31
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -20,12 +20,6 @@ function getSelection(root) {
|
|
|
20
20
|
function contains(dom, node) {
|
|
21
21
|
return node ? dom == node || dom.contains(node.nodeType != 1 ? node.parentNode : node) : false;
|
|
22
22
|
}
|
|
23
|
-
function deepActiveElement(doc) {
|
|
24
|
-
let elt = doc.activeElement;
|
|
25
|
-
while (elt && elt.shadowRoot)
|
|
26
|
-
elt = elt.shadowRoot.activeElement;
|
|
27
|
-
return elt;
|
|
28
|
-
}
|
|
29
23
|
function hasSelection(dom, selection) {
|
|
30
24
|
if (!selection.anchorNode)
|
|
31
25
|
return false;
|
|
@@ -2365,6 +2359,8 @@ const exceptionSink = state.Facet.define();
|
|
|
2365
2359
|
const updateListener = state.Facet.define();
|
|
2366
2360
|
const inputHandler = state.Facet.define();
|
|
2367
2361
|
const focusChangeEffect = state.Facet.define();
|
|
2362
|
+
const clipboardInputFilter = state.Facet.define();
|
|
2363
|
+
const clipboardOutputFilter = state.Facet.define();
|
|
2368
2364
|
const perLineTextDirection = state.Facet.define({
|
|
2369
2365
|
combine: values => values.some(x => x)
|
|
2370
2366
|
});
|
|
@@ -3579,6 +3575,11 @@ function posAtCoords(view, coords, precise, bias = -1) {
|
|
|
3579
3575
|
node = undefined;
|
|
3580
3576
|
}
|
|
3581
3577
|
}
|
|
3578
|
+
// Chrome will return offsets into <input> elements without child
|
|
3579
|
+
// nodes, which will lead to a null deref below, so clip the
|
|
3580
|
+
// offset to the node size.
|
|
3581
|
+
if (node)
|
|
3582
|
+
offset = Math.min(maxOffset(node), offset);
|
|
3582
3583
|
}
|
|
3583
3584
|
// No luck, do our own (potentially expensive) search
|
|
3584
3585
|
if (!node || !view.docView.dom.contains(node)) {
|
|
@@ -4128,7 +4129,6 @@ function selectionFromPoints(points, base) {
|
|
|
4128
4129
|
return anchor > -1 && head > -1 ? state.EditorSelection.single(anchor + base, head + base) : null;
|
|
4129
4130
|
}
|
|
4130
4131
|
|
|
4131
|
-
// This will also be where dragging info and such goes
|
|
4132
4132
|
class InputState {
|
|
4133
4133
|
setSelectionOrigin(origin) {
|
|
4134
4134
|
this.lastSelectionOrigin = origin;
|
|
@@ -4546,7 +4546,13 @@ function capturePaste(view) {
|
|
|
4546
4546
|
doPaste(view, target.value);
|
|
4547
4547
|
}, 50);
|
|
4548
4548
|
}
|
|
4549
|
+
function textFilter(state, facet, text) {
|
|
4550
|
+
for (let filter of state.facet(facet))
|
|
4551
|
+
text = filter(text, state);
|
|
4552
|
+
return text;
|
|
4553
|
+
}
|
|
4549
4554
|
function doPaste(view, input) {
|
|
4555
|
+
input = textFilter(view.state, clipboardInputFilter, input);
|
|
4550
4556
|
let { state: state$1 } = view, changes, i = 1, text = state$1.toText(input);
|
|
4551
4557
|
let byLine = text.lines == state$1.selection.ranges.length;
|
|
4552
4558
|
let linewise = lastLinewiseCopy != null && state$1.selection.ranges.every(r => r.empty) && lastLinewiseCopy == text.toString();
|
|
@@ -4731,7 +4737,7 @@ handlers.dragstart = (view, event) => {
|
|
|
4731
4737
|
inputState.mouseSelection.dragging = true;
|
|
4732
4738
|
inputState.draggedContent = range;
|
|
4733
4739
|
if (event.dataTransfer) {
|
|
4734
|
-
event.dataTransfer.setData("Text", view.state.sliceDoc(range.from, range.to));
|
|
4740
|
+
event.dataTransfer.setData("Text", textFilter(view.state, clipboardOutputFilter, view.state.sliceDoc(range.from, range.to)));
|
|
4735
4741
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
4736
4742
|
}
|
|
4737
4743
|
return false;
|
|
@@ -4741,6 +4747,7 @@ handlers.dragend = view => {
|
|
|
4741
4747
|
return false;
|
|
4742
4748
|
};
|
|
4743
4749
|
function dropText(view, event, text, direct) {
|
|
4750
|
+
text = textFilter(view.state, clipboardInputFilter, text);
|
|
4744
4751
|
if (!text)
|
|
4745
4752
|
return;
|
|
4746
4753
|
let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
@@ -4841,7 +4848,7 @@ function copiedRange(state) {
|
|
|
4841
4848
|
}
|
|
4842
4849
|
linewise = true;
|
|
4843
4850
|
}
|
|
4844
|
-
return { text: content.join(state.lineBreak), ranges, linewise };
|
|
4851
|
+
return { text: textFilter(state, clipboardOutputFilter, content.join(state.lineBreak)), ranges, linewise };
|
|
4845
4852
|
}
|
|
4846
4853
|
let lastLinewiseCopy = null;
|
|
4847
4854
|
handlers.copy = handlers.cut = (view, event) => {
|
|
@@ -6565,11 +6572,9 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
|
|
|
6565
6572
|
display: "inline-block",
|
|
6566
6573
|
verticalAlign: "top",
|
|
6567
6574
|
},
|
|
6568
|
-
".cm-highlightSpace
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
pointerEvents: "none",
|
|
6572
|
-
color: "#888"
|
|
6575
|
+
".cm-highlightSpace": {
|
|
6576
|
+
backgroundImage: "radial-gradient(circle at 50% 55%, #aaa 20%, transparent 5%)",
|
|
6577
|
+
backgroundPosition: "center",
|
|
6573
6578
|
},
|
|
6574
6579
|
".cm-highlightTab": {
|
|
6575
6580
|
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>')`,
|
|
@@ -6767,7 +6772,7 @@ class DOMObserver {
|
|
|
6767
6772
|
if (!this.readSelectionRange() || this.delayedAndroidKey)
|
|
6768
6773
|
return;
|
|
6769
6774
|
let { view } = this, sel = this.selectionRange;
|
|
6770
|
-
if (view.state.facet(editable) ? view.root.activeElement != this.dom : !hasSelection(
|
|
6775
|
+
if (view.state.facet(editable) ? view.root.activeElement != this.dom : !hasSelection(this.dom, sel))
|
|
6771
6776
|
return;
|
|
6772
6777
|
let context = sel.anchorNode && view.docView.nearest(sel.anchorNode);
|
|
6773
6778
|
if (context && context.ignoreEvent(event)) {
|
|
@@ -6795,7 +6800,7 @@ class DOMObserver {
|
|
|
6795
6800
|
if (!selection)
|
|
6796
6801
|
return false;
|
|
6797
6802
|
let range = browser.safari && view.root.nodeType == 11 &&
|
|
6798
|
-
|
|
6803
|
+
view.root.activeElement == this.dom &&
|
|
6799
6804
|
safariSelectionRangeHack(this.view, selection) || selection;
|
|
6800
6805
|
if (!range || this.selectionRange.eq(range))
|
|
6801
6806
|
return false;
|
|
@@ -8264,6 +8269,15 @@ dispatching the custom behavior as a separate transaction.
|
|
|
8264
8269
|
*/
|
|
8265
8270
|
EditorView.inputHandler = inputHandler;
|
|
8266
8271
|
/**
|
|
8272
|
+
Functions provided in this facet will be used to transform text
|
|
8273
|
+
pasted or dropped into the editor.
|
|
8274
|
+
*/
|
|
8275
|
+
EditorView.clipboardInputFilter = clipboardInputFilter;
|
|
8276
|
+
/**
|
|
8277
|
+
Transform text copied or dragged from the editor.
|
|
8278
|
+
*/
|
|
8279
|
+
EditorView.clipboardOutputFilter = clipboardOutputFilter;
|
|
8280
|
+
/**
|
|
8267
8281
|
Scroll handlers can override how things are scrolled into view.
|
|
8268
8282
|
If they return `true`, no further handling happens for the
|
|
8269
8283
|
scrolling. If they return false, the default scroll behavior is
|
|
@@ -9474,11 +9488,13 @@ class Placeholder extends WidgetType {
|
|
|
9474
9488
|
super();
|
|
9475
9489
|
this.content = content;
|
|
9476
9490
|
}
|
|
9477
|
-
toDOM() {
|
|
9491
|
+
toDOM(view) {
|
|
9478
9492
|
let wrap = document.createElement("span");
|
|
9479
9493
|
wrap.className = "cm-placeholder";
|
|
9480
9494
|
wrap.style.pointerEvents = "none";
|
|
9481
|
-
wrap.appendChild(typeof this.content == "string" ? document.createTextNode(this.content) :
|
|
9495
|
+
wrap.appendChild(typeof this.content == "string" ? document.createTextNode(this.content) :
|
|
9496
|
+
typeof this.content == "function" ? this.content(view) :
|
|
9497
|
+
this.content.cloneNode(true));
|
|
9482
9498
|
if (typeof this.content == "string")
|
|
9483
9499
|
wrap.setAttribute("aria-label", "placeholder " + this.content);
|
|
9484
9500
|
else
|
|
@@ -10235,9 +10251,14 @@ class HoverPlugin {
|
|
|
10235
10251
|
}
|
|
10236
10252
|
const tooltipMargin = 4;
|
|
10237
10253
|
function isInTooltip(tooltip, event) {
|
|
10238
|
-
let
|
|
10239
|
-
|
|
10240
|
-
|
|
10254
|
+
let { left, right, top, bottom } = tooltip.getBoundingClientRect(), arrow;
|
|
10255
|
+
if (arrow = tooltip.querySelector(".cm-tooltip-arrow")) {
|
|
10256
|
+
let arrowRect = arrow.getBoundingClientRect();
|
|
10257
|
+
top = Math.min(arrowRect.top, top);
|
|
10258
|
+
bottom = Math.max(arrowRect.bottom, bottom);
|
|
10259
|
+
}
|
|
10260
|
+
return event.clientX >= left - tooltipMargin && event.clientX <= right + tooltipMargin &&
|
|
10261
|
+
event.clientY >= top - tooltipMargin && event.clientY <= bottom + tooltipMargin;
|
|
10241
10262
|
}
|
|
10242
10263
|
function isOverRange(view, from, to, x, y, margin) {
|
|
10243
10264
|
let rect = view.scrollDOM.getBoundingClientRect();
|
|
@@ -11008,20 +11029,6 @@ function highlightActiveLineGutter() {
|
|
|
11008
11029
|
return activeLineGutterHighlighter;
|
|
11009
11030
|
}
|
|
11010
11031
|
|
|
11011
|
-
const WhitespaceDeco = new Map();
|
|
11012
|
-
function getWhitespaceDeco(space) {
|
|
11013
|
-
let deco = WhitespaceDeco.get(space);
|
|
11014
|
-
if (!deco)
|
|
11015
|
-
WhitespaceDeco.set(space, deco = Decoration.mark({
|
|
11016
|
-
attributes: space === "\t" ? {
|
|
11017
|
-
class: "cm-highlightTab",
|
|
11018
|
-
} : {
|
|
11019
|
-
class: "cm-highlightSpace",
|
|
11020
|
-
"data-display": space.replace(/ /g, "·")
|
|
11021
|
-
}
|
|
11022
|
-
}));
|
|
11023
|
-
return deco;
|
|
11024
|
-
}
|
|
11025
11032
|
function matcher(decorator) {
|
|
11026
11033
|
return ViewPlugin.define(view => ({
|
|
11027
11034
|
decorations: decorator.createDeco(view),
|
|
@@ -11032,9 +11039,11 @@ function matcher(decorator) {
|
|
|
11032
11039
|
decorations: v => v.decorations
|
|
11033
11040
|
});
|
|
11034
11041
|
}
|
|
11042
|
+
const tabDeco = Decoration.mark({ class: "cm-highlightTab" });
|
|
11043
|
+
const spaceDeco = Decoration.mark({ class: "cm-highlightSpace" });
|
|
11035
11044
|
const whitespaceHighlighter = matcher(new MatchDecorator({
|
|
11036
|
-
regexp: /\t|
|
|
11037
|
-
decoration: match =>
|
|
11045
|
+
regexp: /\t| /g,
|
|
11046
|
+
decoration: match => match[0] == "\t" ? tabDeco : spaceDeco,
|
|
11038
11047
|
boundary: /\S/,
|
|
11039
11048
|
}));
|
|
11040
11049
|
/**
|
package/dist/index.d.cts
CHANGED
|
@@ -1146,6 +1146,15 @@ declare class EditorView {
|
|
|
1146
1146
|
*/
|
|
1147
1147
|
static inputHandler: Facet<(view: EditorView, from: number, to: number, text: string, insert: () => Transaction) => boolean, readonly ((view: EditorView, from: number, to: number, text: string, insert: () => Transaction) => boolean)[]>;
|
|
1148
1148
|
/**
|
|
1149
|
+
Functions provided in this facet will be used to transform text
|
|
1150
|
+
pasted or dropped into the editor.
|
|
1151
|
+
*/
|
|
1152
|
+
static clipboardInputFilter: Facet<(text: string, state: EditorState) => string, readonly ((text: string, state: EditorState) => string)[]>;
|
|
1153
|
+
/**
|
|
1154
|
+
Transform text copied or dragged from the editor.
|
|
1155
|
+
*/
|
|
1156
|
+
static clipboardOutputFilter: Facet<(text: string, state: EditorState) => string, readonly ((text: string, state: EditorState) => string)[]>;
|
|
1157
|
+
/**
|
|
1149
1158
|
Scroll handlers can override how things are scrolled into view.
|
|
1150
1159
|
If they return `true`, no further handling happens for the
|
|
1151
1160
|
scrolling. If they return false, the default scroll behavior is
|
|
@@ -1576,7 +1585,7 @@ declare function highlightActiveLine(): Extension;
|
|
|
1576
1585
|
Extension that enables a placeholder—a piece of example content
|
|
1577
1586
|
to show when the editor is empty.
|
|
1578
1587
|
*/
|
|
1579
|
-
declare function placeholder(content: string | HTMLElement): Extension;
|
|
1588
|
+
declare function placeholder(content: string | HTMLElement | ((view: EditorView) => HTMLElement)): Extension;
|
|
1580
1589
|
|
|
1581
1590
|
/**
|
|
1582
1591
|
Markers shown in a [layer](https://codemirror.net/6/docs/ref/#view.layer) must conform to this
|
package/dist/index.d.ts
CHANGED
|
@@ -1146,6 +1146,15 @@ declare class EditorView {
|
|
|
1146
1146
|
*/
|
|
1147
1147
|
static inputHandler: Facet<(view: EditorView, from: number, to: number, text: string, insert: () => Transaction) => boolean, readonly ((view: EditorView, from: number, to: number, text: string, insert: () => Transaction) => boolean)[]>;
|
|
1148
1148
|
/**
|
|
1149
|
+
Functions provided in this facet will be used to transform text
|
|
1150
|
+
pasted or dropped into the editor.
|
|
1151
|
+
*/
|
|
1152
|
+
static clipboardInputFilter: Facet<(text: string, state: EditorState) => string, readonly ((text: string, state: EditorState) => string)[]>;
|
|
1153
|
+
/**
|
|
1154
|
+
Transform text copied or dragged from the editor.
|
|
1155
|
+
*/
|
|
1156
|
+
static clipboardOutputFilter: Facet<(text: string, state: EditorState) => string, readonly ((text: string, state: EditorState) => string)[]>;
|
|
1157
|
+
/**
|
|
1149
1158
|
Scroll handlers can override how things are scrolled into view.
|
|
1150
1159
|
If they return `true`, no further handling happens for the
|
|
1151
1160
|
scrolling. If they return false, the default scroll behavior is
|
|
@@ -1576,7 +1585,7 @@ declare function highlightActiveLine(): Extension;
|
|
|
1576
1585
|
Extension that enables a placeholder—a piece of example content
|
|
1577
1586
|
to show when the editor is empty.
|
|
1578
1587
|
*/
|
|
1579
|
-
declare function placeholder(content: string | HTMLElement): Extension;
|
|
1588
|
+
declare function placeholder(content: string | HTMLElement | ((view: EditorView) => HTMLElement)): Extension;
|
|
1580
1589
|
|
|
1581
1590
|
/**
|
|
1582
1591
|
Markers shown in a [layer](https://codemirror.net/6/docs/ref/#view.layer) must conform to this
|
package/dist/index.js
CHANGED
|
@@ -18,12 +18,6 @@ function getSelection(root) {
|
|
|
18
18
|
function contains(dom, node) {
|
|
19
19
|
return node ? dom == node || dom.contains(node.nodeType != 1 ? node.parentNode : node) : false;
|
|
20
20
|
}
|
|
21
|
-
function deepActiveElement(doc) {
|
|
22
|
-
let elt = doc.activeElement;
|
|
23
|
-
while (elt && elt.shadowRoot)
|
|
24
|
-
elt = elt.shadowRoot.activeElement;
|
|
25
|
-
return elt;
|
|
26
|
-
}
|
|
27
21
|
function hasSelection(dom, selection) {
|
|
28
22
|
if (!selection.anchorNode)
|
|
29
23
|
return false;
|
|
@@ -2361,6 +2355,8 @@ const exceptionSink = /*@__PURE__*/Facet.define();
|
|
|
2361
2355
|
const updateListener = /*@__PURE__*/Facet.define();
|
|
2362
2356
|
const inputHandler = /*@__PURE__*/Facet.define();
|
|
2363
2357
|
const focusChangeEffect = /*@__PURE__*/Facet.define();
|
|
2358
|
+
const clipboardInputFilter = /*@__PURE__*/Facet.define();
|
|
2359
|
+
const clipboardOutputFilter = /*@__PURE__*/Facet.define();
|
|
2364
2360
|
const perLineTextDirection = /*@__PURE__*/Facet.define({
|
|
2365
2361
|
combine: values => values.some(x => x)
|
|
2366
2362
|
});
|
|
@@ -3575,6 +3571,11 @@ function posAtCoords(view, coords, precise, bias = -1) {
|
|
|
3575
3571
|
node = undefined;
|
|
3576
3572
|
}
|
|
3577
3573
|
}
|
|
3574
|
+
// Chrome will return offsets into <input> elements without child
|
|
3575
|
+
// nodes, which will lead to a null deref below, so clip the
|
|
3576
|
+
// offset to the node size.
|
|
3577
|
+
if (node)
|
|
3578
|
+
offset = Math.min(maxOffset(node), offset);
|
|
3578
3579
|
}
|
|
3579
3580
|
// No luck, do our own (potentially expensive) search
|
|
3580
3581
|
if (!node || !view.docView.dom.contains(node)) {
|
|
@@ -4124,7 +4125,6 @@ function selectionFromPoints(points, base) {
|
|
|
4124
4125
|
return anchor > -1 && head > -1 ? EditorSelection.single(anchor + base, head + base) : null;
|
|
4125
4126
|
}
|
|
4126
4127
|
|
|
4127
|
-
// This will also be where dragging info and such goes
|
|
4128
4128
|
class InputState {
|
|
4129
4129
|
setSelectionOrigin(origin) {
|
|
4130
4130
|
this.lastSelectionOrigin = origin;
|
|
@@ -4542,7 +4542,13 @@ function capturePaste(view) {
|
|
|
4542
4542
|
doPaste(view, target.value);
|
|
4543
4543
|
}, 50);
|
|
4544
4544
|
}
|
|
4545
|
+
function textFilter(state, facet, text) {
|
|
4546
|
+
for (let filter of state.facet(facet))
|
|
4547
|
+
text = filter(text, state);
|
|
4548
|
+
return text;
|
|
4549
|
+
}
|
|
4545
4550
|
function doPaste(view, input) {
|
|
4551
|
+
input = textFilter(view.state, clipboardInputFilter, input);
|
|
4546
4552
|
let { state } = view, changes, i = 1, text = state.toText(input);
|
|
4547
4553
|
let byLine = text.lines == state.selection.ranges.length;
|
|
4548
4554
|
let linewise = lastLinewiseCopy != null && state.selection.ranges.every(r => r.empty) && lastLinewiseCopy == text.toString();
|
|
@@ -4727,7 +4733,7 @@ handlers.dragstart = (view, event) => {
|
|
|
4727
4733
|
inputState.mouseSelection.dragging = true;
|
|
4728
4734
|
inputState.draggedContent = range;
|
|
4729
4735
|
if (event.dataTransfer) {
|
|
4730
|
-
event.dataTransfer.setData("Text", view.state.sliceDoc(range.from, range.to));
|
|
4736
|
+
event.dataTransfer.setData("Text", textFilter(view.state, clipboardOutputFilter, view.state.sliceDoc(range.from, range.to)));
|
|
4731
4737
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
4732
4738
|
}
|
|
4733
4739
|
return false;
|
|
@@ -4737,6 +4743,7 @@ handlers.dragend = view => {
|
|
|
4737
4743
|
return false;
|
|
4738
4744
|
};
|
|
4739
4745
|
function dropText(view, event, text, direct) {
|
|
4746
|
+
text = textFilter(view.state, clipboardInputFilter, text);
|
|
4740
4747
|
if (!text)
|
|
4741
4748
|
return;
|
|
4742
4749
|
let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
@@ -4837,7 +4844,7 @@ function copiedRange(state) {
|
|
|
4837
4844
|
}
|
|
4838
4845
|
linewise = true;
|
|
4839
4846
|
}
|
|
4840
|
-
return { text: content.join(state.lineBreak), ranges, linewise };
|
|
4847
|
+
return { text: textFilter(state, clipboardOutputFilter, content.join(state.lineBreak)), ranges, linewise };
|
|
4841
4848
|
}
|
|
4842
4849
|
let lastLinewiseCopy = null;
|
|
4843
4850
|
handlers.copy = handlers.cut = (view, event) => {
|
|
@@ -6560,11 +6567,9 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
6560
6567
|
display: "inline-block",
|
|
6561
6568
|
verticalAlign: "top",
|
|
6562
6569
|
},
|
|
6563
|
-
".cm-highlightSpace
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
pointerEvents: "none",
|
|
6567
|
-
color: "#888"
|
|
6570
|
+
".cm-highlightSpace": {
|
|
6571
|
+
backgroundImage: "radial-gradient(circle at 50% 55%, #aaa 20%, transparent 5%)",
|
|
6572
|
+
backgroundPosition: "center",
|
|
6568
6573
|
},
|
|
6569
6574
|
".cm-highlightTab": {
|
|
6570
6575
|
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>')`,
|
|
@@ -6762,7 +6767,7 @@ class DOMObserver {
|
|
|
6762
6767
|
if (!this.readSelectionRange() || this.delayedAndroidKey)
|
|
6763
6768
|
return;
|
|
6764
6769
|
let { view } = this, sel = this.selectionRange;
|
|
6765
|
-
if (view.state.facet(editable) ? view.root.activeElement != this.dom : !hasSelection(
|
|
6770
|
+
if (view.state.facet(editable) ? view.root.activeElement != this.dom : !hasSelection(this.dom, sel))
|
|
6766
6771
|
return;
|
|
6767
6772
|
let context = sel.anchorNode && view.docView.nearest(sel.anchorNode);
|
|
6768
6773
|
if (context && context.ignoreEvent(event)) {
|
|
@@ -6790,7 +6795,7 @@ class DOMObserver {
|
|
|
6790
6795
|
if (!selection)
|
|
6791
6796
|
return false;
|
|
6792
6797
|
let range = browser.safari && view.root.nodeType == 11 &&
|
|
6793
|
-
|
|
6798
|
+
view.root.activeElement == this.dom &&
|
|
6794
6799
|
safariSelectionRangeHack(this.view, selection) || selection;
|
|
6795
6800
|
if (!range || this.selectionRange.eq(range))
|
|
6796
6801
|
return false;
|
|
@@ -8259,6 +8264,15 @@ dispatching the custom behavior as a separate transaction.
|
|
|
8259
8264
|
*/
|
|
8260
8265
|
EditorView.inputHandler = inputHandler;
|
|
8261
8266
|
/**
|
|
8267
|
+
Functions provided in this facet will be used to transform text
|
|
8268
|
+
pasted or dropped into the editor.
|
|
8269
|
+
*/
|
|
8270
|
+
EditorView.clipboardInputFilter = clipboardInputFilter;
|
|
8271
|
+
/**
|
|
8272
|
+
Transform text copied or dragged from the editor.
|
|
8273
|
+
*/
|
|
8274
|
+
EditorView.clipboardOutputFilter = clipboardOutputFilter;
|
|
8275
|
+
/**
|
|
8262
8276
|
Scroll handlers can override how things are scrolled into view.
|
|
8263
8277
|
If they return `true`, no further handling happens for the
|
|
8264
8278
|
scrolling. If they return false, the default scroll behavior is
|
|
@@ -9469,11 +9483,13 @@ class Placeholder extends WidgetType {
|
|
|
9469
9483
|
super();
|
|
9470
9484
|
this.content = content;
|
|
9471
9485
|
}
|
|
9472
|
-
toDOM() {
|
|
9486
|
+
toDOM(view) {
|
|
9473
9487
|
let wrap = document.createElement("span");
|
|
9474
9488
|
wrap.className = "cm-placeholder";
|
|
9475
9489
|
wrap.style.pointerEvents = "none";
|
|
9476
|
-
wrap.appendChild(typeof this.content == "string" ? document.createTextNode(this.content) :
|
|
9490
|
+
wrap.appendChild(typeof this.content == "string" ? document.createTextNode(this.content) :
|
|
9491
|
+
typeof this.content == "function" ? this.content(view) :
|
|
9492
|
+
this.content.cloneNode(true));
|
|
9477
9493
|
if (typeof this.content == "string")
|
|
9478
9494
|
wrap.setAttribute("aria-label", "placeholder " + this.content);
|
|
9479
9495
|
else
|
|
@@ -10230,9 +10246,14 @@ class HoverPlugin {
|
|
|
10230
10246
|
}
|
|
10231
10247
|
const tooltipMargin = 4;
|
|
10232
10248
|
function isInTooltip(tooltip, event) {
|
|
10233
|
-
let
|
|
10234
|
-
|
|
10235
|
-
|
|
10249
|
+
let { left, right, top, bottom } = tooltip.getBoundingClientRect(), arrow;
|
|
10250
|
+
if (arrow = tooltip.querySelector(".cm-tooltip-arrow")) {
|
|
10251
|
+
let arrowRect = arrow.getBoundingClientRect();
|
|
10252
|
+
top = Math.min(arrowRect.top, top);
|
|
10253
|
+
bottom = Math.max(arrowRect.bottom, bottom);
|
|
10254
|
+
}
|
|
10255
|
+
return event.clientX >= left - tooltipMargin && event.clientX <= right + tooltipMargin &&
|
|
10256
|
+
event.clientY >= top - tooltipMargin && event.clientY <= bottom + tooltipMargin;
|
|
10236
10257
|
}
|
|
10237
10258
|
function isOverRange(view, from, to, x, y, margin) {
|
|
10238
10259
|
let rect = view.scrollDOM.getBoundingClientRect();
|
|
@@ -11003,20 +11024,6 @@ function highlightActiveLineGutter() {
|
|
|
11003
11024
|
return activeLineGutterHighlighter;
|
|
11004
11025
|
}
|
|
11005
11026
|
|
|
11006
|
-
const WhitespaceDeco = /*@__PURE__*/new Map();
|
|
11007
|
-
function getWhitespaceDeco(space) {
|
|
11008
|
-
let deco = WhitespaceDeco.get(space);
|
|
11009
|
-
if (!deco)
|
|
11010
|
-
WhitespaceDeco.set(space, deco = Decoration.mark({
|
|
11011
|
-
attributes: space === "\t" ? {
|
|
11012
|
-
class: "cm-highlightTab",
|
|
11013
|
-
} : {
|
|
11014
|
-
class: "cm-highlightSpace",
|
|
11015
|
-
"data-display": space.replace(/ /g, "·")
|
|
11016
|
-
}
|
|
11017
|
-
}));
|
|
11018
|
-
return deco;
|
|
11019
|
-
}
|
|
11020
11027
|
function matcher(decorator) {
|
|
11021
11028
|
return ViewPlugin.define(view => ({
|
|
11022
11029
|
decorations: decorator.createDeco(view),
|
|
@@ -11027,9 +11034,11 @@ function matcher(decorator) {
|
|
|
11027
11034
|
decorations: v => v.decorations
|
|
11028
11035
|
});
|
|
11029
11036
|
}
|
|
11037
|
+
const tabDeco = /*@__PURE__*/Decoration.mark({ class: "cm-highlightTab" });
|
|
11038
|
+
const spaceDeco = /*@__PURE__*/Decoration.mark({ class: "cm-highlightSpace" });
|
|
11030
11039
|
const whitespaceHighlighter = /*@__PURE__*/matcher(/*@__PURE__*/new MatchDecorator({
|
|
11031
|
-
regexp: /\t|
|
|
11032
|
-
decoration: match =>
|
|
11040
|
+
regexp: /\t| /g,
|
|
11041
|
+
decoration: match => match[0] == "\t" ? tabDeco : spaceDeco,
|
|
11033
11042
|
boundary: /\S/,
|
|
11034
11043
|
}));
|
|
11035
11044
|
/**
|