@codemirror/view 6.39.2 → 6.39.4
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 +18 -0
- package/dist/index.cjs +21 -44
- package/dist/index.js +21 -44
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## 6.39.4 (2025-12-12)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix a bug where paste events handlers on Chrome could fail to run when pasting on a blank line.
|
|
6
|
+
|
|
7
|
+
Fix a regression causing the native cursor to get stuck before block widgets with side>0.
|
|
8
|
+
|
|
9
|
+
Fix a crash in content DOM building after a block widget.
|
|
10
|
+
|
|
11
|
+
Fix a bug in `posAtCoords` that would in some circumstances make it return positions on the wrong side of a block widget.
|
|
12
|
+
|
|
13
|
+
## 6.39.3 (2025-12-11)
|
|
14
|
+
|
|
15
|
+
### Bug fixes
|
|
16
|
+
|
|
17
|
+
Fix a bug that could corrupt the rendered document in some situations involving adjacent mark decorations of the same type.
|
|
18
|
+
|
|
1
19
|
## 6.39.2 (2025-12-09)
|
|
2
20
|
|
|
3
21
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -1991,7 +1991,7 @@ class LineTile extends CompositeTile {
|
|
|
1991
1991
|
if (this.dom.contains(tile.dom)) {
|
|
1992
1992
|
if (tile.isText())
|
|
1993
1993
|
return new DOMPos(tile.dom, Math.min(tile.dom.nodeValue.length, offset));
|
|
1994
|
-
return tile.domPosFor(offset, side);
|
|
1994
|
+
return tile.domPosFor(offset, tile.flags & 16 /* TileFlag.Before */ ? 1 : tile.flags & 32 /* TileFlag.After */ ? -1 : side);
|
|
1995
1995
|
}
|
|
1996
1996
|
let parent = found.tile.parent, saw = false;
|
|
1997
1997
|
for (let ch of parent.children) {
|
|
@@ -2623,12 +2623,14 @@ class TileUpdate {
|
|
|
2623
2623
|
this.builder.addBlockWidget(widget);
|
|
2624
2624
|
}
|
|
2625
2625
|
else {
|
|
2626
|
+
this.builder.ensureLine(null);
|
|
2626
2627
|
this.builder.addInlineWidget(widget, activeMarks, openMarks);
|
|
2627
2628
|
openMarks = activeMarks.length;
|
|
2628
2629
|
}
|
|
2629
2630
|
}
|
|
2630
2631
|
}
|
|
2631
2632
|
else if (tile.isText()) {
|
|
2633
|
+
this.builder.ensureLine(null);
|
|
2632
2634
|
if (!from && to == tile.length) {
|
|
2633
2635
|
this.builder.addText(tile.text, activeMarks, openMarks, this.cache.reuse(tile));
|
|
2634
2636
|
}
|
|
@@ -2647,8 +2649,10 @@ class TileUpdate {
|
|
|
2647
2649
|
this.cache.add(tile);
|
|
2648
2650
|
}
|
|
2649
2651
|
else if (tile instanceof MarkTile) {
|
|
2652
|
+
this.builder.ensureLine(null);
|
|
2650
2653
|
this.builder.addMark(tile, activeMarks, openMarks);
|
|
2651
2654
|
this.cache.reused.set(tile, 1 /* Reused.Full */);
|
|
2655
|
+
openMarks = activeMarks.length;
|
|
2652
2656
|
}
|
|
2653
2657
|
else {
|
|
2654
2658
|
return false;
|
|
@@ -2661,10 +2665,8 @@ class TileUpdate {
|
|
|
2661
2665
|
}
|
|
2662
2666
|
else {
|
|
2663
2667
|
this.cache.add(tile);
|
|
2664
|
-
if (tile instanceof MarkTile)
|
|
2668
|
+
if (tile instanceof MarkTile)
|
|
2665
2669
|
activeMarks.unshift(tile.mark);
|
|
2666
|
-
openMarks++;
|
|
2667
|
-
}
|
|
2668
2670
|
}
|
|
2669
2671
|
this.openWidget = false;
|
|
2670
2672
|
},
|
|
@@ -3075,7 +3077,7 @@ class DocView {
|
|
|
3075
3077
|
let { anchorNode, anchorOffset } = view.observer.selectionRange;
|
|
3076
3078
|
if (!sel || !cursor.empty || !cursor.assoc || !sel.modify)
|
|
3077
3079
|
return;
|
|
3078
|
-
let line = this.lineAt(cursor.head);
|
|
3080
|
+
let line = this.lineAt(cursor.head, cursor.assoc);
|
|
3079
3081
|
if (!line)
|
|
3080
3082
|
return;
|
|
3081
3083
|
let lineStart = line.posAtStart;
|
|
@@ -3154,7 +3156,7 @@ class DocView {
|
|
|
3154
3156
|
let after, afterOff = -1, afterBad = false;
|
|
3155
3157
|
this.tile.blockTiles((tile, off) => {
|
|
3156
3158
|
if (tile.isWidget()) {
|
|
3157
|
-
if ((tile.flags & 32 /* TileFlag.After */) &&
|
|
3159
|
+
if ((tile.flags & 32 /* TileFlag.After */) && off >= pos)
|
|
3158
3160
|
return true;
|
|
3159
3161
|
if (tile.flags & 16 /* TileFlag.Before */)
|
|
3160
3162
|
beforeBad = true;
|
|
@@ -3192,8 +3194,8 @@ class DocView {
|
|
|
3192
3194
|
}
|
|
3193
3195
|
return tile.coordsIn(offset, side);
|
|
3194
3196
|
}
|
|
3195
|
-
lineAt(pos) {
|
|
3196
|
-
let { tile } = this.tile.resolveBlock(pos,
|
|
3197
|
+
lineAt(pos, side) {
|
|
3198
|
+
let { tile } = this.tile.resolveBlock(pos, side);
|
|
3197
3199
|
return tile.isLine() ? tile : null;
|
|
3198
3200
|
}
|
|
3199
3201
|
coordsForChar(pos) {
|
|
@@ -3739,7 +3741,10 @@ function posAtCoords(view, coords, precise, scanY) {
|
|
|
3739
3741
|
if (block.type != exports.BlockType.Text)
|
|
3740
3742
|
return yOffset < (block.top + block.bottom) / 2 ? new PosAssoc(block.from, 1) : new PosAssoc(block.to, -1);
|
|
3741
3743
|
// Here we know we're in a line, so run the logic for inline layout
|
|
3742
|
-
|
|
3744
|
+
let line = view.docView.lineAt(block.from, 2);
|
|
3745
|
+
if (!line || line.length != block.length)
|
|
3746
|
+
line = view.docView.lineAt(block.from, -2);
|
|
3747
|
+
return posAtCoordsInline(view, line, block.from, x, y);
|
|
3743
3748
|
}
|
|
3744
3749
|
// Scan through the rectangles for the content of a tile, finding the
|
|
3745
3750
|
// one closest to the given coordinates, prefering closeness in Y over
|
|
@@ -4658,7 +4663,8 @@ function eventBelongsToEditor(view, event) {
|
|
|
4658
4663
|
if (event.defaultPrevented)
|
|
4659
4664
|
return false;
|
|
4660
4665
|
for (let node = event.target, tile; node != view.contentDOM; node = node.parentNode)
|
|
4661
|
-
if (!node || node.nodeType == 11 ||
|
|
4666
|
+
if (!node || node.nodeType == 11 ||
|
|
4667
|
+
((tile = Tile.get(node)) && tile.isWidget() && !tile.isHidden && tile.widget.ignoreEvent(event)))
|
|
4662
4668
|
return false;
|
|
4663
4669
|
return true;
|
|
4664
4670
|
}
|
|
@@ -4777,42 +4783,13 @@ function rangeForClick(view, pos, bias, type) {
|
|
|
4777
4783
|
return groupAt(view.state, pos, bias);
|
|
4778
4784
|
}
|
|
4779
4785
|
else { // Triple click
|
|
4780
|
-
let visual = view.docView.lineAt(pos), line = view.state.doc.lineAt(visual ? visual.posAtEnd : pos);
|
|
4786
|
+
let visual = view.docView.lineAt(pos, bias), line = view.state.doc.lineAt(visual ? visual.posAtEnd : pos);
|
|
4781
4787
|
let from = visual ? visual.posAtStart : line.from, to = visual ? visual.posAtEnd : line.to;
|
|
4782
4788
|
if (to < view.state.doc.length && to == line.to)
|
|
4783
4789
|
to++;
|
|
4784
4790
|
return state.EditorSelection.range(from, to);
|
|
4785
4791
|
}
|
|
4786
4792
|
}
|
|
4787
|
-
let inside = (x, y, rect) => y >= rect.top && y <= rect.bottom && x >= rect.left && x <= rect.right;
|
|
4788
|
-
// Try to determine, for the given coordinates, associated with the
|
|
4789
|
-
// given position, whether they are related to the element before or
|
|
4790
|
-
// the element after the position.
|
|
4791
|
-
function findPositionSide(view, pos, x, y) {
|
|
4792
|
-
let line = view.docView.lineAt(pos);
|
|
4793
|
-
if (!line)
|
|
4794
|
-
return 1;
|
|
4795
|
-
let off = pos - line.posAtStart;
|
|
4796
|
-
// Line boundaries point into the line
|
|
4797
|
-
if (off == 0)
|
|
4798
|
-
return 1;
|
|
4799
|
-
if (off == line.length)
|
|
4800
|
-
return -1;
|
|
4801
|
-
// Positions on top of an element point at that element
|
|
4802
|
-
let before = line.coordsIn(off, -1);
|
|
4803
|
-
if (before && inside(x, y, before))
|
|
4804
|
-
return -1;
|
|
4805
|
-
let after = line.coordsIn(off, 1);
|
|
4806
|
-
if (after && inside(x, y, after))
|
|
4807
|
-
return 1;
|
|
4808
|
-
// This is probably a line wrap point. Pick before if the point is
|
|
4809
|
-
// above its bottom.
|
|
4810
|
-
return before && before.bottom >= y ? -1 : 1;
|
|
4811
|
-
}
|
|
4812
|
-
function queryPos(view, event) {
|
|
4813
|
-
let pos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
4814
|
-
return { pos, bias: findPositionSide(view, pos, event.clientX, event.clientY) };
|
|
4815
|
-
}
|
|
4816
4793
|
const BadMouseDetail = browser.ie && browser.ie_version <= 11;
|
|
4817
4794
|
let lastMouseDown = null, lastMouseDownCount = 0, lastMouseDownTime = 0;
|
|
4818
4795
|
function getClickType(event) {
|
|
@@ -4825,7 +4802,7 @@ function getClickType(event) {
|
|
|
4825
4802
|
Math.abs(last.clientY - event.clientY) < 2) ? (lastMouseDownCount + 1) % 3 : 1;
|
|
4826
4803
|
}
|
|
4827
4804
|
function basicMouseSelection(view, event) {
|
|
4828
|
-
let start =
|
|
4805
|
+
let start = view.posAndSideAtCoords({ x: event.clientX, y: event.clientY }, false), type = getClickType(event);
|
|
4829
4806
|
let startSel = view.state.selection;
|
|
4830
4807
|
return {
|
|
4831
4808
|
update(update) {
|
|
@@ -4835,10 +4812,10 @@ function basicMouseSelection(view, event) {
|
|
|
4835
4812
|
}
|
|
4836
4813
|
},
|
|
4837
4814
|
get(event, extend, multiple) {
|
|
4838
|
-
let cur =
|
|
4839
|
-
let range = rangeForClick(view, cur.pos, cur.
|
|
4815
|
+
let cur = view.posAndSideAtCoords({ x: event.clientX, y: event.clientY }, false), removed;
|
|
4816
|
+
let range = rangeForClick(view, cur.pos, cur.assoc, type);
|
|
4840
4817
|
if (start.pos != cur.pos && !extend) {
|
|
4841
|
-
let startRange = rangeForClick(view, start.pos, start.
|
|
4818
|
+
let startRange = rangeForClick(view, start.pos, start.assoc, type);
|
|
4842
4819
|
let from = Math.min(startRange.from, range.from), to = Math.max(startRange.to, range.to);
|
|
4843
4820
|
range = from < range.from ? state.EditorSelection.range(from, to) : state.EditorSelection.range(to, from);
|
|
4844
4821
|
}
|
package/dist/index.js
CHANGED
|
@@ -1987,7 +1987,7 @@ class LineTile extends CompositeTile {
|
|
|
1987
1987
|
if (this.dom.contains(tile.dom)) {
|
|
1988
1988
|
if (tile.isText())
|
|
1989
1989
|
return new DOMPos(tile.dom, Math.min(tile.dom.nodeValue.length, offset));
|
|
1990
|
-
return tile.domPosFor(offset, side);
|
|
1990
|
+
return tile.domPosFor(offset, tile.flags & 16 /* TileFlag.Before */ ? 1 : tile.flags & 32 /* TileFlag.After */ ? -1 : side);
|
|
1991
1991
|
}
|
|
1992
1992
|
let parent = found.tile.parent, saw = false;
|
|
1993
1993
|
for (let ch of parent.children) {
|
|
@@ -2619,12 +2619,14 @@ class TileUpdate {
|
|
|
2619
2619
|
this.builder.addBlockWidget(widget);
|
|
2620
2620
|
}
|
|
2621
2621
|
else {
|
|
2622
|
+
this.builder.ensureLine(null);
|
|
2622
2623
|
this.builder.addInlineWidget(widget, activeMarks, openMarks);
|
|
2623
2624
|
openMarks = activeMarks.length;
|
|
2624
2625
|
}
|
|
2625
2626
|
}
|
|
2626
2627
|
}
|
|
2627
2628
|
else if (tile.isText()) {
|
|
2629
|
+
this.builder.ensureLine(null);
|
|
2628
2630
|
if (!from && to == tile.length) {
|
|
2629
2631
|
this.builder.addText(tile.text, activeMarks, openMarks, this.cache.reuse(tile));
|
|
2630
2632
|
}
|
|
@@ -2643,8 +2645,10 @@ class TileUpdate {
|
|
|
2643
2645
|
this.cache.add(tile);
|
|
2644
2646
|
}
|
|
2645
2647
|
else if (tile instanceof MarkTile) {
|
|
2648
|
+
this.builder.ensureLine(null);
|
|
2646
2649
|
this.builder.addMark(tile, activeMarks, openMarks);
|
|
2647
2650
|
this.cache.reused.set(tile, 1 /* Reused.Full */);
|
|
2651
|
+
openMarks = activeMarks.length;
|
|
2648
2652
|
}
|
|
2649
2653
|
else {
|
|
2650
2654
|
return false;
|
|
@@ -2657,10 +2661,8 @@ class TileUpdate {
|
|
|
2657
2661
|
}
|
|
2658
2662
|
else {
|
|
2659
2663
|
this.cache.add(tile);
|
|
2660
|
-
if (tile instanceof MarkTile)
|
|
2664
|
+
if (tile instanceof MarkTile)
|
|
2661
2665
|
activeMarks.unshift(tile.mark);
|
|
2662
|
-
openMarks++;
|
|
2663
|
-
}
|
|
2664
2666
|
}
|
|
2665
2667
|
this.openWidget = false;
|
|
2666
2668
|
},
|
|
@@ -3071,7 +3073,7 @@ class DocView {
|
|
|
3071
3073
|
let { anchorNode, anchorOffset } = view.observer.selectionRange;
|
|
3072
3074
|
if (!sel || !cursor.empty || !cursor.assoc || !sel.modify)
|
|
3073
3075
|
return;
|
|
3074
|
-
let line = this.lineAt(cursor.head);
|
|
3076
|
+
let line = this.lineAt(cursor.head, cursor.assoc);
|
|
3075
3077
|
if (!line)
|
|
3076
3078
|
return;
|
|
3077
3079
|
let lineStart = line.posAtStart;
|
|
@@ -3150,7 +3152,7 @@ class DocView {
|
|
|
3150
3152
|
let after, afterOff = -1, afterBad = false;
|
|
3151
3153
|
this.tile.blockTiles((tile, off) => {
|
|
3152
3154
|
if (tile.isWidget()) {
|
|
3153
|
-
if ((tile.flags & 32 /* TileFlag.After */) &&
|
|
3155
|
+
if ((tile.flags & 32 /* TileFlag.After */) && off >= pos)
|
|
3154
3156
|
return true;
|
|
3155
3157
|
if (tile.flags & 16 /* TileFlag.Before */)
|
|
3156
3158
|
beforeBad = true;
|
|
@@ -3188,8 +3190,8 @@ class DocView {
|
|
|
3188
3190
|
}
|
|
3189
3191
|
return tile.coordsIn(offset, side);
|
|
3190
3192
|
}
|
|
3191
|
-
lineAt(pos) {
|
|
3192
|
-
let { tile } = this.tile.resolveBlock(pos,
|
|
3193
|
+
lineAt(pos, side) {
|
|
3194
|
+
let { tile } = this.tile.resolveBlock(pos, side);
|
|
3193
3195
|
return tile.isLine() ? tile : null;
|
|
3194
3196
|
}
|
|
3195
3197
|
coordsForChar(pos) {
|
|
@@ -3735,7 +3737,10 @@ function posAtCoords(view, coords, precise, scanY) {
|
|
|
3735
3737
|
if (block.type != BlockType.Text)
|
|
3736
3738
|
return yOffset < (block.top + block.bottom) / 2 ? new PosAssoc(block.from, 1) : new PosAssoc(block.to, -1);
|
|
3737
3739
|
// Here we know we're in a line, so run the logic for inline layout
|
|
3738
|
-
|
|
3740
|
+
let line = view.docView.lineAt(block.from, 2);
|
|
3741
|
+
if (!line || line.length != block.length)
|
|
3742
|
+
line = view.docView.lineAt(block.from, -2);
|
|
3743
|
+
return posAtCoordsInline(view, line, block.from, x, y);
|
|
3739
3744
|
}
|
|
3740
3745
|
// Scan through the rectangles for the content of a tile, finding the
|
|
3741
3746
|
// one closest to the given coordinates, prefering closeness in Y over
|
|
@@ -4654,7 +4659,8 @@ function eventBelongsToEditor(view, event) {
|
|
|
4654
4659
|
if (event.defaultPrevented)
|
|
4655
4660
|
return false;
|
|
4656
4661
|
for (let node = event.target, tile; node != view.contentDOM; node = node.parentNode)
|
|
4657
|
-
if (!node || node.nodeType == 11 ||
|
|
4662
|
+
if (!node || node.nodeType == 11 ||
|
|
4663
|
+
((tile = Tile.get(node)) && tile.isWidget() && !tile.isHidden && tile.widget.ignoreEvent(event)))
|
|
4658
4664
|
return false;
|
|
4659
4665
|
return true;
|
|
4660
4666
|
}
|
|
@@ -4773,42 +4779,13 @@ function rangeForClick(view, pos, bias, type) {
|
|
|
4773
4779
|
return groupAt(view.state, pos, bias);
|
|
4774
4780
|
}
|
|
4775
4781
|
else { // Triple click
|
|
4776
|
-
let visual = view.docView.lineAt(pos), line = view.state.doc.lineAt(visual ? visual.posAtEnd : pos);
|
|
4782
|
+
let visual = view.docView.lineAt(pos, bias), line = view.state.doc.lineAt(visual ? visual.posAtEnd : pos);
|
|
4777
4783
|
let from = visual ? visual.posAtStart : line.from, to = visual ? visual.posAtEnd : line.to;
|
|
4778
4784
|
if (to < view.state.doc.length && to == line.to)
|
|
4779
4785
|
to++;
|
|
4780
4786
|
return EditorSelection.range(from, to);
|
|
4781
4787
|
}
|
|
4782
4788
|
}
|
|
4783
|
-
let inside = (x, y, rect) => y >= rect.top && y <= rect.bottom && x >= rect.left && x <= rect.right;
|
|
4784
|
-
// Try to determine, for the given coordinates, associated with the
|
|
4785
|
-
// given position, whether they are related to the element before or
|
|
4786
|
-
// the element after the position.
|
|
4787
|
-
function findPositionSide(view, pos, x, y) {
|
|
4788
|
-
let line = view.docView.lineAt(pos);
|
|
4789
|
-
if (!line)
|
|
4790
|
-
return 1;
|
|
4791
|
-
let off = pos - line.posAtStart;
|
|
4792
|
-
// Line boundaries point into the line
|
|
4793
|
-
if (off == 0)
|
|
4794
|
-
return 1;
|
|
4795
|
-
if (off == line.length)
|
|
4796
|
-
return -1;
|
|
4797
|
-
// Positions on top of an element point at that element
|
|
4798
|
-
let before = line.coordsIn(off, -1);
|
|
4799
|
-
if (before && inside(x, y, before))
|
|
4800
|
-
return -1;
|
|
4801
|
-
let after = line.coordsIn(off, 1);
|
|
4802
|
-
if (after && inside(x, y, after))
|
|
4803
|
-
return 1;
|
|
4804
|
-
// This is probably a line wrap point. Pick before if the point is
|
|
4805
|
-
// above its bottom.
|
|
4806
|
-
return before && before.bottom >= y ? -1 : 1;
|
|
4807
|
-
}
|
|
4808
|
-
function queryPos(view, event) {
|
|
4809
|
-
let pos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
4810
|
-
return { pos, bias: findPositionSide(view, pos, event.clientX, event.clientY) };
|
|
4811
|
-
}
|
|
4812
4789
|
const BadMouseDetail = browser.ie && browser.ie_version <= 11;
|
|
4813
4790
|
let lastMouseDown = null, lastMouseDownCount = 0, lastMouseDownTime = 0;
|
|
4814
4791
|
function getClickType(event) {
|
|
@@ -4821,7 +4798,7 @@ function getClickType(event) {
|
|
|
4821
4798
|
Math.abs(last.clientY - event.clientY) < 2) ? (lastMouseDownCount + 1) % 3 : 1;
|
|
4822
4799
|
}
|
|
4823
4800
|
function basicMouseSelection(view, event) {
|
|
4824
|
-
let start =
|
|
4801
|
+
let start = view.posAndSideAtCoords({ x: event.clientX, y: event.clientY }, false), type = getClickType(event);
|
|
4825
4802
|
let startSel = view.state.selection;
|
|
4826
4803
|
return {
|
|
4827
4804
|
update(update) {
|
|
@@ -4831,10 +4808,10 @@ function basicMouseSelection(view, event) {
|
|
|
4831
4808
|
}
|
|
4832
4809
|
},
|
|
4833
4810
|
get(event, extend, multiple) {
|
|
4834
|
-
let cur =
|
|
4835
|
-
let range = rangeForClick(view, cur.pos, cur.
|
|
4811
|
+
let cur = view.posAndSideAtCoords({ x: event.clientX, y: event.clientY }, false), removed;
|
|
4812
|
+
let range = rangeForClick(view, cur.pos, cur.assoc, type);
|
|
4836
4813
|
if (start.pos != cur.pos && !extend) {
|
|
4837
|
-
let startRange = rangeForClick(view, start.pos, start.
|
|
4814
|
+
let startRange = rangeForClick(view, start.pos, start.assoc, type);
|
|
4838
4815
|
let from = Math.min(startRange.from, range.from), to = Math.max(startRange.to, range.to);
|
|
4839
4816
|
range = from < range.from ? EditorSelection.range(from, to) : EditorSelection.range(to, from);
|
|
4840
4817
|
}
|