@codemirror/view 0.19.33 → 0.19.37
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 +32 -0
- package/dist/index.cjs +65 -41
- package/dist/index.d.ts +16 -10
- package/dist/index.js +65 -41
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
## 0.19.37 (2021-12-22)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix regression where plugin replacing decorations that span to the end of the line are ignored.
|
|
6
|
+
|
|
7
|
+
## 0.19.36 (2021-12-22)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Fix a crash in `posAtCoords` when the position lies in a block widget that is rendered but scrolled out of view.
|
|
12
|
+
|
|
13
|
+
Adding block decorations from a plugin now raises an error. Replacing decorations that cross lines are ignored, when provided by a plugin.
|
|
14
|
+
|
|
15
|
+
Fix inverted interpretation of the `precise` argument to `posAtCoords`.
|
|
16
|
+
|
|
17
|
+
## 0.19.35 (2021-12-20)
|
|
18
|
+
|
|
19
|
+
### Bug fixes
|
|
20
|
+
|
|
21
|
+
The editor will now handle double-taps as if they are double-clicks, rather than letting the browser's native behavior happen (because the latter often does the wrong thing).
|
|
22
|
+
|
|
23
|
+
Fix an issue where backspacing out a selection on Chrome Android would sometimes only delete the last character due to event order issues.
|
|
24
|
+
|
|
25
|
+
`posAtCoords`, without second argument, will no longer return null for positions below or above the document.
|
|
26
|
+
|
|
27
|
+
## 0.19.34 (2021-12-17)
|
|
28
|
+
|
|
29
|
+
### Bug fixes
|
|
30
|
+
|
|
31
|
+
Fix a bug where content line elements would in some cases lose their `cm-line` class. Move test to scrollIntoView
|
|
32
|
+
|
|
1
33
|
## 0.19.33 (2021-12-16)
|
|
2
34
|
|
|
3
35
|
### Breaking changes
|
package/dist/index.cjs
CHANGED
|
@@ -1331,6 +1331,7 @@ class LineView extends ContentView {
|
|
|
1331
1331
|
}
|
|
1332
1332
|
else if (this.dirty & 4 /* Attrs */) {
|
|
1333
1333
|
clearAttributes(this.dom);
|
|
1334
|
+
this.dom.className = "cm-line";
|
|
1334
1335
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
1335
1336
|
}
|
|
1336
1337
|
if (this.prevAttrs !== undefined) {
|
|
@@ -1371,16 +1372,17 @@ class LineView extends ContentView {
|
|
|
1371
1372
|
become(_other) { return false; }
|
|
1372
1373
|
get type() { return exports.BlockType.Text; }
|
|
1373
1374
|
static find(docView, pos) {
|
|
1374
|
-
for (let i = 0, off = 0
|
|
1375
|
+
for (let i = 0, off = 0; i < docView.children.length; i++) {
|
|
1375
1376
|
let block = docView.children[i], end = off + block.length;
|
|
1376
1377
|
if (end >= pos) {
|
|
1377
1378
|
if (block instanceof LineView)
|
|
1378
1379
|
return block;
|
|
1379
|
-
if (
|
|
1380
|
-
|
|
1380
|
+
if (end > pos)
|
|
1381
|
+
break;
|
|
1381
1382
|
}
|
|
1382
1383
|
off = end + block.breakAfter;
|
|
1383
1384
|
}
|
|
1385
|
+
return null;
|
|
1384
1386
|
}
|
|
1385
1387
|
}
|
|
1386
1388
|
class BlockWidgetView extends ContentView {
|
|
@@ -1441,10 +1443,11 @@ class BlockWidgetView extends ContentView {
|
|
|
1441
1443
|
}
|
|
1442
1444
|
|
|
1443
1445
|
class ContentBuilder {
|
|
1444
|
-
constructor(doc, pos, end) {
|
|
1446
|
+
constructor(doc, pos, end, disallowBlockEffectsBelow) {
|
|
1445
1447
|
this.doc = doc;
|
|
1446
1448
|
this.pos = pos;
|
|
1447
1449
|
this.end = end;
|
|
1450
|
+
this.disallowBlockEffectsBelow = disallowBlockEffectsBelow;
|
|
1448
1451
|
this.content = [];
|
|
1449
1452
|
this.curLine = null;
|
|
1450
1453
|
this.breakAtStart = 0;
|
|
@@ -1573,8 +1576,15 @@ class ContentBuilder {
|
|
|
1573
1576
|
if (this.openStart < 0)
|
|
1574
1577
|
this.openStart = openStart;
|
|
1575
1578
|
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1579
|
+
filterPoint(from, to, value, index) {
|
|
1580
|
+
if (index >= this.disallowBlockEffectsBelow || !(value instanceof PointDecoration))
|
|
1581
|
+
return true;
|
|
1582
|
+
if (value.block)
|
|
1583
|
+
throw new RangeError("Block decorations may not be specified via plugins");
|
|
1584
|
+
return to <= this.doc.lineAt(this.pos).to;
|
|
1585
|
+
}
|
|
1586
|
+
static build(text, from, to, decorations, pluginDecorationLength) {
|
|
1587
|
+
let builder = new ContentBuilder(text, from, to, pluginDecorationLength);
|
|
1578
1588
|
builder.openEnd = rangeset.RangeSet.spans(decorations, from, to, builder);
|
|
1579
1589
|
if (builder.openStart < 0)
|
|
1580
1590
|
builder.openStart = builder.openEnd;
|
|
@@ -1697,11 +1707,13 @@ This field can be used by plugins to provide
|
|
|
1697
1707
|
**Note**: For reasons of data flow (plugins are only updated
|
|
1698
1708
|
after the viewport is computed), decorations produced by plugins
|
|
1699
1709
|
are _not_ taken into account when predicting the vertical layout
|
|
1700
|
-
structure of the editor.
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1710
|
+
structure of the editor. They **must not** introduce block
|
|
1711
|
+
widgets (that will raise an error) or replacing decorations that
|
|
1712
|
+
cover line breaks (these will be ignored if they occur). Such
|
|
1713
|
+
decorations, or others that cause a large amount of vertical
|
|
1714
|
+
size shift compared to the undecorated content, should be
|
|
1715
|
+
provided through the state-level [`decorations`
|
|
1716
|
+
facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations) instead.
|
|
1705
1717
|
*/
|
|
1706
1718
|
PluginField.decorations = PluginField.define();
|
|
1707
1719
|
/**
|
|
@@ -1934,8 +1946,6 @@ class ViewUpdate {
|
|
|
1934
1946
|
view.inputState.notifiedFocused = focus;
|
|
1935
1947
|
this.flags |= 1 /* Focus */;
|
|
1936
1948
|
}
|
|
1937
|
-
if (this.docChanged)
|
|
1938
|
-
this.flags |= 2 /* Height */;
|
|
1939
1949
|
}
|
|
1940
1950
|
/**
|
|
1941
1951
|
Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
|
|
@@ -1946,14 +1956,15 @@ class ViewUpdate {
|
|
|
1946
1956
|
return (this.flags & 4 /* Viewport */) > 0;
|
|
1947
1957
|
}
|
|
1948
1958
|
/**
|
|
1949
|
-
Indicates whether the
|
|
1959
|
+
Indicates whether the height of an element in the editor changed
|
|
1960
|
+
in this update.
|
|
1950
1961
|
*/
|
|
1951
1962
|
get heightChanged() {
|
|
1952
1963
|
return (this.flags & 2 /* Height */) > 0;
|
|
1953
1964
|
}
|
|
1954
1965
|
/**
|
|
1955
|
-
Returns true when the document
|
|
1956
|
-
|
|
1966
|
+
Returns true when the document was modified or the size of the
|
|
1967
|
+
editor, or elements within the editor, changed.
|
|
1957
1968
|
*/
|
|
1958
1969
|
get geometryChanged() {
|
|
1959
1970
|
return this.docChanged || (this.flags & (8 /* Geometry */ | 2 /* Height */)) > 0;
|
|
@@ -2372,6 +2383,7 @@ class DocView extends ContentView {
|
|
|
2372
2383
|
this.view = view;
|
|
2373
2384
|
this.compositionDeco = Decoration.none;
|
|
2374
2385
|
this.decorations = [];
|
|
2386
|
+
this.pluginDecorationLength = 0;
|
|
2375
2387
|
// Track a minimum width for the editor. When measuring sizes in
|
|
2376
2388
|
// measureVisibleLineHeights, this is updated to point at the width
|
|
2377
2389
|
// of a given element and its extent in the document. When a change
|
|
@@ -2393,7 +2405,8 @@ class DocView extends ContentView {
|
|
|
2393
2405
|
this.setDOM(view.contentDOM);
|
|
2394
2406
|
this.children = [new LineView];
|
|
2395
2407
|
this.children[0].setParent(this);
|
|
2396
|
-
this.
|
|
2408
|
+
this.updateDeco();
|
|
2409
|
+
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
|
|
2397
2410
|
}
|
|
2398
2411
|
get root() { return this.view.root; }
|
|
2399
2412
|
get editorView() { return this.view; }
|
|
@@ -2432,7 +2445,7 @@ class DocView extends ContentView {
|
|
|
2432
2445
|
return false;
|
|
2433
2446
|
}
|
|
2434
2447
|
else {
|
|
2435
|
-
this.updateInner(changedRanges,
|
|
2448
|
+
this.updateInner(changedRanges, update.startState.doc.length);
|
|
2436
2449
|
if (update.transactions.length)
|
|
2437
2450
|
this.lastUpdate = Date.now();
|
|
2438
2451
|
return true;
|
|
@@ -2440,9 +2453,9 @@ class DocView extends ContentView {
|
|
|
2440
2453
|
}
|
|
2441
2454
|
// Used by update and the constructor do perform the actual DOM
|
|
2442
2455
|
// update
|
|
2443
|
-
updateInner(changes,
|
|
2456
|
+
updateInner(changes, oldLength) {
|
|
2444
2457
|
this.view.viewState.mustMeasureContent = true;
|
|
2445
|
-
this.updateChildren(changes,
|
|
2458
|
+
this.updateChildren(changes, oldLength);
|
|
2446
2459
|
let { observer } = this.view;
|
|
2447
2460
|
observer.ignore(() => {
|
|
2448
2461
|
// Lock the height during redrawing, since Chrome sometimes
|
|
@@ -2469,14 +2482,14 @@ class DocView extends ContentView {
|
|
|
2469
2482
|
gaps.push(child.dom);
|
|
2470
2483
|
observer.updateGaps(gaps);
|
|
2471
2484
|
}
|
|
2472
|
-
updateChildren(changes,
|
|
2485
|
+
updateChildren(changes, oldLength) {
|
|
2473
2486
|
let cursor = this.childCursor(oldLength);
|
|
2474
2487
|
for (let i = changes.length - 1;; i--) {
|
|
2475
2488
|
let next = i >= 0 ? changes[i] : null;
|
|
2476
2489
|
if (!next)
|
|
2477
2490
|
break;
|
|
2478
2491
|
let { fromA, toA, fromB, toB } = next;
|
|
2479
|
-
let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB,
|
|
2492
|
+
let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, this.decorations, this.pluginDecorationLength);
|
|
2480
2493
|
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2481
2494
|
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2482
2495
|
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
@@ -2695,8 +2708,10 @@ class DocView extends ContentView {
|
|
|
2695
2708
|
return Decoration.set(deco);
|
|
2696
2709
|
}
|
|
2697
2710
|
updateDeco() {
|
|
2711
|
+
let pluginDecorations = this.view.pluginField(PluginField.decorations);
|
|
2712
|
+
this.pluginDecorationLength = pluginDecorations.length;
|
|
2698
2713
|
return this.decorations = [
|
|
2699
|
-
...
|
|
2714
|
+
...pluginDecorations,
|
|
2700
2715
|
...this.view.state.facet(decorations),
|
|
2701
2716
|
this.compositionDeco,
|
|
2702
2717
|
this.computeBlockGapDeco(),
|
|
@@ -2989,12 +3004,8 @@ function domPosInText(node, x, y) {
|
|
|
2989
3004
|
function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
2990
3005
|
var _a;
|
|
2991
3006
|
let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
|
|
2992
|
-
let block,
|
|
2993
|
-
|
|
2994
|
-
if (precise)
|
|
2995
|
-
return null;
|
|
2996
|
-
yOffset = yOffset < 0 ? 0 : docHeight;
|
|
2997
|
-
}
|
|
3007
|
+
let block, { docHeight } = view.viewState;
|
|
3008
|
+
let yOffset = Math.max(0, Math.min(y - docTop, docHeight));
|
|
2998
3009
|
// Scan for a text block near the queried y position
|
|
2999
3010
|
for (let halfLine = view.defaultLineHeight / 2, bounced = false;;) {
|
|
3000
3011
|
block = view.elementAtHeight(yOffset);
|
|
@@ -3015,20 +3026,29 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3015
3026
|
}
|
|
3016
3027
|
y = docTop + yOffset;
|
|
3017
3028
|
let lineStart = block.from;
|
|
3018
|
-
// Clip x to the viewport sides
|
|
3019
|
-
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
3020
3029
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
3021
3030
|
if (lineStart < view.viewport.from)
|
|
3022
|
-
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
3031
|
+
return view.viewport.from == 0 ? 0 : precise ? null : posAtCoordsImprecise(view, content, block, x, y);
|
|
3023
3032
|
if (lineStart > view.viewport.to)
|
|
3024
|
-
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3033
|
+
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3034
|
+
precise ? null : posAtCoordsImprecise(view, content, block, x, y);
|
|
3025
3035
|
// Prefer ShadowRootOrDocument.elementFromPoint if present, fall back to document if not
|
|
3026
3036
|
let doc = view.dom.ownerDocument;
|
|
3027
|
-
let
|
|
3037
|
+
let root = view.root.elementFromPoint ? view.root : doc;
|
|
3038
|
+
let element = root.elementFromPoint(x, y);
|
|
3039
|
+
if (element && !view.contentDOM.contains(element))
|
|
3040
|
+
element = null;
|
|
3041
|
+
// If the element is unexpected, clip x at the sides of the content area and try again
|
|
3042
|
+
if (!element) {
|
|
3043
|
+
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
3044
|
+
element = root.elementFromPoint(x, y);
|
|
3045
|
+
if (element && !view.contentDOM.contains(element))
|
|
3046
|
+
element = null;
|
|
3047
|
+
}
|
|
3028
3048
|
// There's visible editor content under the point, so we can try
|
|
3029
3049
|
// using caret(Position|Range)FromPoint as a shortcut
|
|
3030
3050
|
let node, offset = -1;
|
|
3031
|
-
if (element &&
|
|
3051
|
+
if (element && ((_a = view.docView.nearest(element)) === null || _a === void 0 ? void 0 : _a.isEditable) != false) {
|
|
3032
3052
|
if (doc.caretPositionFromPoint) {
|
|
3033
3053
|
let pos = doc.caretPositionFromPoint(x, y);
|
|
3034
3054
|
if (pos)
|
|
@@ -3046,6 +3066,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3046
3066
|
// No luck, do our own (potentially expensive) search
|
|
3047
3067
|
if (!node || !view.docView.dom.contains(node)) {
|
|
3048
3068
|
let line = LineView.find(view.docView, lineStart);
|
|
3069
|
+
if (!line)
|
|
3070
|
+
return yOffset > block.top + block.height / 2 ? block.to : block.from;
|
|
3049
3071
|
({ node, offset } = domPosAtCoords(line.dom, x, y));
|
|
3050
3072
|
}
|
|
3051
3073
|
return view.docView.posFromDOM(node, offset);
|
|
@@ -3509,7 +3531,7 @@ handlers.touchmove = view => {
|
|
|
3509
3531
|
};
|
|
3510
3532
|
handlers.mousedown = (view, event) => {
|
|
3511
3533
|
view.observer.flush();
|
|
3512
|
-
if (lastTouch > Date.now() - 2000)
|
|
3534
|
+
if (lastTouch > Date.now() - 2000 && getClickType(event) == 1)
|
|
3513
3535
|
return; // Ignore touch interaction
|
|
3514
3536
|
let style = null;
|
|
3515
3537
|
for (let makeStyle of view.state.facet(mouseSelectionStyle)) {
|
|
@@ -3631,9 +3653,9 @@ handlers.dragstart = (view, event) => {
|
|
|
3631
3653
|
}
|
|
3632
3654
|
};
|
|
3633
3655
|
function dropText(view, event, text, direct) {
|
|
3634
|
-
|
|
3635
|
-
if (dropPos == null || !text)
|
|
3656
|
+
if (!text)
|
|
3636
3657
|
return;
|
|
3658
|
+
let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
3637
3659
|
event.preventDefault();
|
|
3638
3660
|
let { mouseSelection } = view.inputState;
|
|
3639
3661
|
let del = direct && mouseSelection && mouseSelection.dragging && mouseSelection.dragMove ?
|
|
@@ -4744,7 +4766,7 @@ class ViewState {
|
|
|
4744
4766
|
let block = map.lineAt(head, QueryType.ByPos, doc, 0, 0), topPos;
|
|
4745
4767
|
if (scrollTarget.y == "center")
|
|
4746
4768
|
topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
|
|
4747
|
-
else if (scrollTarget.y == "start" || head < viewport.from)
|
|
4769
|
+
else if (scrollTarget.y == "start" || scrollTarget.y == "nearest" && head < viewport.from)
|
|
4748
4770
|
topPos = block.top;
|
|
4749
4771
|
else
|
|
4750
4772
|
topPos = block.bottom - viewHeight;
|
|
@@ -5291,8 +5313,10 @@ class DOMObserver {
|
|
|
5291
5313
|
// Deletions on IE11 fire their events in the wrong order, giving
|
|
5292
5314
|
// us a selection change event before the DOM changes are
|
|
5293
5315
|
// reported.
|
|
5294
|
-
//
|
|
5295
|
-
|
|
5316
|
+
// Chrome Android has a similar issue when backspacing out a
|
|
5317
|
+
// selection (#645).
|
|
5318
|
+
if ((browser.ie && browser.ie_version <= 11 || browser.android && browser.chrome) && !view.state.selection.main.empty &&
|
|
5319
|
+
// (Selection.isCollapsed isn't reliable on IE)
|
|
5296
5320
|
sel.focusNode && isEquivalentPosition(sel.focusNode, sel.focusOffset, sel.anchorNode, sel.anchorOffset))
|
|
5297
5321
|
this.flushSoon();
|
|
5298
5322
|
else
|
package/dist/index.d.ts
CHANGED
|
@@ -340,11 +340,13 @@ declare class PluginField<T> {
|
|
|
340
340
|
**Note**: For reasons of data flow (plugins are only updated
|
|
341
341
|
after the viewport is computed), decorations produced by plugins
|
|
342
342
|
are _not_ taken into account when predicting the vertical layout
|
|
343
|
-
structure of the editor.
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
343
|
+
structure of the editor. They **must not** introduce block
|
|
344
|
+
widgets (that will raise an error) or replacing decorations that
|
|
345
|
+
cover line breaks (these will be ignored if they occur). Such
|
|
346
|
+
decorations, or others that cause a large amount of vertical
|
|
347
|
+
size shift compared to the undecorated content, should be
|
|
348
|
+
provided through the state-level [`decorations`
|
|
349
|
+
facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations) instead.
|
|
348
350
|
*/
|
|
349
351
|
static decorations: PluginField<DecorationSet>;
|
|
350
352
|
/**
|
|
@@ -470,12 +472,13 @@ declare class ViewUpdate {
|
|
|
470
472
|
*/
|
|
471
473
|
get viewportChanged(): boolean;
|
|
472
474
|
/**
|
|
473
|
-
Indicates whether the
|
|
475
|
+
Indicates whether the height of an element in the editor changed
|
|
476
|
+
in this update.
|
|
474
477
|
*/
|
|
475
478
|
get heightChanged(): boolean;
|
|
476
479
|
/**
|
|
477
|
-
Returns true when the document
|
|
478
|
-
|
|
480
|
+
Returns true when the document was modified or the size of the
|
|
481
|
+
editor, or elements within the editor, changed.
|
|
479
482
|
*/
|
|
480
483
|
get geometryChanged(): boolean;
|
|
481
484
|
/**
|
|
@@ -937,8 +940,11 @@ declare class EditorView {
|
|
|
937
940
|
*/
|
|
938
941
|
posAtDOM(node: Node, offset?: number): number;
|
|
939
942
|
/**
|
|
940
|
-
Get the document position at the given screen coordinates.
|
|
941
|
-
|
|
943
|
+
Get the document position at the given screen coordinates. For
|
|
944
|
+
positions not covered by the visible viewport's DOM structure,
|
|
945
|
+
this will return null, unless `false` is passed as second
|
|
946
|
+
argument, in which case it'll return an estimated position that
|
|
947
|
+
would be near the coordinates if it were rendered.
|
|
942
948
|
*/
|
|
943
949
|
posAtCoords(coords: {
|
|
944
950
|
x: number;
|
package/dist/index.js
CHANGED
|
@@ -1327,6 +1327,7 @@ class LineView extends ContentView {
|
|
|
1327
1327
|
}
|
|
1328
1328
|
else if (this.dirty & 4 /* Attrs */) {
|
|
1329
1329
|
clearAttributes(this.dom);
|
|
1330
|
+
this.dom.className = "cm-line";
|
|
1330
1331
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
1331
1332
|
}
|
|
1332
1333
|
if (this.prevAttrs !== undefined) {
|
|
@@ -1367,16 +1368,17 @@ class LineView extends ContentView {
|
|
|
1367
1368
|
become(_other) { return false; }
|
|
1368
1369
|
get type() { return BlockType.Text; }
|
|
1369
1370
|
static find(docView, pos) {
|
|
1370
|
-
for (let i = 0, off = 0
|
|
1371
|
+
for (let i = 0, off = 0; i < docView.children.length; i++) {
|
|
1371
1372
|
let block = docView.children[i], end = off + block.length;
|
|
1372
1373
|
if (end >= pos) {
|
|
1373
1374
|
if (block instanceof LineView)
|
|
1374
1375
|
return block;
|
|
1375
|
-
if (
|
|
1376
|
-
|
|
1376
|
+
if (end > pos)
|
|
1377
|
+
break;
|
|
1377
1378
|
}
|
|
1378
1379
|
off = end + block.breakAfter;
|
|
1379
1380
|
}
|
|
1381
|
+
return null;
|
|
1380
1382
|
}
|
|
1381
1383
|
}
|
|
1382
1384
|
class BlockWidgetView extends ContentView {
|
|
@@ -1437,10 +1439,11 @@ class BlockWidgetView extends ContentView {
|
|
|
1437
1439
|
}
|
|
1438
1440
|
|
|
1439
1441
|
class ContentBuilder {
|
|
1440
|
-
constructor(doc, pos, end) {
|
|
1442
|
+
constructor(doc, pos, end, disallowBlockEffectsBelow) {
|
|
1441
1443
|
this.doc = doc;
|
|
1442
1444
|
this.pos = pos;
|
|
1443
1445
|
this.end = end;
|
|
1446
|
+
this.disallowBlockEffectsBelow = disallowBlockEffectsBelow;
|
|
1444
1447
|
this.content = [];
|
|
1445
1448
|
this.curLine = null;
|
|
1446
1449
|
this.breakAtStart = 0;
|
|
@@ -1569,8 +1572,15 @@ class ContentBuilder {
|
|
|
1569
1572
|
if (this.openStart < 0)
|
|
1570
1573
|
this.openStart = openStart;
|
|
1571
1574
|
}
|
|
1572
|
-
|
|
1573
|
-
|
|
1575
|
+
filterPoint(from, to, value, index) {
|
|
1576
|
+
if (index >= this.disallowBlockEffectsBelow || !(value instanceof PointDecoration))
|
|
1577
|
+
return true;
|
|
1578
|
+
if (value.block)
|
|
1579
|
+
throw new RangeError("Block decorations may not be specified via plugins");
|
|
1580
|
+
return to <= this.doc.lineAt(this.pos).to;
|
|
1581
|
+
}
|
|
1582
|
+
static build(text, from, to, decorations, pluginDecorationLength) {
|
|
1583
|
+
let builder = new ContentBuilder(text, from, to, pluginDecorationLength);
|
|
1574
1584
|
builder.openEnd = RangeSet.spans(decorations, from, to, builder);
|
|
1575
1585
|
if (builder.openStart < 0)
|
|
1576
1586
|
builder.openStart = builder.openEnd;
|
|
@@ -1693,11 +1703,13 @@ This field can be used by plugins to provide
|
|
|
1693
1703
|
**Note**: For reasons of data flow (plugins are only updated
|
|
1694
1704
|
after the viewport is computed), decorations produced by plugins
|
|
1695
1705
|
are _not_ taken into account when predicting the vertical layout
|
|
1696
|
-
structure of the editor.
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1706
|
+
structure of the editor. They **must not** introduce block
|
|
1707
|
+
widgets (that will raise an error) or replacing decorations that
|
|
1708
|
+
cover line breaks (these will be ignored if they occur). Such
|
|
1709
|
+
decorations, or others that cause a large amount of vertical
|
|
1710
|
+
size shift compared to the undecorated content, should be
|
|
1711
|
+
provided through the state-level [`decorations`
|
|
1712
|
+
facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations) instead.
|
|
1701
1713
|
*/
|
|
1702
1714
|
PluginField.decorations = /*@__PURE__*/PluginField.define();
|
|
1703
1715
|
/**
|
|
@@ -1930,8 +1942,6 @@ class ViewUpdate {
|
|
|
1930
1942
|
view.inputState.notifiedFocused = focus;
|
|
1931
1943
|
this.flags |= 1 /* Focus */;
|
|
1932
1944
|
}
|
|
1933
|
-
if (this.docChanged)
|
|
1934
|
-
this.flags |= 2 /* Height */;
|
|
1935
1945
|
}
|
|
1936
1946
|
/**
|
|
1937
1947
|
Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
|
|
@@ -1942,14 +1952,15 @@ class ViewUpdate {
|
|
|
1942
1952
|
return (this.flags & 4 /* Viewport */) > 0;
|
|
1943
1953
|
}
|
|
1944
1954
|
/**
|
|
1945
|
-
Indicates whether the
|
|
1955
|
+
Indicates whether the height of an element in the editor changed
|
|
1956
|
+
in this update.
|
|
1946
1957
|
*/
|
|
1947
1958
|
get heightChanged() {
|
|
1948
1959
|
return (this.flags & 2 /* Height */) > 0;
|
|
1949
1960
|
}
|
|
1950
1961
|
/**
|
|
1951
|
-
Returns true when the document
|
|
1952
|
-
|
|
1962
|
+
Returns true when the document was modified or the size of the
|
|
1963
|
+
editor, or elements within the editor, changed.
|
|
1953
1964
|
*/
|
|
1954
1965
|
get geometryChanged() {
|
|
1955
1966
|
return this.docChanged || (this.flags & (8 /* Geometry */ | 2 /* Height */)) > 0;
|
|
@@ -2367,6 +2378,7 @@ class DocView extends ContentView {
|
|
|
2367
2378
|
this.view = view;
|
|
2368
2379
|
this.compositionDeco = Decoration.none;
|
|
2369
2380
|
this.decorations = [];
|
|
2381
|
+
this.pluginDecorationLength = 0;
|
|
2370
2382
|
// Track a minimum width for the editor. When measuring sizes in
|
|
2371
2383
|
// measureVisibleLineHeights, this is updated to point at the width
|
|
2372
2384
|
// of a given element and its extent in the document. When a change
|
|
@@ -2388,7 +2400,8 @@ class DocView extends ContentView {
|
|
|
2388
2400
|
this.setDOM(view.contentDOM);
|
|
2389
2401
|
this.children = [new LineView];
|
|
2390
2402
|
this.children[0].setParent(this);
|
|
2391
|
-
this.
|
|
2403
|
+
this.updateDeco();
|
|
2404
|
+
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
|
|
2392
2405
|
}
|
|
2393
2406
|
get root() { return this.view.root; }
|
|
2394
2407
|
get editorView() { return this.view; }
|
|
@@ -2427,7 +2440,7 @@ class DocView extends ContentView {
|
|
|
2427
2440
|
return false;
|
|
2428
2441
|
}
|
|
2429
2442
|
else {
|
|
2430
|
-
this.updateInner(changedRanges,
|
|
2443
|
+
this.updateInner(changedRanges, update.startState.doc.length);
|
|
2431
2444
|
if (update.transactions.length)
|
|
2432
2445
|
this.lastUpdate = Date.now();
|
|
2433
2446
|
return true;
|
|
@@ -2435,9 +2448,9 @@ class DocView extends ContentView {
|
|
|
2435
2448
|
}
|
|
2436
2449
|
// Used by update and the constructor do perform the actual DOM
|
|
2437
2450
|
// update
|
|
2438
|
-
updateInner(changes,
|
|
2451
|
+
updateInner(changes, oldLength) {
|
|
2439
2452
|
this.view.viewState.mustMeasureContent = true;
|
|
2440
|
-
this.updateChildren(changes,
|
|
2453
|
+
this.updateChildren(changes, oldLength);
|
|
2441
2454
|
let { observer } = this.view;
|
|
2442
2455
|
observer.ignore(() => {
|
|
2443
2456
|
// Lock the height during redrawing, since Chrome sometimes
|
|
@@ -2464,14 +2477,14 @@ class DocView extends ContentView {
|
|
|
2464
2477
|
gaps.push(child.dom);
|
|
2465
2478
|
observer.updateGaps(gaps);
|
|
2466
2479
|
}
|
|
2467
|
-
updateChildren(changes,
|
|
2480
|
+
updateChildren(changes, oldLength) {
|
|
2468
2481
|
let cursor = this.childCursor(oldLength);
|
|
2469
2482
|
for (let i = changes.length - 1;; i--) {
|
|
2470
2483
|
let next = i >= 0 ? changes[i] : null;
|
|
2471
2484
|
if (!next)
|
|
2472
2485
|
break;
|
|
2473
2486
|
let { fromA, toA, fromB, toB } = next;
|
|
2474
|
-
let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB,
|
|
2487
|
+
let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, this.decorations, this.pluginDecorationLength);
|
|
2475
2488
|
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2476
2489
|
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2477
2490
|
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
@@ -2690,8 +2703,10 @@ class DocView extends ContentView {
|
|
|
2690
2703
|
return Decoration.set(deco);
|
|
2691
2704
|
}
|
|
2692
2705
|
updateDeco() {
|
|
2706
|
+
let pluginDecorations = this.view.pluginField(PluginField.decorations);
|
|
2707
|
+
this.pluginDecorationLength = pluginDecorations.length;
|
|
2693
2708
|
return this.decorations = [
|
|
2694
|
-
...
|
|
2709
|
+
...pluginDecorations,
|
|
2695
2710
|
...this.view.state.facet(decorations),
|
|
2696
2711
|
this.compositionDeco,
|
|
2697
2712
|
this.computeBlockGapDeco(),
|
|
@@ -2984,12 +2999,8 @@ function domPosInText(node, x, y) {
|
|
|
2984
2999
|
function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
2985
3000
|
var _a;
|
|
2986
3001
|
let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
|
|
2987
|
-
let block,
|
|
2988
|
-
|
|
2989
|
-
if (precise)
|
|
2990
|
-
return null;
|
|
2991
|
-
yOffset = yOffset < 0 ? 0 : docHeight;
|
|
2992
|
-
}
|
|
3002
|
+
let block, { docHeight } = view.viewState;
|
|
3003
|
+
let yOffset = Math.max(0, Math.min(y - docTop, docHeight));
|
|
2993
3004
|
// Scan for a text block near the queried y position
|
|
2994
3005
|
for (let halfLine = view.defaultLineHeight / 2, bounced = false;;) {
|
|
2995
3006
|
block = view.elementAtHeight(yOffset);
|
|
@@ -3010,20 +3021,29 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3010
3021
|
}
|
|
3011
3022
|
y = docTop + yOffset;
|
|
3012
3023
|
let lineStart = block.from;
|
|
3013
|
-
// Clip x to the viewport sides
|
|
3014
|
-
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
3015
3024
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
3016
3025
|
if (lineStart < view.viewport.from)
|
|
3017
|
-
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
3026
|
+
return view.viewport.from == 0 ? 0 : precise ? null : posAtCoordsImprecise(view, content, block, x, y);
|
|
3018
3027
|
if (lineStart > view.viewport.to)
|
|
3019
|
-
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3028
|
+
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3029
|
+
precise ? null : posAtCoordsImprecise(view, content, block, x, y);
|
|
3020
3030
|
// Prefer ShadowRootOrDocument.elementFromPoint if present, fall back to document if not
|
|
3021
3031
|
let doc = view.dom.ownerDocument;
|
|
3022
|
-
let
|
|
3032
|
+
let root = view.root.elementFromPoint ? view.root : doc;
|
|
3033
|
+
let element = root.elementFromPoint(x, y);
|
|
3034
|
+
if (element && !view.contentDOM.contains(element))
|
|
3035
|
+
element = null;
|
|
3036
|
+
// If the element is unexpected, clip x at the sides of the content area and try again
|
|
3037
|
+
if (!element) {
|
|
3038
|
+
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
3039
|
+
element = root.elementFromPoint(x, y);
|
|
3040
|
+
if (element && !view.contentDOM.contains(element))
|
|
3041
|
+
element = null;
|
|
3042
|
+
}
|
|
3023
3043
|
// There's visible editor content under the point, so we can try
|
|
3024
3044
|
// using caret(Position|Range)FromPoint as a shortcut
|
|
3025
3045
|
let node, offset = -1;
|
|
3026
|
-
if (element &&
|
|
3046
|
+
if (element && ((_a = view.docView.nearest(element)) === null || _a === void 0 ? void 0 : _a.isEditable) != false) {
|
|
3027
3047
|
if (doc.caretPositionFromPoint) {
|
|
3028
3048
|
let pos = doc.caretPositionFromPoint(x, y);
|
|
3029
3049
|
if (pos)
|
|
@@ -3041,6 +3061,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3041
3061
|
// No luck, do our own (potentially expensive) search
|
|
3042
3062
|
if (!node || !view.docView.dom.contains(node)) {
|
|
3043
3063
|
let line = LineView.find(view.docView, lineStart);
|
|
3064
|
+
if (!line)
|
|
3065
|
+
return yOffset > block.top + block.height / 2 ? block.to : block.from;
|
|
3044
3066
|
({ node, offset } = domPosAtCoords(line.dom, x, y));
|
|
3045
3067
|
}
|
|
3046
3068
|
return view.docView.posFromDOM(node, offset);
|
|
@@ -3504,7 +3526,7 @@ handlers.touchmove = view => {
|
|
|
3504
3526
|
};
|
|
3505
3527
|
handlers.mousedown = (view, event) => {
|
|
3506
3528
|
view.observer.flush();
|
|
3507
|
-
if (lastTouch > Date.now() - 2000)
|
|
3529
|
+
if (lastTouch > Date.now() - 2000 && getClickType(event) == 1)
|
|
3508
3530
|
return; // Ignore touch interaction
|
|
3509
3531
|
let style = null;
|
|
3510
3532
|
for (let makeStyle of view.state.facet(mouseSelectionStyle)) {
|
|
@@ -3626,9 +3648,9 @@ handlers.dragstart = (view, event) => {
|
|
|
3626
3648
|
}
|
|
3627
3649
|
};
|
|
3628
3650
|
function dropText(view, event, text, direct) {
|
|
3629
|
-
|
|
3630
|
-
if (dropPos == null || !text)
|
|
3651
|
+
if (!text)
|
|
3631
3652
|
return;
|
|
3653
|
+
let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
3632
3654
|
event.preventDefault();
|
|
3633
3655
|
let { mouseSelection } = view.inputState;
|
|
3634
3656
|
let del = direct && mouseSelection && mouseSelection.dragging && mouseSelection.dragMove ?
|
|
@@ -4738,7 +4760,7 @@ class ViewState {
|
|
|
4738
4760
|
let block = map.lineAt(head, QueryType.ByPos, doc, 0, 0), topPos;
|
|
4739
4761
|
if (scrollTarget.y == "center")
|
|
4740
4762
|
topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
|
|
4741
|
-
else if (scrollTarget.y == "start" || head < viewport.from)
|
|
4763
|
+
else if (scrollTarget.y == "start" || scrollTarget.y == "nearest" && head < viewport.from)
|
|
4742
4764
|
topPos = block.top;
|
|
4743
4765
|
else
|
|
4744
4766
|
topPos = block.bottom - viewHeight;
|
|
@@ -5285,8 +5307,10 @@ class DOMObserver {
|
|
|
5285
5307
|
// Deletions on IE11 fire their events in the wrong order, giving
|
|
5286
5308
|
// us a selection change event before the DOM changes are
|
|
5287
5309
|
// reported.
|
|
5288
|
-
//
|
|
5289
|
-
|
|
5310
|
+
// Chrome Android has a similar issue when backspacing out a
|
|
5311
|
+
// selection (#645).
|
|
5312
|
+
if ((browser.ie && browser.ie_version <= 11 || browser.android && browser.chrome) && !view.state.selection.main.empty &&
|
|
5313
|
+
// (Selection.isCollapsed isn't reliable on IE)
|
|
5290
5314
|
sel.focusNode && isEquivalentPosition(sel.focusNode, sel.focusOffset, sel.anchorNode, sel.anchorOffset))
|
|
5291
5315
|
this.flushSoon();
|
|
5292
5316
|
else
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemirror/view",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.37",
|
|
4
4
|
"description": "DOM view component for the CodeMirror code editor",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "cm-runtests",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"sideEffects": false,
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@codemirror/rangeset": "^0.19.
|
|
29
|
+
"@codemirror/rangeset": "^0.19.5",
|
|
30
30
|
"@codemirror/state": "^0.19.3",
|
|
31
31
|
"@codemirror/text": "^0.19.0",
|
|
32
32
|
"style-mod": "^4.0.0",
|