@codemirror/view 6.11.2 → 6.12.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 +109 -78
- package/dist/index.d.ts +12 -12
- package/dist/index.js +109 -78
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## 6.12.0 (2023-05-18)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Remove an accidentally included `console.log`.
|
|
6
|
+
|
|
7
|
+
### New features
|
|
8
|
+
|
|
9
|
+
`EditorViewConfig.dispatch` is now passed the view object as a second argument.
|
|
10
|
+
|
|
11
|
+
## 6.11.3 (2023-05-17)
|
|
12
|
+
|
|
13
|
+
### Bug fixes
|
|
14
|
+
|
|
15
|
+
Make sure pointer selection respects `EditorView.atomicRanges`.
|
|
16
|
+
|
|
17
|
+
Preserve DOM widgets when their decoration type changes but they otherwise stay in the same place.
|
|
18
|
+
|
|
19
|
+
Fix a bug in `drawSelection` that could lead to invisible or incorrect selections for a blank line below a block widget.
|
|
20
|
+
|
|
1
21
|
## 6.11.2 (2023-05-13)
|
|
2
22
|
|
|
3
23
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -822,6 +822,9 @@ function textCoords(text, pos, side) {
|
|
|
822
822
|
}
|
|
823
823
|
// Also used for collapsed ranges that don't have a placeholder widget!
|
|
824
824
|
class WidgetView extends ContentView {
|
|
825
|
+
static create(widget, length, side) {
|
|
826
|
+
return new (widget.customView || WidgetView)(widget, length, side);
|
|
827
|
+
}
|
|
825
828
|
constructor(widget, length, side) {
|
|
826
829
|
super();
|
|
827
830
|
this.widget = widget;
|
|
@@ -829,9 +832,6 @@ class WidgetView extends ContentView {
|
|
|
829
832
|
this.side = side;
|
|
830
833
|
this.prevWidget = null;
|
|
831
834
|
}
|
|
832
|
-
static create(widget, length, side) {
|
|
833
|
-
return new (widget.customView || WidgetView)(widget, length, side);
|
|
834
|
-
}
|
|
835
835
|
split(from) {
|
|
836
836
|
let result = WidgetView.create(this.widget, this.length - from, this.side);
|
|
837
837
|
this.length -= from;
|
|
@@ -1647,7 +1647,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1647
1647
|
}
|
|
1648
1648
|
domBoundsAround() { return null; }
|
|
1649
1649
|
become(other) {
|
|
1650
|
-
if (other instanceof BlockWidgetView &&
|
|
1650
|
+
if (other instanceof BlockWidgetView &&
|
|
1651
1651
|
other.widget.constructor == this.widget.constructor) {
|
|
1652
1652
|
if (!other.widget.compare(this.widget))
|
|
1653
1653
|
this.markDirty(true);
|
|
@@ -1655,6 +1655,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1655
1655
|
this.prevWidget = this.widget;
|
|
1656
1656
|
this.widget = other.widget;
|
|
1657
1657
|
this.length = other.length;
|
|
1658
|
+
this.type = other.type;
|
|
1658
1659
|
this.breakAfter = other.breakAfter;
|
|
1659
1660
|
return true;
|
|
1660
1661
|
}
|
|
@@ -2215,6 +2216,10 @@ Represents a contiguous range of text that has a single direction
|
|
|
2215
2216
|
(as in left-to-right or right-to-left).
|
|
2216
2217
|
*/
|
|
2217
2218
|
class BidiSpan {
|
|
2219
|
+
/**
|
|
2220
|
+
The direction of this span.
|
|
2221
|
+
*/
|
|
2222
|
+
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2218
2223
|
/**
|
|
2219
2224
|
@internal
|
|
2220
2225
|
*/
|
|
@@ -2240,10 +2245,6 @@ class BidiSpan {
|
|
|
2240
2245
|
this.level = level;
|
|
2241
2246
|
}
|
|
2242
2247
|
/**
|
|
2243
|
-
The direction of this span.
|
|
2244
|
-
*/
|
|
2245
|
-
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2246
|
-
/**
|
|
2247
2248
|
@internal
|
|
2248
2249
|
*/
|
|
2249
2250
|
side(end, dir) { return (this.dir == dir) == end ? this.to : this.from; }
|
|
@@ -2495,6 +2496,7 @@ class DOMReader {
|
|
|
2495
2496
|
let parent = start.parentNode;
|
|
2496
2497
|
for (let cur = start;;) {
|
|
2497
2498
|
this.findPointBefore(parent, cur);
|
|
2499
|
+
let oldLen = this.text.length;
|
|
2498
2500
|
this.readNode(cur);
|
|
2499
2501
|
let next = cur.nextSibling;
|
|
2500
2502
|
if (next == end)
|
|
@@ -2502,7 +2504,7 @@ class DOMReader {
|
|
|
2502
2504
|
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
2503
2505
|
if (view && nextView ? view.breakAfter :
|
|
2504
2506
|
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
2505
|
-
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore)))
|
|
2507
|
+
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
2506
2508
|
this.lineBreak();
|
|
2507
2509
|
cur = next;
|
|
2508
2510
|
}
|
|
@@ -2583,6 +2585,7 @@ class DOMPoint {
|
|
|
2583
2585
|
}
|
|
2584
2586
|
|
|
2585
2587
|
class DocView extends ContentView {
|
|
2588
|
+
get length() { return this.view.state.doc.length; }
|
|
2586
2589
|
constructor(view) {
|
|
2587
2590
|
super();
|
|
2588
2591
|
this.view = view;
|
|
@@ -2613,7 +2616,6 @@ class DocView extends ContentView {
|
|
|
2613
2616
|
this.updateDeco();
|
|
2614
2617
|
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
|
|
2615
2618
|
}
|
|
2616
|
-
get length() { return this.view.state.doc.length; }
|
|
2617
2619
|
// Update the document view to a given state. scrollIntoView can be
|
|
2618
2620
|
// used as a hint to compute a new viewport that includes that
|
|
2619
2621
|
// position, if we know the editor is going to scroll that position
|
|
@@ -3451,15 +3453,15 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3451
3453
|
return state.EditorSelection.cursor(pos, start.assoc, undefined, goal);
|
|
3452
3454
|
}
|
|
3453
3455
|
}
|
|
3454
|
-
function
|
|
3455
|
-
let atoms = view.state.facet(atomicRanges).map(f => f(view));
|
|
3456
|
+
function skipAtomicRanges(atoms, pos, bias) {
|
|
3456
3457
|
for (;;) {
|
|
3457
|
-
let moved =
|
|
3458
|
+
let moved = 0;
|
|
3458
3459
|
for (let set of atoms) {
|
|
3459
|
-
set.between(pos
|
|
3460
|
-
if (pos
|
|
3461
|
-
|
|
3462
|
-
|
|
3460
|
+
set.between(pos - 1, pos + 1, (from, to, value) => {
|
|
3461
|
+
if (pos > from && pos < to) {
|
|
3462
|
+
let side = moved || bias || (pos - from < to - pos ? -1 : 1);
|
|
3463
|
+
pos = side < 0 ? from : to;
|
|
3464
|
+
moved = side;
|
|
3463
3465
|
}
|
|
3464
3466
|
});
|
|
3465
3467
|
}
|
|
@@ -3467,9 +3469,17 @@ function skipAtoms(view, oldPos, pos) {
|
|
|
3467
3469
|
return pos;
|
|
3468
3470
|
}
|
|
3469
3471
|
}
|
|
3472
|
+
function skipAtoms(view, oldPos, pos) {
|
|
3473
|
+
let newPos = skipAtomicRanges(view.state.facet(atomicRanges).map(f => f(view)), pos.from, oldPos.head > pos.from ? -1 : 1);
|
|
3474
|
+
return newPos == pos.from ? pos : state.EditorSelection.cursor(newPos, newPos < pos.from ? 1 : -1);
|
|
3475
|
+
}
|
|
3470
3476
|
|
|
3471
3477
|
// This will also be where dragging info and such goes
|
|
3472
3478
|
class InputState {
|
|
3479
|
+
setSelectionOrigin(origin) {
|
|
3480
|
+
this.lastSelectionOrigin = origin;
|
|
3481
|
+
this.lastSelectionTime = Date.now();
|
|
3482
|
+
}
|
|
3473
3483
|
constructor(view) {
|
|
3474
3484
|
this.lastKeyCode = 0;
|
|
3475
3485
|
this.lastKeyTime = 0;
|
|
@@ -3566,10 +3576,6 @@ class InputState {
|
|
|
3566
3576
|
if (browser.safari)
|
|
3567
3577
|
view.contentDOM.addEventListener("input", () => null);
|
|
3568
3578
|
}
|
|
3569
|
-
setSelectionOrigin(origin) {
|
|
3570
|
-
this.lastSelectionOrigin = origin;
|
|
3571
|
-
this.lastSelectionTime = Date.now();
|
|
3572
|
-
}
|
|
3573
3579
|
ensureHandlers(view, plugins) {
|
|
3574
3580
|
var _a;
|
|
3575
3581
|
let handlers;
|
|
@@ -3716,6 +3722,7 @@ class MouseSelection {
|
|
|
3716
3722
|
this.scrolling = -1;
|
|
3717
3723
|
this.lastEvent = startEvent;
|
|
3718
3724
|
this.scrollParent = scrollableParent(view.contentDOM);
|
|
3725
|
+
this.atoms = view.state.facet(atomicRanges).map(f => f(view));
|
|
3719
3726
|
let doc = view.contentDOM.ownerDocument;
|
|
3720
3727
|
doc.addEventListener("mousemove", this.move = this.move.bind(this));
|
|
3721
3728
|
doc.addEventListener("mouseup", this.up = this.up.bind(this));
|
|
@@ -3789,10 +3796,33 @@ class MouseSelection {
|
|
|
3789
3796
|
if (this.dragging === false)
|
|
3790
3797
|
this.select(this.lastEvent);
|
|
3791
3798
|
}
|
|
3799
|
+
skipAtoms(sel) {
|
|
3800
|
+
let ranges = null;
|
|
3801
|
+
for (let i = 0; i < sel.ranges.length; i++) {
|
|
3802
|
+
let range = sel.ranges[i], updated = null;
|
|
3803
|
+
if (range.empty) {
|
|
3804
|
+
let pos = skipAtomicRanges(this.atoms, range.from, 0);
|
|
3805
|
+
if (pos != range.from)
|
|
3806
|
+
updated = state.EditorSelection.cursor(pos, -1);
|
|
3807
|
+
}
|
|
3808
|
+
else {
|
|
3809
|
+
let from = skipAtomicRanges(this.atoms, range.from, -1);
|
|
3810
|
+
let to = skipAtomicRanges(this.atoms, range.to, 1);
|
|
3811
|
+
if (from != range.from || to != range.to)
|
|
3812
|
+
updated = state.EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to);
|
|
3813
|
+
}
|
|
3814
|
+
if (updated) {
|
|
3815
|
+
if (!ranges)
|
|
3816
|
+
ranges = sel.ranges.slice();
|
|
3817
|
+
ranges[i] = updated;
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3820
|
+
return ranges ? state.EditorSelection.create(ranges, sel.mainIndex) : sel;
|
|
3821
|
+
}
|
|
3792
3822
|
select(event) {
|
|
3793
|
-
let selection = this.style.get(event, this.extend, this.multiple);
|
|
3794
|
-
if (this.mustSelect || !selection.eq(
|
|
3795
|
-
selection.main.assoc !=
|
|
3823
|
+
let { view } = this, selection = this.skipAtoms(this.style.get(event, this.extend, this.multiple));
|
|
3824
|
+
if (this.mustSelect || !selection.eq(view.state.selection) ||
|
|
3825
|
+
selection.main.assoc != view.state.selection.main.assoc)
|
|
3796
3826
|
this.view.dispatch({
|
|
3797
3827
|
selection,
|
|
3798
3828
|
userEvent: "select.pointer"
|
|
@@ -6469,6 +6499,53 @@ line number gutter. It handles events and dispatches state
|
|
|
6469
6499
|
transactions for editing actions.
|
|
6470
6500
|
*/
|
|
6471
6501
|
class EditorView {
|
|
6502
|
+
/**
|
|
6503
|
+
The current editor state.
|
|
6504
|
+
*/
|
|
6505
|
+
get state() { return this.viewState.state; }
|
|
6506
|
+
/**
|
|
6507
|
+
To be able to display large documents without consuming too much
|
|
6508
|
+
memory or overloading the browser, CodeMirror only draws the
|
|
6509
|
+
code that is visible (plus a margin around it) to the DOM. This
|
|
6510
|
+
property tells you the extent of the current drawn viewport, in
|
|
6511
|
+
document positions.
|
|
6512
|
+
*/
|
|
6513
|
+
get viewport() { return this.viewState.viewport; }
|
|
6514
|
+
/**
|
|
6515
|
+
When there are, for example, large collapsed ranges in the
|
|
6516
|
+
viewport, its size can be a lot bigger than the actual visible
|
|
6517
|
+
content. Thus, if you are doing something like styling the
|
|
6518
|
+
content in the viewport, it is preferable to only do so for
|
|
6519
|
+
these ranges, which are the subset of the viewport that is
|
|
6520
|
+
actually drawn.
|
|
6521
|
+
*/
|
|
6522
|
+
get visibleRanges() { return this.viewState.visibleRanges; }
|
|
6523
|
+
/**
|
|
6524
|
+
Returns false when the editor is entirely scrolled out of view
|
|
6525
|
+
or otherwise hidden.
|
|
6526
|
+
*/
|
|
6527
|
+
get inView() { return this.viewState.inView; }
|
|
6528
|
+
/**
|
|
6529
|
+
Indicates whether the user is currently composing text via
|
|
6530
|
+
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
6531
|
+
one change has been made in the current composition.
|
|
6532
|
+
*/
|
|
6533
|
+
get composing() { return this.inputState.composing > 0; }
|
|
6534
|
+
/**
|
|
6535
|
+
Indicates whether the user is currently in composing state. Note
|
|
6536
|
+
that on some platforms, like Android, this will be the case a
|
|
6537
|
+
lot, since just putting the cursor on a word starts a
|
|
6538
|
+
composition there.
|
|
6539
|
+
*/
|
|
6540
|
+
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
6541
|
+
/**
|
|
6542
|
+
The document or shadow root that the view lives in.
|
|
6543
|
+
*/
|
|
6544
|
+
get root() { return this._root; }
|
|
6545
|
+
/**
|
|
6546
|
+
@internal
|
|
6547
|
+
*/
|
|
6548
|
+
get win() { return this.dom.ownerDocument.defaultView || window; }
|
|
6472
6549
|
/**
|
|
6473
6550
|
Construct a new view. You'll want to either provide a `parent`
|
|
6474
6551
|
option, or put `view.dom` into your document after creating a
|
|
@@ -6522,56 +6599,10 @@ class EditorView {
|
|
|
6522
6599
|
if (config.parent)
|
|
6523
6600
|
config.parent.appendChild(this.dom);
|
|
6524
6601
|
}
|
|
6525
|
-
/**
|
|
6526
|
-
The current editor state.
|
|
6527
|
-
*/
|
|
6528
|
-
get state() { return this.viewState.state; }
|
|
6529
|
-
/**
|
|
6530
|
-
To be able to display large documents without consuming too much
|
|
6531
|
-
memory or overloading the browser, CodeMirror only draws the
|
|
6532
|
-
code that is visible (plus a margin around it) to the DOM. This
|
|
6533
|
-
property tells you the extent of the current drawn viewport, in
|
|
6534
|
-
document positions.
|
|
6535
|
-
*/
|
|
6536
|
-
get viewport() { return this.viewState.viewport; }
|
|
6537
|
-
/**
|
|
6538
|
-
When there are, for example, large collapsed ranges in the
|
|
6539
|
-
viewport, its size can be a lot bigger than the actual visible
|
|
6540
|
-
content. Thus, if you are doing something like styling the
|
|
6541
|
-
content in the viewport, it is preferable to only do so for
|
|
6542
|
-
these ranges, which are the subset of the viewport that is
|
|
6543
|
-
actually drawn.
|
|
6544
|
-
*/
|
|
6545
|
-
get visibleRanges() { return this.viewState.visibleRanges; }
|
|
6546
|
-
/**
|
|
6547
|
-
Returns false when the editor is entirely scrolled out of view
|
|
6548
|
-
or otherwise hidden.
|
|
6549
|
-
*/
|
|
6550
|
-
get inView() { return this.viewState.inView; }
|
|
6551
|
-
/**
|
|
6552
|
-
Indicates whether the user is currently composing text via
|
|
6553
|
-
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
6554
|
-
one change has been made in the current composition.
|
|
6555
|
-
*/
|
|
6556
|
-
get composing() { return this.inputState.composing > 0; }
|
|
6557
|
-
/**
|
|
6558
|
-
Indicates whether the user is currently in composing state. Note
|
|
6559
|
-
that on some platforms, like Android, this will be the case a
|
|
6560
|
-
lot, since just putting the cursor on a word starts a
|
|
6561
|
-
composition there.
|
|
6562
|
-
*/
|
|
6563
|
-
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
6564
|
-
/**
|
|
6565
|
-
The document or shadow root that the view lives in.
|
|
6566
|
-
*/
|
|
6567
|
-
get root() { return this._root; }
|
|
6568
|
-
/**
|
|
6569
|
-
@internal
|
|
6570
|
-
*/
|
|
6571
|
-
get win() { return this.dom.ownerDocument.defaultView || window; }
|
|
6572
6602
|
dispatch(...input) {
|
|
6573
|
-
|
|
6574
|
-
: this.state.update(...input)
|
|
6603
|
+
let tr = input.length == 1 && input[0] instanceof state.Transaction ? input[0]
|
|
6604
|
+
: this.state.update(...input);
|
|
6605
|
+
this._dispatch(tr, this);
|
|
6575
6606
|
}
|
|
6576
6607
|
/**
|
|
6577
6608
|
Update the view for the given array of transactions. This will
|
|
@@ -7718,7 +7749,7 @@ function rectanglesForRange(view, className, range) {
|
|
|
7718
7749
|
let top = visualStart ? drawForLine(range.from, null, visualStart) : drawForWidget(startBlock, false);
|
|
7719
7750
|
let bottom = visualEnd ? drawForLine(null, range.to, visualEnd) : drawForWidget(endBlock, true);
|
|
7720
7751
|
let between = [];
|
|
7721
|
-
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - 1)
|
|
7752
|
+
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - (visualStart && visualEnd ? 1 : 0))
|
|
7722
7753
|
between.push(piece(leftSide, top.bottom, rightSide, bottom.top));
|
|
7723
7754
|
else if (top.bottom < bottom.top && view.elementAtHeight((top.bottom + bottom.top) / 2).type == exports.BlockType.Text)
|
|
7724
7755
|
top.bottom = bottom.top = (top.bottom + bottom.top) / 2;
|
|
@@ -8876,6 +8907,10 @@ const showTooltip = state.Facet.define({
|
|
|
8876
8907
|
});
|
|
8877
8908
|
const showHoverTooltip = state.Facet.define();
|
|
8878
8909
|
class HoverTooltipHost {
|
|
8910
|
+
// Needs to be static so that host tooltip instances always match
|
|
8911
|
+
static create(view) {
|
|
8912
|
+
return new HoverTooltipHost(view);
|
|
8913
|
+
}
|
|
8879
8914
|
constructor(view) {
|
|
8880
8915
|
this.view = view;
|
|
8881
8916
|
this.mounted = false;
|
|
@@ -8883,10 +8918,6 @@ class HoverTooltipHost {
|
|
|
8883
8918
|
this.dom.classList.add("cm-tooltip-hover");
|
|
8884
8919
|
this.manager = new TooltipViewManager(view, showHoverTooltip, t => this.createHostedView(t));
|
|
8885
8920
|
}
|
|
8886
|
-
// Needs to be static so that host tooltip instances always match
|
|
8887
|
-
static create(view) {
|
|
8888
|
-
return new HoverTooltipHost(view);
|
|
8889
|
-
}
|
|
8890
8921
|
createHostedView(tooltip) {
|
|
8891
8922
|
let hostedView = tooltip.create(this.view);
|
|
8892
8923
|
hostedView.dom.classList.add("cm-tooltip-section");
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as _codemirror_state from '@codemirror/state';
|
|
|
2
2
|
import { RangeSet, RangeValue, Range, EditorState, Extension, Transaction, ChangeSet, EditorSelection, EditorStateConfig, TransactionSpec, SelectionRange, Line, StateEffect, Facet } from '@codemirror/state';
|
|
3
3
|
import { StyleModule, StyleSpec } from 'style-mod';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
type Attrs = {
|
|
6
6
|
[name: string]: string;
|
|
7
7
|
};
|
|
8
8
|
|
|
@@ -15,7 +15,7 @@ interface Rect {
|
|
|
15
15
|
readonly top: number;
|
|
16
16
|
readonly bottom: number;
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
type ScrollStrategy = "nearest" | "start" | "end" | "center";
|
|
19
19
|
|
|
20
20
|
interface MarkDecorationSpec {
|
|
21
21
|
/**
|
|
@@ -198,7 +198,7 @@ A decoration set represents a collection of decorated ranges,
|
|
|
198
198
|
organized for efficient access and mapping. See
|
|
199
199
|
[`RangeSet`](https://codemirror.net/6/docs/ref/#state.RangeSet) for its methods.
|
|
200
200
|
*/
|
|
201
|
-
|
|
201
|
+
type DecorationSet = RangeSet<Decoration>;
|
|
202
202
|
/**
|
|
203
203
|
The different types of blocks that can occur in an editor view.
|
|
204
204
|
*/
|
|
@@ -297,7 +297,7 @@ apply to the editor, and if it can, perform it as a side effect
|
|
|
297
297
|
(which usually means [dispatching](https://codemirror.net/6/docs/ref/#view.EditorView.dispatch) a
|
|
298
298
|
transaction) and return `true`.
|
|
299
299
|
*/
|
|
300
|
-
|
|
300
|
+
type Command = (target: EditorView) => boolean;
|
|
301
301
|
/**
|
|
302
302
|
Log or report an unhandled exception in client code. Should
|
|
303
303
|
probably only be used by extension code that allows client code to
|
|
@@ -399,7 +399,7 @@ interface MeasureRequest<T> {
|
|
|
399
399
|
*/
|
|
400
400
|
key?: any;
|
|
401
401
|
}
|
|
402
|
-
|
|
402
|
+
type AttrSource = Attrs | ((view: EditorView) => Attrs | null);
|
|
403
403
|
/**
|
|
404
404
|
View [plugins](https://codemirror.net/6/docs/ref/#view.ViewPlugin) are given instances of this
|
|
405
405
|
class, which describe what happened, whenever the view is updated.
|
|
@@ -488,7 +488,7 @@ interface MouseSelectionStyle {
|
|
|
488
488
|
*/
|
|
489
489
|
update: (update: ViewUpdate) => boolean | void;
|
|
490
490
|
}
|
|
491
|
-
|
|
491
|
+
type MakeSelectionStyle = (view: EditorView, event: MouseEvent) => MouseSelectionStyle | null;
|
|
492
492
|
|
|
493
493
|
/**
|
|
494
494
|
Record used to represent information about a block-level element
|
|
@@ -605,7 +605,7 @@ interface EditorViewConfig extends EditorStateConfig {
|
|
|
605
605
|
if provided, should probably call the view's [`update`
|
|
606
606
|
method](https://codemirror.net/6/docs/ref/#view.EditorView.update).
|
|
607
607
|
*/
|
|
608
|
-
dispatch?: (tr: Transaction) => void;
|
|
608
|
+
dispatch?: (tr: Transaction, view: EditorView) => void;
|
|
609
609
|
}
|
|
610
610
|
/**
|
|
611
611
|
An editor view represents the editor's user interface. It holds
|
|
@@ -1183,7 +1183,7 @@ to hold the appropriate event object type. For unknown events, it
|
|
|
1183
1183
|
is inferred to `any`, and should be explicitly set if you want type
|
|
1184
1184
|
checking.
|
|
1185
1185
|
*/
|
|
1186
|
-
|
|
1186
|
+
type DOMEventHandlers<This> = {
|
|
1187
1187
|
[event in keyof DOMEventMap]?: (this: This, event: DOMEventMap[event], view: EditorView) => boolean | void;
|
|
1188
1188
|
};
|
|
1189
1189
|
|
|
@@ -1285,7 +1285,7 @@ handlers handled it.
|
|
|
1285
1285
|
*/
|
|
1286
1286
|
declare function runScopeHandlers(view: EditorView, event: KeyboardEvent, scope: string): boolean;
|
|
1287
1287
|
|
|
1288
|
-
|
|
1288
|
+
type SelectionConfig = {
|
|
1289
1289
|
/**
|
|
1290
1290
|
The length of a full cursor blink cycle, in milliseconds.
|
|
1291
1291
|
Defaults to 1200. Can be set to 0 to disable blinking.
|
|
@@ -1751,7 +1751,7 @@ invalidate the existing tooltip positions.
|
|
|
1751
1751
|
*/
|
|
1752
1752
|
declare function repositionTooltips(view: EditorView): void;
|
|
1753
1753
|
|
|
1754
|
-
|
|
1754
|
+
type PanelConfig = {
|
|
1755
1755
|
/**
|
|
1756
1756
|
By default, panels will be placed inside the editor's DOM
|
|
1757
1757
|
structure. You can use this option to override where panels with
|
|
@@ -1805,7 +1805,7 @@ declare function getPanel(view: EditorView, panel: PanelConstructor): Panel | nu
|
|
|
1805
1805
|
A function that initializes a panel. Used in
|
|
1806
1806
|
[`showPanel`](https://codemirror.net/6/docs/ref/#view.showPanel).
|
|
1807
1807
|
*/
|
|
1808
|
-
|
|
1808
|
+
type PanelConstructor = (view: EditorView) => Panel;
|
|
1809
1809
|
/**
|
|
1810
1810
|
Opening a panel is done by providing a constructor function for
|
|
1811
1811
|
the panel through this facet. (The panel is closed again when its
|
|
@@ -1846,7 +1846,7 @@ Markers given to this facet should _only_ define an
|
|
|
1846
1846
|
in all gutters for the line).
|
|
1847
1847
|
*/
|
|
1848
1848
|
declare const gutterLineClass: Facet<RangeSet<GutterMarker>, readonly RangeSet<GutterMarker>[]>;
|
|
1849
|
-
|
|
1849
|
+
type Handlers = {
|
|
1850
1850
|
[event: string]: (view: EditorView, line: BlockInfo, event: Event) => boolean;
|
|
1851
1851
|
};
|
|
1852
1852
|
interface GutterConfig {
|
package/dist/index.js
CHANGED
|
@@ -818,6 +818,9 @@ function textCoords(text, pos, side) {
|
|
|
818
818
|
}
|
|
819
819
|
// Also used for collapsed ranges that don't have a placeholder widget!
|
|
820
820
|
class WidgetView extends ContentView {
|
|
821
|
+
static create(widget, length, side) {
|
|
822
|
+
return new (widget.customView || WidgetView)(widget, length, side);
|
|
823
|
+
}
|
|
821
824
|
constructor(widget, length, side) {
|
|
822
825
|
super();
|
|
823
826
|
this.widget = widget;
|
|
@@ -825,9 +828,6 @@ class WidgetView extends ContentView {
|
|
|
825
828
|
this.side = side;
|
|
826
829
|
this.prevWidget = null;
|
|
827
830
|
}
|
|
828
|
-
static create(widget, length, side) {
|
|
829
|
-
return new (widget.customView || WidgetView)(widget, length, side);
|
|
830
|
-
}
|
|
831
831
|
split(from) {
|
|
832
832
|
let result = WidgetView.create(this.widget, this.length - from, this.side);
|
|
833
833
|
this.length -= from;
|
|
@@ -1642,7 +1642,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1642
1642
|
}
|
|
1643
1643
|
domBoundsAround() { return null; }
|
|
1644
1644
|
become(other) {
|
|
1645
|
-
if (other instanceof BlockWidgetView &&
|
|
1645
|
+
if (other instanceof BlockWidgetView &&
|
|
1646
1646
|
other.widget.constructor == this.widget.constructor) {
|
|
1647
1647
|
if (!other.widget.compare(this.widget))
|
|
1648
1648
|
this.markDirty(true);
|
|
@@ -1650,6 +1650,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1650
1650
|
this.prevWidget = this.widget;
|
|
1651
1651
|
this.widget = other.widget;
|
|
1652
1652
|
this.length = other.length;
|
|
1653
|
+
this.type = other.type;
|
|
1653
1654
|
this.breakAfter = other.breakAfter;
|
|
1654
1655
|
return true;
|
|
1655
1656
|
}
|
|
@@ -2209,6 +2210,10 @@ Represents a contiguous range of text that has a single direction
|
|
|
2209
2210
|
(as in left-to-right or right-to-left).
|
|
2210
2211
|
*/
|
|
2211
2212
|
class BidiSpan {
|
|
2213
|
+
/**
|
|
2214
|
+
The direction of this span.
|
|
2215
|
+
*/
|
|
2216
|
+
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2212
2217
|
/**
|
|
2213
2218
|
@internal
|
|
2214
2219
|
*/
|
|
@@ -2234,10 +2239,6 @@ class BidiSpan {
|
|
|
2234
2239
|
this.level = level;
|
|
2235
2240
|
}
|
|
2236
2241
|
/**
|
|
2237
|
-
The direction of this span.
|
|
2238
|
-
*/
|
|
2239
|
-
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2240
|
-
/**
|
|
2241
2242
|
@internal
|
|
2242
2243
|
*/
|
|
2243
2244
|
side(end, dir) { return (this.dir == dir) == end ? this.to : this.from; }
|
|
@@ -2489,6 +2490,7 @@ class DOMReader {
|
|
|
2489
2490
|
let parent = start.parentNode;
|
|
2490
2491
|
for (let cur = start;;) {
|
|
2491
2492
|
this.findPointBefore(parent, cur);
|
|
2493
|
+
let oldLen = this.text.length;
|
|
2492
2494
|
this.readNode(cur);
|
|
2493
2495
|
let next = cur.nextSibling;
|
|
2494
2496
|
if (next == end)
|
|
@@ -2496,7 +2498,7 @@ class DOMReader {
|
|
|
2496
2498
|
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
2497
2499
|
if (view && nextView ? view.breakAfter :
|
|
2498
2500
|
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
2499
|
-
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore)))
|
|
2501
|
+
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
2500
2502
|
this.lineBreak();
|
|
2501
2503
|
cur = next;
|
|
2502
2504
|
}
|
|
@@ -2577,6 +2579,7 @@ class DOMPoint {
|
|
|
2577
2579
|
}
|
|
2578
2580
|
|
|
2579
2581
|
class DocView extends ContentView {
|
|
2582
|
+
get length() { return this.view.state.doc.length; }
|
|
2580
2583
|
constructor(view) {
|
|
2581
2584
|
super();
|
|
2582
2585
|
this.view = view;
|
|
@@ -2607,7 +2610,6 @@ class DocView extends ContentView {
|
|
|
2607
2610
|
this.updateDeco();
|
|
2608
2611
|
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
|
|
2609
2612
|
}
|
|
2610
|
-
get length() { return this.view.state.doc.length; }
|
|
2611
2613
|
// Update the document view to a given state. scrollIntoView can be
|
|
2612
2614
|
// used as a hint to compute a new viewport that includes that
|
|
2613
2615
|
// position, if we know the editor is going to scroll that position
|
|
@@ -3445,15 +3447,15 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3445
3447
|
return EditorSelection.cursor(pos, start.assoc, undefined, goal);
|
|
3446
3448
|
}
|
|
3447
3449
|
}
|
|
3448
|
-
function
|
|
3449
|
-
let atoms = view.state.facet(atomicRanges).map(f => f(view));
|
|
3450
|
+
function skipAtomicRanges(atoms, pos, bias) {
|
|
3450
3451
|
for (;;) {
|
|
3451
|
-
let moved =
|
|
3452
|
+
let moved = 0;
|
|
3452
3453
|
for (let set of atoms) {
|
|
3453
|
-
set.between(pos
|
|
3454
|
-
if (pos
|
|
3455
|
-
|
|
3456
|
-
|
|
3454
|
+
set.between(pos - 1, pos + 1, (from, to, value) => {
|
|
3455
|
+
if (pos > from && pos < to) {
|
|
3456
|
+
let side = moved || bias || (pos - from < to - pos ? -1 : 1);
|
|
3457
|
+
pos = side < 0 ? from : to;
|
|
3458
|
+
moved = side;
|
|
3457
3459
|
}
|
|
3458
3460
|
});
|
|
3459
3461
|
}
|
|
@@ -3461,9 +3463,17 @@ function skipAtoms(view, oldPos, pos) {
|
|
|
3461
3463
|
return pos;
|
|
3462
3464
|
}
|
|
3463
3465
|
}
|
|
3466
|
+
function skipAtoms(view, oldPos, pos) {
|
|
3467
|
+
let newPos = skipAtomicRanges(view.state.facet(atomicRanges).map(f => f(view)), pos.from, oldPos.head > pos.from ? -1 : 1);
|
|
3468
|
+
return newPos == pos.from ? pos : EditorSelection.cursor(newPos, newPos < pos.from ? 1 : -1);
|
|
3469
|
+
}
|
|
3464
3470
|
|
|
3465
3471
|
// This will also be where dragging info and such goes
|
|
3466
3472
|
class InputState {
|
|
3473
|
+
setSelectionOrigin(origin) {
|
|
3474
|
+
this.lastSelectionOrigin = origin;
|
|
3475
|
+
this.lastSelectionTime = Date.now();
|
|
3476
|
+
}
|
|
3467
3477
|
constructor(view) {
|
|
3468
3478
|
this.lastKeyCode = 0;
|
|
3469
3479
|
this.lastKeyTime = 0;
|
|
@@ -3560,10 +3570,6 @@ class InputState {
|
|
|
3560
3570
|
if (browser.safari)
|
|
3561
3571
|
view.contentDOM.addEventListener("input", () => null);
|
|
3562
3572
|
}
|
|
3563
|
-
setSelectionOrigin(origin) {
|
|
3564
|
-
this.lastSelectionOrigin = origin;
|
|
3565
|
-
this.lastSelectionTime = Date.now();
|
|
3566
|
-
}
|
|
3567
3573
|
ensureHandlers(view, plugins) {
|
|
3568
3574
|
var _a;
|
|
3569
3575
|
let handlers;
|
|
@@ -3710,6 +3716,7 @@ class MouseSelection {
|
|
|
3710
3716
|
this.scrolling = -1;
|
|
3711
3717
|
this.lastEvent = startEvent;
|
|
3712
3718
|
this.scrollParent = scrollableParent(view.contentDOM);
|
|
3719
|
+
this.atoms = view.state.facet(atomicRanges).map(f => f(view));
|
|
3713
3720
|
let doc = view.contentDOM.ownerDocument;
|
|
3714
3721
|
doc.addEventListener("mousemove", this.move = this.move.bind(this));
|
|
3715
3722
|
doc.addEventListener("mouseup", this.up = this.up.bind(this));
|
|
@@ -3783,10 +3790,33 @@ class MouseSelection {
|
|
|
3783
3790
|
if (this.dragging === false)
|
|
3784
3791
|
this.select(this.lastEvent);
|
|
3785
3792
|
}
|
|
3793
|
+
skipAtoms(sel) {
|
|
3794
|
+
let ranges = null;
|
|
3795
|
+
for (let i = 0; i < sel.ranges.length; i++) {
|
|
3796
|
+
let range = sel.ranges[i], updated = null;
|
|
3797
|
+
if (range.empty) {
|
|
3798
|
+
let pos = skipAtomicRanges(this.atoms, range.from, 0);
|
|
3799
|
+
if (pos != range.from)
|
|
3800
|
+
updated = EditorSelection.cursor(pos, -1);
|
|
3801
|
+
}
|
|
3802
|
+
else {
|
|
3803
|
+
let from = skipAtomicRanges(this.atoms, range.from, -1);
|
|
3804
|
+
let to = skipAtomicRanges(this.atoms, range.to, 1);
|
|
3805
|
+
if (from != range.from || to != range.to)
|
|
3806
|
+
updated = EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to);
|
|
3807
|
+
}
|
|
3808
|
+
if (updated) {
|
|
3809
|
+
if (!ranges)
|
|
3810
|
+
ranges = sel.ranges.slice();
|
|
3811
|
+
ranges[i] = updated;
|
|
3812
|
+
}
|
|
3813
|
+
}
|
|
3814
|
+
return ranges ? EditorSelection.create(ranges, sel.mainIndex) : sel;
|
|
3815
|
+
}
|
|
3786
3816
|
select(event) {
|
|
3787
|
-
let selection = this.style.get(event, this.extend, this.multiple);
|
|
3788
|
-
if (this.mustSelect || !selection.eq(
|
|
3789
|
-
selection.main.assoc !=
|
|
3817
|
+
let { view } = this, selection = this.skipAtoms(this.style.get(event, this.extend, this.multiple));
|
|
3818
|
+
if (this.mustSelect || !selection.eq(view.state.selection) ||
|
|
3819
|
+
selection.main.assoc != view.state.selection.main.assoc)
|
|
3790
3820
|
this.view.dispatch({
|
|
3791
3821
|
selection,
|
|
3792
3822
|
userEvent: "select.pointer"
|
|
@@ -6462,6 +6492,53 @@ line number gutter. It handles events and dispatches state
|
|
|
6462
6492
|
transactions for editing actions.
|
|
6463
6493
|
*/
|
|
6464
6494
|
class EditorView {
|
|
6495
|
+
/**
|
|
6496
|
+
The current editor state.
|
|
6497
|
+
*/
|
|
6498
|
+
get state() { return this.viewState.state; }
|
|
6499
|
+
/**
|
|
6500
|
+
To be able to display large documents without consuming too much
|
|
6501
|
+
memory or overloading the browser, CodeMirror only draws the
|
|
6502
|
+
code that is visible (plus a margin around it) to the DOM. This
|
|
6503
|
+
property tells you the extent of the current drawn viewport, in
|
|
6504
|
+
document positions.
|
|
6505
|
+
*/
|
|
6506
|
+
get viewport() { return this.viewState.viewport; }
|
|
6507
|
+
/**
|
|
6508
|
+
When there are, for example, large collapsed ranges in the
|
|
6509
|
+
viewport, its size can be a lot bigger than the actual visible
|
|
6510
|
+
content. Thus, if you are doing something like styling the
|
|
6511
|
+
content in the viewport, it is preferable to only do so for
|
|
6512
|
+
these ranges, which are the subset of the viewport that is
|
|
6513
|
+
actually drawn.
|
|
6514
|
+
*/
|
|
6515
|
+
get visibleRanges() { return this.viewState.visibleRanges; }
|
|
6516
|
+
/**
|
|
6517
|
+
Returns false when the editor is entirely scrolled out of view
|
|
6518
|
+
or otherwise hidden.
|
|
6519
|
+
*/
|
|
6520
|
+
get inView() { return this.viewState.inView; }
|
|
6521
|
+
/**
|
|
6522
|
+
Indicates whether the user is currently composing text via
|
|
6523
|
+
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
6524
|
+
one change has been made in the current composition.
|
|
6525
|
+
*/
|
|
6526
|
+
get composing() { return this.inputState.composing > 0; }
|
|
6527
|
+
/**
|
|
6528
|
+
Indicates whether the user is currently in composing state. Note
|
|
6529
|
+
that on some platforms, like Android, this will be the case a
|
|
6530
|
+
lot, since just putting the cursor on a word starts a
|
|
6531
|
+
composition there.
|
|
6532
|
+
*/
|
|
6533
|
+
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
6534
|
+
/**
|
|
6535
|
+
The document or shadow root that the view lives in.
|
|
6536
|
+
*/
|
|
6537
|
+
get root() { return this._root; }
|
|
6538
|
+
/**
|
|
6539
|
+
@internal
|
|
6540
|
+
*/
|
|
6541
|
+
get win() { return this.dom.ownerDocument.defaultView || window; }
|
|
6465
6542
|
/**
|
|
6466
6543
|
Construct a new view. You'll want to either provide a `parent`
|
|
6467
6544
|
option, or put `view.dom` into your document after creating a
|
|
@@ -6515,56 +6592,10 @@ class EditorView {
|
|
|
6515
6592
|
if (config.parent)
|
|
6516
6593
|
config.parent.appendChild(this.dom);
|
|
6517
6594
|
}
|
|
6518
|
-
/**
|
|
6519
|
-
The current editor state.
|
|
6520
|
-
*/
|
|
6521
|
-
get state() { return this.viewState.state; }
|
|
6522
|
-
/**
|
|
6523
|
-
To be able to display large documents without consuming too much
|
|
6524
|
-
memory or overloading the browser, CodeMirror only draws the
|
|
6525
|
-
code that is visible (plus a margin around it) to the DOM. This
|
|
6526
|
-
property tells you the extent of the current drawn viewport, in
|
|
6527
|
-
document positions.
|
|
6528
|
-
*/
|
|
6529
|
-
get viewport() { return this.viewState.viewport; }
|
|
6530
|
-
/**
|
|
6531
|
-
When there are, for example, large collapsed ranges in the
|
|
6532
|
-
viewport, its size can be a lot bigger than the actual visible
|
|
6533
|
-
content. Thus, if you are doing something like styling the
|
|
6534
|
-
content in the viewport, it is preferable to only do so for
|
|
6535
|
-
these ranges, which are the subset of the viewport that is
|
|
6536
|
-
actually drawn.
|
|
6537
|
-
*/
|
|
6538
|
-
get visibleRanges() { return this.viewState.visibleRanges; }
|
|
6539
|
-
/**
|
|
6540
|
-
Returns false when the editor is entirely scrolled out of view
|
|
6541
|
-
or otherwise hidden.
|
|
6542
|
-
*/
|
|
6543
|
-
get inView() { return this.viewState.inView; }
|
|
6544
|
-
/**
|
|
6545
|
-
Indicates whether the user is currently composing text via
|
|
6546
|
-
[IME](https://en.wikipedia.org/wiki/Input_method), and at least
|
|
6547
|
-
one change has been made in the current composition.
|
|
6548
|
-
*/
|
|
6549
|
-
get composing() { return this.inputState.composing > 0; }
|
|
6550
|
-
/**
|
|
6551
|
-
Indicates whether the user is currently in composing state. Note
|
|
6552
|
-
that on some platforms, like Android, this will be the case a
|
|
6553
|
-
lot, since just putting the cursor on a word starts a
|
|
6554
|
-
composition there.
|
|
6555
|
-
*/
|
|
6556
|
-
get compositionStarted() { return this.inputState.composing >= 0; }
|
|
6557
|
-
/**
|
|
6558
|
-
The document or shadow root that the view lives in.
|
|
6559
|
-
*/
|
|
6560
|
-
get root() { return this._root; }
|
|
6561
|
-
/**
|
|
6562
|
-
@internal
|
|
6563
|
-
*/
|
|
6564
|
-
get win() { return this.dom.ownerDocument.defaultView || window; }
|
|
6565
6595
|
dispatch(...input) {
|
|
6566
|
-
|
|
6567
|
-
: this.state.update(...input)
|
|
6596
|
+
let tr = input.length == 1 && input[0] instanceof Transaction ? input[0]
|
|
6597
|
+
: this.state.update(...input);
|
|
6598
|
+
this._dispatch(tr, this);
|
|
6568
6599
|
}
|
|
6569
6600
|
/**
|
|
6570
6601
|
Update the view for the given array of transactions. This will
|
|
@@ -7711,7 +7742,7 @@ function rectanglesForRange(view, className, range) {
|
|
|
7711
7742
|
let top = visualStart ? drawForLine(range.from, null, visualStart) : drawForWidget(startBlock, false);
|
|
7712
7743
|
let bottom = visualEnd ? drawForLine(null, range.to, visualEnd) : drawForWidget(endBlock, true);
|
|
7713
7744
|
let between = [];
|
|
7714
|
-
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - 1)
|
|
7745
|
+
if ((visualStart || startBlock).to < (visualEnd || endBlock).from - (visualStart && visualEnd ? 1 : 0))
|
|
7715
7746
|
between.push(piece(leftSide, top.bottom, rightSide, bottom.top));
|
|
7716
7747
|
else if (top.bottom < bottom.top && view.elementAtHeight((top.bottom + bottom.top) / 2).type == BlockType.Text)
|
|
7717
7748
|
top.bottom = bottom.top = (top.bottom + bottom.top) / 2;
|
|
@@ -8869,6 +8900,10 @@ const showTooltip = /*@__PURE__*/Facet.define({
|
|
|
8869
8900
|
});
|
|
8870
8901
|
const showHoverTooltip = /*@__PURE__*/Facet.define();
|
|
8871
8902
|
class HoverTooltipHost {
|
|
8903
|
+
// Needs to be static so that host tooltip instances always match
|
|
8904
|
+
static create(view) {
|
|
8905
|
+
return new HoverTooltipHost(view);
|
|
8906
|
+
}
|
|
8872
8907
|
constructor(view) {
|
|
8873
8908
|
this.view = view;
|
|
8874
8909
|
this.mounted = false;
|
|
@@ -8876,10 +8911,6 @@ class HoverTooltipHost {
|
|
|
8876
8911
|
this.dom.classList.add("cm-tooltip-hover");
|
|
8877
8912
|
this.manager = new TooltipViewManager(view, showHoverTooltip, t => this.createHostedView(t));
|
|
8878
8913
|
}
|
|
8879
|
-
// Needs to be static so that host tooltip instances always match
|
|
8880
|
-
static create(view) {
|
|
8881
|
-
return new HoverTooltipHost(view);
|
|
8882
|
-
}
|
|
8883
8914
|
createHostedView(tooltip) {
|
|
8884
8915
|
let hostedView = tooltip.create(this.view);
|
|
8885
8916
|
hostedView.dom.classList.add("cm-tooltip-section");
|