@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.cjs
CHANGED
|
@@ -1086,8 +1086,9 @@ class Decoration extends rangeset.RangeValue {
|
|
|
1086
1086
|
position.
|
|
1087
1087
|
*/
|
|
1088
1088
|
static widget(spec) {
|
|
1089
|
-
let side = spec.side || 0;
|
|
1090
|
-
|
|
1089
|
+
let side = spec.side || 0, block = !!spec.block;
|
|
1090
|
+
side += block ? (side > 0 ? 300000000 /* BlockAfter */ : -400000000 /* BlockBefore */) : (side > 0 ? 100000000 /* InlineAfter */ : -100000000 /* InlineBefore */);
|
|
1091
|
+
return new PointDecoration(spec, side, side, block, spec.widget || null, false);
|
|
1091
1092
|
}
|
|
1092
1093
|
/**
|
|
1093
1094
|
Create a replace decoration which replaces the given range with
|
|
@@ -1096,8 +1097,8 @@ class Decoration extends rangeset.RangeValue {
|
|
|
1096
1097
|
static replace(spec) {
|
|
1097
1098
|
let block = !!spec.block;
|
|
1098
1099
|
let { start, end } = getInclusive(spec, block);
|
|
1099
|
-
let startSide =
|
|
1100
|
-
let endSide =
|
|
1100
|
+
let startSide = block ? (start ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 400000000 /* NonIncStart */;
|
|
1101
|
+
let endSide = block ? (end ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -500000000 /* NonIncEnd */;
|
|
1101
1102
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1102
1103
|
}
|
|
1103
1104
|
/**
|
|
@@ -1127,7 +1128,7 @@ Decoration.none = rangeset.RangeSet.empty;
|
|
|
1127
1128
|
class MarkDecoration extends Decoration {
|
|
1128
1129
|
constructor(spec) {
|
|
1129
1130
|
let { start, end } = getInclusive(spec);
|
|
1130
|
-
super(
|
|
1131
|
+
super(start ? -1 /* InlineIncStart */ : 400000000 /* NonIncStart */, end ? 1 /* InlineIncEnd */ : -500000000 /* NonIncEnd */, null, spec);
|
|
1131
1132
|
this.tagName = spec.tagName || "span";
|
|
1132
1133
|
this.class = spec.class || "";
|
|
1133
1134
|
this.attrs = spec.attributes || null;
|
|
@@ -1148,7 +1149,7 @@ class MarkDecoration extends Decoration {
|
|
|
1148
1149
|
MarkDecoration.prototype.point = false;
|
|
1149
1150
|
class LineDecoration extends Decoration {
|
|
1150
1151
|
constructor(spec) {
|
|
1151
|
-
super(-
|
|
1152
|
+
super(-200000000 /* Line */, -200000000 /* Line */, null, spec);
|
|
1152
1153
|
}
|
|
1153
1154
|
eq(other) {
|
|
1154
1155
|
return other instanceof LineDecoration && attrsEq(this.spec.attributes, other.spec.attributes);
|
|
@@ -1727,36 +1728,39 @@ class PluginInstance {
|
|
|
1727
1728
|
this.value = null;
|
|
1728
1729
|
}
|
|
1729
1730
|
takeField(type, target) {
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1731
|
+
if (this.spec)
|
|
1732
|
+
for (let { field, get } of this.spec.fields)
|
|
1733
|
+
if (field == type)
|
|
1734
|
+
target.push(get(this.value));
|
|
1733
1735
|
}
|
|
1734
1736
|
update(view) {
|
|
1735
1737
|
if (!this.value) {
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1738
|
+
if (this.spec) {
|
|
1739
|
+
try {
|
|
1740
|
+
this.value = this.spec.create(view);
|
|
1741
|
+
}
|
|
1742
|
+
catch (e) {
|
|
1743
|
+
logException(view.state, e, "CodeMirror plugin crashed");
|
|
1744
|
+
this.deactivate();
|
|
1745
|
+
}
|
|
1742
1746
|
}
|
|
1743
1747
|
}
|
|
1744
1748
|
else if (this.mustUpdate) {
|
|
1745
1749
|
let update = this.mustUpdate;
|
|
1746
1750
|
this.mustUpdate = null;
|
|
1747
|
-
if (
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1751
|
+
if (this.value.update) {
|
|
1752
|
+
try {
|
|
1753
|
+
this.value.update(update);
|
|
1754
|
+
}
|
|
1755
|
+
catch (e) {
|
|
1756
|
+
logException(update.state, e, "CodeMirror plugin crashed");
|
|
1757
|
+
if (this.value.destroy)
|
|
1758
|
+
try {
|
|
1759
|
+
this.value.destroy();
|
|
1760
|
+
}
|
|
1761
|
+
catch (_) { }
|
|
1762
|
+
this.deactivate();
|
|
1763
|
+
}
|
|
1760
1764
|
}
|
|
1761
1765
|
}
|
|
1762
1766
|
return this;
|
|
@@ -1772,20 +1776,12 @@ class PluginInstance {
|
|
|
1772
1776
|
}
|
|
1773
1777
|
}
|
|
1774
1778
|
}
|
|
1779
|
+
deactivate() {
|
|
1780
|
+
this.spec = this.value = null;
|
|
1781
|
+
}
|
|
1775
1782
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
let result = {};
|
|
1779
|
-
for (let i = values.length - 1; i >= 0; i--)
|
|
1780
|
-
combineAttrs(values[i], result);
|
|
1781
|
-
return result;
|
|
1782
|
-
}
|
|
1783
|
-
const editorAttributes = state.Facet.define({
|
|
1784
|
-
combine: combineFacetAttrs
|
|
1785
|
-
});
|
|
1786
|
-
const contentAttributes = state.Facet.define({
|
|
1787
|
-
combine: combineFacetAttrs
|
|
1788
|
-
});
|
|
1783
|
+
const editorAttributes = state.Facet.define();
|
|
1784
|
+
const contentAttributes = state.Facet.define();
|
|
1789
1785
|
// Provide decorations
|
|
1790
1786
|
const decorations = state.Facet.define();
|
|
1791
1787
|
const styleModule = state.Facet.define();
|
|
@@ -1912,7 +1908,7 @@ class ViewUpdate {
|
|
|
1912
1908
|
Whether the document changed in this update.
|
|
1913
1909
|
*/
|
|
1914
1910
|
get docChanged() {
|
|
1915
|
-
return this.
|
|
1911
|
+
return !this.changes.empty;
|
|
1916
1912
|
}
|
|
1917
1913
|
/**
|
|
1918
1914
|
Whether the selection was explicitly set in this update.
|
|
@@ -1933,12 +1929,12 @@ class DocView extends ContentView {
|
|
|
1933
1929
|
this.compositionDeco = Decoration.none;
|
|
1934
1930
|
this.decorations = [];
|
|
1935
1931
|
// Track a minimum width for the editor. When measuring sizes in
|
|
1936
|
-
//
|
|
1937
|
-
// element and its extent in the document. When a change
|
|
1938
|
-
// that range, these are reset. That way, once we've seen
|
|
1939
|
-
// line/element of a given length, we keep the editor wide enough
|
|
1940
|
-
// fit at least that element, until it is changed, at which point
|
|
1941
|
-
// forget it again.
|
|
1932
|
+
// measureVisibleLineHeights, this is updated to point at the width
|
|
1933
|
+
// of a given element and its extent in the document. When a change
|
|
1934
|
+
// happens in that range, these are reset. That way, once we've seen
|
|
1935
|
+
// a line/element of a given length, we keep the editor wide enough
|
|
1936
|
+
// to fit at least that element, until it is changed, at which point
|
|
1937
|
+
// we forget it again.
|
|
1942
1938
|
this.minWidth = 0;
|
|
1943
1939
|
this.minWidthFrom = 0;
|
|
1944
1940
|
this.minWidthTo = 0;
|
|
@@ -1988,10 +1984,7 @@ class DocView extends ContentView {
|
|
|
1988
1984
|
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
1989
1985
|
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
1990
1986
|
changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
|
|
1991
|
-
if (this.dirty == 0 /* Not */ && changedRanges.length == 0
|
|
1992
|
-
!(update.flags & 4 /* Viewport */) &&
|
|
1993
|
-
update.state.selection.main.from >= this.view.viewport.from &&
|
|
1994
|
-
update.state.selection.main.to <= this.view.viewport.to) {
|
|
1987
|
+
if (this.dirty == 0 /* Not */ && changedRanges.length == 0) {
|
|
1995
1988
|
return false;
|
|
1996
1989
|
}
|
|
1997
1990
|
else {
|
|
@@ -2011,9 +2004,10 @@ class DocView extends ContentView {
|
|
|
2011
2004
|
this.updateSelection();
|
|
2012
2005
|
}
|
|
2013
2006
|
}
|
|
2014
|
-
// Used
|
|
2007
|
+
// Used by update and the constructor do perform the actual DOM
|
|
2015
2008
|
// update
|
|
2016
2009
|
updateInner(changes, deco, oldLength) {
|
|
2010
|
+
this.view.viewState.mustMeasureContent = true;
|
|
2017
2011
|
this.updateChildren(changes, deco, oldLength);
|
|
2018
2012
|
let { observer } = this.view;
|
|
2019
2013
|
observer.ignore(() => {
|
|
@@ -2021,7 +2015,7 @@ class DocView extends ContentView {
|
|
|
2021
2015
|
// messes with the scroll position during DOM mutation (though
|
|
2022
2016
|
// no relayout is triggered and I cannot imagine how it can
|
|
2023
2017
|
// recompute the scroll position without a layout)
|
|
2024
|
-
this.dom.style.height = this.view.viewState.
|
|
2018
|
+
this.dom.style.height = this.view.viewState.contentHeight + "px";
|
|
2025
2019
|
this.dom.style.minWidth = this.minWidth ? this.minWidth + "px" : "";
|
|
2026
2020
|
// Chrome will sometimes, when DOM mutations occur directly
|
|
2027
2021
|
// around the selection, get confused and report a different
|
|
@@ -2306,7 +2300,7 @@ class DocView extends ContentView {
|
|
|
2306
2300
|
let next = i == vs.viewports.length ? null : vs.viewports[i];
|
|
2307
2301
|
let end = next ? next.from - 1 : this.length;
|
|
2308
2302
|
if (end > pos) {
|
|
2309
|
-
let height = vs.
|
|
2303
|
+
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
2310
2304
|
deco.push(Decoration.replace({ widget: new BlockGapWidget(height), block: true, inclusive: true }).range(pos, end));
|
|
2311
2305
|
}
|
|
2312
2306
|
if (!next)
|
|
@@ -2913,13 +2907,14 @@ function domPosInText(node, x, y) {
|
|
|
2913
2907
|
}
|
|
2914
2908
|
function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
2915
2909
|
var _a;
|
|
2916
|
-
let content = view.contentDOM.getBoundingClientRect(),
|
|
2910
|
+
let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
|
|
2917
2911
|
let halfLine = view.defaultLineHeight / 2;
|
|
2912
|
+
let block, yOffset = y - docTop;
|
|
2918
2913
|
for (let bounced = false;;) {
|
|
2919
|
-
block = view.
|
|
2920
|
-
if (block.top >
|
|
2921
|
-
bias = block.top >
|
|
2922
|
-
|
|
2914
|
+
block = view.elementAtHeight(yOffset);
|
|
2915
|
+
if (block.top > yOffset || block.bottom < yOffset) {
|
|
2916
|
+
bias = block.top > yOffset ? -1 : 1;
|
|
2917
|
+
yOffset = Math.min(block.bottom - halfLine, Math.max(block.top + halfLine, yOffset));
|
|
2923
2918
|
if (bounced)
|
|
2924
2919
|
return precise ? null : 0;
|
|
2925
2920
|
else
|
|
@@ -2927,11 +2922,12 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
2927
2922
|
}
|
|
2928
2923
|
if (block.type == exports.BlockType.Text)
|
|
2929
2924
|
break;
|
|
2930
|
-
|
|
2925
|
+
yOffset = bias > 0 ? block.bottom + halfLine : block.top - halfLine;
|
|
2931
2926
|
}
|
|
2927
|
+
y = docTop + yOffset;
|
|
2932
2928
|
let lineStart = block.from;
|
|
2933
2929
|
// Clip x to the viewport sides
|
|
2934
|
-
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
2930
|
+
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
2935
2931
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
2936
2932
|
if (lineStart < view.viewport.from)
|
|
2937
2933
|
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
@@ -3041,17 +3037,17 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3041
3037
|
return state.EditorSelection.cursor(startPos);
|
|
3042
3038
|
let goal = start.goalColumn, startY;
|
|
3043
3039
|
let rect = view.contentDOM.getBoundingClientRect();
|
|
3044
|
-
let startCoords = view.coordsAtPos(startPos);
|
|
3040
|
+
let startCoords = view.coordsAtPos(startPos), docTop = view.documentTop;
|
|
3045
3041
|
if (startCoords) {
|
|
3046
3042
|
if (goal == null)
|
|
3047
3043
|
goal = startCoords.left - rect.left;
|
|
3048
3044
|
startY = dir < 0 ? startCoords.top : startCoords.bottom;
|
|
3049
3045
|
}
|
|
3050
3046
|
else {
|
|
3051
|
-
let line = view.viewState.
|
|
3047
|
+
let line = view.viewState.lineBlockAt(startPos - docTop);
|
|
3052
3048
|
if (goal == null)
|
|
3053
3049
|
goal = Math.min(rect.right - rect.left, view.defaultCharacterWidth * (startPos - line.from));
|
|
3054
|
-
startY = dir < 0 ? line.top : line.bottom;
|
|
3050
|
+
startY = (dir < 0 ? line.top : line.bottom) + docTop;
|
|
3055
3051
|
}
|
|
3056
3052
|
let resolvedGoal = rect.left + goal;
|
|
3057
3053
|
let dist = distance !== null && distance !== void 0 ? distance : (view.defaultLineHeight >> 1);
|
|
@@ -3302,7 +3298,7 @@ class MouseSelection {
|
|
|
3302
3298
|
this.extend = startEvent.shiftKey;
|
|
3303
3299
|
this.multiple = view.state.facet(state.EditorState.allowMultipleSelections) && addsSelectionRange(view, startEvent);
|
|
3304
3300
|
this.dragMove = dragMovesSelection(view, startEvent);
|
|
3305
|
-
this.dragging = isInPrimarySelection(view, startEvent) ? null : false;
|
|
3301
|
+
this.dragging = isInPrimarySelection(view, startEvent) && getClickType(startEvent) == 1 ? null : false;
|
|
3306
3302
|
// When clicking outside of the selection, immediately apply the
|
|
3307
3303
|
// effect of starting the selection
|
|
3308
3304
|
if (this.dragging === false) {
|
|
@@ -3523,7 +3519,7 @@ function basicMouseSelection(view, event) {
|
|
|
3523
3519
|
let last = start, lastEvent = event;
|
|
3524
3520
|
return {
|
|
3525
3521
|
update(update) {
|
|
3526
|
-
if (update.
|
|
3522
|
+
if (update.docChanged) {
|
|
3527
3523
|
if (start)
|
|
3528
3524
|
start.pos = update.changes.mapPos(start.pos);
|
|
3529
3525
|
startSel = startSel.map(update.changes);
|
|
@@ -3787,7 +3783,10 @@ class HeightOracle {
|
|
|
3787
3783
|
return lines * this.lineHeight;
|
|
3788
3784
|
}
|
|
3789
3785
|
setDoc(doc) { this.doc = doc; return this; }
|
|
3790
|
-
|
|
3786
|
+
mustRefreshForStyle(whiteSpace, direction) {
|
|
3787
|
+
return (wrappingWhiteSpace.indexOf(whiteSpace) > -1) != this.lineWrapping || this.direction != direction;
|
|
3788
|
+
}
|
|
3789
|
+
mustRefreshForHeights(lineHeights) {
|
|
3791
3790
|
let newHeight = false;
|
|
3792
3791
|
for (let i = 0; i < lineHeights.length; i++) {
|
|
3793
3792
|
let h = lineHeights[i];
|
|
@@ -3799,7 +3798,7 @@ class HeightOracle {
|
|
|
3799
3798
|
this.heightSamples[Math.floor(h * 10)] = true;
|
|
3800
3799
|
}
|
|
3801
3800
|
}
|
|
3802
|
-
return newHeight
|
|
3801
|
+
return newHeight;
|
|
3803
3802
|
}
|
|
3804
3803
|
refresh(whiteSpace, direction, lineHeight, charWidth, lineLength, knownHeights) {
|
|
3805
3804
|
let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
|
|
@@ -3853,7 +3852,8 @@ class BlockInfo {
|
|
|
3853
3852
|
*/
|
|
3854
3853
|
length,
|
|
3855
3854
|
/**
|
|
3856
|
-
The top position of the element
|
|
3855
|
+
The top position of the element (relative to the top of the
|
|
3856
|
+
document).
|
|
3857
3857
|
*/
|
|
3858
3858
|
top,
|
|
3859
3859
|
/**
|
|
@@ -3887,6 +3887,12 @@ class BlockInfo {
|
|
|
3887
3887
|
.concat(Array.isArray(other.type) ? other.type : [other]);
|
|
3888
3888
|
return new BlockInfo(this.from, this.length + other.length, this.top, this.height + other.height, detail);
|
|
3889
3889
|
}
|
|
3890
|
+
/**
|
|
3891
|
+
FIXME remove on next breaking release @internal
|
|
3892
|
+
*/
|
|
3893
|
+
moveY(offset) {
|
|
3894
|
+
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);
|
|
3895
|
+
}
|
|
3890
3896
|
}
|
|
3891
3897
|
var QueryType;
|
|
3892
3898
|
(function (QueryType) {
|
|
@@ -3894,7 +3900,7 @@ var QueryType;
|
|
|
3894
3900
|
QueryType[QueryType["ByHeight"] = 1] = "ByHeight";
|
|
3895
3901
|
QueryType[QueryType["ByPosNoHeight"] = 2] = "ByPosNoHeight";
|
|
3896
3902
|
})(QueryType || (QueryType = {}));
|
|
3897
|
-
const Epsilon = 1e-
|
|
3903
|
+
const Epsilon = 1e-3;
|
|
3898
3904
|
class HeightMap {
|
|
3899
3905
|
constructor(length, // The number of characters covered
|
|
3900
3906
|
height, // Height of this part of the document
|
|
@@ -4121,22 +4127,30 @@ class HeightMapGap extends HeightMap {
|
|
|
4121
4127
|
// can't be widgets or collapsed ranges in those lines, because
|
|
4122
4128
|
// they would already have been added to the heightmap (gaps
|
|
4123
4129
|
// only contain plain text).
|
|
4124
|
-
let nodes = [], pos = Math.max(offset, measured.from);
|
|
4130
|
+
let nodes = [], pos = Math.max(offset, measured.from), singleHeight = -1;
|
|
4131
|
+
let wasChanged = oracle.heightChanged;
|
|
4125
4132
|
if (measured.from > offset)
|
|
4126
4133
|
nodes.push(new HeightMapGap(measured.from - offset - 1).updateHeight(oracle, offset));
|
|
4127
4134
|
while (pos <= end && measured.more) {
|
|
4128
4135
|
let len = oracle.doc.lineAt(pos).length;
|
|
4129
4136
|
if (nodes.length)
|
|
4130
4137
|
nodes.push(null);
|
|
4131
|
-
let
|
|
4138
|
+
let height = measured.heights[measured.index++];
|
|
4139
|
+
if (singleHeight == -1)
|
|
4140
|
+
singleHeight = height;
|
|
4141
|
+
else if (Math.abs(height - singleHeight) >= Epsilon)
|
|
4142
|
+
singleHeight = -2;
|
|
4143
|
+
let line = new HeightMapText(len, height);
|
|
4132
4144
|
line.outdated = false;
|
|
4133
4145
|
nodes.push(line);
|
|
4134
4146
|
pos += len + 1;
|
|
4135
4147
|
}
|
|
4136
4148
|
if (pos <= end)
|
|
4137
4149
|
nodes.push(null, new HeightMapGap(end - pos).updateHeight(oracle, pos));
|
|
4138
|
-
|
|
4139
|
-
|
|
4150
|
+
let result = HeightMap.of(nodes);
|
|
4151
|
+
oracle.heightChanged = wasChanged || singleHeight < 0 || Math.abs(result.height - this.height) >= Epsilon ||
|
|
4152
|
+
Math.abs(singleHeight - this.lines(oracle.doc, offset).lineHeight) >= Epsilon;
|
|
4153
|
+
return result;
|
|
4140
4154
|
}
|
|
4141
4155
|
else if (force || this.outdated) {
|
|
4142
4156
|
this.setHeight(oracle, oracle.heightForGap(offset, offset + this.length));
|
|
@@ -4494,7 +4508,8 @@ class ViewState {
|
|
|
4494
4508
|
this.inView = true;
|
|
4495
4509
|
this.paddingTop = 0;
|
|
4496
4510
|
this.paddingBottom = 0;
|
|
4497
|
-
this.
|
|
4511
|
+
this.contentDOMWidth = 0;
|
|
4512
|
+
this.contentDOMHeight = 0;
|
|
4498
4513
|
this.editorHeight = 0;
|
|
4499
4514
|
this.heightOracle = new HeightOracle;
|
|
4500
4515
|
// See VP.MaxDOMHeight
|
|
@@ -4502,6 +4517,9 @@ class ViewState {
|
|
|
4502
4517
|
this.scrollTarget = null;
|
|
4503
4518
|
// Briefly set to true when printing, to disable viewport limiting
|
|
4504
4519
|
this.printing = false;
|
|
4520
|
+
// Flag set when editor content was redrawn, so that the next
|
|
4521
|
+
// measure stage knows it must read DOM layout
|
|
4522
|
+
this.mustMeasureContent = true;
|
|
4505
4523
|
this.visibleRanges = [];
|
|
4506
4524
|
// Cursor 'assoc' is only significant when the cursor is on a line
|
|
4507
4525
|
// wrap point, where it must stick to the character that it is
|
|
@@ -4514,6 +4532,7 @@ class ViewState {
|
|
|
4514
4532
|
this.mustEnforceCursorAssoc = false;
|
|
4515
4533
|
this.heightMap = HeightMap.empty().applyChanges(state.facet(decorations), text.Text.empty, this.heightOracle.setDoc(state.doc), [new ChangedRange(0, 0, 0, state.doc.length)]);
|
|
4516
4534
|
this.viewport = this.getViewport(0, null);
|
|
4535
|
+
this.updateViewportLines();
|
|
4517
4536
|
this.updateForViewport();
|
|
4518
4537
|
this.lineGaps = this.ensureLineGaps([]);
|
|
4519
4538
|
this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(false)));
|
|
@@ -4524,7 +4543,7 @@ class ViewState {
|
|
|
4524
4543
|
for (let i = 0; i <= 1; i++) {
|
|
4525
4544
|
let pos = i ? main.head : main.anchor;
|
|
4526
4545
|
if (!viewports.some(({ from, to }) => pos >= from && pos <= to)) {
|
|
4527
|
-
let { from, to } = this.
|
|
4546
|
+
let { from, to } = this.lineBlockAt(pos);
|
|
4528
4547
|
viewports.push(new Viewport(from, to));
|
|
4529
4548
|
}
|
|
4530
4549
|
}
|
|
@@ -4532,6 +4551,12 @@ class ViewState {
|
|
|
4532
4551
|
this.scaler = this.heightMap.height <= 7000000 /* MaxDOMHeight */ ? IdScaler :
|
|
4533
4552
|
new BigScaler(this.heightOracle.doc, this.heightMap, this.viewports);
|
|
4534
4553
|
}
|
|
4554
|
+
updateViewportLines() {
|
|
4555
|
+
this.viewportLines = [];
|
|
4556
|
+
this.heightMap.forEachLine(this.viewport.from, this.viewport.to, this.state.doc, 0, 0, block => {
|
|
4557
|
+
this.viewportLines.push(this.scaler.scale == 1 ? block : scaleBlock(block, this.scaler));
|
|
4558
|
+
});
|
|
4559
|
+
}
|
|
4535
4560
|
update(update, scrollTarget = null) {
|
|
4536
4561
|
let prev = this.state;
|
|
4537
4562
|
this.state = update.state;
|
|
@@ -4546,7 +4571,11 @@ class ViewState {
|
|
|
4546
4571
|
if (scrollTarget && (scrollTarget.range.head < viewport.from || scrollTarget.range.head > viewport.to) ||
|
|
4547
4572
|
!this.viewportIsAppropriate(viewport))
|
|
4548
4573
|
viewport = this.getViewport(0, scrollTarget);
|
|
4574
|
+
let updateLines = !update.changes.empty || (update.flags & 2 /* Height */) ||
|
|
4575
|
+
viewport.from != this.viewport.from || viewport.to != this.viewport.to;
|
|
4549
4576
|
this.viewport = viewport;
|
|
4577
|
+
if (updateLines)
|
|
4578
|
+
this.updateViewportLines();
|
|
4550
4579
|
this.updateForViewport();
|
|
4551
4580
|
if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
|
|
4552
4581
|
this.updateLineGaps(this.ensureLineGaps(this.mapLineGaps(this.lineGaps, update.changes)));
|
|
@@ -4557,13 +4586,17 @@ class ViewState {
|
|
|
4557
4586
|
update.state.selection.main.empty && update.state.selection.main.assoc)
|
|
4558
4587
|
this.mustEnforceCursorAssoc = true;
|
|
4559
4588
|
}
|
|
4560
|
-
measure(
|
|
4561
|
-
let dom =
|
|
4562
|
-
let
|
|
4563
|
-
|
|
4589
|
+
measure(view) {
|
|
4590
|
+
let dom = view.contentDOM, style = window.getComputedStyle(dom);
|
|
4591
|
+
let oracle = this.heightOracle;
|
|
4592
|
+
let whiteSpace = style.whiteSpace, direction = style.direction == "rtl" ? exports.Direction.RTL : exports.Direction.LTR;
|
|
4593
|
+
let refresh = this.heightOracle.mustRefreshForStyle(whiteSpace, direction);
|
|
4594
|
+
let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != dom.clientHeight;
|
|
4595
|
+
let result = 0, bias = 0;
|
|
4596
|
+
if (measureContent) {
|
|
4597
|
+
this.mustMeasureContent = false;
|
|
4598
|
+
this.contentDOMHeight = dom.clientHeight;
|
|
4564
4599
|
// Vertical padding
|
|
4565
|
-
let style = window.getComputedStyle(dom);
|
|
4566
|
-
whiteSpace = style.whiteSpace, direction = (style.direction == "rtl" ? exports.Direction.RTL : exports.Direction.LTR);
|
|
4567
4600
|
let paddingTop = parseInt(style.paddingTop) || 0, paddingBottom = parseInt(style.paddingBottom) || 0;
|
|
4568
4601
|
if (this.paddingTop != paddingTop || this.paddingBottom != paddingBottom) {
|
|
4569
4602
|
result |= 8 /* Geometry */;
|
|
@@ -4578,39 +4611,42 @@ class ViewState {
|
|
|
4578
4611
|
this.inView = this.pixelViewport.bottom > this.pixelViewport.top && this.pixelViewport.right > this.pixelViewport.left;
|
|
4579
4612
|
if (!this.inView)
|
|
4580
4613
|
return 0;
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
let { lineHeight, charWidth } = docView.measureTextSize();
|
|
4614
|
+
if (measureContent) {
|
|
4615
|
+
let lineHeights = view.docView.measureVisibleLineHeights();
|
|
4616
|
+
if (oracle.mustRefreshForHeights(lineHeights))
|
|
4617
|
+
refresh = true;
|
|
4618
|
+
let contentWidth = dom.clientWidth;
|
|
4619
|
+
if (refresh || oracle.lineWrapping && Math.abs(contentWidth - this.contentDOMWidth) > oracle.charWidth) {
|
|
4620
|
+
let { lineHeight, charWidth } = view.docView.measureTextSize();
|
|
4588
4621
|
refresh = oracle.refresh(whiteSpace, direction, lineHeight, charWidth, contentWidth / charWidth, lineHeights);
|
|
4589
4622
|
if (refresh) {
|
|
4590
|
-
docView.minWidth = 0;
|
|
4623
|
+
view.docView.minWidth = 0;
|
|
4591
4624
|
result |= 8 /* Geometry */;
|
|
4592
4625
|
}
|
|
4593
4626
|
}
|
|
4594
|
-
if (this.
|
|
4595
|
-
this.
|
|
4627
|
+
if (this.contentDOMWidth != contentWidth) {
|
|
4628
|
+
this.contentDOMWidth = contentWidth;
|
|
4596
4629
|
result |= 8 /* Geometry */;
|
|
4597
4630
|
}
|
|
4598
|
-
if (this.editorHeight !=
|
|
4599
|
-
this.editorHeight =
|
|
4631
|
+
if (this.editorHeight != view.scrollDOM.clientHeight) {
|
|
4632
|
+
this.editorHeight = view.scrollDOM.clientHeight;
|
|
4600
4633
|
result |= 8 /* Geometry */;
|
|
4601
4634
|
}
|
|
4602
4635
|
if (dTop > 0 && dBottom > 0)
|
|
4603
4636
|
bias = Math.max(dTop, dBottom);
|
|
4604
4637
|
else if (dTop < 0 && dBottom < 0)
|
|
4605
4638
|
bias = Math.min(dTop, dBottom);
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from || this.scrollTarget.range.head > this.viewport.to)
|
|
4639
|
+
oracle.heightChanged = false;
|
|
4640
|
+
this.heightMap = this.heightMap.updateHeight(oracle, 0, refresh, new MeasuredHeights(this.viewport.from, lineHeights));
|
|
4641
|
+
if (oracle.heightChanged)
|
|
4642
|
+
result |= 2 /* Height */;
|
|
4643
|
+
}
|
|
4644
|
+
let viewportChange = !this.viewportIsAppropriate(this.viewport, bias) ||
|
|
4645
|
+
this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from || this.scrollTarget.range.head > this.viewport.to);
|
|
4646
|
+
if (viewportChange)
|
|
4613
4647
|
this.viewport = this.getViewport(bias, this.scrollTarget);
|
|
4648
|
+
if ((result & 2 /* Height */) || viewportChange)
|
|
4649
|
+
this.updateViewportLines();
|
|
4614
4650
|
this.updateForViewport();
|
|
4615
4651
|
if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
|
|
4616
4652
|
this.updateLineGaps(this.ensureLineGaps(refresh ? [] : this.lineGaps));
|
|
@@ -4621,12 +4657,12 @@ class ViewState {
|
|
|
4621
4657
|
// to a line end is going to trigger a layout anyway, so it
|
|
4622
4658
|
// can't be a pure write. It should be rare that it does any
|
|
4623
4659
|
// writing.
|
|
4624
|
-
docView.enforceCursorAssoc();
|
|
4660
|
+
view.docView.enforceCursorAssoc();
|
|
4625
4661
|
}
|
|
4626
4662
|
return result;
|
|
4627
4663
|
}
|
|
4628
|
-
get visibleTop() { return this.scaler.fromDOM(this.pixelViewport.top
|
|
4629
|
-
get visibleBottom() { return this.scaler.fromDOM(this.pixelViewport.bottom
|
|
4664
|
+
get visibleTop() { return this.scaler.fromDOM(this.pixelViewport.top); }
|
|
4665
|
+
get visibleBottom() { return this.scaler.fromDOM(this.pixelViewport.bottom); }
|
|
4630
4666
|
getViewport(bias, scrollTarget) {
|
|
4631
4667
|
// This will divide VP.Margin between the top and the
|
|
4632
4668
|
// bottom, depending on the bias (the change in viewport position
|
|
@@ -4686,12 +4722,12 @@ class ViewState {
|
|
|
4686
4722
|
// This won't work at all in predominantly right-to-left text.
|
|
4687
4723
|
if (this.heightOracle.direction != exports.Direction.LTR)
|
|
4688
4724
|
return gaps;
|
|
4689
|
-
|
|
4725
|
+
for (let line of this.viewportLines) {
|
|
4690
4726
|
if (line.length < 4000 /* DoubleMargin */)
|
|
4691
|
-
|
|
4727
|
+
continue;
|
|
4692
4728
|
let structure = lineStructure(line.from, line.to, this.state);
|
|
4693
4729
|
if (structure.total < 4000 /* DoubleMargin */)
|
|
4694
|
-
|
|
4730
|
+
continue;
|
|
4695
4731
|
let viewFrom, viewTo;
|
|
4696
4732
|
if (this.heightOracle.lineWrapping) {
|
|
4697
4733
|
let marginHeight = (2000 /* Margin */ / this.heightOracle.lineLength) * this.heightOracle.lineHeight;
|
|
@@ -4721,7 +4757,7 @@ class ViewState {
|
|
|
4721
4757
|
Math.abs(gap.from - from) < 1000 /* HalfMargin */ && Math.abs(gap.to - to) < 1000 /* HalfMargin */) ||
|
|
4722
4758
|
new LineGap(from, to, this.gapSize(line, from, to, structure)));
|
|
4723
4759
|
}
|
|
4724
|
-
}
|
|
4760
|
+
}
|
|
4725
4761
|
return gaps;
|
|
4726
4762
|
}
|
|
4727
4763
|
gapSize(line, from, to, structure) {
|
|
@@ -4753,27 +4789,18 @@ class ViewState {
|
|
|
4753
4789
|
this.visibleRanges = ranges;
|
|
4754
4790
|
return changed ? 4 /* Viewport */ : 0;
|
|
4755
4791
|
}
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
}
|
|
4760
|
-
lineAtHeight(height, editorTop) {
|
|
4761
|
-
editorTop += this.paddingTop;
|
|
4762
|
-
return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height, editorTop), QueryType.ByHeight, this.state.doc, editorTop, 0), this.scaler, editorTop);
|
|
4792
|
+
lineBlockAt(pos) {
|
|
4793
|
+
return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to >= pos)) ||
|
|
4794
|
+
scaleBlock(this.heightMap.lineAt(pos, QueryType.ByPos, this.state.doc, 0, 0), this.scaler);
|
|
4763
4795
|
}
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height, editorTop), this.state.doc, editorTop, 0), this.scaler, editorTop);
|
|
4796
|
+
lineBlockAtHeight(height) {
|
|
4797
|
+
return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height), QueryType.ByHeight, this.state.doc, 0, 0), this.scaler);
|
|
4767
4798
|
}
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
return this.heightMap.forEachLine(from, to, this.state.doc, editorTop, 0, this.scaler.scale == 1 ? f : b => f(scaleBlock(b, this.scaler, editorTop)));
|
|
4799
|
+
elementAtHeight(height) {
|
|
4800
|
+
return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height), this.state.doc, 0, 0), this.scaler);
|
|
4771
4801
|
}
|
|
4772
4802
|
get contentHeight() {
|
|
4773
|
-
return this.
|
|
4774
|
-
}
|
|
4775
|
-
get domHeight() {
|
|
4776
|
-
return this.scaler.toDOM(this.heightMap.height, this.paddingTop);
|
|
4803
|
+
return this.scaler.toDOM(this.heightMap.height) + this.paddingTop + this.paddingBottom;
|
|
4777
4804
|
}
|
|
4778
4805
|
}
|
|
4779
4806
|
class Viewport {
|
|
@@ -4870,36 +4897,34 @@ class BigScaler {
|
|
|
4870
4897
|
base = obj.bottom;
|
|
4871
4898
|
}
|
|
4872
4899
|
}
|
|
4873
|
-
toDOM(n
|
|
4874
|
-
n -= top;
|
|
4900
|
+
toDOM(n) {
|
|
4875
4901
|
for (let i = 0, base = 0, domBase = 0;; i++) {
|
|
4876
4902
|
let vp = i < this.viewports.length ? this.viewports[i] : null;
|
|
4877
4903
|
if (!vp || n < vp.top)
|
|
4878
|
-
return domBase + (n - base) * this.scale
|
|
4904
|
+
return domBase + (n - base) * this.scale;
|
|
4879
4905
|
if (n <= vp.bottom)
|
|
4880
|
-
return vp.domTop + (n - vp.top)
|
|
4906
|
+
return vp.domTop + (n - vp.top);
|
|
4881
4907
|
base = vp.bottom;
|
|
4882
4908
|
domBase = vp.domBottom;
|
|
4883
4909
|
}
|
|
4884
4910
|
}
|
|
4885
|
-
fromDOM(n
|
|
4886
|
-
n -= top;
|
|
4911
|
+
fromDOM(n) {
|
|
4887
4912
|
for (let i = 0, base = 0, domBase = 0;; i++) {
|
|
4888
4913
|
let vp = i < this.viewports.length ? this.viewports[i] : null;
|
|
4889
4914
|
if (!vp || n < vp.domTop)
|
|
4890
|
-
return base + (n - domBase) / this.scale
|
|
4915
|
+
return base + (n - domBase) / this.scale;
|
|
4891
4916
|
if (n <= vp.domBottom)
|
|
4892
|
-
return vp.top + (n - vp.domTop)
|
|
4917
|
+
return vp.top + (n - vp.domTop);
|
|
4893
4918
|
base = vp.bottom;
|
|
4894
4919
|
domBase = vp.domBottom;
|
|
4895
4920
|
}
|
|
4896
4921
|
}
|
|
4897
4922
|
}
|
|
4898
|
-
function scaleBlock(block, scaler
|
|
4923
|
+
function scaleBlock(block, scaler) {
|
|
4899
4924
|
if (scaler.scale == 1)
|
|
4900
4925
|
return block;
|
|
4901
|
-
let bTop = scaler.toDOM(block.top
|
|
4902
|
-
return new BlockInfo(block.from, block.length, bTop, bBottom - bTop, Array.isArray(block.type) ? block.type.map(b => scaleBlock(b, scaler
|
|
4926
|
+
let bTop = scaler.toDOM(block.top), bBottom = scaler.toDOM(block.bottom);
|
|
4927
|
+
return new BlockInfo(block.from, block.length, bTop, bBottom - bTop, Array.isArray(block.type) ? block.type.map(b => scaleBlock(b, scaler)) : block.type);
|
|
4903
4928
|
}
|
|
4904
4929
|
|
|
4905
4930
|
const theme = state.Facet.define({ combine: strs => strs.join(" ") });
|
|
@@ -5036,7 +5061,7 @@ const baseTheme = buildTheme("." + baseThemeID, {
|
|
|
5036
5061
|
color: "inherit",
|
|
5037
5062
|
fontSize: "70%",
|
|
5038
5063
|
padding: ".2em 1em",
|
|
5039
|
-
borderRadius: "
|
|
5064
|
+
borderRadius: "1px"
|
|
5040
5065
|
},
|
|
5041
5066
|
"&light .cm-button": {
|
|
5042
5067
|
backgroundImage: "linear-gradient(#eff1f5, #d9d9df)",
|
|
@@ -5358,6 +5383,7 @@ class DOMObserver {
|
|
|
5358
5383
|
for (let dom of this.scrollTargets)
|
|
5359
5384
|
dom.removeEventListener("scroll", this.onScroll);
|
|
5360
5385
|
window.removeEventListener("scroll", this.onScroll);
|
|
5386
|
+
this.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange);
|
|
5361
5387
|
clearTimeout(this.parentCheck);
|
|
5362
5388
|
clearTimeout(this.resizeTimeout);
|
|
5363
5389
|
}
|
|
@@ -5654,6 +5680,7 @@ class EditorView {
|
|
|
5654
5680
|
*/
|
|
5655
5681
|
config = {}) {
|
|
5656
5682
|
this.plugins = [];
|
|
5683
|
+
this.pluginMap = new Map;
|
|
5657
5684
|
this.editorAttrs = {};
|
|
5658
5685
|
this.contentAttrs = {};
|
|
5659
5686
|
this.bidiCache = [];
|
|
@@ -5823,6 +5850,7 @@ class EditorView {
|
|
|
5823
5850
|
plugin.destroy(this);
|
|
5824
5851
|
this.viewState = new ViewState(newState);
|
|
5825
5852
|
this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec).update(this));
|
|
5853
|
+
this.pluginMap.clear();
|
|
5826
5854
|
this.docView = new DocView(this);
|
|
5827
5855
|
this.inputState.ensureHandlers(this);
|
|
5828
5856
|
this.mountStyles();
|
|
@@ -5853,6 +5881,7 @@ class EditorView {
|
|
|
5853
5881
|
if (plugin.mustUpdate != update)
|
|
5854
5882
|
plugin.destroy(this);
|
|
5855
5883
|
this.plugins = newPlugins;
|
|
5884
|
+
this.pluginMap.clear();
|
|
5856
5885
|
this.inputState.ensureHandlers(this);
|
|
5857
5886
|
}
|
|
5858
5887
|
else {
|
|
@@ -5860,7 +5889,7 @@ class EditorView {
|
|
|
5860
5889
|
p.mustUpdate = update;
|
|
5861
5890
|
}
|
|
5862
5891
|
for (let i = 0; i < this.plugins.length; i++)
|
|
5863
|
-
this.plugins[i]
|
|
5892
|
+
this.plugins[i].update(this);
|
|
5864
5893
|
}
|
|
5865
5894
|
/**
|
|
5866
5895
|
@internal
|
|
@@ -5878,11 +5907,11 @@ class EditorView {
|
|
|
5878
5907
|
for (let i = 0;; i++) {
|
|
5879
5908
|
this.updateState = 1 /* Measuring */;
|
|
5880
5909
|
let oldViewport = this.viewport;
|
|
5881
|
-
let changed = this.viewState.measure(this
|
|
5910
|
+
let changed = this.viewState.measure(this);
|
|
5882
5911
|
if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null)
|
|
5883
5912
|
break;
|
|
5884
5913
|
if (i > 5) {
|
|
5885
|
-
console.warn("Viewport failed to stabilize");
|
|
5914
|
+
console.warn(this.measureRequests.length ? "Measure loop restarted more than 5 times" : "Viewport failed to stabilize");
|
|
5886
5915
|
break;
|
|
5887
5916
|
}
|
|
5888
5917
|
let measuring = [];
|
|
@@ -5898,7 +5927,7 @@ class EditorView {
|
|
|
5898
5927
|
return BadMeasure;
|
|
5899
5928
|
}
|
|
5900
5929
|
});
|
|
5901
|
-
let update = new ViewUpdate(this, this.state);
|
|
5930
|
+
let update = new ViewUpdate(this, this.state), redrawn = false;
|
|
5902
5931
|
update.flags |= changed;
|
|
5903
5932
|
if (!updated)
|
|
5904
5933
|
updated = update;
|
|
@@ -5908,13 +5937,15 @@ class EditorView {
|
|
|
5908
5937
|
if (!update.empty) {
|
|
5909
5938
|
this.updatePlugins(update);
|
|
5910
5939
|
this.inputState.update(update);
|
|
5940
|
+
this.updateAttrs();
|
|
5941
|
+
redrawn = this.docView.update(update);
|
|
5911
5942
|
}
|
|
5912
|
-
this.updateAttrs();
|
|
5913
|
-
let redrawn = changed > 0 && this.docView.update(update);
|
|
5914
5943
|
for (let i = 0; i < measuring.length; i++)
|
|
5915
5944
|
if (measured[i] != BadMeasure) {
|
|
5916
5945
|
try {
|
|
5917
|
-
measuring[i]
|
|
5946
|
+
let m = measuring[i];
|
|
5947
|
+
if (m.write)
|
|
5948
|
+
m.write(measured[i], this);
|
|
5918
5949
|
}
|
|
5919
5950
|
catch (e) {
|
|
5920
5951
|
logException(this.state, e);
|
|
@@ -5924,8 +5955,8 @@ class EditorView {
|
|
|
5924
5955
|
this.docView.scrollIntoView(this.viewState.scrollTarget);
|
|
5925
5956
|
this.viewState.scrollTarget = null;
|
|
5926
5957
|
}
|
|
5927
|
-
if (
|
|
5928
|
-
this.docView.updateSelection(
|
|
5958
|
+
if (redrawn)
|
|
5959
|
+
this.docView.updateSelection(true);
|
|
5929
5960
|
if (this.viewport.from == oldViewport.from && this.viewport.to == oldViewport.to && this.measureRequests.length == 0)
|
|
5930
5961
|
break;
|
|
5931
5962
|
}
|
|
@@ -5947,7 +5978,7 @@ class EditorView {
|
|
|
5947
5978
|
this.state.facet(theme);
|
|
5948
5979
|
}
|
|
5949
5980
|
updateAttrs() {
|
|
5950
|
-
let editorAttrs =
|
|
5981
|
+
let editorAttrs = attrsFromFacet(this, editorAttributes, {
|
|
5951
5982
|
class: "cm-editor" + (this.hasFocus ? " cm-focused " : " ") + this.themeClasses
|
|
5952
5983
|
});
|
|
5953
5984
|
let contentAttrs = {
|
|
@@ -5963,7 +5994,7 @@ class EditorView {
|
|
|
5963
5994
|
};
|
|
5964
5995
|
if (this.state.readOnly)
|
|
5965
5996
|
contentAttrs["aria-readonly"] = "true";
|
|
5966
|
-
|
|
5997
|
+
attrsFromFacet(this, contentAttributes, contentAttrs);
|
|
5967
5998
|
this.observer.ignore(() => {
|
|
5968
5999
|
updateAttrs(this.contentDOM, this.contentAttrs, contentAttrs);
|
|
5969
6000
|
updateAttrs(this.dom, this.editorAttrs, editorAttrs);
|
|
@@ -6032,10 +6063,24 @@ class EditorView {
|
|
|
6032
6063
|
the return value of this method.
|
|
6033
6064
|
*/
|
|
6034
6065
|
plugin(plugin) {
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
return
|
|
6066
|
+
let known = this.pluginMap.get(plugin);
|
|
6067
|
+
if (known === undefined || known && known.spec != plugin)
|
|
6068
|
+
this.pluginMap.set(plugin, known = this.plugins.find(p => p.spec == plugin) || null);
|
|
6069
|
+
return known && known.update(this).value;
|
|
6070
|
+
}
|
|
6071
|
+
/**
|
|
6072
|
+
The top position of the document, in screen coordinates. This
|
|
6073
|
+
may be negative when the editor is scrolled down. Points
|
|
6074
|
+
directly to the top of the first line, not above the padding.
|
|
6075
|
+
*/
|
|
6076
|
+
get documentTop() {
|
|
6077
|
+
return this.contentDOM.getBoundingClientRect().top + this.viewState.paddingTop;
|
|
6078
|
+
}
|
|
6079
|
+
/**
|
|
6080
|
+
Reports the padding above and below the document.
|
|
6081
|
+
*/
|
|
6082
|
+
get documentPadding() {
|
|
6083
|
+
return { top: this.viewState.paddingTop, bottom: this.viewState.paddingBottom };
|
|
6039
6084
|
}
|
|
6040
6085
|
/**
|
|
6041
6086
|
Find the line or block widget at the given vertical position.
|
|
@@ -6047,10 +6092,21 @@ class EditorView {
|
|
|
6047
6092
|
position, or a precomputed document top
|
|
6048
6093
|
(`view.contentDOM.getBoundingClientRect().top`) to limit layout
|
|
6049
6094
|
queries.
|
|
6095
|
+
|
|
6096
|
+
*Deprecated: use `blockAtHeight` instead.*
|
|
6050
6097
|
*/
|
|
6051
6098
|
blockAtHeight(height, docTop) {
|
|
6099
|
+
let top = ensureTop(docTop, this);
|
|
6100
|
+
return this.elementAtHeight(height - top).moveY(top);
|
|
6101
|
+
}
|
|
6102
|
+
/**
|
|
6103
|
+
Find the text line or block widget at the given vertical
|
|
6104
|
+
position (which is interpreted as relative to the [top of the
|
|
6105
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)
|
|
6106
|
+
*/
|
|
6107
|
+
elementAtHeight(height) {
|
|
6052
6108
|
this.readMeasured();
|
|
6053
|
-
return this.viewState.
|
|
6109
|
+
return this.viewState.elementAtHeight(height);
|
|
6054
6110
|
}
|
|
6055
6111
|
/**
|
|
6056
6112
|
Find information for the visual line (see
|
|
@@ -6062,20 +6118,43 @@ class EditorView {
|
|
|
6062
6118
|
Defaults to treating `height` as a screen position. See
|
|
6063
6119
|
[`blockAtHeight`](https://codemirror.net/6/docs/ref/#view.EditorView.blockAtHeight) for the
|
|
6064
6120
|
interpretation of the `docTop` parameter.
|
|
6121
|
+
|
|
6122
|
+
*Deprecated: use `lineBlockAtHeight` instead.*
|
|
6065
6123
|
*/
|
|
6066
6124
|
visualLineAtHeight(height, docTop) {
|
|
6125
|
+
let top = ensureTop(docTop, this);
|
|
6126
|
+
return this.lineBlockAtHeight(height - top).moveY(top);
|
|
6127
|
+
}
|
|
6128
|
+
/**
|
|
6129
|
+
Find the line block (see
|
|
6130
|
+
[`lineBlockAt`](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) at the given
|
|
6131
|
+
height.
|
|
6132
|
+
*/
|
|
6133
|
+
lineBlockAtHeight(height) {
|
|
6067
6134
|
this.readMeasured();
|
|
6068
|
-
return this.viewState.
|
|
6135
|
+
return this.viewState.lineBlockAtHeight(height);
|
|
6069
6136
|
}
|
|
6070
6137
|
/**
|
|
6071
6138
|
Iterate over the height information of the visual lines in the
|
|
6072
6139
|
viewport. The heights of lines are reported relative to the
|
|
6073
6140
|
given document top, which defaults to the screen position of the
|
|
6074
6141
|
document (forcing a layout).
|
|
6142
|
+
|
|
6143
|
+
*Deprecated: use `viewportLineBlocks` instead.*
|
|
6075
6144
|
*/
|
|
6076
6145
|
viewportLines(f, docTop) {
|
|
6077
|
-
let
|
|
6078
|
-
|
|
6146
|
+
let top = ensureTop(docTop, this);
|
|
6147
|
+
for (let line of this.viewportLineBlocks)
|
|
6148
|
+
f(line.moveY(top));
|
|
6149
|
+
}
|
|
6150
|
+
/**
|
|
6151
|
+
Get the extent and vertical position of all [line
|
|
6152
|
+
blocks](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) in the viewport. Positions
|
|
6153
|
+
are relative to the [top of the
|
|
6154
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop);
|
|
6155
|
+
*/
|
|
6156
|
+
get viewportLineBlocks() {
|
|
6157
|
+
return this.viewState.viewportLines;
|
|
6079
6158
|
}
|
|
6080
6159
|
/**
|
|
6081
6160
|
Find the extent and height of the visual line (a range delimited
|
|
@@ -6086,9 +6165,22 @@ class EditorView {
|
|
|
6086
6165
|
argument, which defaults to 0 for this method. You can pass
|
|
6087
6166
|
`view.contentDOM.getBoundingClientRect().top` here to get screen
|
|
6088
6167
|
coordinates.
|
|
6168
|
+
|
|
6169
|
+
*Deprecated: use `lineBlockAt` instead.*
|
|
6089
6170
|
*/
|
|
6090
6171
|
visualLineAt(pos, docTop = 0) {
|
|
6091
|
-
return this.
|
|
6172
|
+
return this.lineBlockAt(pos).moveY(docTop + this.viewState.paddingTop);
|
|
6173
|
+
}
|
|
6174
|
+
/**
|
|
6175
|
+
Find the line block around the given document position. A line
|
|
6176
|
+
block is a range delimited on both sides by either a
|
|
6177
|
+
non-[hidden](https://codemirror.net/6/docs/ref/#view.Decoration^range) line breaks, or the
|
|
6178
|
+
start/end of the document. It will usually just hold a line of
|
|
6179
|
+
text, but may be broken into multiple textblocks by block
|
|
6180
|
+
widgets.
|
|
6181
|
+
*/
|
|
6182
|
+
lineBlockAt(pos) {
|
|
6183
|
+
return this.viewState.lineBlockAt(pos);
|
|
6092
6184
|
}
|
|
6093
6185
|
/**
|
|
6094
6186
|
The editor's total content height.
|
|
@@ -6421,8 +6513,9 @@ search match).
|
|
|
6421
6513
|
EditorView.announce = state.StateEffect.define();
|
|
6422
6514
|
// Maximum line length for which we compute accurate bidi info
|
|
6423
6515
|
const MaxBidiLine = 4096;
|
|
6424
|
-
|
|
6425
|
-
|
|
6516
|
+
// FIXME remove this and its callers on next breaking release
|
|
6517
|
+
function ensureTop(given, view) {
|
|
6518
|
+
return (given == null ? view.contentDOM.getBoundingClientRect().top : given) + view.viewState.paddingTop;
|
|
6426
6519
|
}
|
|
6427
6520
|
let resizeDebounce = -1;
|
|
6428
6521
|
function ensureGlobalHandler() {
|
|
@@ -6460,6 +6553,14 @@ class CachedOrder {
|
|
|
6460
6553
|
return result;
|
|
6461
6554
|
}
|
|
6462
6555
|
}
|
|
6556
|
+
function attrsFromFacet(view, facet, base) {
|
|
6557
|
+
for (let sources = view.state.facet(facet), i = sources.length - 1; i >= 0; i--) {
|
|
6558
|
+
let source = sources[i], value = typeof source == "function" ? source(view) : source;
|
|
6559
|
+
if (value)
|
|
6560
|
+
combineAttrs(value, base);
|
|
6561
|
+
}
|
|
6562
|
+
return base;
|
|
6563
|
+
}
|
|
6463
6564
|
|
|
6464
6565
|
const currentPlatform = browser.mac ? "mac" : browser.windows ? "win" : browser.linux ? "linux" : "key";
|
|
6465
6566
|
function normalizeKeyName(name, platform) {
|
|
@@ -6773,7 +6874,7 @@ function wrappedLine(view, pos, inside) {
|
|
|
6773
6874
|
type: exports.BlockType.Text };
|
|
6774
6875
|
}
|
|
6775
6876
|
function blockAt(view, pos) {
|
|
6776
|
-
let line = view.
|
|
6877
|
+
let line = view.lineBlockAt(pos);
|
|
6777
6878
|
if (Array.isArray(line.type))
|
|
6778
6879
|
for (let l of line.type) {
|
|
6779
6880
|
if (l.to > pos || l.to == pos && (l.to == line.to || l.type == exports.BlockType.Text))
|
|
@@ -7112,35 +7213,29 @@ class TabWidget extends WidgetType {
|
|
|
7112
7213
|
}
|
|
7113
7214
|
|
|
7114
7215
|
const plugin = ViewPlugin.fromClass(class {
|
|
7115
|
-
constructor(
|
|
7116
|
-
this.height =
|
|
7117
|
-
this.
|
|
7118
|
-
read: view => Math.max(0, view.scrollDOM.clientHeight - view.defaultLineHeight),
|
|
7119
|
-
write: (value, view) => {
|
|
7120
|
-
if (Math.abs(value - this.height) > 1) {
|
|
7121
|
-
this.height = value;
|
|
7122
|
-
view.contentDOM.style.paddingBottom = value + "px";
|
|
7123
|
-
}
|
|
7124
|
-
}
|
|
7125
|
-
};
|
|
7126
|
-
view.requestMeasure(this.measure);
|
|
7216
|
+
constructor() {
|
|
7217
|
+
this.height = 1000;
|
|
7218
|
+
this.attrs = { style: "padding-bottom: 1000px" };
|
|
7127
7219
|
}
|
|
7128
7220
|
update(update) {
|
|
7129
|
-
|
|
7130
|
-
|
|
7221
|
+
let height = update.view.viewState.editorHeight - update.view.defaultLineHeight;
|
|
7222
|
+
if (height != this.height) {
|
|
7223
|
+
this.height = height;
|
|
7224
|
+
this.attrs = { style: `padding-bottom: ${height}px` };
|
|
7225
|
+
}
|
|
7131
7226
|
}
|
|
7132
7227
|
});
|
|
7133
7228
|
/**
|
|
7134
|
-
Returns
|
|
7135
|
-
equivalent to the height of the editor, minus one line
|
|
7136
|
-
that every line in the document can be scrolled to the
|
|
7137
|
-
editor.
|
|
7229
|
+
Returns an extension that makes sure the content has a bottom
|
|
7230
|
+
margin equivalent to the height of the editor, minus one line
|
|
7231
|
+
height, so that every line in the document can be scrolled to the
|
|
7232
|
+
top of the editor.
|
|
7138
7233
|
|
|
7139
7234
|
This is only meaningful when the editor is scrollable, and should
|
|
7140
7235
|
not be enabled in editors that take the size of their content.
|
|
7141
7236
|
*/
|
|
7142
7237
|
function scrollPastEnd() {
|
|
7143
|
-
return plugin;
|
|
7238
|
+
return [plugin, contentAttributes.of(view => { var _a; return ((_a = view.plugin(plugin)) === null || _a === void 0 ? void 0 : _a.attrs) || null; })];
|
|
7144
7239
|
}
|
|
7145
7240
|
|
|
7146
7241
|
/**
|
|
@@ -7164,7 +7259,7 @@ const activeLineHighlighter = ViewPlugin.fromClass(class {
|
|
|
7164
7259
|
for (let r of view.state.selection.ranges) {
|
|
7165
7260
|
if (!r.empty)
|
|
7166
7261
|
return Decoration.none;
|
|
7167
|
-
let line = view.
|
|
7262
|
+
let line = view.lineBlockAt(r.head);
|
|
7168
7263
|
if (line.from > lastLineStart) {
|
|
7169
7264
|
deco.push(lineDeco.range(line.from));
|
|
7170
7265
|
lastLineStart = line.from;
|