@codemirror/view 0.19.21 → 0.19.25
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 +46 -0
- package/dist/index.cjs +276 -181
- package/dist/index.d.ts +69 -17
- package/dist/index.js +276 -181
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1082,8 +1082,9 @@ class Decoration extends RangeValue {
|
|
|
1082
1082
|
position.
|
|
1083
1083
|
*/
|
|
1084
1084
|
static widget(spec) {
|
|
1085
|
-
let side = spec.side || 0;
|
|
1086
|
-
|
|
1085
|
+
let side = spec.side || 0, block = !!spec.block;
|
|
1086
|
+
side += block ? (side > 0 ? 300000000 /* BlockAfter */ : -400000000 /* BlockBefore */) : (side > 0 ? 100000000 /* InlineAfter */ : -100000000 /* InlineBefore */);
|
|
1087
|
+
return new PointDecoration(spec, side, side, block, spec.widget || null, false);
|
|
1087
1088
|
}
|
|
1088
1089
|
/**
|
|
1089
1090
|
Create a replace decoration which replaces the given range with
|
|
@@ -1092,8 +1093,8 @@ class Decoration extends RangeValue {
|
|
|
1092
1093
|
static replace(spec) {
|
|
1093
1094
|
let block = !!spec.block;
|
|
1094
1095
|
let { start, end } = getInclusive(spec, block);
|
|
1095
|
-
let startSide =
|
|
1096
|
-
let endSide =
|
|
1096
|
+
let startSide = block ? (start ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 400000000 /* NonIncStart */;
|
|
1097
|
+
let endSide = block ? (end ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -500000000 /* NonIncEnd */;
|
|
1097
1098
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1098
1099
|
}
|
|
1099
1100
|
/**
|
|
@@ -1123,7 +1124,7 @@ Decoration.none = RangeSet.empty;
|
|
|
1123
1124
|
class MarkDecoration extends Decoration {
|
|
1124
1125
|
constructor(spec) {
|
|
1125
1126
|
let { start, end } = getInclusive(spec);
|
|
1126
|
-
super(
|
|
1127
|
+
super(start ? -1 /* InlineIncStart */ : 400000000 /* NonIncStart */, end ? 1 /* InlineIncEnd */ : -500000000 /* NonIncEnd */, null, spec);
|
|
1127
1128
|
this.tagName = spec.tagName || "span";
|
|
1128
1129
|
this.class = spec.class || "";
|
|
1129
1130
|
this.attrs = spec.attributes || null;
|
|
@@ -1144,7 +1145,7 @@ class MarkDecoration extends Decoration {
|
|
|
1144
1145
|
MarkDecoration.prototype.point = false;
|
|
1145
1146
|
class LineDecoration extends Decoration {
|
|
1146
1147
|
constructor(spec) {
|
|
1147
|
-
super(-
|
|
1148
|
+
super(-200000000 /* Line */, -200000000 /* Line */, null, spec);
|
|
1148
1149
|
}
|
|
1149
1150
|
eq(other) {
|
|
1150
1151
|
return other instanceof LineDecoration && attrsEq(this.spec.attributes, other.spec.attributes);
|
|
@@ -1723,36 +1724,39 @@ class PluginInstance {
|
|
|
1723
1724
|
this.value = null;
|
|
1724
1725
|
}
|
|
1725
1726
|
takeField(type, target) {
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1727
|
+
if (this.spec)
|
|
1728
|
+
for (let { field, get } of this.spec.fields)
|
|
1729
|
+
if (field == type)
|
|
1730
|
+
target.push(get(this.value));
|
|
1729
1731
|
}
|
|
1730
1732
|
update(view) {
|
|
1731
1733
|
if (!this.value) {
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1734
|
+
if (this.spec) {
|
|
1735
|
+
try {
|
|
1736
|
+
this.value = this.spec.create(view);
|
|
1737
|
+
}
|
|
1738
|
+
catch (e) {
|
|
1739
|
+
logException(view.state, e, "CodeMirror plugin crashed");
|
|
1740
|
+
this.deactivate();
|
|
1741
|
+
}
|
|
1738
1742
|
}
|
|
1739
1743
|
}
|
|
1740
1744
|
else if (this.mustUpdate) {
|
|
1741
1745
|
let update = this.mustUpdate;
|
|
1742
1746
|
this.mustUpdate = null;
|
|
1743
|
-
if (
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1747
|
+
if (this.value.update) {
|
|
1748
|
+
try {
|
|
1749
|
+
this.value.update(update);
|
|
1750
|
+
}
|
|
1751
|
+
catch (e) {
|
|
1752
|
+
logException(update.state, e, "CodeMirror plugin crashed");
|
|
1753
|
+
if (this.value.destroy)
|
|
1754
|
+
try {
|
|
1755
|
+
this.value.destroy();
|
|
1756
|
+
}
|
|
1757
|
+
catch (_) { }
|
|
1758
|
+
this.deactivate();
|
|
1759
|
+
}
|
|
1756
1760
|
}
|
|
1757
1761
|
}
|
|
1758
1762
|
return this;
|
|
@@ -1768,20 +1772,12 @@ class PluginInstance {
|
|
|
1768
1772
|
}
|
|
1769
1773
|
}
|
|
1770
1774
|
}
|
|
1775
|
+
deactivate() {
|
|
1776
|
+
this.spec = this.value = null;
|
|
1777
|
+
}
|
|
1771
1778
|
}
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
let result = {};
|
|
1775
|
-
for (let i = values.length - 1; i >= 0; i--)
|
|
1776
|
-
combineAttrs(values[i], result);
|
|
1777
|
-
return result;
|
|
1778
|
-
}
|
|
1779
|
-
const editorAttributes = /*@__PURE__*/Facet.define({
|
|
1780
|
-
combine: combineFacetAttrs
|
|
1781
|
-
});
|
|
1782
|
-
const contentAttributes = /*@__PURE__*/Facet.define({
|
|
1783
|
-
combine: combineFacetAttrs
|
|
1784
|
-
});
|
|
1779
|
+
const editorAttributes = /*@__PURE__*/Facet.define();
|
|
1780
|
+
const contentAttributes = /*@__PURE__*/Facet.define();
|
|
1785
1781
|
// Provide decorations
|
|
1786
1782
|
const decorations = /*@__PURE__*/Facet.define();
|
|
1787
1783
|
const styleModule = /*@__PURE__*/Facet.define();
|
|
@@ -1908,7 +1904,7 @@ class ViewUpdate {
|
|
|
1908
1904
|
Whether the document changed in this update.
|
|
1909
1905
|
*/
|
|
1910
1906
|
get docChanged() {
|
|
1911
|
-
return this.
|
|
1907
|
+
return !this.changes.empty;
|
|
1912
1908
|
}
|
|
1913
1909
|
/**
|
|
1914
1910
|
Whether the selection was explicitly set in this update.
|
|
@@ -1929,12 +1925,12 @@ class DocView extends ContentView {
|
|
|
1929
1925
|
this.compositionDeco = Decoration.none;
|
|
1930
1926
|
this.decorations = [];
|
|
1931
1927
|
// Track a minimum width for the editor. When measuring sizes in
|
|
1932
|
-
//
|
|
1933
|
-
// element and its extent in the document. When a change
|
|
1934
|
-
// that range, these are reset. That way, once we've seen
|
|
1935
|
-
// line/element of a given length, we keep the editor wide enough
|
|
1936
|
-
// fit at least that element, until it is changed, at which point
|
|
1937
|
-
// forget it again.
|
|
1928
|
+
// measureVisibleLineHeights, this is updated to point at the width
|
|
1929
|
+
// of a given element and its extent in the document. When a change
|
|
1930
|
+
// happens in that range, these are reset. That way, once we've seen
|
|
1931
|
+
// a line/element of a given length, we keep the editor wide enough
|
|
1932
|
+
// to fit at least that element, until it is changed, at which point
|
|
1933
|
+
// we forget it again.
|
|
1938
1934
|
this.minWidth = 0;
|
|
1939
1935
|
this.minWidthFrom = 0;
|
|
1940
1936
|
this.minWidthTo = 0;
|
|
@@ -1984,10 +1980,7 @@ class DocView extends ContentView {
|
|
|
1984
1980
|
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
1985
1981
|
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
1986
1982
|
changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
|
|
1987
|
-
if (this.dirty == 0 /* Not */ && changedRanges.length == 0
|
|
1988
|
-
!(update.flags & 4 /* Viewport */) &&
|
|
1989
|
-
update.state.selection.main.from >= this.view.viewport.from &&
|
|
1990
|
-
update.state.selection.main.to <= this.view.viewport.to) {
|
|
1983
|
+
if (this.dirty == 0 /* Not */ && changedRanges.length == 0) {
|
|
1991
1984
|
return false;
|
|
1992
1985
|
}
|
|
1993
1986
|
else {
|
|
@@ -2007,9 +2000,10 @@ class DocView extends ContentView {
|
|
|
2007
2000
|
this.updateSelection();
|
|
2008
2001
|
}
|
|
2009
2002
|
}
|
|
2010
|
-
// Used
|
|
2003
|
+
// Used by update and the constructor do perform the actual DOM
|
|
2011
2004
|
// update
|
|
2012
2005
|
updateInner(changes, deco, oldLength) {
|
|
2006
|
+
this.view.viewState.mustMeasureContent = true;
|
|
2013
2007
|
this.updateChildren(changes, deco, oldLength);
|
|
2014
2008
|
let { observer } = this.view;
|
|
2015
2009
|
observer.ignore(() => {
|
|
@@ -2017,7 +2011,7 @@ class DocView extends ContentView {
|
|
|
2017
2011
|
// messes with the scroll position during DOM mutation (though
|
|
2018
2012
|
// no relayout is triggered and I cannot imagine how it can
|
|
2019
2013
|
// recompute the scroll position without a layout)
|
|
2020
|
-
this.dom.style.height = this.view.viewState.
|
|
2014
|
+
this.dom.style.height = this.view.viewState.contentHeight + "px";
|
|
2021
2015
|
this.dom.style.minWidth = this.minWidth ? this.minWidth + "px" : "";
|
|
2022
2016
|
// Chrome will sometimes, when DOM mutations occur directly
|
|
2023
2017
|
// around the selection, get confused and report a different
|
|
@@ -2302,7 +2296,7 @@ class DocView extends ContentView {
|
|
|
2302
2296
|
let next = i == vs.viewports.length ? null : vs.viewports[i];
|
|
2303
2297
|
let end = next ? next.from - 1 : this.length;
|
|
2304
2298
|
if (end > pos) {
|
|
2305
|
-
let height = vs.
|
|
2299
|
+
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
2306
2300
|
deco.push(Decoration.replace({ widget: new BlockGapWidget(height), block: true, inclusive: true }).range(pos, end));
|
|
2307
2301
|
}
|
|
2308
2302
|
if (!next)
|
|
@@ -2908,13 +2902,14 @@ function domPosInText(node, x, y) {
|
|
|
2908
2902
|
}
|
|
2909
2903
|
function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
2910
2904
|
var _a;
|
|
2911
|
-
let content = view.contentDOM.getBoundingClientRect(),
|
|
2905
|
+
let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
|
|
2912
2906
|
let halfLine = view.defaultLineHeight / 2;
|
|
2907
|
+
let block, yOffset = y - docTop;
|
|
2913
2908
|
for (let bounced = false;;) {
|
|
2914
|
-
block = view.
|
|
2915
|
-
if (block.top >
|
|
2916
|
-
bias = block.top >
|
|
2917
|
-
|
|
2909
|
+
block = view.elementAtHeight(yOffset);
|
|
2910
|
+
if (block.top > yOffset || block.bottom < yOffset) {
|
|
2911
|
+
bias = block.top > yOffset ? -1 : 1;
|
|
2912
|
+
yOffset = Math.min(block.bottom - halfLine, Math.max(block.top + halfLine, yOffset));
|
|
2918
2913
|
if (bounced)
|
|
2919
2914
|
return precise ? null : 0;
|
|
2920
2915
|
else
|
|
@@ -2922,11 +2917,12 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
2922
2917
|
}
|
|
2923
2918
|
if (block.type == BlockType.Text)
|
|
2924
2919
|
break;
|
|
2925
|
-
|
|
2920
|
+
yOffset = bias > 0 ? block.bottom + halfLine : block.top - halfLine;
|
|
2926
2921
|
}
|
|
2922
|
+
y = docTop + yOffset;
|
|
2927
2923
|
let lineStart = block.from;
|
|
2928
2924
|
// Clip x to the viewport sides
|
|
2929
|
-
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
2925
|
+
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
2930
2926
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
2931
2927
|
if (lineStart < view.viewport.from)
|
|
2932
2928
|
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
@@ -3036,17 +3032,17 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3036
3032
|
return EditorSelection.cursor(startPos);
|
|
3037
3033
|
let goal = start.goalColumn, startY;
|
|
3038
3034
|
let rect = view.contentDOM.getBoundingClientRect();
|
|
3039
|
-
let startCoords = view.coordsAtPos(startPos);
|
|
3035
|
+
let startCoords = view.coordsAtPos(startPos), docTop = view.documentTop;
|
|
3040
3036
|
if (startCoords) {
|
|
3041
3037
|
if (goal == null)
|
|
3042
3038
|
goal = startCoords.left - rect.left;
|
|
3043
3039
|
startY = dir < 0 ? startCoords.top : startCoords.bottom;
|
|
3044
3040
|
}
|
|
3045
3041
|
else {
|
|
3046
|
-
let line = view.viewState.
|
|
3042
|
+
let line = view.viewState.lineBlockAt(startPos - docTop);
|
|
3047
3043
|
if (goal == null)
|
|
3048
3044
|
goal = Math.min(rect.right - rect.left, view.defaultCharacterWidth * (startPos - line.from));
|
|
3049
|
-
startY = dir < 0 ? line.top : line.bottom;
|
|
3045
|
+
startY = (dir < 0 ? line.top : line.bottom) + docTop;
|
|
3050
3046
|
}
|
|
3051
3047
|
let resolvedGoal = rect.left + goal;
|
|
3052
3048
|
let dist = distance !== null && distance !== void 0 ? distance : (view.defaultLineHeight >> 1);
|
|
@@ -3297,7 +3293,7 @@ class MouseSelection {
|
|
|
3297
3293
|
this.extend = startEvent.shiftKey;
|
|
3298
3294
|
this.multiple = view.state.facet(EditorState.allowMultipleSelections) && addsSelectionRange(view, startEvent);
|
|
3299
3295
|
this.dragMove = dragMovesSelection(view, startEvent);
|
|
3300
|
-
this.dragging = isInPrimarySelection(view, startEvent) ? null : false;
|
|
3296
|
+
this.dragging = isInPrimarySelection(view, startEvent) && getClickType(startEvent) == 1 ? null : false;
|
|
3301
3297
|
// When clicking outside of the selection, immediately apply the
|
|
3302
3298
|
// effect of starting the selection
|
|
3303
3299
|
if (this.dragging === false) {
|
|
@@ -3518,7 +3514,7 @@ function basicMouseSelection(view, event) {
|
|
|
3518
3514
|
let last = start, lastEvent = event;
|
|
3519
3515
|
return {
|
|
3520
3516
|
update(update) {
|
|
3521
|
-
if (update.
|
|
3517
|
+
if (update.docChanged) {
|
|
3522
3518
|
if (start)
|
|
3523
3519
|
start.pos = update.changes.mapPos(start.pos);
|
|
3524
3520
|
startSel = startSel.map(update.changes);
|
|
@@ -3782,7 +3778,10 @@ class HeightOracle {
|
|
|
3782
3778
|
return lines * this.lineHeight;
|
|
3783
3779
|
}
|
|
3784
3780
|
setDoc(doc) { this.doc = doc; return this; }
|
|
3785
|
-
|
|
3781
|
+
mustRefreshForStyle(whiteSpace, direction) {
|
|
3782
|
+
return (wrappingWhiteSpace.indexOf(whiteSpace) > -1) != this.lineWrapping || this.direction != direction;
|
|
3783
|
+
}
|
|
3784
|
+
mustRefreshForHeights(lineHeights) {
|
|
3786
3785
|
let newHeight = false;
|
|
3787
3786
|
for (let i = 0; i < lineHeights.length; i++) {
|
|
3788
3787
|
let h = lineHeights[i];
|
|
@@ -3794,7 +3793,7 @@ class HeightOracle {
|
|
|
3794
3793
|
this.heightSamples[Math.floor(h * 10)] = true;
|
|
3795
3794
|
}
|
|
3796
3795
|
}
|
|
3797
|
-
return newHeight
|
|
3796
|
+
return newHeight;
|
|
3798
3797
|
}
|
|
3799
3798
|
refresh(whiteSpace, direction, lineHeight, charWidth, lineLength, knownHeights) {
|
|
3800
3799
|
let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
|
|
@@ -3848,7 +3847,8 @@ class BlockInfo {
|
|
|
3848
3847
|
*/
|
|
3849
3848
|
length,
|
|
3850
3849
|
/**
|
|
3851
|
-
The top position of the element
|
|
3850
|
+
The top position of the element (relative to the top of the
|
|
3851
|
+
document).
|
|
3852
3852
|
*/
|
|
3853
3853
|
top,
|
|
3854
3854
|
/**
|
|
@@ -3882,13 +3882,19 @@ class BlockInfo {
|
|
|
3882
3882
|
.concat(Array.isArray(other.type) ? other.type : [other]);
|
|
3883
3883
|
return new BlockInfo(this.from, this.length + other.length, this.top, this.height + other.height, detail);
|
|
3884
3884
|
}
|
|
3885
|
+
/**
|
|
3886
|
+
FIXME remove on next breaking release @internal
|
|
3887
|
+
*/
|
|
3888
|
+
moveY(offset) {
|
|
3889
|
+
return !offset ? this : new BlockInfo(this.from, this.length, this.top + offset, this.height, Array.isArray(this.type) ? this.type.map(b => b.moveY(offset)) : this.type);
|
|
3890
|
+
}
|
|
3885
3891
|
}
|
|
3886
3892
|
var QueryType = /*@__PURE__*/(function (QueryType) {
|
|
3887
3893
|
QueryType[QueryType["ByPos"] = 0] = "ByPos";
|
|
3888
3894
|
QueryType[QueryType["ByHeight"] = 1] = "ByHeight";
|
|
3889
3895
|
QueryType[QueryType["ByPosNoHeight"] = 2] = "ByPosNoHeight";
|
|
3890
3896
|
return QueryType})(QueryType || (QueryType = {}));
|
|
3891
|
-
const Epsilon = 1e-
|
|
3897
|
+
const Epsilon = 1e-3;
|
|
3892
3898
|
class HeightMap {
|
|
3893
3899
|
constructor(length, // The number of characters covered
|
|
3894
3900
|
height, // Height of this part of the document
|
|
@@ -4115,22 +4121,30 @@ class HeightMapGap extends HeightMap {
|
|
|
4115
4121
|
// can't be widgets or collapsed ranges in those lines, because
|
|
4116
4122
|
// they would already have been added to the heightmap (gaps
|
|
4117
4123
|
// only contain plain text).
|
|
4118
|
-
let nodes = [], pos = Math.max(offset, measured.from);
|
|
4124
|
+
let nodes = [], pos = Math.max(offset, measured.from), singleHeight = -1;
|
|
4125
|
+
let wasChanged = oracle.heightChanged;
|
|
4119
4126
|
if (measured.from > offset)
|
|
4120
4127
|
nodes.push(new HeightMapGap(measured.from - offset - 1).updateHeight(oracle, offset));
|
|
4121
4128
|
while (pos <= end && measured.more) {
|
|
4122
4129
|
let len = oracle.doc.lineAt(pos).length;
|
|
4123
4130
|
if (nodes.length)
|
|
4124
4131
|
nodes.push(null);
|
|
4125
|
-
let
|
|
4132
|
+
let height = measured.heights[measured.index++];
|
|
4133
|
+
if (singleHeight == -1)
|
|
4134
|
+
singleHeight = height;
|
|
4135
|
+
else if (Math.abs(height - singleHeight) >= Epsilon)
|
|
4136
|
+
singleHeight = -2;
|
|
4137
|
+
let line = new HeightMapText(len, height);
|
|
4126
4138
|
line.outdated = false;
|
|
4127
4139
|
nodes.push(line);
|
|
4128
4140
|
pos += len + 1;
|
|
4129
4141
|
}
|
|
4130
4142
|
if (pos <= end)
|
|
4131
4143
|
nodes.push(null, new HeightMapGap(end - pos).updateHeight(oracle, pos));
|
|
4132
|
-
|
|
4133
|
-
|
|
4144
|
+
let result = HeightMap.of(nodes);
|
|
4145
|
+
oracle.heightChanged = wasChanged || singleHeight < 0 || Math.abs(result.height - this.height) >= Epsilon ||
|
|
4146
|
+
Math.abs(singleHeight - this.lines(oracle.doc, offset).lineHeight) >= Epsilon;
|
|
4147
|
+
return result;
|
|
4134
4148
|
}
|
|
4135
4149
|
else if (force || this.outdated) {
|
|
4136
4150
|
this.setHeight(oracle, oracle.heightForGap(offset, offset + this.length));
|
|
@@ -4488,7 +4502,8 @@ class ViewState {
|
|
|
4488
4502
|
this.inView = true;
|
|
4489
4503
|
this.paddingTop = 0;
|
|
4490
4504
|
this.paddingBottom = 0;
|
|
4491
|
-
this.
|
|
4505
|
+
this.contentDOMWidth = 0;
|
|
4506
|
+
this.contentDOMHeight = 0;
|
|
4492
4507
|
this.editorHeight = 0;
|
|
4493
4508
|
this.heightOracle = new HeightOracle;
|
|
4494
4509
|
// See VP.MaxDOMHeight
|
|
@@ -4496,6 +4511,9 @@ class ViewState {
|
|
|
4496
4511
|
this.scrollTarget = null;
|
|
4497
4512
|
// Briefly set to true when printing, to disable viewport limiting
|
|
4498
4513
|
this.printing = false;
|
|
4514
|
+
// Flag set when editor content was redrawn, so that the next
|
|
4515
|
+
// measure stage knows it must read DOM layout
|
|
4516
|
+
this.mustMeasureContent = true;
|
|
4499
4517
|
this.visibleRanges = [];
|
|
4500
4518
|
// Cursor 'assoc' is only significant when the cursor is on a line
|
|
4501
4519
|
// wrap point, where it must stick to the character that it is
|
|
@@ -4508,6 +4526,7 @@ class ViewState {
|
|
|
4508
4526
|
this.mustEnforceCursorAssoc = false;
|
|
4509
4527
|
this.heightMap = HeightMap.empty().applyChanges(state.facet(decorations), Text.empty, this.heightOracle.setDoc(state.doc), [new ChangedRange(0, 0, 0, state.doc.length)]);
|
|
4510
4528
|
this.viewport = this.getViewport(0, null);
|
|
4529
|
+
this.updateViewportLines();
|
|
4511
4530
|
this.updateForViewport();
|
|
4512
4531
|
this.lineGaps = this.ensureLineGaps([]);
|
|
4513
4532
|
this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(false)));
|
|
@@ -4518,7 +4537,7 @@ class ViewState {
|
|
|
4518
4537
|
for (let i = 0; i <= 1; i++) {
|
|
4519
4538
|
let pos = i ? main.head : main.anchor;
|
|
4520
4539
|
if (!viewports.some(({ from, to }) => pos >= from && pos <= to)) {
|
|
4521
|
-
let { from, to } = this.
|
|
4540
|
+
let { from, to } = this.lineBlockAt(pos);
|
|
4522
4541
|
viewports.push(new Viewport(from, to));
|
|
4523
4542
|
}
|
|
4524
4543
|
}
|
|
@@ -4526,6 +4545,12 @@ class ViewState {
|
|
|
4526
4545
|
this.scaler = this.heightMap.height <= 7000000 /* MaxDOMHeight */ ? IdScaler :
|
|
4527
4546
|
new BigScaler(this.heightOracle.doc, this.heightMap, this.viewports);
|
|
4528
4547
|
}
|
|
4548
|
+
updateViewportLines() {
|
|
4549
|
+
this.viewportLines = [];
|
|
4550
|
+
this.heightMap.forEachLine(this.viewport.from, this.viewport.to, this.state.doc, 0, 0, block => {
|
|
4551
|
+
this.viewportLines.push(this.scaler.scale == 1 ? block : scaleBlock(block, this.scaler));
|
|
4552
|
+
});
|
|
4553
|
+
}
|
|
4529
4554
|
update(update, scrollTarget = null) {
|
|
4530
4555
|
let prev = this.state;
|
|
4531
4556
|
this.state = update.state;
|
|
@@ -4540,7 +4565,11 @@ class ViewState {
|
|
|
4540
4565
|
if (scrollTarget && (scrollTarget.range.head < viewport.from || scrollTarget.range.head > viewport.to) ||
|
|
4541
4566
|
!this.viewportIsAppropriate(viewport))
|
|
4542
4567
|
viewport = this.getViewport(0, scrollTarget);
|
|
4568
|
+
let updateLines = !update.changes.empty || (update.flags & 2 /* Height */) ||
|
|
4569
|
+
viewport.from != this.viewport.from || viewport.to != this.viewport.to;
|
|
4543
4570
|
this.viewport = viewport;
|
|
4571
|
+
if (updateLines)
|
|
4572
|
+
this.updateViewportLines();
|
|
4544
4573
|
this.updateForViewport();
|
|
4545
4574
|
if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
|
|
4546
4575
|
this.updateLineGaps(this.ensureLineGaps(this.mapLineGaps(this.lineGaps, update.changes)));
|
|
@@ -4551,13 +4580,17 @@ class ViewState {
|
|
|
4551
4580
|
update.state.selection.main.empty && update.state.selection.main.assoc)
|
|
4552
4581
|
this.mustEnforceCursorAssoc = true;
|
|
4553
4582
|
}
|
|
4554
|
-
measure(
|
|
4555
|
-
let dom =
|
|
4556
|
-
let
|
|
4557
|
-
|
|
4583
|
+
measure(view) {
|
|
4584
|
+
let dom = view.contentDOM, style = window.getComputedStyle(dom);
|
|
4585
|
+
let oracle = this.heightOracle;
|
|
4586
|
+
let whiteSpace = style.whiteSpace, direction = style.direction == "rtl" ? Direction.RTL : Direction.LTR;
|
|
4587
|
+
let refresh = this.heightOracle.mustRefreshForStyle(whiteSpace, direction);
|
|
4588
|
+
let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != dom.clientHeight;
|
|
4589
|
+
let result = 0, bias = 0;
|
|
4590
|
+
if (measureContent) {
|
|
4591
|
+
this.mustMeasureContent = false;
|
|
4592
|
+
this.contentDOMHeight = dom.clientHeight;
|
|
4558
4593
|
// Vertical padding
|
|
4559
|
-
let style = window.getComputedStyle(dom);
|
|
4560
|
-
whiteSpace = style.whiteSpace, direction = (style.direction == "rtl" ? Direction.RTL : Direction.LTR);
|
|
4561
4594
|
let paddingTop = parseInt(style.paddingTop) || 0, paddingBottom = parseInt(style.paddingBottom) || 0;
|
|
4562
4595
|
if (this.paddingTop != paddingTop || this.paddingBottom != paddingBottom) {
|
|
4563
4596
|
result |= 8 /* Geometry */;
|
|
@@ -4572,39 +4605,42 @@ class ViewState {
|
|
|
4572
4605
|
this.inView = this.pixelViewport.bottom > this.pixelViewport.top && this.pixelViewport.right > this.pixelViewport.left;
|
|
4573
4606
|
if (!this.inView)
|
|
4574
4607
|
return 0;
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
let { lineHeight, charWidth } = docView.measureTextSize();
|
|
4608
|
+
if (measureContent) {
|
|
4609
|
+
let lineHeights = view.docView.measureVisibleLineHeights();
|
|
4610
|
+
if (oracle.mustRefreshForHeights(lineHeights))
|
|
4611
|
+
refresh = true;
|
|
4612
|
+
let contentWidth = dom.clientWidth;
|
|
4613
|
+
if (refresh || oracle.lineWrapping && Math.abs(contentWidth - this.contentDOMWidth) > oracle.charWidth) {
|
|
4614
|
+
let { lineHeight, charWidth } = view.docView.measureTextSize();
|
|
4582
4615
|
refresh = oracle.refresh(whiteSpace, direction, lineHeight, charWidth, contentWidth / charWidth, lineHeights);
|
|
4583
4616
|
if (refresh) {
|
|
4584
|
-
docView.minWidth = 0;
|
|
4617
|
+
view.docView.minWidth = 0;
|
|
4585
4618
|
result |= 8 /* Geometry */;
|
|
4586
4619
|
}
|
|
4587
4620
|
}
|
|
4588
|
-
if (this.
|
|
4589
|
-
this.
|
|
4621
|
+
if (this.contentDOMWidth != contentWidth) {
|
|
4622
|
+
this.contentDOMWidth = contentWidth;
|
|
4590
4623
|
result |= 8 /* Geometry */;
|
|
4591
4624
|
}
|
|
4592
|
-
if (this.editorHeight !=
|
|
4593
|
-
this.editorHeight =
|
|
4625
|
+
if (this.editorHeight != view.scrollDOM.clientHeight) {
|
|
4626
|
+
this.editorHeight = view.scrollDOM.clientHeight;
|
|
4594
4627
|
result |= 8 /* Geometry */;
|
|
4595
4628
|
}
|
|
4596
4629
|
if (dTop > 0 && dBottom > 0)
|
|
4597
4630
|
bias = Math.max(dTop, dBottom);
|
|
4598
4631
|
else if (dTop < 0 && dBottom < 0)
|
|
4599
4632
|
bias = Math.min(dTop, dBottom);
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from || this.scrollTarget.range.head > this.viewport.to)
|
|
4633
|
+
oracle.heightChanged = false;
|
|
4634
|
+
this.heightMap = this.heightMap.updateHeight(oracle, 0, refresh, new MeasuredHeights(this.viewport.from, lineHeights));
|
|
4635
|
+
if (oracle.heightChanged)
|
|
4636
|
+
result |= 2 /* Height */;
|
|
4637
|
+
}
|
|
4638
|
+
let viewportChange = !this.viewportIsAppropriate(this.viewport, bias) ||
|
|
4639
|
+
this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from || this.scrollTarget.range.head > this.viewport.to);
|
|
4640
|
+
if (viewportChange)
|
|
4607
4641
|
this.viewport = this.getViewport(bias, this.scrollTarget);
|
|
4642
|
+
if ((result & 2 /* Height */) || viewportChange)
|
|
4643
|
+
this.updateViewportLines();
|
|
4608
4644
|
this.updateForViewport();
|
|
4609
4645
|
if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
|
|
4610
4646
|
this.updateLineGaps(this.ensureLineGaps(refresh ? [] : this.lineGaps));
|
|
@@ -4615,12 +4651,12 @@ class ViewState {
|
|
|
4615
4651
|
// to a line end is going to trigger a layout anyway, so it
|
|
4616
4652
|
// can't be a pure write. It should be rare that it does any
|
|
4617
4653
|
// writing.
|
|
4618
|
-
docView.enforceCursorAssoc();
|
|
4654
|
+
view.docView.enforceCursorAssoc();
|
|
4619
4655
|
}
|
|
4620
4656
|
return result;
|
|
4621
4657
|
}
|
|
4622
|
-
get visibleTop() { return this.scaler.fromDOM(this.pixelViewport.top
|
|
4623
|
-
get visibleBottom() { return this.scaler.fromDOM(this.pixelViewport.bottom
|
|
4658
|
+
get visibleTop() { return this.scaler.fromDOM(this.pixelViewport.top); }
|
|
4659
|
+
get visibleBottom() { return this.scaler.fromDOM(this.pixelViewport.bottom); }
|
|
4624
4660
|
getViewport(bias, scrollTarget) {
|
|
4625
4661
|
// This will divide VP.Margin between the top and the
|
|
4626
4662
|
// bottom, depending on the bias (the change in viewport position
|
|
@@ -4680,12 +4716,12 @@ class ViewState {
|
|
|
4680
4716
|
// This won't work at all in predominantly right-to-left text.
|
|
4681
4717
|
if (this.heightOracle.direction != Direction.LTR)
|
|
4682
4718
|
return gaps;
|
|
4683
|
-
|
|
4719
|
+
for (let line of this.viewportLines) {
|
|
4684
4720
|
if (line.length < 4000 /* DoubleMargin */)
|
|
4685
|
-
|
|
4721
|
+
continue;
|
|
4686
4722
|
let structure = lineStructure(line.from, line.to, this.state);
|
|
4687
4723
|
if (structure.total < 4000 /* DoubleMargin */)
|
|
4688
|
-
|
|
4724
|
+
continue;
|
|
4689
4725
|
let viewFrom, viewTo;
|
|
4690
4726
|
if (this.heightOracle.lineWrapping) {
|
|
4691
4727
|
let marginHeight = (2000 /* Margin */ / this.heightOracle.lineLength) * this.heightOracle.lineHeight;
|
|
@@ -4715,7 +4751,7 @@ class ViewState {
|
|
|
4715
4751
|
Math.abs(gap.from - from) < 1000 /* HalfMargin */ && Math.abs(gap.to - to) < 1000 /* HalfMargin */) ||
|
|
4716
4752
|
new LineGap(from, to, this.gapSize(line, from, to, structure)));
|
|
4717
4753
|
}
|
|
4718
|
-
}
|
|
4754
|
+
}
|
|
4719
4755
|
return gaps;
|
|
4720
4756
|
}
|
|
4721
4757
|
gapSize(line, from, to, structure) {
|
|
@@ -4747,27 +4783,18 @@ class ViewState {
|
|
|
4747
4783
|
this.visibleRanges = ranges;
|
|
4748
4784
|
return changed ? 4 /* Viewport */ : 0;
|
|
4749
4785
|
}
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
}
|
|
4754
|
-
lineAtHeight(height, editorTop) {
|
|
4755
|
-
editorTop += this.paddingTop;
|
|
4756
|
-
return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height, editorTop), QueryType.ByHeight, this.state.doc, editorTop, 0), this.scaler, editorTop);
|
|
4786
|
+
lineBlockAt(pos) {
|
|
4787
|
+
return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to >= pos)) ||
|
|
4788
|
+
scaleBlock(this.heightMap.lineAt(pos, QueryType.ByPos, this.state.doc, 0, 0), this.scaler);
|
|
4757
4789
|
}
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height, editorTop), this.state.doc, editorTop, 0), this.scaler, editorTop);
|
|
4790
|
+
lineBlockAtHeight(height) {
|
|
4791
|
+
return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height), QueryType.ByHeight, this.state.doc, 0, 0), this.scaler);
|
|
4761
4792
|
}
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
return this.heightMap.forEachLine(from, to, this.state.doc, editorTop, 0, this.scaler.scale == 1 ? f : b => f(scaleBlock(b, this.scaler, editorTop)));
|
|
4793
|
+
elementAtHeight(height) {
|
|
4794
|
+
return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height), this.state.doc, 0, 0), this.scaler);
|
|
4765
4795
|
}
|
|
4766
4796
|
get contentHeight() {
|
|
4767
|
-
return this.
|
|
4768
|
-
}
|
|
4769
|
-
get domHeight() {
|
|
4770
|
-
return this.scaler.toDOM(this.heightMap.height, this.paddingTop);
|
|
4797
|
+
return this.scaler.toDOM(this.heightMap.height) + this.paddingTop + this.paddingBottom;
|
|
4771
4798
|
}
|
|
4772
4799
|
}
|
|
4773
4800
|
class Viewport {
|
|
@@ -4864,36 +4891,34 @@ class BigScaler {
|
|
|
4864
4891
|
base = obj.bottom;
|
|
4865
4892
|
}
|
|
4866
4893
|
}
|
|
4867
|
-
toDOM(n
|
|
4868
|
-
n -= top;
|
|
4894
|
+
toDOM(n) {
|
|
4869
4895
|
for (let i = 0, base = 0, domBase = 0;; i++) {
|
|
4870
4896
|
let vp = i < this.viewports.length ? this.viewports[i] : null;
|
|
4871
4897
|
if (!vp || n < vp.top)
|
|
4872
|
-
return domBase + (n - base) * this.scale
|
|
4898
|
+
return domBase + (n - base) * this.scale;
|
|
4873
4899
|
if (n <= vp.bottom)
|
|
4874
|
-
return vp.domTop + (n - vp.top)
|
|
4900
|
+
return vp.domTop + (n - vp.top);
|
|
4875
4901
|
base = vp.bottom;
|
|
4876
4902
|
domBase = vp.domBottom;
|
|
4877
4903
|
}
|
|
4878
4904
|
}
|
|
4879
|
-
fromDOM(n
|
|
4880
|
-
n -= top;
|
|
4905
|
+
fromDOM(n) {
|
|
4881
4906
|
for (let i = 0, base = 0, domBase = 0;; i++) {
|
|
4882
4907
|
let vp = i < this.viewports.length ? this.viewports[i] : null;
|
|
4883
4908
|
if (!vp || n < vp.domTop)
|
|
4884
|
-
return base + (n - domBase) / this.scale
|
|
4909
|
+
return base + (n - domBase) / this.scale;
|
|
4885
4910
|
if (n <= vp.domBottom)
|
|
4886
|
-
return vp.top + (n - vp.domTop)
|
|
4911
|
+
return vp.top + (n - vp.domTop);
|
|
4887
4912
|
base = vp.bottom;
|
|
4888
4913
|
domBase = vp.domBottom;
|
|
4889
4914
|
}
|
|
4890
4915
|
}
|
|
4891
4916
|
}
|
|
4892
|
-
function scaleBlock(block, scaler
|
|
4917
|
+
function scaleBlock(block, scaler) {
|
|
4893
4918
|
if (scaler.scale == 1)
|
|
4894
4919
|
return block;
|
|
4895
|
-
let bTop = scaler.toDOM(block.top
|
|
4896
|
-
return new BlockInfo(block.from, block.length, bTop, bBottom - bTop, Array.isArray(block.type) ? block.type.map(b => scaleBlock(b, scaler
|
|
4920
|
+
let bTop = scaler.toDOM(block.top), bBottom = scaler.toDOM(block.bottom);
|
|
4921
|
+
return new BlockInfo(block.from, block.length, bTop, bBottom - bTop, Array.isArray(block.type) ? block.type.map(b => scaleBlock(b, scaler)) : block.type);
|
|
4897
4922
|
}
|
|
4898
4923
|
|
|
4899
4924
|
const theme = /*@__PURE__*/Facet.define({ combine: strs => strs.join(" ") });
|
|
@@ -5030,7 +5055,7 @@ const baseTheme = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5030
5055
|
color: "inherit",
|
|
5031
5056
|
fontSize: "70%",
|
|
5032
5057
|
padding: ".2em 1em",
|
|
5033
|
-
borderRadius: "
|
|
5058
|
+
borderRadius: "1px"
|
|
5034
5059
|
},
|
|
5035
5060
|
"&light .cm-button": {
|
|
5036
5061
|
backgroundImage: "linear-gradient(#eff1f5, #d9d9df)",
|
|
@@ -5352,6 +5377,7 @@ class DOMObserver {
|
|
|
5352
5377
|
for (let dom of this.scrollTargets)
|
|
5353
5378
|
dom.removeEventListener("scroll", this.onScroll);
|
|
5354
5379
|
window.removeEventListener("scroll", this.onScroll);
|
|
5380
|
+
this.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange);
|
|
5355
5381
|
clearTimeout(this.parentCheck);
|
|
5356
5382
|
clearTimeout(this.resizeTimeout);
|
|
5357
5383
|
}
|
|
@@ -5648,6 +5674,7 @@ class EditorView {
|
|
|
5648
5674
|
*/
|
|
5649
5675
|
config = {}) {
|
|
5650
5676
|
this.plugins = [];
|
|
5677
|
+
this.pluginMap = new Map;
|
|
5651
5678
|
this.editorAttrs = {};
|
|
5652
5679
|
this.contentAttrs = {};
|
|
5653
5680
|
this.bidiCache = [];
|
|
@@ -5817,6 +5844,7 @@ class EditorView {
|
|
|
5817
5844
|
plugin.destroy(this);
|
|
5818
5845
|
this.viewState = new ViewState(newState);
|
|
5819
5846
|
this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec).update(this));
|
|
5847
|
+
this.pluginMap.clear();
|
|
5820
5848
|
this.docView = new DocView(this);
|
|
5821
5849
|
this.inputState.ensureHandlers(this);
|
|
5822
5850
|
this.mountStyles();
|
|
@@ -5847,6 +5875,7 @@ class EditorView {
|
|
|
5847
5875
|
if (plugin.mustUpdate != update)
|
|
5848
5876
|
plugin.destroy(this);
|
|
5849
5877
|
this.plugins = newPlugins;
|
|
5878
|
+
this.pluginMap.clear();
|
|
5850
5879
|
this.inputState.ensureHandlers(this);
|
|
5851
5880
|
}
|
|
5852
5881
|
else {
|
|
@@ -5854,7 +5883,7 @@ class EditorView {
|
|
|
5854
5883
|
p.mustUpdate = update;
|
|
5855
5884
|
}
|
|
5856
5885
|
for (let i = 0; i < this.plugins.length; i++)
|
|
5857
|
-
this.plugins[i]
|
|
5886
|
+
this.plugins[i].update(this);
|
|
5858
5887
|
}
|
|
5859
5888
|
/**
|
|
5860
5889
|
@internal
|
|
@@ -5872,11 +5901,11 @@ class EditorView {
|
|
|
5872
5901
|
for (let i = 0;; i++) {
|
|
5873
5902
|
this.updateState = 1 /* Measuring */;
|
|
5874
5903
|
let oldViewport = this.viewport;
|
|
5875
|
-
let changed = this.viewState.measure(this
|
|
5904
|
+
let changed = this.viewState.measure(this);
|
|
5876
5905
|
if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null)
|
|
5877
5906
|
break;
|
|
5878
5907
|
if (i > 5) {
|
|
5879
|
-
console.warn("Viewport failed to stabilize");
|
|
5908
|
+
console.warn(this.measureRequests.length ? "Measure loop restarted more than 5 times" : "Viewport failed to stabilize");
|
|
5880
5909
|
break;
|
|
5881
5910
|
}
|
|
5882
5911
|
let measuring = [];
|
|
@@ -5892,7 +5921,7 @@ class EditorView {
|
|
|
5892
5921
|
return BadMeasure;
|
|
5893
5922
|
}
|
|
5894
5923
|
});
|
|
5895
|
-
let update = new ViewUpdate(this, this.state);
|
|
5924
|
+
let update = new ViewUpdate(this, this.state), redrawn = false;
|
|
5896
5925
|
update.flags |= changed;
|
|
5897
5926
|
if (!updated)
|
|
5898
5927
|
updated = update;
|
|
@@ -5902,13 +5931,15 @@ class EditorView {
|
|
|
5902
5931
|
if (!update.empty) {
|
|
5903
5932
|
this.updatePlugins(update);
|
|
5904
5933
|
this.inputState.update(update);
|
|
5934
|
+
this.updateAttrs();
|
|
5935
|
+
redrawn = this.docView.update(update);
|
|
5905
5936
|
}
|
|
5906
|
-
this.updateAttrs();
|
|
5907
|
-
let redrawn = changed > 0 && this.docView.update(update);
|
|
5908
5937
|
for (let i = 0; i < measuring.length; i++)
|
|
5909
5938
|
if (measured[i] != BadMeasure) {
|
|
5910
5939
|
try {
|
|
5911
|
-
measuring[i]
|
|
5940
|
+
let m = measuring[i];
|
|
5941
|
+
if (m.write)
|
|
5942
|
+
m.write(measured[i], this);
|
|
5912
5943
|
}
|
|
5913
5944
|
catch (e) {
|
|
5914
5945
|
logException(this.state, e);
|
|
@@ -5918,8 +5949,8 @@ class EditorView {
|
|
|
5918
5949
|
this.docView.scrollIntoView(this.viewState.scrollTarget);
|
|
5919
5950
|
this.viewState.scrollTarget = null;
|
|
5920
5951
|
}
|
|
5921
|
-
if (
|
|
5922
|
-
this.docView.updateSelection(
|
|
5952
|
+
if (redrawn)
|
|
5953
|
+
this.docView.updateSelection(true);
|
|
5923
5954
|
if (this.viewport.from == oldViewport.from && this.viewport.to == oldViewport.to && this.measureRequests.length == 0)
|
|
5924
5955
|
break;
|
|
5925
5956
|
}
|
|
@@ -5941,7 +5972,7 @@ class EditorView {
|
|
|
5941
5972
|
this.state.facet(theme);
|
|
5942
5973
|
}
|
|
5943
5974
|
updateAttrs() {
|
|
5944
|
-
let editorAttrs =
|
|
5975
|
+
let editorAttrs = attrsFromFacet(this, editorAttributes, {
|
|
5945
5976
|
class: "cm-editor" + (this.hasFocus ? " cm-focused " : " ") + this.themeClasses
|
|
5946
5977
|
});
|
|
5947
5978
|
let contentAttrs = {
|
|
@@ -5957,7 +5988,7 @@ class EditorView {
|
|
|
5957
5988
|
};
|
|
5958
5989
|
if (this.state.readOnly)
|
|
5959
5990
|
contentAttrs["aria-readonly"] = "true";
|
|
5960
|
-
|
|
5991
|
+
attrsFromFacet(this, contentAttributes, contentAttrs);
|
|
5961
5992
|
this.observer.ignore(() => {
|
|
5962
5993
|
updateAttrs(this.contentDOM, this.contentAttrs, contentAttrs);
|
|
5963
5994
|
updateAttrs(this.dom, this.editorAttrs, editorAttrs);
|
|
@@ -6026,10 +6057,24 @@ class EditorView {
|
|
|
6026
6057
|
the return value of this method.
|
|
6027
6058
|
*/
|
|
6028
6059
|
plugin(plugin) {
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
return
|
|
6060
|
+
let known = this.pluginMap.get(plugin);
|
|
6061
|
+
if (known === undefined || known && known.spec != plugin)
|
|
6062
|
+
this.pluginMap.set(plugin, known = this.plugins.find(p => p.spec == plugin) || null);
|
|
6063
|
+
return known && known.update(this).value;
|
|
6064
|
+
}
|
|
6065
|
+
/**
|
|
6066
|
+
The top position of the document, in screen coordinates. This
|
|
6067
|
+
may be negative when the editor is scrolled down. Points
|
|
6068
|
+
directly to the top of the first line, not above the padding.
|
|
6069
|
+
*/
|
|
6070
|
+
get documentTop() {
|
|
6071
|
+
return this.contentDOM.getBoundingClientRect().top + this.viewState.paddingTop;
|
|
6072
|
+
}
|
|
6073
|
+
/**
|
|
6074
|
+
Reports the padding above and below the document.
|
|
6075
|
+
*/
|
|
6076
|
+
get documentPadding() {
|
|
6077
|
+
return { top: this.viewState.paddingTop, bottom: this.viewState.paddingBottom };
|
|
6033
6078
|
}
|
|
6034
6079
|
/**
|
|
6035
6080
|
Find the line or block widget at the given vertical position.
|
|
@@ -6041,10 +6086,21 @@ class EditorView {
|
|
|
6041
6086
|
position, or a precomputed document top
|
|
6042
6087
|
(`view.contentDOM.getBoundingClientRect().top`) to limit layout
|
|
6043
6088
|
queries.
|
|
6089
|
+
|
|
6090
|
+
*Deprecated: use `blockAtHeight` instead.*
|
|
6044
6091
|
*/
|
|
6045
6092
|
blockAtHeight(height, docTop) {
|
|
6093
|
+
let top = ensureTop(docTop, this);
|
|
6094
|
+
return this.elementAtHeight(height - top).moveY(top);
|
|
6095
|
+
}
|
|
6096
|
+
/**
|
|
6097
|
+
Find the text line or block widget at the given vertical
|
|
6098
|
+
position (which is interpreted as relative to the [top of the
|
|
6099
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)
|
|
6100
|
+
*/
|
|
6101
|
+
elementAtHeight(height) {
|
|
6046
6102
|
this.readMeasured();
|
|
6047
|
-
return this.viewState.
|
|
6103
|
+
return this.viewState.elementAtHeight(height);
|
|
6048
6104
|
}
|
|
6049
6105
|
/**
|
|
6050
6106
|
Find information for the visual line (see
|
|
@@ -6056,20 +6112,43 @@ class EditorView {
|
|
|
6056
6112
|
Defaults to treating `height` as a screen position. See
|
|
6057
6113
|
[`blockAtHeight`](https://codemirror.net/6/docs/ref/#view.EditorView.blockAtHeight) for the
|
|
6058
6114
|
interpretation of the `docTop` parameter.
|
|
6115
|
+
|
|
6116
|
+
*Deprecated: use `lineBlockAtHeight` instead.*
|
|
6059
6117
|
*/
|
|
6060
6118
|
visualLineAtHeight(height, docTop) {
|
|
6119
|
+
let top = ensureTop(docTop, this);
|
|
6120
|
+
return this.lineBlockAtHeight(height - top).moveY(top);
|
|
6121
|
+
}
|
|
6122
|
+
/**
|
|
6123
|
+
Find the line block (see
|
|
6124
|
+
[`lineBlockAt`](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) at the given
|
|
6125
|
+
height.
|
|
6126
|
+
*/
|
|
6127
|
+
lineBlockAtHeight(height) {
|
|
6061
6128
|
this.readMeasured();
|
|
6062
|
-
return this.viewState.
|
|
6129
|
+
return this.viewState.lineBlockAtHeight(height);
|
|
6063
6130
|
}
|
|
6064
6131
|
/**
|
|
6065
6132
|
Iterate over the height information of the visual lines in the
|
|
6066
6133
|
viewport. The heights of lines are reported relative to the
|
|
6067
6134
|
given document top, which defaults to the screen position of the
|
|
6068
6135
|
document (forcing a layout).
|
|
6136
|
+
|
|
6137
|
+
*Deprecated: use `viewportLineBlocks` instead.*
|
|
6069
6138
|
*/
|
|
6070
6139
|
viewportLines(f, docTop) {
|
|
6071
|
-
let
|
|
6072
|
-
|
|
6140
|
+
let top = ensureTop(docTop, this);
|
|
6141
|
+
for (let line of this.viewportLineBlocks)
|
|
6142
|
+
f(line.moveY(top));
|
|
6143
|
+
}
|
|
6144
|
+
/**
|
|
6145
|
+
Get the extent and vertical position of all [line
|
|
6146
|
+
blocks](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) in the viewport. Positions
|
|
6147
|
+
are relative to the [top of the
|
|
6148
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop);
|
|
6149
|
+
*/
|
|
6150
|
+
get viewportLineBlocks() {
|
|
6151
|
+
return this.viewState.viewportLines;
|
|
6073
6152
|
}
|
|
6074
6153
|
/**
|
|
6075
6154
|
Find the extent and height of the visual line (a range delimited
|
|
@@ -6080,9 +6159,22 @@ class EditorView {
|
|
|
6080
6159
|
argument, which defaults to 0 for this method. You can pass
|
|
6081
6160
|
`view.contentDOM.getBoundingClientRect().top` here to get screen
|
|
6082
6161
|
coordinates.
|
|
6162
|
+
|
|
6163
|
+
*Deprecated: use `lineBlockAt` instead.*
|
|
6083
6164
|
*/
|
|
6084
6165
|
visualLineAt(pos, docTop = 0) {
|
|
6085
|
-
return this.
|
|
6166
|
+
return this.lineBlockAt(pos).moveY(docTop + this.viewState.paddingTop);
|
|
6167
|
+
}
|
|
6168
|
+
/**
|
|
6169
|
+
Find the line block around the given document position. A line
|
|
6170
|
+
block is a range delimited on both sides by either a
|
|
6171
|
+
non-[hidden](https://codemirror.net/6/docs/ref/#view.Decoration^range) line breaks, or the
|
|
6172
|
+
start/end of the document. It will usually just hold a line of
|
|
6173
|
+
text, but may be broken into multiple textblocks by block
|
|
6174
|
+
widgets.
|
|
6175
|
+
*/
|
|
6176
|
+
lineBlockAt(pos) {
|
|
6177
|
+
return this.viewState.lineBlockAt(pos);
|
|
6086
6178
|
}
|
|
6087
6179
|
/**
|
|
6088
6180
|
The editor's total content height.
|
|
@@ -6415,8 +6507,9 @@ search match).
|
|
|
6415
6507
|
EditorView.announce = /*@__PURE__*/StateEffect.define();
|
|
6416
6508
|
// Maximum line length for which we compute accurate bidi info
|
|
6417
6509
|
const MaxBidiLine = 4096;
|
|
6418
|
-
|
|
6419
|
-
|
|
6510
|
+
// FIXME remove this and its callers on next breaking release
|
|
6511
|
+
function ensureTop(given, view) {
|
|
6512
|
+
return (given == null ? view.contentDOM.getBoundingClientRect().top : given) + view.viewState.paddingTop;
|
|
6420
6513
|
}
|
|
6421
6514
|
let resizeDebounce = -1;
|
|
6422
6515
|
function ensureGlobalHandler() {
|
|
@@ -6454,6 +6547,14 @@ class CachedOrder {
|
|
|
6454
6547
|
return result;
|
|
6455
6548
|
}
|
|
6456
6549
|
}
|
|
6550
|
+
function attrsFromFacet(view, facet, base) {
|
|
6551
|
+
for (let sources = view.state.facet(facet), i = sources.length - 1; i >= 0; i--) {
|
|
6552
|
+
let source = sources[i], value = typeof source == "function" ? source(view) : source;
|
|
6553
|
+
if (value)
|
|
6554
|
+
combineAttrs(value, base);
|
|
6555
|
+
}
|
|
6556
|
+
return base;
|
|
6557
|
+
}
|
|
6457
6558
|
|
|
6458
6559
|
const currentPlatform = browser.mac ? "mac" : browser.windows ? "win" : browser.linux ? "linux" : "key";
|
|
6459
6560
|
function normalizeKeyName(name, platform) {
|
|
@@ -6767,7 +6868,7 @@ function wrappedLine(view, pos, inside) {
|
|
|
6767
6868
|
type: BlockType.Text };
|
|
6768
6869
|
}
|
|
6769
6870
|
function blockAt(view, pos) {
|
|
6770
|
-
let line = view.
|
|
6871
|
+
let line = view.lineBlockAt(pos);
|
|
6771
6872
|
if (Array.isArray(line.type))
|
|
6772
6873
|
for (let l of line.type) {
|
|
6773
6874
|
if (l.to > pos || l.to == pos && (l.to == line.to || l.type == BlockType.Text))
|
|
@@ -7106,35 +7207,29 @@ class TabWidget extends WidgetType {
|
|
|
7106
7207
|
}
|
|
7107
7208
|
|
|
7108
7209
|
const plugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
7109
|
-
constructor(
|
|
7110
|
-
this.height =
|
|
7111
|
-
this.
|
|
7112
|
-
read: view => Math.max(0, view.scrollDOM.clientHeight - view.defaultLineHeight),
|
|
7113
|
-
write: (value, view) => {
|
|
7114
|
-
if (Math.abs(value - this.height) > 1) {
|
|
7115
|
-
this.height = value;
|
|
7116
|
-
view.contentDOM.style.paddingBottom = value + "px";
|
|
7117
|
-
}
|
|
7118
|
-
}
|
|
7119
|
-
};
|
|
7120
|
-
view.requestMeasure(this.measure);
|
|
7210
|
+
constructor() {
|
|
7211
|
+
this.height = 1000;
|
|
7212
|
+
this.attrs = { style: "padding-bottom: 1000px" };
|
|
7121
7213
|
}
|
|
7122
7214
|
update(update) {
|
|
7123
|
-
|
|
7124
|
-
|
|
7215
|
+
let height = update.view.viewState.editorHeight - update.view.defaultLineHeight;
|
|
7216
|
+
if (height != this.height) {
|
|
7217
|
+
this.height = height;
|
|
7218
|
+
this.attrs = { style: `padding-bottom: ${height}px` };
|
|
7219
|
+
}
|
|
7125
7220
|
}
|
|
7126
7221
|
});
|
|
7127
7222
|
/**
|
|
7128
|
-
Returns
|
|
7129
|
-
equivalent to the height of the editor, minus one line
|
|
7130
|
-
that every line in the document can be scrolled to the
|
|
7131
|
-
editor.
|
|
7223
|
+
Returns an extension that makes sure the content has a bottom
|
|
7224
|
+
margin equivalent to the height of the editor, minus one line
|
|
7225
|
+
height, so that every line in the document can be scrolled to the
|
|
7226
|
+
top of the editor.
|
|
7132
7227
|
|
|
7133
7228
|
This is only meaningful when the editor is scrollable, and should
|
|
7134
7229
|
not be enabled in editors that take the size of their content.
|
|
7135
7230
|
*/
|
|
7136
7231
|
function scrollPastEnd() {
|
|
7137
|
-
return plugin;
|
|
7232
|
+
return [plugin, contentAttributes.of(view => { var _a; return ((_a = view.plugin(plugin)) === null || _a === void 0 ? void 0 : _a.attrs) || null; })];
|
|
7138
7233
|
}
|
|
7139
7234
|
|
|
7140
7235
|
/**
|
|
@@ -7158,7 +7253,7 @@ const activeLineHighlighter = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
7158
7253
|
for (let r of view.state.selection.ranges) {
|
|
7159
7254
|
if (!r.empty)
|
|
7160
7255
|
return Decoration.none;
|
|
7161
|
-
let line = view.
|
|
7256
|
+
let line = view.lineBlockAt(r.head);
|
|
7162
7257
|
if (line.from > lastLineStart) {
|
|
7163
7258
|
deco.push(lineDeco.range(line.from));
|
|
7164
7259
|
lastLineStart = line.from;
|