@codemirror/view 6.39.8 → 6.39.10
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 +22 -0
- package/dist/index.cjs +30 -11
- package/dist/index.js +30 -11
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## 6.39.10 (2026-01-13)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix a regression in the way widget are reused when content next to them changes.
|
|
6
|
+
|
|
7
|
+
Make sure font metrics get recomputed on `fonts.ready` even if the line height doesn't change.
|
|
8
|
+
|
|
9
|
+
Fix an issue where compositions next to a widget that create a new text node could get needlessly interrupted during an editor update.
|
|
10
|
+
|
|
11
|
+
## 6.39.9 (2026-01-06)
|
|
12
|
+
|
|
13
|
+
### Bug fixes
|
|
14
|
+
|
|
15
|
+
Fix a bug where `EditorSelection.cursor()` with a non-zero `assoc` value would not be visually respected at soft-wrap boundaries on initial view creation.
|
|
16
|
+
|
|
17
|
+
Fix error caused by hover tooltips running a scheduled timeout after their editor has been destroyed.
|
|
18
|
+
|
|
19
|
+
Fix a bug that caused `EditorView.outerDecorations` to not affect the content height map.
|
|
20
|
+
|
|
21
|
+
Fix an issue where composition near a widget could get unnecessarily interrupted.
|
|
22
|
+
|
|
1
23
|
## 6.39.8 (2025-12-30)
|
|
2
24
|
|
|
3
25
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -2541,7 +2541,7 @@ class TileCache {
|
|
|
2541
2541
|
widgets.splice(i, 1);
|
|
2542
2542
|
if (i < this.index[0])
|
|
2543
2543
|
this.index[0]--;
|
|
2544
|
-
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) {
|
|
2545
2545
|
this.reused.set(tile, 1 /* Reused.Full */);
|
|
2546
2546
|
return tile;
|
|
2547
2547
|
}
|
|
@@ -2562,6 +2562,10 @@ class TileCache {
|
|
|
2562
2562
|
this.reused.set(tile, type);
|
|
2563
2563
|
return tile.dom;
|
|
2564
2564
|
}
|
|
2565
|
+
clear() {
|
|
2566
|
+
for (let i = 0; i < this.buckets.length; i++)
|
|
2567
|
+
this.buckets[i].length = this.index[i] = 0;
|
|
2568
|
+
}
|
|
2565
2569
|
}
|
|
2566
2570
|
// This class organizes a pass over the document, guided by the array
|
|
2567
2571
|
// of replaced ranges. For ranges that haven't changed, it iterates
|
|
@@ -2604,17 +2608,20 @@ class TileUpdate {
|
|
|
2604
2608
|
}
|
|
2605
2609
|
if (!next)
|
|
2606
2610
|
break;
|
|
2607
|
-
this.forward(next.fromA, next.toA);
|
|
2608
2611
|
// Compositions need to be handled specially, forcing the
|
|
2609
2612
|
// focused text node and its parent nodes to remain stable at
|
|
2610
2613
|
// that point in the document.
|
|
2611
2614
|
if (composition && next.fromA <= composition.range.fromA && next.toA >= composition.range.toA) {
|
|
2615
|
+
this.forward(next.fromA, composition.range.fromA, composition.range.fromA < composition.range.toA ? 1 : -1);
|
|
2612
2616
|
this.emit(posB, composition.range.fromB);
|
|
2617
|
+
this.cache.clear(); // Must not reuse DOM across composition
|
|
2613
2618
|
this.builder.addComposition(composition, compositionContext);
|
|
2614
2619
|
this.text.skip(composition.range.toB - composition.range.fromB);
|
|
2620
|
+
this.forward(composition.range.fromA, next.toA);
|
|
2615
2621
|
this.emit(composition.range.toB, next.toB);
|
|
2616
2622
|
}
|
|
2617
2623
|
else {
|
|
2624
|
+
this.forward(next.fromA, next.toA);
|
|
2618
2625
|
this.emit(posB, next.toB);
|
|
2619
2626
|
}
|
|
2620
2627
|
posB = next.toB;
|
|
@@ -2764,14 +2771,14 @@ class TileUpdate {
|
|
|
2764
2771
|
this.openWidget = openEnd > markCount;
|
|
2765
2772
|
this.openMarks = openEnd;
|
|
2766
2773
|
}
|
|
2767
|
-
forward(from, to) {
|
|
2774
|
+
forward(from, to, side = 1) {
|
|
2768
2775
|
if (to - from <= 10) {
|
|
2769
|
-
this.old.advance(to - from,
|
|
2776
|
+
this.old.advance(to - from, side, this.reuseWalker);
|
|
2770
2777
|
}
|
|
2771
2778
|
else {
|
|
2772
2779
|
this.old.advance(5, -1, this.reuseWalker);
|
|
2773
2780
|
this.old.advance(to - from - 10, -1);
|
|
2774
|
-
this.old.advance(5,
|
|
2781
|
+
this.old.advance(5, side, this.reuseWalker);
|
|
2775
2782
|
}
|
|
2776
2783
|
}
|
|
2777
2784
|
getCompositionContext(text) {
|
|
@@ -5193,7 +5200,8 @@ class HeightOracle {
|
|
|
5193
5200
|
}
|
|
5194
5201
|
refresh(whiteSpace, lineHeight, charWidth, textHeight, lineLength, knownHeights) {
|
|
5195
5202
|
let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
|
|
5196
|
-
let changed = Math.
|
|
5203
|
+
let changed = Math.abs(lineHeight - this.lineHeight) > 0.3 || this.lineWrapping != lineWrapping ||
|
|
5204
|
+
Math.abs(charWidth - this.charWidth) > 0.1;
|
|
5197
5205
|
this.lineWrapping = lineWrapping;
|
|
5198
5206
|
this.lineHeight = lineHeight;
|
|
5199
5207
|
this.charWidth = charWidth;
|
|
@@ -6027,7 +6035,7 @@ class ViewState {
|
|
|
6027
6035
|
this.mustEnforceCursorAssoc = false;
|
|
6028
6036
|
let guessWrapping = state$1.facet(contentAttributes).some(v => typeof v != "function" && v.class == "cm-lineWrapping");
|
|
6029
6037
|
this.heightOracle = new HeightOracle(guessWrapping);
|
|
6030
|
-
this.stateDeco = state$1
|
|
6038
|
+
this.stateDeco = staticDeco(state$1);
|
|
6031
6039
|
this.heightMap = HeightMap.empty().applyChanges(this.stateDeco, state.Text.empty, this.heightOracle.setDoc(state$1.doc), [new ChangedRange(0, 0, 0, state$1.doc.length)]);
|
|
6032
6040
|
for (let i = 0; i < 2; i++) {
|
|
6033
6041
|
this.viewport = this.getViewport(0, null);
|
|
@@ -6066,7 +6074,7 @@ class ViewState {
|
|
|
6066
6074
|
update(update, scrollTarget = null) {
|
|
6067
6075
|
this.state = update.state;
|
|
6068
6076
|
let prevDeco = this.stateDeco;
|
|
6069
|
-
this.stateDeco = this.state
|
|
6077
|
+
this.stateDeco = staticDeco(this.state);
|
|
6070
6078
|
let contentChanges = update.changedRanges;
|
|
6071
6079
|
let heightChanges = ChangedRange.extendWithRanges(contentChanges, heightRelevantDecoChanges(prevDeco, this.stateDeco, update ? update.changes : state.ChangeSet.empty(this.state.doc.length)));
|
|
6072
6080
|
let prevHeight = this.heightMap.height;
|
|
@@ -6097,7 +6105,7 @@ class ViewState {
|
|
|
6097
6105
|
update.flags |= this.computeVisibleRanges(update.changes);
|
|
6098
6106
|
if (scrollTarget)
|
|
6099
6107
|
this.scrollTarget = scrollTarget;
|
|
6100
|
-
if (!this.mustEnforceCursorAssoc && update.selectionSet && update.view.lineWrapping &&
|
|
6108
|
+
if (!this.mustEnforceCursorAssoc && (update.selectionSet || update.focusChanged) && update.view.lineWrapping &&
|
|
6101
6109
|
update.state.selection.main.empty && update.state.selection.main.assoc &&
|
|
6102
6110
|
!update.state.facet(nativeSelectionHidden))
|
|
6103
6111
|
this.mustEnforceCursorAssoc = true;
|
|
@@ -6107,7 +6115,7 @@ class ViewState {
|
|
|
6107
6115
|
let oracle = this.heightOracle;
|
|
6108
6116
|
let whiteSpace = style.whiteSpace;
|
|
6109
6117
|
this.defaultTextDirection = style.direction == "rtl" ? exports.Direction.RTL : exports.Direction.LTR;
|
|
6110
|
-
let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace);
|
|
6118
|
+
let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace) || this.mustMeasureContent;
|
|
6111
6119
|
let domRect = dom.getBoundingClientRect();
|
|
6112
6120
|
let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != domRect.height;
|
|
6113
6121
|
this.contentDOMHeight = domRect.height;
|
|
@@ -6495,6 +6503,13 @@ const IdScaler = {
|
|
|
6495
6503
|
scale: 1,
|
|
6496
6504
|
eq(other) { return other == this; }
|
|
6497
6505
|
};
|
|
6506
|
+
function staticDeco(state$1) {
|
|
6507
|
+
let deco = state$1.facet(decorations).filter(d => typeof d != "function");
|
|
6508
|
+
let outer = state$1.facet(outerDecorations).filter(d => typeof d != "function");
|
|
6509
|
+
if (outer.length)
|
|
6510
|
+
deco.push(state.RangeSet.join(outer));
|
|
6511
|
+
return deco;
|
|
6512
|
+
}
|
|
6498
6513
|
// When the height is too big (> VP.MaxDOMHeight), scale down the
|
|
6499
6514
|
// regions outside the viewports so that the total height is
|
|
6500
6515
|
// VP.MaxDOMHeight.
|
|
@@ -7676,7 +7691,10 @@ class EditorView {
|
|
|
7676
7691
|
this.updateState = 0 /* UpdateState.Idle */;
|
|
7677
7692
|
this.requestMeasure();
|
|
7678
7693
|
if ((_a = document.fonts) === null || _a === void 0 ? void 0 : _a.ready)
|
|
7679
|
-
document.fonts.ready.then(() =>
|
|
7694
|
+
document.fonts.ready.then(() => {
|
|
7695
|
+
this.viewState.mustMeasureContent = true;
|
|
7696
|
+
this.requestMeasure();
|
|
7697
|
+
});
|
|
7680
7698
|
}
|
|
7681
7699
|
dispatch(...input) {
|
|
7682
7700
|
let trs = input.length == 1 && input[0] instanceof state.Transaction ? input
|
|
@@ -10524,6 +10542,7 @@ class HoverPlugin {
|
|
|
10524
10542
|
}
|
|
10525
10543
|
destroy() {
|
|
10526
10544
|
clearTimeout(this.hoverTimeout);
|
|
10545
|
+
clearTimeout(this.restartTimeout);
|
|
10527
10546
|
this.view.dom.removeEventListener("mouseleave", this.mouseleave);
|
|
10528
10547
|
this.view.dom.removeEventListener("mousemove", this.mousemove);
|
|
10529
10548
|
}
|
package/dist/index.js
CHANGED
|
@@ -2537,7 +2537,7 @@ class TileCache {
|
|
|
2537
2537
|
widgets.splice(i, 1);
|
|
2538
2538
|
if (i < this.index[0])
|
|
2539
2539
|
this.index[0]--;
|
|
2540
|
-
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) {
|
|
2541
2541
|
this.reused.set(tile, 1 /* Reused.Full */);
|
|
2542
2542
|
return tile;
|
|
2543
2543
|
}
|
|
@@ -2558,6 +2558,10 @@ class TileCache {
|
|
|
2558
2558
|
this.reused.set(tile, type);
|
|
2559
2559
|
return tile.dom;
|
|
2560
2560
|
}
|
|
2561
|
+
clear() {
|
|
2562
|
+
for (let i = 0; i < this.buckets.length; i++)
|
|
2563
|
+
this.buckets[i].length = this.index[i] = 0;
|
|
2564
|
+
}
|
|
2561
2565
|
}
|
|
2562
2566
|
// This class organizes a pass over the document, guided by the array
|
|
2563
2567
|
// of replaced ranges. For ranges that haven't changed, it iterates
|
|
@@ -2600,17 +2604,20 @@ class TileUpdate {
|
|
|
2600
2604
|
}
|
|
2601
2605
|
if (!next)
|
|
2602
2606
|
break;
|
|
2603
|
-
this.forward(next.fromA, next.toA);
|
|
2604
2607
|
// Compositions need to be handled specially, forcing the
|
|
2605
2608
|
// focused text node and its parent nodes to remain stable at
|
|
2606
2609
|
// that point in the document.
|
|
2607
2610
|
if (composition && next.fromA <= composition.range.fromA && next.toA >= composition.range.toA) {
|
|
2611
|
+
this.forward(next.fromA, composition.range.fromA, composition.range.fromA < composition.range.toA ? 1 : -1);
|
|
2608
2612
|
this.emit(posB, composition.range.fromB);
|
|
2613
|
+
this.cache.clear(); // Must not reuse DOM across composition
|
|
2609
2614
|
this.builder.addComposition(composition, compositionContext);
|
|
2610
2615
|
this.text.skip(composition.range.toB - composition.range.fromB);
|
|
2616
|
+
this.forward(composition.range.fromA, next.toA);
|
|
2611
2617
|
this.emit(composition.range.toB, next.toB);
|
|
2612
2618
|
}
|
|
2613
2619
|
else {
|
|
2620
|
+
this.forward(next.fromA, next.toA);
|
|
2614
2621
|
this.emit(posB, next.toB);
|
|
2615
2622
|
}
|
|
2616
2623
|
posB = next.toB;
|
|
@@ -2760,14 +2767,14 @@ class TileUpdate {
|
|
|
2760
2767
|
this.openWidget = openEnd > markCount;
|
|
2761
2768
|
this.openMarks = openEnd;
|
|
2762
2769
|
}
|
|
2763
|
-
forward(from, to) {
|
|
2770
|
+
forward(from, to, side = 1) {
|
|
2764
2771
|
if (to - from <= 10) {
|
|
2765
|
-
this.old.advance(to - from,
|
|
2772
|
+
this.old.advance(to - from, side, this.reuseWalker);
|
|
2766
2773
|
}
|
|
2767
2774
|
else {
|
|
2768
2775
|
this.old.advance(5, -1, this.reuseWalker);
|
|
2769
2776
|
this.old.advance(to - from - 10, -1);
|
|
2770
|
-
this.old.advance(5,
|
|
2777
|
+
this.old.advance(5, side, this.reuseWalker);
|
|
2771
2778
|
}
|
|
2772
2779
|
}
|
|
2773
2780
|
getCompositionContext(text) {
|
|
@@ -5189,7 +5196,8 @@ class HeightOracle {
|
|
|
5189
5196
|
}
|
|
5190
5197
|
refresh(whiteSpace, lineHeight, charWidth, textHeight, lineLength, knownHeights) {
|
|
5191
5198
|
let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
|
|
5192
|
-
let changed = Math.
|
|
5199
|
+
let changed = Math.abs(lineHeight - this.lineHeight) > 0.3 || this.lineWrapping != lineWrapping ||
|
|
5200
|
+
Math.abs(charWidth - this.charWidth) > 0.1;
|
|
5193
5201
|
this.lineWrapping = lineWrapping;
|
|
5194
5202
|
this.lineHeight = lineHeight;
|
|
5195
5203
|
this.charWidth = charWidth;
|
|
@@ -6022,7 +6030,7 @@ class ViewState {
|
|
|
6022
6030
|
this.mustEnforceCursorAssoc = false;
|
|
6023
6031
|
let guessWrapping = state.facet(contentAttributes).some(v => typeof v != "function" && v.class == "cm-lineWrapping");
|
|
6024
6032
|
this.heightOracle = new HeightOracle(guessWrapping);
|
|
6025
|
-
this.stateDeco = state
|
|
6033
|
+
this.stateDeco = staticDeco(state);
|
|
6026
6034
|
this.heightMap = HeightMap.empty().applyChanges(this.stateDeco, Text.empty, this.heightOracle.setDoc(state.doc), [new ChangedRange(0, 0, 0, state.doc.length)]);
|
|
6027
6035
|
for (let i = 0; i < 2; i++) {
|
|
6028
6036
|
this.viewport = this.getViewport(0, null);
|
|
@@ -6061,7 +6069,7 @@ class ViewState {
|
|
|
6061
6069
|
update(update, scrollTarget = null) {
|
|
6062
6070
|
this.state = update.state;
|
|
6063
6071
|
let prevDeco = this.stateDeco;
|
|
6064
|
-
this.stateDeco = this.state
|
|
6072
|
+
this.stateDeco = staticDeco(this.state);
|
|
6065
6073
|
let contentChanges = update.changedRanges;
|
|
6066
6074
|
let heightChanges = ChangedRange.extendWithRanges(contentChanges, heightRelevantDecoChanges(prevDeco, this.stateDeco, update ? update.changes : ChangeSet.empty(this.state.doc.length)));
|
|
6067
6075
|
let prevHeight = this.heightMap.height;
|
|
@@ -6092,7 +6100,7 @@ class ViewState {
|
|
|
6092
6100
|
update.flags |= this.computeVisibleRanges(update.changes);
|
|
6093
6101
|
if (scrollTarget)
|
|
6094
6102
|
this.scrollTarget = scrollTarget;
|
|
6095
|
-
if (!this.mustEnforceCursorAssoc && update.selectionSet && update.view.lineWrapping &&
|
|
6103
|
+
if (!this.mustEnforceCursorAssoc && (update.selectionSet || update.focusChanged) && update.view.lineWrapping &&
|
|
6096
6104
|
update.state.selection.main.empty && update.state.selection.main.assoc &&
|
|
6097
6105
|
!update.state.facet(nativeSelectionHidden))
|
|
6098
6106
|
this.mustEnforceCursorAssoc = true;
|
|
@@ -6102,7 +6110,7 @@ class ViewState {
|
|
|
6102
6110
|
let oracle = this.heightOracle;
|
|
6103
6111
|
let whiteSpace = style.whiteSpace;
|
|
6104
6112
|
this.defaultTextDirection = style.direction == "rtl" ? Direction.RTL : Direction.LTR;
|
|
6105
|
-
let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace);
|
|
6113
|
+
let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace) || this.mustMeasureContent;
|
|
6106
6114
|
let domRect = dom.getBoundingClientRect();
|
|
6107
6115
|
let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != domRect.height;
|
|
6108
6116
|
this.contentDOMHeight = domRect.height;
|
|
@@ -6490,6 +6498,13 @@ const IdScaler = {
|
|
|
6490
6498
|
scale: 1,
|
|
6491
6499
|
eq(other) { return other == this; }
|
|
6492
6500
|
};
|
|
6501
|
+
function staticDeco(state) {
|
|
6502
|
+
let deco = state.facet(decorations).filter(d => typeof d != "function");
|
|
6503
|
+
let outer = state.facet(outerDecorations).filter(d => typeof d != "function");
|
|
6504
|
+
if (outer.length)
|
|
6505
|
+
deco.push(RangeSet.join(outer));
|
|
6506
|
+
return deco;
|
|
6507
|
+
}
|
|
6493
6508
|
// When the height is too big (> VP.MaxDOMHeight), scale down the
|
|
6494
6509
|
// regions outside the viewports so that the total height is
|
|
6495
6510
|
// VP.MaxDOMHeight.
|
|
@@ -7671,7 +7686,10 @@ class EditorView {
|
|
|
7671
7686
|
this.updateState = 0 /* UpdateState.Idle */;
|
|
7672
7687
|
this.requestMeasure();
|
|
7673
7688
|
if ((_a = document.fonts) === null || _a === void 0 ? void 0 : _a.ready)
|
|
7674
|
-
document.fonts.ready.then(() =>
|
|
7689
|
+
document.fonts.ready.then(() => {
|
|
7690
|
+
this.viewState.mustMeasureContent = true;
|
|
7691
|
+
this.requestMeasure();
|
|
7692
|
+
});
|
|
7675
7693
|
}
|
|
7676
7694
|
dispatch(...input) {
|
|
7677
7695
|
let trs = input.length == 1 && input[0] instanceof Transaction ? input
|
|
@@ -10519,6 +10537,7 @@ class HoverPlugin {
|
|
|
10519
10537
|
}
|
|
10520
10538
|
destroy() {
|
|
10521
10539
|
clearTimeout(this.hoverTimeout);
|
|
10540
|
+
clearTimeout(this.restartTimeout);
|
|
10522
10541
|
this.view.dom.removeEventListener("mouseleave", this.mouseleave);
|
|
10523
10542
|
this.view.dom.removeEventListener("mousemove", this.mousemove);
|
|
10524
10543
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemirror/view",
|
|
3
|
-
"version": "6.39.
|
|
3
|
+
"version": "6.39.10",
|
|
4
4
|
"description": "DOM view component for the CodeMirror code editor",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "cm-runtests",
|
|
@@ -36,6 +36,6 @@
|
|
|
36
36
|
},
|
|
37
37
|
"repository": {
|
|
38
38
|
"type": "git",
|
|
39
|
-
"url": "https://github.com/codemirror/view.git"
|
|
39
|
+
"url": "git+https://github.com/codemirror/view.git"
|
|
40
40
|
}
|
|
41
41
|
}
|