@codemirror/view 0.19.34 → 0.19.38
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 +36 -0
- package/dist/index.cjs +70 -43
- package/dist/index.d.ts +16 -10
- package/dist/index.js +70 -43
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
## 0.19.38 (2022-01-05)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix a bug that caused line decorations with a `class` property to suppress all other line decorations for that line.
|
|
6
|
+
|
|
7
|
+
Fix a bug that caused scroll effects to be corrupted when further updates came in before they were applied.
|
|
8
|
+
|
|
9
|
+
Fix an issue where, depending on which way a floating point rounding error fell, `posAtCoords` (and thus vertical cursor motion) for positions outside of the vertical range of the document might or might not return the start/end of the document.
|
|
10
|
+
|
|
11
|
+
## 0.19.37 (2021-12-22)
|
|
12
|
+
|
|
13
|
+
### Bug fixes
|
|
14
|
+
|
|
15
|
+
Fix regression where plugin replacing decorations that span to the end of the line are ignored.
|
|
16
|
+
|
|
17
|
+
## 0.19.36 (2021-12-22)
|
|
18
|
+
|
|
19
|
+
### Bug fixes
|
|
20
|
+
|
|
21
|
+
Fix a crash in `posAtCoords` when the position lies in a block widget that is rendered but scrolled out of view.
|
|
22
|
+
|
|
23
|
+
Adding block decorations from a plugin now raises an error. Replacing decorations that cross lines are ignored, when provided by a plugin.
|
|
24
|
+
|
|
25
|
+
Fix inverted interpretation of the `precise` argument to `posAtCoords`.
|
|
26
|
+
|
|
27
|
+
## 0.19.35 (2021-12-20)
|
|
28
|
+
|
|
29
|
+
### Bug fixes
|
|
30
|
+
|
|
31
|
+
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).
|
|
32
|
+
|
|
33
|
+
Fix an issue where backspacing out a selection on Chrome Android would sometimes only delete the last character due to event order issues.
|
|
34
|
+
|
|
35
|
+
`posAtCoords`, without second argument, will no longer return null for positions below or above the document.
|
|
36
|
+
|
|
1
37
|
## 0.19.34 (2021-12-17)
|
|
2
38
|
|
|
3
39
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -1311,7 +1311,7 @@ class LineView extends ContentView {
|
|
|
1311
1311
|
if (attrs)
|
|
1312
1312
|
this.attrs = combineAttrs(attrs, this.attrs || {});
|
|
1313
1313
|
if (cls)
|
|
1314
|
-
this.attrs = combineAttrs(
|
|
1314
|
+
this.attrs = combineAttrs({ class: cls }, this.attrs || {});
|
|
1315
1315
|
}
|
|
1316
1316
|
domAtPos(pos) {
|
|
1317
1317
|
return inlineDOMAtPos(this.dom, this.children, pos);
|
|
@@ -1372,16 +1372,17 @@ class LineView extends ContentView {
|
|
|
1372
1372
|
become(_other) { return false; }
|
|
1373
1373
|
get type() { return exports.BlockType.Text; }
|
|
1374
1374
|
static find(docView, pos) {
|
|
1375
|
-
for (let i = 0, off = 0
|
|
1375
|
+
for (let i = 0, off = 0; i < docView.children.length; i++) {
|
|
1376
1376
|
let block = docView.children[i], end = off + block.length;
|
|
1377
1377
|
if (end >= pos) {
|
|
1378
1378
|
if (block instanceof LineView)
|
|
1379
1379
|
return block;
|
|
1380
|
-
if (
|
|
1381
|
-
|
|
1380
|
+
if (end > pos)
|
|
1381
|
+
break;
|
|
1382
1382
|
}
|
|
1383
1383
|
off = end + block.breakAfter;
|
|
1384
1384
|
}
|
|
1385
|
+
return null;
|
|
1385
1386
|
}
|
|
1386
1387
|
}
|
|
1387
1388
|
class BlockWidgetView extends ContentView {
|
|
@@ -1442,10 +1443,11 @@ class BlockWidgetView extends ContentView {
|
|
|
1442
1443
|
}
|
|
1443
1444
|
|
|
1444
1445
|
class ContentBuilder {
|
|
1445
|
-
constructor(doc, pos, end) {
|
|
1446
|
+
constructor(doc, pos, end, disallowBlockEffectsBelow) {
|
|
1446
1447
|
this.doc = doc;
|
|
1447
1448
|
this.pos = pos;
|
|
1448
1449
|
this.end = end;
|
|
1450
|
+
this.disallowBlockEffectsBelow = disallowBlockEffectsBelow;
|
|
1449
1451
|
this.content = [];
|
|
1450
1452
|
this.curLine = null;
|
|
1451
1453
|
this.breakAtStart = 0;
|
|
@@ -1574,8 +1576,15 @@ class ContentBuilder {
|
|
|
1574
1576
|
if (this.openStart < 0)
|
|
1575
1577
|
this.openStart = openStart;
|
|
1576
1578
|
}
|
|
1577
|
-
|
|
1578
|
-
|
|
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);
|
|
1579
1588
|
builder.openEnd = rangeset.RangeSet.spans(decorations, from, to, builder);
|
|
1580
1589
|
if (builder.openStart < 0)
|
|
1581
1590
|
builder.openStart = builder.openEnd;
|
|
@@ -1698,11 +1707,13 @@ This field can be used by plugins to provide
|
|
|
1698
1707
|
**Note**: For reasons of data flow (plugins are only updated
|
|
1699
1708
|
after the viewport is computed), decorations produced by plugins
|
|
1700
1709
|
are _not_ taken into account when predicting the vertical layout
|
|
1701
|
-
structure of the editor.
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
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.
|
|
1706
1717
|
*/
|
|
1707
1718
|
PluginField.decorations = PluginField.define();
|
|
1708
1719
|
/**
|
|
@@ -1935,8 +1946,6 @@ class ViewUpdate {
|
|
|
1935
1946
|
view.inputState.notifiedFocused = focus;
|
|
1936
1947
|
this.flags |= 1 /* Focus */;
|
|
1937
1948
|
}
|
|
1938
|
-
if (this.docChanged)
|
|
1939
|
-
this.flags |= 2 /* Height */;
|
|
1940
1949
|
}
|
|
1941
1950
|
/**
|
|
1942
1951
|
Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
|
|
@@ -1947,14 +1956,15 @@ class ViewUpdate {
|
|
|
1947
1956
|
return (this.flags & 4 /* Viewport */) > 0;
|
|
1948
1957
|
}
|
|
1949
1958
|
/**
|
|
1950
|
-
Indicates whether the
|
|
1959
|
+
Indicates whether the height of an element in the editor changed
|
|
1960
|
+
in this update.
|
|
1951
1961
|
*/
|
|
1952
1962
|
get heightChanged() {
|
|
1953
1963
|
return (this.flags & 2 /* Height */) > 0;
|
|
1954
1964
|
}
|
|
1955
1965
|
/**
|
|
1956
|
-
Returns true when the document
|
|
1957
|
-
|
|
1966
|
+
Returns true when the document was modified or the size of the
|
|
1967
|
+
editor, or elements within the editor, changed.
|
|
1958
1968
|
*/
|
|
1959
1969
|
get geometryChanged() {
|
|
1960
1970
|
return this.docChanged || (this.flags & (8 /* Geometry */ | 2 /* Height */)) > 0;
|
|
@@ -2373,6 +2383,7 @@ class DocView extends ContentView {
|
|
|
2373
2383
|
this.view = view;
|
|
2374
2384
|
this.compositionDeco = Decoration.none;
|
|
2375
2385
|
this.decorations = [];
|
|
2386
|
+
this.pluginDecorationLength = 0;
|
|
2376
2387
|
// Track a minimum width for the editor. When measuring sizes in
|
|
2377
2388
|
// measureVisibleLineHeights, this is updated to point at the width
|
|
2378
2389
|
// of a given element and its extent in the document. When a change
|
|
@@ -2394,7 +2405,8 @@ class DocView extends ContentView {
|
|
|
2394
2405
|
this.setDOM(view.contentDOM);
|
|
2395
2406
|
this.children = [new LineView];
|
|
2396
2407
|
this.children[0].setParent(this);
|
|
2397
|
-
this.
|
|
2408
|
+
this.updateDeco();
|
|
2409
|
+
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
|
|
2398
2410
|
}
|
|
2399
2411
|
get root() { return this.view.root; }
|
|
2400
2412
|
get editorView() { return this.view; }
|
|
@@ -2433,7 +2445,7 @@ class DocView extends ContentView {
|
|
|
2433
2445
|
return false;
|
|
2434
2446
|
}
|
|
2435
2447
|
else {
|
|
2436
|
-
this.updateInner(changedRanges,
|
|
2448
|
+
this.updateInner(changedRanges, update.startState.doc.length);
|
|
2437
2449
|
if (update.transactions.length)
|
|
2438
2450
|
this.lastUpdate = Date.now();
|
|
2439
2451
|
return true;
|
|
@@ -2441,9 +2453,9 @@ class DocView extends ContentView {
|
|
|
2441
2453
|
}
|
|
2442
2454
|
// Used by update and the constructor do perform the actual DOM
|
|
2443
2455
|
// update
|
|
2444
|
-
updateInner(changes,
|
|
2456
|
+
updateInner(changes, oldLength) {
|
|
2445
2457
|
this.view.viewState.mustMeasureContent = true;
|
|
2446
|
-
this.updateChildren(changes,
|
|
2458
|
+
this.updateChildren(changes, oldLength);
|
|
2447
2459
|
let { observer } = this.view;
|
|
2448
2460
|
observer.ignore(() => {
|
|
2449
2461
|
// Lock the height during redrawing, since Chrome sometimes
|
|
@@ -2470,14 +2482,14 @@ class DocView extends ContentView {
|
|
|
2470
2482
|
gaps.push(child.dom);
|
|
2471
2483
|
observer.updateGaps(gaps);
|
|
2472
2484
|
}
|
|
2473
|
-
updateChildren(changes,
|
|
2485
|
+
updateChildren(changes, oldLength) {
|
|
2474
2486
|
let cursor = this.childCursor(oldLength);
|
|
2475
2487
|
for (let i = changes.length - 1;; i--) {
|
|
2476
2488
|
let next = i >= 0 ? changes[i] : null;
|
|
2477
2489
|
if (!next)
|
|
2478
2490
|
break;
|
|
2479
2491
|
let { fromA, toA, fromB, toB } = next;
|
|
2480
|
-
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);
|
|
2481
2493
|
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2482
2494
|
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2483
2495
|
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
@@ -2696,8 +2708,10 @@ class DocView extends ContentView {
|
|
|
2696
2708
|
return Decoration.set(deco);
|
|
2697
2709
|
}
|
|
2698
2710
|
updateDeco() {
|
|
2711
|
+
let pluginDecorations = this.view.pluginField(PluginField.decorations);
|
|
2712
|
+
this.pluginDecorationLength = pluginDecorations.length;
|
|
2699
2713
|
return this.decorations = [
|
|
2700
|
-
...
|
|
2714
|
+
...pluginDecorations,
|
|
2701
2715
|
...this.view.state.facet(decorations),
|
|
2702
2716
|
this.compositionDeco,
|
|
2703
2717
|
this.computeBlockGapDeco(),
|
|
@@ -2990,12 +3004,12 @@ function domPosInText(node, x, y) {
|
|
|
2990
3004
|
function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
2991
3005
|
var _a;
|
|
2992
3006
|
let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
|
|
2993
|
-
let block,
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
3007
|
+
let block, { docHeight } = view.viewState;
|
|
3008
|
+
let yOffset = y - docTop;
|
|
3009
|
+
if (yOffset < 0)
|
|
3010
|
+
return 0;
|
|
3011
|
+
if (yOffset > docHeight)
|
|
3012
|
+
return view.state.doc.length;
|
|
2999
3013
|
// Scan for a text block near the queried y position
|
|
3000
3014
|
for (let halfLine = view.defaultLineHeight / 2, bounced = false;;) {
|
|
3001
3015
|
block = view.elementAtHeight(yOffset);
|
|
@@ -3016,20 +3030,29 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3016
3030
|
}
|
|
3017
3031
|
y = docTop + yOffset;
|
|
3018
3032
|
let lineStart = block.from;
|
|
3019
|
-
// Clip x to the viewport sides
|
|
3020
|
-
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
3021
3033
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
3022
3034
|
if (lineStart < view.viewport.from)
|
|
3023
|
-
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
3035
|
+
return view.viewport.from == 0 ? 0 : precise ? null : posAtCoordsImprecise(view, content, block, x, y);
|
|
3024
3036
|
if (lineStart > view.viewport.to)
|
|
3025
|
-
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3037
|
+
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3038
|
+
precise ? null : posAtCoordsImprecise(view, content, block, x, y);
|
|
3026
3039
|
// Prefer ShadowRootOrDocument.elementFromPoint if present, fall back to document if not
|
|
3027
3040
|
let doc = view.dom.ownerDocument;
|
|
3028
|
-
let
|
|
3041
|
+
let root = view.root.elementFromPoint ? view.root : doc;
|
|
3042
|
+
let element = root.elementFromPoint(x, y);
|
|
3043
|
+
if (element && !view.contentDOM.contains(element))
|
|
3044
|
+
element = null;
|
|
3045
|
+
// If the element is unexpected, clip x at the sides of the content area and try again
|
|
3046
|
+
if (!element) {
|
|
3047
|
+
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
3048
|
+
element = root.elementFromPoint(x, y);
|
|
3049
|
+
if (element && !view.contentDOM.contains(element))
|
|
3050
|
+
element = null;
|
|
3051
|
+
}
|
|
3029
3052
|
// There's visible editor content under the point, so we can try
|
|
3030
3053
|
// using caret(Position|Range)FromPoint as a shortcut
|
|
3031
3054
|
let node, offset = -1;
|
|
3032
|
-
if (element &&
|
|
3055
|
+
if (element && ((_a = view.docView.nearest(element)) === null || _a === void 0 ? void 0 : _a.isEditable) != false) {
|
|
3033
3056
|
if (doc.caretPositionFromPoint) {
|
|
3034
3057
|
let pos = doc.caretPositionFromPoint(x, y);
|
|
3035
3058
|
if (pos)
|
|
@@ -3047,6 +3070,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3047
3070
|
// No luck, do our own (potentially expensive) search
|
|
3048
3071
|
if (!node || !view.docView.dom.contains(node)) {
|
|
3049
3072
|
let line = LineView.find(view.docView, lineStart);
|
|
3073
|
+
if (!line)
|
|
3074
|
+
return yOffset > block.top + block.height / 2 ? block.to : block.from;
|
|
3050
3075
|
({ node, offset } = domPosAtCoords(line.dom, x, y));
|
|
3051
3076
|
}
|
|
3052
3077
|
return view.docView.posFromDOM(node, offset);
|
|
@@ -3510,7 +3535,7 @@ handlers.touchmove = view => {
|
|
|
3510
3535
|
};
|
|
3511
3536
|
handlers.mousedown = (view, event) => {
|
|
3512
3537
|
view.observer.flush();
|
|
3513
|
-
if (lastTouch > Date.now() - 2000)
|
|
3538
|
+
if (lastTouch > Date.now() - 2000 && getClickType(event) == 1)
|
|
3514
3539
|
return; // Ignore touch interaction
|
|
3515
3540
|
let style = null;
|
|
3516
3541
|
for (let makeStyle of view.state.facet(mouseSelectionStyle)) {
|
|
@@ -3632,9 +3657,9 @@ handlers.dragstart = (view, event) => {
|
|
|
3632
3657
|
}
|
|
3633
3658
|
};
|
|
3634
3659
|
function dropText(view, event, text, direct) {
|
|
3635
|
-
|
|
3636
|
-
if (dropPos == null || !text)
|
|
3660
|
+
if (!text)
|
|
3637
3661
|
return;
|
|
3662
|
+
let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
3638
3663
|
event.preventDefault();
|
|
3639
3664
|
let { mouseSelection } = view.inputState;
|
|
3640
3665
|
let del = direct && mouseSelection && mouseSelection.dragging && mouseSelection.dragMove ?
|
|
@@ -4745,7 +4770,7 @@ class ViewState {
|
|
|
4745
4770
|
let block = map.lineAt(head, QueryType.ByPos, doc, 0, 0), topPos;
|
|
4746
4771
|
if (scrollTarget.y == "center")
|
|
4747
4772
|
topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
|
|
4748
|
-
else if (scrollTarget.y == "start" || head < viewport.from)
|
|
4773
|
+
else if (scrollTarget.y == "start" || scrollTarget.y == "nearest" && head < viewport.from)
|
|
4749
4774
|
topPos = block.top;
|
|
4750
4775
|
else
|
|
4751
4776
|
topPos = block.bottom - viewHeight;
|
|
@@ -5292,8 +5317,10 @@ class DOMObserver {
|
|
|
5292
5317
|
// Deletions on IE11 fire their events in the wrong order, giving
|
|
5293
5318
|
// us a selection change event before the DOM changes are
|
|
5294
5319
|
// reported.
|
|
5295
|
-
//
|
|
5296
|
-
|
|
5320
|
+
// Chrome Android has a similar issue when backspacing out a
|
|
5321
|
+
// selection (#645).
|
|
5322
|
+
if ((browser.ie && browser.ie_version <= 11 || browser.android && browser.chrome) && !view.state.selection.main.empty &&
|
|
5323
|
+
// (Selection.isCollapsed isn't reliable on IE)
|
|
5297
5324
|
sel.focusNode && isEquivalentPosition(sel.focusNode, sel.focusOffset, sel.anchorNode, sel.anchorOffset))
|
|
5298
5325
|
this.flushSoon();
|
|
5299
5326
|
else
|
|
@@ -5837,7 +5864,7 @@ class EditorView {
|
|
|
5837
5864
|
if (state$1.facet(state.EditorState.phrases) != this.state.facet(state.EditorState.phrases))
|
|
5838
5865
|
return this.setState(state$1);
|
|
5839
5866
|
update = new ViewUpdate(this, state$1, transactions);
|
|
5840
|
-
let scrollTarget =
|
|
5867
|
+
let scrollTarget = this.viewState.scrollTarget;
|
|
5841
5868
|
try {
|
|
5842
5869
|
this.updateState = 2 /* Updating */;
|
|
5843
5870
|
for (let tr of transactions) {
|
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
|
@@ -1307,7 +1307,7 @@ class LineView extends ContentView {
|
|
|
1307
1307
|
if (attrs)
|
|
1308
1308
|
this.attrs = combineAttrs(attrs, this.attrs || {});
|
|
1309
1309
|
if (cls)
|
|
1310
|
-
this.attrs = combineAttrs(
|
|
1310
|
+
this.attrs = combineAttrs({ class: cls }, this.attrs || {});
|
|
1311
1311
|
}
|
|
1312
1312
|
domAtPos(pos) {
|
|
1313
1313
|
return inlineDOMAtPos(this.dom, this.children, pos);
|
|
@@ -1368,16 +1368,17 @@ class LineView extends ContentView {
|
|
|
1368
1368
|
become(_other) { return false; }
|
|
1369
1369
|
get type() { return BlockType.Text; }
|
|
1370
1370
|
static find(docView, pos) {
|
|
1371
|
-
for (let i = 0, off = 0
|
|
1371
|
+
for (let i = 0, off = 0; i < docView.children.length; i++) {
|
|
1372
1372
|
let block = docView.children[i], end = off + block.length;
|
|
1373
1373
|
if (end >= pos) {
|
|
1374
1374
|
if (block instanceof LineView)
|
|
1375
1375
|
return block;
|
|
1376
|
-
if (
|
|
1377
|
-
|
|
1376
|
+
if (end > pos)
|
|
1377
|
+
break;
|
|
1378
1378
|
}
|
|
1379
1379
|
off = end + block.breakAfter;
|
|
1380
1380
|
}
|
|
1381
|
+
return null;
|
|
1381
1382
|
}
|
|
1382
1383
|
}
|
|
1383
1384
|
class BlockWidgetView extends ContentView {
|
|
@@ -1438,10 +1439,11 @@ class BlockWidgetView extends ContentView {
|
|
|
1438
1439
|
}
|
|
1439
1440
|
|
|
1440
1441
|
class ContentBuilder {
|
|
1441
|
-
constructor(doc, pos, end) {
|
|
1442
|
+
constructor(doc, pos, end, disallowBlockEffectsBelow) {
|
|
1442
1443
|
this.doc = doc;
|
|
1443
1444
|
this.pos = pos;
|
|
1444
1445
|
this.end = end;
|
|
1446
|
+
this.disallowBlockEffectsBelow = disallowBlockEffectsBelow;
|
|
1445
1447
|
this.content = [];
|
|
1446
1448
|
this.curLine = null;
|
|
1447
1449
|
this.breakAtStart = 0;
|
|
@@ -1570,8 +1572,15 @@ class ContentBuilder {
|
|
|
1570
1572
|
if (this.openStart < 0)
|
|
1571
1573
|
this.openStart = openStart;
|
|
1572
1574
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
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);
|
|
1575
1584
|
builder.openEnd = RangeSet.spans(decorations, from, to, builder);
|
|
1576
1585
|
if (builder.openStart < 0)
|
|
1577
1586
|
builder.openStart = builder.openEnd;
|
|
@@ -1694,11 +1703,13 @@ This field can be used by plugins to provide
|
|
|
1694
1703
|
**Note**: For reasons of data flow (plugins are only updated
|
|
1695
1704
|
after the viewport is computed), decorations produced by plugins
|
|
1696
1705
|
are _not_ taken into account when predicting the vertical layout
|
|
1697
|
-
structure of the editor.
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
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.
|
|
1702
1713
|
*/
|
|
1703
1714
|
PluginField.decorations = /*@__PURE__*/PluginField.define();
|
|
1704
1715
|
/**
|
|
@@ -1931,8 +1942,6 @@ class ViewUpdate {
|
|
|
1931
1942
|
view.inputState.notifiedFocused = focus;
|
|
1932
1943
|
this.flags |= 1 /* Focus */;
|
|
1933
1944
|
}
|
|
1934
|
-
if (this.docChanged)
|
|
1935
|
-
this.flags |= 2 /* Height */;
|
|
1936
1945
|
}
|
|
1937
1946
|
/**
|
|
1938
1947
|
Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
|
|
@@ -1943,14 +1952,15 @@ class ViewUpdate {
|
|
|
1943
1952
|
return (this.flags & 4 /* Viewport */) > 0;
|
|
1944
1953
|
}
|
|
1945
1954
|
/**
|
|
1946
|
-
Indicates whether the
|
|
1955
|
+
Indicates whether the height of an element in the editor changed
|
|
1956
|
+
in this update.
|
|
1947
1957
|
*/
|
|
1948
1958
|
get heightChanged() {
|
|
1949
1959
|
return (this.flags & 2 /* Height */) > 0;
|
|
1950
1960
|
}
|
|
1951
1961
|
/**
|
|
1952
|
-
Returns true when the document
|
|
1953
|
-
|
|
1962
|
+
Returns true when the document was modified or the size of the
|
|
1963
|
+
editor, or elements within the editor, changed.
|
|
1954
1964
|
*/
|
|
1955
1965
|
get geometryChanged() {
|
|
1956
1966
|
return this.docChanged || (this.flags & (8 /* Geometry */ | 2 /* Height */)) > 0;
|
|
@@ -2368,6 +2378,7 @@ class DocView extends ContentView {
|
|
|
2368
2378
|
this.view = view;
|
|
2369
2379
|
this.compositionDeco = Decoration.none;
|
|
2370
2380
|
this.decorations = [];
|
|
2381
|
+
this.pluginDecorationLength = 0;
|
|
2371
2382
|
// Track a minimum width for the editor. When measuring sizes in
|
|
2372
2383
|
// measureVisibleLineHeights, this is updated to point at the width
|
|
2373
2384
|
// of a given element and its extent in the document. When a change
|
|
@@ -2389,7 +2400,8 @@ class DocView extends ContentView {
|
|
|
2389
2400
|
this.setDOM(view.contentDOM);
|
|
2390
2401
|
this.children = [new LineView];
|
|
2391
2402
|
this.children[0].setParent(this);
|
|
2392
|
-
this.
|
|
2403
|
+
this.updateDeco();
|
|
2404
|
+
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
|
|
2393
2405
|
}
|
|
2394
2406
|
get root() { return this.view.root; }
|
|
2395
2407
|
get editorView() { return this.view; }
|
|
@@ -2428,7 +2440,7 @@ class DocView extends ContentView {
|
|
|
2428
2440
|
return false;
|
|
2429
2441
|
}
|
|
2430
2442
|
else {
|
|
2431
|
-
this.updateInner(changedRanges,
|
|
2443
|
+
this.updateInner(changedRanges, update.startState.doc.length);
|
|
2432
2444
|
if (update.transactions.length)
|
|
2433
2445
|
this.lastUpdate = Date.now();
|
|
2434
2446
|
return true;
|
|
@@ -2436,9 +2448,9 @@ class DocView extends ContentView {
|
|
|
2436
2448
|
}
|
|
2437
2449
|
// Used by update and the constructor do perform the actual DOM
|
|
2438
2450
|
// update
|
|
2439
|
-
updateInner(changes,
|
|
2451
|
+
updateInner(changes, oldLength) {
|
|
2440
2452
|
this.view.viewState.mustMeasureContent = true;
|
|
2441
|
-
this.updateChildren(changes,
|
|
2453
|
+
this.updateChildren(changes, oldLength);
|
|
2442
2454
|
let { observer } = this.view;
|
|
2443
2455
|
observer.ignore(() => {
|
|
2444
2456
|
// Lock the height during redrawing, since Chrome sometimes
|
|
@@ -2465,14 +2477,14 @@ class DocView extends ContentView {
|
|
|
2465
2477
|
gaps.push(child.dom);
|
|
2466
2478
|
observer.updateGaps(gaps);
|
|
2467
2479
|
}
|
|
2468
|
-
updateChildren(changes,
|
|
2480
|
+
updateChildren(changes, oldLength) {
|
|
2469
2481
|
let cursor = this.childCursor(oldLength);
|
|
2470
2482
|
for (let i = changes.length - 1;; i--) {
|
|
2471
2483
|
let next = i >= 0 ? changes[i] : null;
|
|
2472
2484
|
if (!next)
|
|
2473
2485
|
break;
|
|
2474
2486
|
let { fromA, toA, fromB, toB } = next;
|
|
2475
|
-
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);
|
|
2476
2488
|
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2477
2489
|
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2478
2490
|
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
@@ -2691,8 +2703,10 @@ class DocView extends ContentView {
|
|
|
2691
2703
|
return Decoration.set(deco);
|
|
2692
2704
|
}
|
|
2693
2705
|
updateDeco() {
|
|
2706
|
+
let pluginDecorations = this.view.pluginField(PluginField.decorations);
|
|
2707
|
+
this.pluginDecorationLength = pluginDecorations.length;
|
|
2694
2708
|
return this.decorations = [
|
|
2695
|
-
...
|
|
2709
|
+
...pluginDecorations,
|
|
2696
2710
|
...this.view.state.facet(decorations),
|
|
2697
2711
|
this.compositionDeco,
|
|
2698
2712
|
this.computeBlockGapDeco(),
|
|
@@ -2985,12 +2999,12 @@ function domPosInText(node, x, y) {
|
|
|
2985
2999
|
function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
2986
3000
|
var _a;
|
|
2987
3001
|
let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
|
|
2988
|
-
let block,
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
3002
|
+
let block, { docHeight } = view.viewState;
|
|
3003
|
+
let yOffset = y - docTop;
|
|
3004
|
+
if (yOffset < 0)
|
|
3005
|
+
return 0;
|
|
3006
|
+
if (yOffset > docHeight)
|
|
3007
|
+
return view.state.doc.length;
|
|
2994
3008
|
// Scan for a text block near the queried y position
|
|
2995
3009
|
for (let halfLine = view.defaultLineHeight / 2, bounced = false;;) {
|
|
2996
3010
|
block = view.elementAtHeight(yOffset);
|
|
@@ -3011,20 +3025,29 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3011
3025
|
}
|
|
3012
3026
|
y = docTop + yOffset;
|
|
3013
3027
|
let lineStart = block.from;
|
|
3014
|
-
// Clip x to the viewport sides
|
|
3015
|
-
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
3016
3028
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
3017
3029
|
if (lineStart < view.viewport.from)
|
|
3018
|
-
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
3030
|
+
return view.viewport.from == 0 ? 0 : precise ? null : posAtCoordsImprecise(view, content, block, x, y);
|
|
3019
3031
|
if (lineStart > view.viewport.to)
|
|
3020
|
-
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3032
|
+
return view.viewport.to == view.state.doc.length ? view.state.doc.length :
|
|
3033
|
+
precise ? null : posAtCoordsImprecise(view, content, block, x, y);
|
|
3021
3034
|
// Prefer ShadowRootOrDocument.elementFromPoint if present, fall back to document if not
|
|
3022
3035
|
let doc = view.dom.ownerDocument;
|
|
3023
|
-
let
|
|
3036
|
+
let root = view.root.elementFromPoint ? view.root : doc;
|
|
3037
|
+
let element = root.elementFromPoint(x, y);
|
|
3038
|
+
if (element && !view.contentDOM.contains(element))
|
|
3039
|
+
element = null;
|
|
3040
|
+
// If the element is unexpected, clip x at the sides of the content area and try again
|
|
3041
|
+
if (!element) {
|
|
3042
|
+
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
3043
|
+
element = root.elementFromPoint(x, y);
|
|
3044
|
+
if (element && !view.contentDOM.contains(element))
|
|
3045
|
+
element = null;
|
|
3046
|
+
}
|
|
3024
3047
|
// There's visible editor content under the point, so we can try
|
|
3025
3048
|
// using caret(Position|Range)FromPoint as a shortcut
|
|
3026
3049
|
let node, offset = -1;
|
|
3027
|
-
if (element &&
|
|
3050
|
+
if (element && ((_a = view.docView.nearest(element)) === null || _a === void 0 ? void 0 : _a.isEditable) != false) {
|
|
3028
3051
|
if (doc.caretPositionFromPoint) {
|
|
3029
3052
|
let pos = doc.caretPositionFromPoint(x, y);
|
|
3030
3053
|
if (pos)
|
|
@@ -3042,6 +3065,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
3042
3065
|
// No luck, do our own (potentially expensive) search
|
|
3043
3066
|
if (!node || !view.docView.dom.contains(node)) {
|
|
3044
3067
|
let line = LineView.find(view.docView, lineStart);
|
|
3068
|
+
if (!line)
|
|
3069
|
+
return yOffset > block.top + block.height / 2 ? block.to : block.from;
|
|
3045
3070
|
({ node, offset } = domPosAtCoords(line.dom, x, y));
|
|
3046
3071
|
}
|
|
3047
3072
|
return view.docView.posFromDOM(node, offset);
|
|
@@ -3505,7 +3530,7 @@ handlers.touchmove = view => {
|
|
|
3505
3530
|
};
|
|
3506
3531
|
handlers.mousedown = (view, event) => {
|
|
3507
3532
|
view.observer.flush();
|
|
3508
|
-
if (lastTouch > Date.now() - 2000)
|
|
3533
|
+
if (lastTouch > Date.now() - 2000 && getClickType(event) == 1)
|
|
3509
3534
|
return; // Ignore touch interaction
|
|
3510
3535
|
let style = null;
|
|
3511
3536
|
for (let makeStyle of view.state.facet(mouseSelectionStyle)) {
|
|
@@ -3627,9 +3652,9 @@ handlers.dragstart = (view, event) => {
|
|
|
3627
3652
|
}
|
|
3628
3653
|
};
|
|
3629
3654
|
function dropText(view, event, text, direct) {
|
|
3630
|
-
|
|
3631
|
-
if (dropPos == null || !text)
|
|
3655
|
+
if (!text)
|
|
3632
3656
|
return;
|
|
3657
|
+
let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
3633
3658
|
event.preventDefault();
|
|
3634
3659
|
let { mouseSelection } = view.inputState;
|
|
3635
3660
|
let del = direct && mouseSelection && mouseSelection.dragging && mouseSelection.dragMove ?
|
|
@@ -4739,7 +4764,7 @@ class ViewState {
|
|
|
4739
4764
|
let block = map.lineAt(head, QueryType.ByPos, doc, 0, 0), topPos;
|
|
4740
4765
|
if (scrollTarget.y == "center")
|
|
4741
4766
|
topPos = (block.top + block.bottom) / 2 - viewHeight / 2;
|
|
4742
|
-
else if (scrollTarget.y == "start" || head < viewport.from)
|
|
4767
|
+
else if (scrollTarget.y == "start" || scrollTarget.y == "nearest" && head < viewport.from)
|
|
4743
4768
|
topPos = block.top;
|
|
4744
4769
|
else
|
|
4745
4770
|
topPos = block.bottom - viewHeight;
|
|
@@ -5286,8 +5311,10 @@ class DOMObserver {
|
|
|
5286
5311
|
// Deletions on IE11 fire their events in the wrong order, giving
|
|
5287
5312
|
// us a selection change event before the DOM changes are
|
|
5288
5313
|
// reported.
|
|
5289
|
-
//
|
|
5290
|
-
|
|
5314
|
+
// Chrome Android has a similar issue when backspacing out a
|
|
5315
|
+
// selection (#645).
|
|
5316
|
+
if ((browser.ie && browser.ie_version <= 11 || browser.android && browser.chrome) && !view.state.selection.main.empty &&
|
|
5317
|
+
// (Selection.isCollapsed isn't reliable on IE)
|
|
5291
5318
|
sel.focusNode && isEquivalentPosition(sel.focusNode, sel.focusOffset, sel.anchorNode, sel.anchorOffset))
|
|
5292
5319
|
this.flushSoon();
|
|
5293
5320
|
else
|
|
@@ -5831,7 +5858,7 @@ class EditorView {
|
|
|
5831
5858
|
if (state.facet(EditorState.phrases) != this.state.facet(EditorState.phrases))
|
|
5832
5859
|
return this.setState(state);
|
|
5833
5860
|
update = new ViewUpdate(this, state, transactions);
|
|
5834
|
-
let scrollTarget =
|
|
5861
|
+
let scrollTarget = this.viewState.scrollTarget;
|
|
5835
5862
|
try {
|
|
5836
5863
|
this.updateState = 2 /* Updating */;
|
|
5837
5864
|
for (let tr of transactions) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemirror/view",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.38",
|
|
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",
|