@codemirror/view 6.39.9 → 6.39.11
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 +16 -0
- package/dist/index.cjs +29 -21
- package/dist/index.js +29 -21
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## 6.39.11 (2026-01-14)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Avoid handling copy events for parent editors.
|
|
6
|
+
|
|
7
|
+
## 6.39.10 (2026-01-13)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Fix a regression in the way widget are reused when content next to them changes.
|
|
12
|
+
|
|
13
|
+
Make sure font metrics get recomputed on `fonts.ready` even if the line height doesn't change.
|
|
14
|
+
|
|
15
|
+
Fix an issue where compositions next to a widget that create a new text node could get needlessly interrupted during an editor update.
|
|
16
|
+
|
|
1
17
|
## 6.39.9 (2026-01-06)
|
|
2
18
|
|
|
3
19
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -2502,8 +2502,6 @@ class TileCache {
|
|
|
2502
2502
|
}
|
|
2503
2503
|
// Put a tile in the cache.
|
|
2504
2504
|
add(tile) {
|
|
2505
|
-
if (tile.demo)
|
|
2506
|
-
console.log("Add widget to cache");
|
|
2507
2505
|
let i = tile.constructor.bucket, bucket = this.buckets[i];
|
|
2508
2506
|
if (bucket.length < 6 /* C.Bucket */)
|
|
2509
2507
|
bucket.push(tile);
|
|
@@ -2528,8 +2526,6 @@ class TileCache {
|
|
|
2528
2526
|
}
|
|
2529
2527
|
findWidget(widget, length, flags) {
|
|
2530
2528
|
let widgets = this.buckets[0];
|
|
2531
|
-
if (widget.demo)
|
|
2532
|
-
console.log("looking for widget", widget, "in cache", widgets.slice());
|
|
2533
2529
|
if (widgets.length)
|
|
2534
2530
|
for (let i = 0, pass = 0;; i++) {
|
|
2535
2531
|
if (i == widgets.length) {
|
|
@@ -2545,7 +2541,7 @@ class TileCache {
|
|
|
2545
2541
|
widgets.splice(i, 1);
|
|
2546
2542
|
if (i < this.index[0])
|
|
2547
2543
|
this.index[0]--;
|
|
2548
|
-
if (tile.length == length && (tile.flags & (496 /* TileFlag.Widget */ | 1 /* TileFlag.BreakAfter */)) == flags) {
|
|
2544
|
+
if (tile.widget == widget && tile.length == length && (tile.flags & (496 /* TileFlag.Widget */ | 1 /* TileFlag.BreakAfter */)) == flags) {
|
|
2549
2545
|
this.reused.set(tile, 1 /* Reused.Full */);
|
|
2550
2546
|
return tile;
|
|
2551
2547
|
}
|
|
@@ -2616,7 +2612,7 @@ class TileUpdate {
|
|
|
2616
2612
|
// focused text node and its parent nodes to remain stable at
|
|
2617
2613
|
// that point in the document.
|
|
2618
2614
|
if (composition && next.fromA <= composition.range.fromA && next.toA >= composition.range.toA) {
|
|
2619
|
-
this.forward(next.fromA, composition.range.fromA);
|
|
2615
|
+
this.forward(next.fromA, composition.range.fromA, composition.range.fromA < composition.range.toA ? 1 : -1);
|
|
2620
2616
|
this.emit(posB, composition.range.fromB);
|
|
2621
2617
|
this.cache.clear(); // Must not reuse DOM across composition
|
|
2622
2618
|
this.builder.addComposition(composition, compositionContext);
|
|
@@ -2775,14 +2771,14 @@ class TileUpdate {
|
|
|
2775
2771
|
this.openWidget = openEnd > markCount;
|
|
2776
2772
|
this.openMarks = openEnd;
|
|
2777
2773
|
}
|
|
2778
|
-
forward(from, to) {
|
|
2774
|
+
forward(from, to, side = 1) {
|
|
2779
2775
|
if (to - from <= 10) {
|
|
2780
|
-
this.old.advance(to - from,
|
|
2776
|
+
this.old.advance(to - from, side, this.reuseWalker);
|
|
2781
2777
|
}
|
|
2782
2778
|
else {
|
|
2783
2779
|
this.old.advance(5, -1, this.reuseWalker);
|
|
2784
2780
|
this.old.advance(to - from - 10, -1);
|
|
2785
|
-
this.old.advance(5,
|
|
2781
|
+
this.old.advance(5, side, this.reuseWalker);
|
|
2786
2782
|
}
|
|
2787
2783
|
}
|
|
2788
2784
|
getCompositionContext(text) {
|
|
@@ -3678,11 +3674,8 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3678
3674
|
}
|
|
3679
3675
|
let resolvedGoal = rect.left + goal;
|
|
3680
3676
|
let dist = distance !== null && distance !== void 0 ? distance : (view.viewState.heightOracle.textHeight >> 1);
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
let pos = posAtCoords(view, { x: resolvedGoal, y: curY }, false, dir);
|
|
3684
|
-
return state.EditorSelection.cursor(pos.pos, pos.assoc, undefined, goal);
|
|
3685
|
-
}
|
|
3677
|
+
let pos = posAtCoords(view, { x: resolvedGoal, y: startY + dist * dir }, false, dir);
|
|
3678
|
+
return state.EditorSelection.cursor(pos.pos, pos.assoc, undefined, goal);
|
|
3686
3679
|
}
|
|
3687
3680
|
function skipAtomicRanges(atoms, pos, bias) {
|
|
3688
3681
|
for (;;) {
|
|
@@ -4092,7 +4085,7 @@ function applyDOMChange(view, domChange) {
|
|
|
4092
4085
|
insert: state.Text.of(domChange.text.slice(diff.from, diff.toB).split(LineBreakPlaceholder)) };
|
|
4093
4086
|
}
|
|
4094
4087
|
}
|
|
4095
|
-
else if (newSel && (!view.hasFocus && view.state.facet(editable) || newSel
|
|
4088
|
+
else if (newSel && (!view.hasFocus && view.state.facet(editable) || sameSelPos(newSel, sel))) {
|
|
4096
4089
|
newSel = null;
|
|
4097
4090
|
}
|
|
4098
4091
|
if (!change && !newSel)
|
|
@@ -4144,7 +4137,7 @@ function applyDOMChange(view, domChange) {
|
|
|
4144
4137
|
if (change) {
|
|
4145
4138
|
return applyDOMChangeInner(view, change, newSel, lastKey);
|
|
4146
4139
|
}
|
|
4147
|
-
else if (newSel && !newSel
|
|
4140
|
+
else if (newSel && !sameSelPos(newSel, sel)) {
|
|
4148
4141
|
let scrollIntoView = false, userEvent = "select";
|
|
4149
4142
|
if (view.inputState.lastSelectionTime > Date.now() - 50) {
|
|
4150
4143
|
if (view.inputState.lastSelectionOrigin == "select")
|
|
@@ -4315,6 +4308,9 @@ function selectionFromPoints(points, base) {
|
|
|
4315
4308
|
let anchor = points[0].pos, head = points.length == 2 ? points[1].pos : anchor;
|
|
4316
4309
|
return anchor > -1 && head > -1 ? state.EditorSelection.single(anchor + base, head + base) : null;
|
|
4317
4310
|
}
|
|
4311
|
+
function sameSelPos(selection, range) {
|
|
4312
|
+
return range.head == selection.main.head && range.anchor == selection.main.anchor;
|
|
4313
|
+
}
|
|
4318
4314
|
|
|
4319
4315
|
class InputState {
|
|
4320
4316
|
setSelectionOrigin(origin) {
|
|
@@ -4997,6 +4993,14 @@ function copiedRange(state) {
|
|
|
4997
4993
|
}
|
|
4998
4994
|
let lastLinewiseCopy = null;
|
|
4999
4995
|
handlers.copy = handlers.cut = (view, event) => {
|
|
4996
|
+
// If the DOM selection is outside this editor, don't intercept.
|
|
4997
|
+
// This happens when a parent editor (like ProseMirror) selects content that
|
|
4998
|
+
// spans multiple elements including this CodeMirror. The copy event may
|
|
4999
|
+
// bubble through CodeMirror (e.g. when CodeMirror is the first or the last
|
|
5000
|
+
// element in the selection), but we should let the parent handle it.
|
|
5001
|
+
let domSel = getSelection(view.root);
|
|
5002
|
+
if (domSel && !hasSelection(view.contentDOM, domSel))
|
|
5003
|
+
return false;
|
|
5000
5004
|
let { text, ranges, linewise } = copiedRange(view.state);
|
|
5001
5005
|
if (!text && !linewise)
|
|
5002
5006
|
return false;
|
|
@@ -5204,7 +5208,8 @@ class HeightOracle {
|
|
|
5204
5208
|
}
|
|
5205
5209
|
refresh(whiteSpace, lineHeight, charWidth, textHeight, lineLength, knownHeights) {
|
|
5206
5210
|
let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
|
|
5207
|
-
let changed = Math.
|
|
5211
|
+
let changed = Math.abs(lineHeight - this.lineHeight) > 0.3 || this.lineWrapping != lineWrapping ||
|
|
5212
|
+
Math.abs(charWidth - this.charWidth) > 0.1;
|
|
5208
5213
|
this.lineWrapping = lineWrapping;
|
|
5209
5214
|
this.lineHeight = lineHeight;
|
|
5210
5215
|
this.charWidth = charWidth;
|
|
@@ -6118,7 +6123,7 @@ class ViewState {
|
|
|
6118
6123
|
let oracle = this.heightOracle;
|
|
6119
6124
|
let whiteSpace = style.whiteSpace;
|
|
6120
6125
|
this.defaultTextDirection = style.direction == "rtl" ? exports.Direction.RTL : exports.Direction.LTR;
|
|
6121
|
-
let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace);
|
|
6126
|
+
let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace) || this.mustMeasureContent;
|
|
6122
6127
|
let domRect = dom.getBoundingClientRect();
|
|
6123
6128
|
let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != domRect.height;
|
|
6124
6129
|
this.contentDOMHeight = domRect.height;
|
|
@@ -7229,7 +7234,7 @@ class DOMObserver {
|
|
|
7229
7234
|
let handled = applyDOMChange(this.view, domChange);
|
|
7230
7235
|
// The view wasn't updated but DOM/selection changes were seen. Reset the view.
|
|
7231
7236
|
if (this.view.state == startState &&
|
|
7232
|
-
(domChange.domChanged || domChange.newSel && !
|
|
7237
|
+
(domChange.domChanged || domChange.newSel && !sameSelPos(this.view.state.selection, domChange.newSel.main)))
|
|
7233
7238
|
this.view.update([]);
|
|
7234
7239
|
return handled;
|
|
7235
7240
|
}
|
|
@@ -7393,7 +7398,7 @@ class EditContextManager {
|
|
|
7393
7398
|
// Edit contexts sometimes fire empty changes
|
|
7394
7399
|
if (!diff) {
|
|
7395
7400
|
let newSel = state.EditorSelection.single(this.toEditorPos(e.selectionStart), this.toEditorPos(e.selectionEnd));
|
|
7396
|
-
if (!newSel
|
|
7401
|
+
if (!sameSelPos(newSel, main))
|
|
7397
7402
|
view.dispatch({ selection: newSel, userEvent: "select" });
|
|
7398
7403
|
return;
|
|
7399
7404
|
}
|
|
@@ -7694,7 +7699,10 @@ class EditorView {
|
|
|
7694
7699
|
this.updateState = 0 /* UpdateState.Idle */;
|
|
7695
7700
|
this.requestMeasure();
|
|
7696
7701
|
if ((_a = document.fonts) === null || _a === void 0 ? void 0 : _a.ready)
|
|
7697
|
-
document.fonts.ready.then(() =>
|
|
7702
|
+
document.fonts.ready.then(() => {
|
|
7703
|
+
this.viewState.mustMeasureContent = true;
|
|
7704
|
+
this.requestMeasure();
|
|
7705
|
+
});
|
|
7698
7706
|
}
|
|
7699
7707
|
dispatch(...input) {
|
|
7700
7708
|
let trs = input.length == 1 && input[0] instanceof state.Transaction ? input
|
package/dist/index.js
CHANGED
|
@@ -2498,8 +2498,6 @@ class TileCache {
|
|
|
2498
2498
|
}
|
|
2499
2499
|
// Put a tile in the cache.
|
|
2500
2500
|
add(tile) {
|
|
2501
|
-
if (tile.demo)
|
|
2502
|
-
console.log("Add widget to cache");
|
|
2503
2501
|
let i = tile.constructor.bucket, bucket = this.buckets[i];
|
|
2504
2502
|
if (bucket.length < 6 /* C.Bucket */)
|
|
2505
2503
|
bucket.push(tile);
|
|
@@ -2524,8 +2522,6 @@ class TileCache {
|
|
|
2524
2522
|
}
|
|
2525
2523
|
findWidget(widget, length, flags) {
|
|
2526
2524
|
let widgets = this.buckets[0];
|
|
2527
|
-
if (widget.demo)
|
|
2528
|
-
console.log("looking for widget", widget, "in cache", widgets.slice());
|
|
2529
2525
|
if (widgets.length)
|
|
2530
2526
|
for (let i = 0, pass = 0;; i++) {
|
|
2531
2527
|
if (i == widgets.length) {
|
|
@@ -2541,7 +2537,7 @@ class TileCache {
|
|
|
2541
2537
|
widgets.splice(i, 1);
|
|
2542
2538
|
if (i < this.index[0])
|
|
2543
2539
|
this.index[0]--;
|
|
2544
|
-
if (tile.length == length && (tile.flags & (496 /* TileFlag.Widget */ | 1 /* TileFlag.BreakAfter */)) == flags) {
|
|
2540
|
+
if (tile.widget == widget && tile.length == length && (tile.flags & (496 /* TileFlag.Widget */ | 1 /* TileFlag.BreakAfter */)) == flags) {
|
|
2545
2541
|
this.reused.set(tile, 1 /* Reused.Full */);
|
|
2546
2542
|
return tile;
|
|
2547
2543
|
}
|
|
@@ -2612,7 +2608,7 @@ class TileUpdate {
|
|
|
2612
2608
|
// focused text node and its parent nodes to remain stable at
|
|
2613
2609
|
// that point in the document.
|
|
2614
2610
|
if (composition && next.fromA <= composition.range.fromA && next.toA >= composition.range.toA) {
|
|
2615
|
-
this.forward(next.fromA, composition.range.fromA);
|
|
2611
|
+
this.forward(next.fromA, composition.range.fromA, composition.range.fromA < composition.range.toA ? 1 : -1);
|
|
2616
2612
|
this.emit(posB, composition.range.fromB);
|
|
2617
2613
|
this.cache.clear(); // Must not reuse DOM across composition
|
|
2618
2614
|
this.builder.addComposition(composition, compositionContext);
|
|
@@ -2771,14 +2767,14 @@ class TileUpdate {
|
|
|
2771
2767
|
this.openWidget = openEnd > markCount;
|
|
2772
2768
|
this.openMarks = openEnd;
|
|
2773
2769
|
}
|
|
2774
|
-
forward(from, to) {
|
|
2770
|
+
forward(from, to, side = 1) {
|
|
2775
2771
|
if (to - from <= 10) {
|
|
2776
|
-
this.old.advance(to - from,
|
|
2772
|
+
this.old.advance(to - from, side, this.reuseWalker);
|
|
2777
2773
|
}
|
|
2778
2774
|
else {
|
|
2779
2775
|
this.old.advance(5, -1, this.reuseWalker);
|
|
2780
2776
|
this.old.advance(to - from - 10, -1);
|
|
2781
|
-
this.old.advance(5,
|
|
2777
|
+
this.old.advance(5, side, this.reuseWalker);
|
|
2782
2778
|
}
|
|
2783
2779
|
}
|
|
2784
2780
|
getCompositionContext(text) {
|
|
@@ -3674,11 +3670,8 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3674
3670
|
}
|
|
3675
3671
|
let resolvedGoal = rect.left + goal;
|
|
3676
3672
|
let dist = distance !== null && distance !== void 0 ? distance : (view.viewState.heightOracle.textHeight >> 1);
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
let pos = posAtCoords(view, { x: resolvedGoal, y: curY }, false, dir);
|
|
3680
|
-
return EditorSelection.cursor(pos.pos, pos.assoc, undefined, goal);
|
|
3681
|
-
}
|
|
3673
|
+
let pos = posAtCoords(view, { x: resolvedGoal, y: startY + dist * dir }, false, dir);
|
|
3674
|
+
return EditorSelection.cursor(pos.pos, pos.assoc, undefined, goal);
|
|
3682
3675
|
}
|
|
3683
3676
|
function skipAtomicRanges(atoms, pos, bias) {
|
|
3684
3677
|
for (;;) {
|
|
@@ -4088,7 +4081,7 @@ function applyDOMChange(view, domChange) {
|
|
|
4088
4081
|
insert: Text.of(domChange.text.slice(diff.from, diff.toB).split(LineBreakPlaceholder)) };
|
|
4089
4082
|
}
|
|
4090
4083
|
}
|
|
4091
|
-
else if (newSel && (!view.hasFocus && view.state.facet(editable) || newSel
|
|
4084
|
+
else if (newSel && (!view.hasFocus && view.state.facet(editable) || sameSelPos(newSel, sel))) {
|
|
4092
4085
|
newSel = null;
|
|
4093
4086
|
}
|
|
4094
4087
|
if (!change && !newSel)
|
|
@@ -4140,7 +4133,7 @@ function applyDOMChange(view, domChange) {
|
|
|
4140
4133
|
if (change) {
|
|
4141
4134
|
return applyDOMChangeInner(view, change, newSel, lastKey);
|
|
4142
4135
|
}
|
|
4143
|
-
else if (newSel && !newSel
|
|
4136
|
+
else if (newSel && !sameSelPos(newSel, sel)) {
|
|
4144
4137
|
let scrollIntoView = false, userEvent = "select";
|
|
4145
4138
|
if (view.inputState.lastSelectionTime > Date.now() - 50) {
|
|
4146
4139
|
if (view.inputState.lastSelectionOrigin == "select")
|
|
@@ -4311,6 +4304,9 @@ function selectionFromPoints(points, base) {
|
|
|
4311
4304
|
let anchor = points[0].pos, head = points.length == 2 ? points[1].pos : anchor;
|
|
4312
4305
|
return anchor > -1 && head > -1 ? EditorSelection.single(anchor + base, head + base) : null;
|
|
4313
4306
|
}
|
|
4307
|
+
function sameSelPos(selection, range) {
|
|
4308
|
+
return range.head == selection.main.head && range.anchor == selection.main.anchor;
|
|
4309
|
+
}
|
|
4314
4310
|
|
|
4315
4311
|
class InputState {
|
|
4316
4312
|
setSelectionOrigin(origin) {
|
|
@@ -4993,6 +4989,14 @@ function copiedRange(state) {
|
|
|
4993
4989
|
}
|
|
4994
4990
|
let lastLinewiseCopy = null;
|
|
4995
4991
|
handlers.copy = handlers.cut = (view, event) => {
|
|
4992
|
+
// If the DOM selection is outside this editor, don't intercept.
|
|
4993
|
+
// This happens when a parent editor (like ProseMirror) selects content that
|
|
4994
|
+
// spans multiple elements including this CodeMirror. The copy event may
|
|
4995
|
+
// bubble through CodeMirror (e.g. when CodeMirror is the first or the last
|
|
4996
|
+
// element in the selection), but we should let the parent handle it.
|
|
4997
|
+
let domSel = getSelection(view.root);
|
|
4998
|
+
if (domSel && !hasSelection(view.contentDOM, domSel))
|
|
4999
|
+
return false;
|
|
4996
5000
|
let { text, ranges, linewise } = copiedRange(view.state);
|
|
4997
5001
|
if (!text && !linewise)
|
|
4998
5002
|
return false;
|
|
@@ -5200,7 +5204,8 @@ class HeightOracle {
|
|
|
5200
5204
|
}
|
|
5201
5205
|
refresh(whiteSpace, lineHeight, charWidth, textHeight, lineLength, knownHeights) {
|
|
5202
5206
|
let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
|
|
5203
|
-
let changed = Math.
|
|
5207
|
+
let changed = Math.abs(lineHeight - this.lineHeight) > 0.3 || this.lineWrapping != lineWrapping ||
|
|
5208
|
+
Math.abs(charWidth - this.charWidth) > 0.1;
|
|
5204
5209
|
this.lineWrapping = lineWrapping;
|
|
5205
5210
|
this.lineHeight = lineHeight;
|
|
5206
5211
|
this.charWidth = charWidth;
|
|
@@ -6113,7 +6118,7 @@ class ViewState {
|
|
|
6113
6118
|
let oracle = this.heightOracle;
|
|
6114
6119
|
let whiteSpace = style.whiteSpace;
|
|
6115
6120
|
this.defaultTextDirection = style.direction == "rtl" ? Direction.RTL : Direction.LTR;
|
|
6116
|
-
let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace);
|
|
6121
|
+
let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace) || this.mustMeasureContent;
|
|
6117
6122
|
let domRect = dom.getBoundingClientRect();
|
|
6118
6123
|
let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != domRect.height;
|
|
6119
6124
|
this.contentDOMHeight = domRect.height;
|
|
@@ -7224,7 +7229,7 @@ class DOMObserver {
|
|
|
7224
7229
|
let handled = applyDOMChange(this.view, domChange);
|
|
7225
7230
|
// The view wasn't updated but DOM/selection changes were seen. Reset the view.
|
|
7226
7231
|
if (this.view.state == startState &&
|
|
7227
|
-
(domChange.domChanged || domChange.newSel && !
|
|
7232
|
+
(domChange.domChanged || domChange.newSel && !sameSelPos(this.view.state.selection, domChange.newSel.main)))
|
|
7228
7233
|
this.view.update([]);
|
|
7229
7234
|
return handled;
|
|
7230
7235
|
}
|
|
@@ -7388,7 +7393,7 @@ class EditContextManager {
|
|
|
7388
7393
|
// Edit contexts sometimes fire empty changes
|
|
7389
7394
|
if (!diff) {
|
|
7390
7395
|
let newSel = EditorSelection.single(this.toEditorPos(e.selectionStart), this.toEditorPos(e.selectionEnd));
|
|
7391
|
-
if (!newSel
|
|
7396
|
+
if (!sameSelPos(newSel, main))
|
|
7392
7397
|
view.dispatch({ selection: newSel, userEvent: "select" });
|
|
7393
7398
|
return;
|
|
7394
7399
|
}
|
|
@@ -7689,7 +7694,10 @@ class EditorView {
|
|
|
7689
7694
|
this.updateState = 0 /* UpdateState.Idle */;
|
|
7690
7695
|
this.requestMeasure();
|
|
7691
7696
|
if ((_a = document.fonts) === null || _a === void 0 ? void 0 : _a.ready)
|
|
7692
|
-
document.fonts.ready.then(() =>
|
|
7697
|
+
document.fonts.ready.then(() => {
|
|
7698
|
+
this.viewState.mustMeasureContent = true;
|
|
7699
|
+
this.requestMeasure();
|
|
7700
|
+
});
|
|
7693
7701
|
}
|
|
7694
7702
|
dispatch(...input) {
|
|
7695
7703
|
let trs = input.length == 1 && input[0] instanceof Transaction ? input
|