@codemirror/view 0.19.21 → 0.19.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/index.cjs +189 -104
- package/dist/index.d.ts +44 -2
- package/dist/index.js +189 -104
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1984,10 +1984,7 @@ class DocView extends ContentView {
|
|
|
1984
1984
|
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
1985
1985
|
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
1986
1986
|
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) {
|
|
1987
|
+
if (this.dirty == 0 /* Not */ && changedRanges.length == 0) {
|
|
1991
1988
|
return false;
|
|
1992
1989
|
}
|
|
1993
1990
|
else {
|
|
@@ -2010,6 +2007,7 @@ class DocView extends ContentView {
|
|
|
2010
2007
|
// Used both by update and checkLayout do perform the actual DOM
|
|
2011
2008
|
// update
|
|
2012
2009
|
updateInner(changes, deco, oldLength) {
|
|
2010
|
+
this.view.viewState.mustMeasureContent = true;
|
|
2013
2011
|
this.updateChildren(changes, deco, oldLength);
|
|
2014
2012
|
let { observer } = this.view;
|
|
2015
2013
|
observer.ignore(() => {
|
|
@@ -2017,7 +2015,7 @@ class DocView extends ContentView {
|
|
|
2017
2015
|
// messes with the scroll position during DOM mutation (though
|
|
2018
2016
|
// no relayout is triggered and I cannot imagine how it can
|
|
2019
2017
|
// recompute the scroll position without a layout)
|
|
2020
|
-
this.dom.style.height = this.view.viewState.
|
|
2018
|
+
this.dom.style.height = this.view.viewState.contentHeight + "px";
|
|
2021
2019
|
this.dom.style.minWidth = this.minWidth ? this.minWidth + "px" : "";
|
|
2022
2020
|
// Chrome will sometimes, when DOM mutations occur directly
|
|
2023
2021
|
// around the selection, get confused and report a different
|
|
@@ -2302,7 +2300,7 @@ class DocView extends ContentView {
|
|
|
2302
2300
|
let next = i == vs.viewports.length ? null : vs.viewports[i];
|
|
2303
2301
|
let end = next ? next.from - 1 : this.length;
|
|
2304
2302
|
if (end > pos) {
|
|
2305
|
-
let height = vs.
|
|
2303
|
+
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
2306
2304
|
deco.push(Decoration.replace({ widget: new BlockGapWidget(height), block: true, inclusive: true }).range(pos, end));
|
|
2307
2305
|
}
|
|
2308
2306
|
if (!next)
|
|
@@ -2908,13 +2906,14 @@ function domPosInText(node, x, y) {
|
|
|
2908
2906
|
}
|
|
2909
2907
|
function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
2910
2908
|
var _a;
|
|
2911
|
-
let content = view.contentDOM.getBoundingClientRect(),
|
|
2909
|
+
let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
|
|
2912
2910
|
let halfLine = view.defaultLineHeight / 2;
|
|
2911
|
+
let block, yOffset = y - docTop;
|
|
2913
2912
|
for (let bounced = false;;) {
|
|
2914
|
-
block = view.
|
|
2915
|
-
if (block.top >
|
|
2916
|
-
bias = block.top >
|
|
2917
|
-
|
|
2913
|
+
block = view.elementAtHeight(yOffset);
|
|
2914
|
+
if (block.top > yOffset || block.bottom < yOffset) {
|
|
2915
|
+
bias = block.top > yOffset ? -1 : 1;
|
|
2916
|
+
yOffset = Math.min(block.bottom - halfLine, Math.max(block.top + halfLine, yOffset));
|
|
2918
2917
|
if (bounced)
|
|
2919
2918
|
return precise ? null : 0;
|
|
2920
2919
|
else
|
|
@@ -2922,8 +2921,9 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
2922
2921
|
}
|
|
2923
2922
|
if (block.type == BlockType.Text)
|
|
2924
2923
|
break;
|
|
2925
|
-
|
|
2924
|
+
yOffset = bias > 0 ? block.bottom + halfLine : block.top - halfLine;
|
|
2926
2925
|
}
|
|
2926
|
+
y = docTop + yOffset;
|
|
2927
2927
|
let lineStart = block.from;
|
|
2928
2928
|
// Clip x to the viewport sides
|
|
2929
2929
|
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
@@ -3036,17 +3036,17 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3036
3036
|
return EditorSelection.cursor(startPos);
|
|
3037
3037
|
let goal = start.goalColumn, startY;
|
|
3038
3038
|
let rect = view.contentDOM.getBoundingClientRect();
|
|
3039
|
-
let startCoords = view.coordsAtPos(startPos);
|
|
3039
|
+
let startCoords = view.coordsAtPos(startPos), docTop = view.documentTop;
|
|
3040
3040
|
if (startCoords) {
|
|
3041
3041
|
if (goal == null)
|
|
3042
3042
|
goal = startCoords.left - rect.left;
|
|
3043
3043
|
startY = dir < 0 ? startCoords.top : startCoords.bottom;
|
|
3044
3044
|
}
|
|
3045
3045
|
else {
|
|
3046
|
-
let line = view.viewState.
|
|
3046
|
+
let line = view.viewState.lineBlockAt(startPos - docTop);
|
|
3047
3047
|
if (goal == null)
|
|
3048
3048
|
goal = Math.min(rect.right - rect.left, view.defaultCharacterWidth * (startPos - line.from));
|
|
3049
|
-
startY = dir < 0 ? line.top : line.bottom;
|
|
3049
|
+
startY = (dir < 0 ? line.top : line.bottom) + docTop;
|
|
3050
3050
|
}
|
|
3051
3051
|
let resolvedGoal = rect.left + goal;
|
|
3052
3052
|
let dist = distance !== null && distance !== void 0 ? distance : (view.defaultLineHeight >> 1);
|
|
@@ -3297,7 +3297,7 @@ class MouseSelection {
|
|
|
3297
3297
|
this.extend = startEvent.shiftKey;
|
|
3298
3298
|
this.multiple = view.state.facet(EditorState.allowMultipleSelections) && addsSelectionRange(view, startEvent);
|
|
3299
3299
|
this.dragMove = dragMovesSelection(view, startEvent);
|
|
3300
|
-
this.dragging = isInPrimarySelection(view, startEvent) ? null : false;
|
|
3300
|
+
this.dragging = isInPrimarySelection(view, startEvent) && getClickType(startEvent) == 1 ? null : false;
|
|
3301
3301
|
// When clicking outside of the selection, immediately apply the
|
|
3302
3302
|
// effect of starting the selection
|
|
3303
3303
|
if (this.dragging === false) {
|
|
@@ -3518,7 +3518,7 @@ function basicMouseSelection(view, event) {
|
|
|
3518
3518
|
let last = start, lastEvent = event;
|
|
3519
3519
|
return {
|
|
3520
3520
|
update(update) {
|
|
3521
|
-
if (update.
|
|
3521
|
+
if (update.docChanged) {
|
|
3522
3522
|
if (start)
|
|
3523
3523
|
start.pos = update.changes.mapPos(start.pos);
|
|
3524
3524
|
startSel = startSel.map(update.changes);
|
|
@@ -3782,7 +3782,10 @@ class HeightOracle {
|
|
|
3782
3782
|
return lines * this.lineHeight;
|
|
3783
3783
|
}
|
|
3784
3784
|
setDoc(doc) { this.doc = doc; return this; }
|
|
3785
|
-
|
|
3785
|
+
mustRefreshForStyle(whiteSpace, direction) {
|
|
3786
|
+
return (wrappingWhiteSpace.indexOf(whiteSpace) > -1) != this.lineWrapping || this.direction != direction;
|
|
3787
|
+
}
|
|
3788
|
+
mustRefreshForHeights(lineHeights) {
|
|
3786
3789
|
let newHeight = false;
|
|
3787
3790
|
for (let i = 0; i < lineHeights.length; i++) {
|
|
3788
3791
|
let h = lineHeights[i];
|
|
@@ -3794,7 +3797,7 @@ class HeightOracle {
|
|
|
3794
3797
|
this.heightSamples[Math.floor(h * 10)] = true;
|
|
3795
3798
|
}
|
|
3796
3799
|
}
|
|
3797
|
-
return newHeight
|
|
3800
|
+
return newHeight;
|
|
3798
3801
|
}
|
|
3799
3802
|
refresh(whiteSpace, direction, lineHeight, charWidth, lineLength, knownHeights) {
|
|
3800
3803
|
let lineWrapping = wrappingWhiteSpace.indexOf(whiteSpace) > -1;
|
|
@@ -3848,7 +3851,8 @@ class BlockInfo {
|
|
|
3848
3851
|
*/
|
|
3849
3852
|
length,
|
|
3850
3853
|
/**
|
|
3851
|
-
The top position of the element
|
|
3854
|
+
The top position of the element (relative to the top of the
|
|
3855
|
+
document).
|
|
3852
3856
|
*/
|
|
3853
3857
|
top,
|
|
3854
3858
|
/**
|
|
@@ -3882,13 +3886,19 @@ class BlockInfo {
|
|
|
3882
3886
|
.concat(Array.isArray(other.type) ? other.type : [other]);
|
|
3883
3887
|
return new BlockInfo(this.from, this.length + other.length, this.top, this.height + other.height, detail);
|
|
3884
3888
|
}
|
|
3889
|
+
/**
|
|
3890
|
+
FIXME remove on next breaking release @internal
|
|
3891
|
+
*/
|
|
3892
|
+
moveY(offset) {
|
|
3893
|
+
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);
|
|
3894
|
+
}
|
|
3885
3895
|
}
|
|
3886
3896
|
var QueryType = /*@__PURE__*/(function (QueryType) {
|
|
3887
3897
|
QueryType[QueryType["ByPos"] = 0] = "ByPos";
|
|
3888
3898
|
QueryType[QueryType["ByHeight"] = 1] = "ByHeight";
|
|
3889
3899
|
QueryType[QueryType["ByPosNoHeight"] = 2] = "ByPosNoHeight";
|
|
3890
3900
|
return QueryType})(QueryType || (QueryType = {}));
|
|
3891
|
-
const Epsilon = 1e-
|
|
3901
|
+
const Epsilon = 1e-3;
|
|
3892
3902
|
class HeightMap {
|
|
3893
3903
|
constructor(length, // The number of characters covered
|
|
3894
3904
|
height, // Height of this part of the document
|
|
@@ -4115,22 +4125,30 @@ class HeightMapGap extends HeightMap {
|
|
|
4115
4125
|
// can't be widgets or collapsed ranges in those lines, because
|
|
4116
4126
|
// they would already have been added to the heightmap (gaps
|
|
4117
4127
|
// only contain plain text).
|
|
4118
|
-
let nodes = [], pos = Math.max(offset, measured.from);
|
|
4128
|
+
let nodes = [], pos = Math.max(offset, measured.from), singleHeight = -1;
|
|
4129
|
+
let wasChanged = oracle.heightChanged;
|
|
4119
4130
|
if (measured.from > offset)
|
|
4120
4131
|
nodes.push(new HeightMapGap(measured.from - offset - 1).updateHeight(oracle, offset));
|
|
4121
4132
|
while (pos <= end && measured.more) {
|
|
4122
4133
|
let len = oracle.doc.lineAt(pos).length;
|
|
4123
4134
|
if (nodes.length)
|
|
4124
4135
|
nodes.push(null);
|
|
4125
|
-
let
|
|
4136
|
+
let height = measured.heights[measured.index++];
|
|
4137
|
+
if (singleHeight == -1)
|
|
4138
|
+
singleHeight = height;
|
|
4139
|
+
else if (Math.abs(height - singleHeight) >= Epsilon)
|
|
4140
|
+
singleHeight = -2;
|
|
4141
|
+
let line = new HeightMapText(len, height);
|
|
4126
4142
|
line.outdated = false;
|
|
4127
4143
|
nodes.push(line);
|
|
4128
4144
|
pos += len + 1;
|
|
4129
4145
|
}
|
|
4130
4146
|
if (pos <= end)
|
|
4131
4147
|
nodes.push(null, new HeightMapGap(end - pos).updateHeight(oracle, pos));
|
|
4132
|
-
|
|
4133
|
-
|
|
4148
|
+
let result = HeightMap.of(nodes);
|
|
4149
|
+
oracle.heightChanged = wasChanged || singleHeight < 0 || Math.abs(result.height - this.height) >= Epsilon ||
|
|
4150
|
+
Math.abs(singleHeight - this.lines(oracle.doc, offset).lineHeight) >= Epsilon;
|
|
4151
|
+
return result;
|
|
4134
4152
|
}
|
|
4135
4153
|
else if (force || this.outdated) {
|
|
4136
4154
|
this.setHeight(oracle, oracle.heightForGap(offset, offset + this.length));
|
|
@@ -4488,7 +4506,8 @@ class ViewState {
|
|
|
4488
4506
|
this.inView = true;
|
|
4489
4507
|
this.paddingTop = 0;
|
|
4490
4508
|
this.paddingBottom = 0;
|
|
4491
|
-
this.
|
|
4509
|
+
this.contentDOMWidth = 0;
|
|
4510
|
+
this.contentDOMHeight = 0;
|
|
4492
4511
|
this.editorHeight = 0;
|
|
4493
4512
|
this.heightOracle = new HeightOracle;
|
|
4494
4513
|
// See VP.MaxDOMHeight
|
|
@@ -4496,6 +4515,9 @@ class ViewState {
|
|
|
4496
4515
|
this.scrollTarget = null;
|
|
4497
4516
|
// Briefly set to true when printing, to disable viewport limiting
|
|
4498
4517
|
this.printing = false;
|
|
4518
|
+
// Flag set when editor content was redrawn, so that the next
|
|
4519
|
+
// measure stage knows it must read DOM layout
|
|
4520
|
+
this.mustMeasureContent = true;
|
|
4499
4521
|
this.visibleRanges = [];
|
|
4500
4522
|
// Cursor 'assoc' is only significant when the cursor is on a line
|
|
4501
4523
|
// wrap point, where it must stick to the character that it is
|
|
@@ -4508,6 +4530,7 @@ class ViewState {
|
|
|
4508
4530
|
this.mustEnforceCursorAssoc = false;
|
|
4509
4531
|
this.heightMap = HeightMap.empty().applyChanges(state.facet(decorations), Text.empty, this.heightOracle.setDoc(state.doc), [new ChangedRange(0, 0, 0, state.doc.length)]);
|
|
4510
4532
|
this.viewport = this.getViewport(0, null);
|
|
4533
|
+
this.updateViewportLines();
|
|
4511
4534
|
this.updateForViewport();
|
|
4512
4535
|
this.lineGaps = this.ensureLineGaps([]);
|
|
4513
4536
|
this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(false)));
|
|
@@ -4518,7 +4541,7 @@ class ViewState {
|
|
|
4518
4541
|
for (let i = 0; i <= 1; i++) {
|
|
4519
4542
|
let pos = i ? main.head : main.anchor;
|
|
4520
4543
|
if (!viewports.some(({ from, to }) => pos >= from && pos <= to)) {
|
|
4521
|
-
let { from, to } = this.
|
|
4544
|
+
let { from, to } = this.lineBlockAt(pos);
|
|
4522
4545
|
viewports.push(new Viewport(from, to));
|
|
4523
4546
|
}
|
|
4524
4547
|
}
|
|
@@ -4526,6 +4549,12 @@ class ViewState {
|
|
|
4526
4549
|
this.scaler = this.heightMap.height <= 7000000 /* MaxDOMHeight */ ? IdScaler :
|
|
4527
4550
|
new BigScaler(this.heightOracle.doc, this.heightMap, this.viewports);
|
|
4528
4551
|
}
|
|
4552
|
+
updateViewportLines() {
|
|
4553
|
+
this.viewportLines = [];
|
|
4554
|
+
this.heightMap.forEachLine(this.viewport.from, this.viewport.to, this.state.doc, 0, 0, block => {
|
|
4555
|
+
this.viewportLines.push(this.scaler.scale == 1 ? block : scaleBlock(block, this.scaler));
|
|
4556
|
+
});
|
|
4557
|
+
}
|
|
4529
4558
|
update(update, scrollTarget = null) {
|
|
4530
4559
|
let prev = this.state;
|
|
4531
4560
|
this.state = update.state;
|
|
@@ -4540,6 +4569,9 @@ class ViewState {
|
|
|
4540
4569
|
if (scrollTarget && (scrollTarget.range.head < viewport.from || scrollTarget.range.head > viewport.to) ||
|
|
4541
4570
|
!this.viewportIsAppropriate(viewport))
|
|
4542
4571
|
viewport = this.getViewport(0, scrollTarget);
|
|
4572
|
+
if (!update.changes.empty || (update.flags & 2 /* Height */) ||
|
|
4573
|
+
viewport.from != this.viewport.from || viewport.to != this.viewport.to)
|
|
4574
|
+
this.updateViewportLines();
|
|
4543
4575
|
this.viewport = viewport;
|
|
4544
4576
|
this.updateForViewport();
|
|
4545
4577
|
if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
|
|
@@ -4551,13 +4583,17 @@ class ViewState {
|
|
|
4551
4583
|
update.state.selection.main.empty && update.state.selection.main.assoc)
|
|
4552
4584
|
this.mustEnforceCursorAssoc = true;
|
|
4553
4585
|
}
|
|
4554
|
-
measure(
|
|
4555
|
-
let dom =
|
|
4556
|
-
let
|
|
4557
|
-
|
|
4586
|
+
measure(view) {
|
|
4587
|
+
let dom = view.contentDOM, style = window.getComputedStyle(dom);
|
|
4588
|
+
let oracle = this.heightOracle;
|
|
4589
|
+
let whiteSpace = style.whiteSpace, direction = style.direction == "rtl" ? Direction.RTL : Direction.LTR;
|
|
4590
|
+
let refresh = this.heightOracle.mustRefreshForStyle(whiteSpace, direction);
|
|
4591
|
+
let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != dom.clientHeight;
|
|
4592
|
+
let result = 0, bias = 0;
|
|
4593
|
+
if (measureContent) {
|
|
4594
|
+
this.mustMeasureContent = false;
|
|
4595
|
+
this.contentDOMHeight = dom.clientHeight;
|
|
4558
4596
|
// Vertical padding
|
|
4559
|
-
let style = window.getComputedStyle(dom);
|
|
4560
|
-
whiteSpace = style.whiteSpace, direction = (style.direction == "rtl" ? Direction.RTL : Direction.LTR);
|
|
4561
4597
|
let paddingTop = parseInt(style.paddingTop) || 0, paddingBottom = parseInt(style.paddingBottom) || 0;
|
|
4562
4598
|
if (this.paddingTop != paddingTop || this.paddingBottom != paddingBottom) {
|
|
4563
4599
|
result |= 8 /* Geometry */;
|
|
@@ -4572,39 +4608,42 @@ class ViewState {
|
|
|
4572
4608
|
this.inView = this.pixelViewport.bottom > this.pixelViewport.top && this.pixelViewport.right > this.pixelViewport.left;
|
|
4573
4609
|
if (!this.inView)
|
|
4574
4610
|
return 0;
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
let { lineHeight, charWidth } = docView.measureTextSize();
|
|
4611
|
+
if (measureContent) {
|
|
4612
|
+
let lineHeights = view.docView.measureVisibleLineHeights();
|
|
4613
|
+
if (oracle.mustRefreshForHeights(lineHeights))
|
|
4614
|
+
refresh = true;
|
|
4615
|
+
let contentWidth = dom.clientWidth;
|
|
4616
|
+
if (refresh || oracle.lineWrapping && Math.abs(contentWidth - this.contentDOMWidth) > oracle.charWidth) {
|
|
4617
|
+
let { lineHeight, charWidth } = view.docView.measureTextSize();
|
|
4582
4618
|
refresh = oracle.refresh(whiteSpace, direction, lineHeight, charWidth, contentWidth / charWidth, lineHeights);
|
|
4583
4619
|
if (refresh) {
|
|
4584
|
-
docView.minWidth = 0;
|
|
4620
|
+
view.docView.minWidth = 0;
|
|
4585
4621
|
result |= 8 /* Geometry */;
|
|
4586
4622
|
}
|
|
4587
4623
|
}
|
|
4588
|
-
if (this.
|
|
4589
|
-
this.
|
|
4624
|
+
if (this.contentDOMWidth != contentWidth) {
|
|
4625
|
+
this.contentDOMWidth = contentWidth;
|
|
4590
4626
|
result |= 8 /* Geometry */;
|
|
4591
4627
|
}
|
|
4592
|
-
if (this.editorHeight !=
|
|
4593
|
-
this.editorHeight =
|
|
4628
|
+
if (this.editorHeight != view.scrollDOM.clientHeight) {
|
|
4629
|
+
this.editorHeight = view.scrollDOM.clientHeight;
|
|
4594
4630
|
result |= 8 /* Geometry */;
|
|
4595
4631
|
}
|
|
4596
4632
|
if (dTop > 0 && dBottom > 0)
|
|
4597
4633
|
bias = Math.max(dTop, dBottom);
|
|
4598
4634
|
else if (dTop < 0 && dBottom < 0)
|
|
4599
4635
|
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)
|
|
4636
|
+
oracle.heightChanged = false;
|
|
4637
|
+
this.heightMap = this.heightMap.updateHeight(oracle, 0, refresh, new MeasuredHeights(this.viewport.from, lineHeights));
|
|
4638
|
+
if (oracle.heightChanged)
|
|
4639
|
+
result |= 2 /* Height */;
|
|
4640
|
+
}
|
|
4641
|
+
let viewportChange = !this.viewportIsAppropriate(this.viewport, bias) ||
|
|
4642
|
+
this.scrollTarget && (this.scrollTarget.range.head < this.viewport.from || this.scrollTarget.range.head > this.viewport.to);
|
|
4643
|
+
if (viewportChange)
|
|
4607
4644
|
this.viewport = this.getViewport(bias, this.scrollTarget);
|
|
4645
|
+
if ((result & 2 /* Height */) || viewportChange)
|
|
4646
|
+
this.updateViewportLines();
|
|
4608
4647
|
this.updateForViewport();
|
|
4609
4648
|
if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
|
|
4610
4649
|
this.updateLineGaps(this.ensureLineGaps(refresh ? [] : this.lineGaps));
|
|
@@ -4615,12 +4654,12 @@ class ViewState {
|
|
|
4615
4654
|
// to a line end is going to trigger a layout anyway, so it
|
|
4616
4655
|
// can't be a pure write. It should be rare that it does any
|
|
4617
4656
|
// writing.
|
|
4618
|
-
docView.enforceCursorAssoc();
|
|
4657
|
+
view.docView.enforceCursorAssoc();
|
|
4619
4658
|
}
|
|
4620
4659
|
return result;
|
|
4621
4660
|
}
|
|
4622
|
-
get visibleTop() { return this.scaler.fromDOM(this.pixelViewport.top
|
|
4623
|
-
get visibleBottom() { return this.scaler.fromDOM(this.pixelViewport.bottom
|
|
4661
|
+
get visibleTop() { return this.scaler.fromDOM(this.pixelViewport.top); }
|
|
4662
|
+
get visibleBottom() { return this.scaler.fromDOM(this.pixelViewport.bottom); }
|
|
4624
4663
|
getViewport(bias, scrollTarget) {
|
|
4625
4664
|
// This will divide VP.Margin between the top and the
|
|
4626
4665
|
// bottom, depending on the bias (the change in viewport position
|
|
@@ -4680,12 +4719,12 @@ class ViewState {
|
|
|
4680
4719
|
// This won't work at all in predominantly right-to-left text.
|
|
4681
4720
|
if (this.heightOracle.direction != Direction.LTR)
|
|
4682
4721
|
return gaps;
|
|
4683
|
-
|
|
4722
|
+
for (let line of this.viewportLines) {
|
|
4684
4723
|
if (line.length < 4000 /* DoubleMargin */)
|
|
4685
|
-
|
|
4724
|
+
continue;
|
|
4686
4725
|
let structure = lineStructure(line.from, line.to, this.state);
|
|
4687
4726
|
if (structure.total < 4000 /* DoubleMargin */)
|
|
4688
|
-
|
|
4727
|
+
continue;
|
|
4689
4728
|
let viewFrom, viewTo;
|
|
4690
4729
|
if (this.heightOracle.lineWrapping) {
|
|
4691
4730
|
let marginHeight = (2000 /* Margin */ / this.heightOracle.lineLength) * this.heightOracle.lineHeight;
|
|
@@ -4715,7 +4754,7 @@ class ViewState {
|
|
|
4715
4754
|
Math.abs(gap.from - from) < 1000 /* HalfMargin */ && Math.abs(gap.to - to) < 1000 /* HalfMargin */) ||
|
|
4716
4755
|
new LineGap(from, to, this.gapSize(line, from, to, structure)));
|
|
4717
4756
|
}
|
|
4718
|
-
}
|
|
4757
|
+
}
|
|
4719
4758
|
return gaps;
|
|
4720
4759
|
}
|
|
4721
4760
|
gapSize(line, from, to, structure) {
|
|
@@ -4747,27 +4786,18 @@ class ViewState {
|
|
|
4747
4786
|
this.visibleRanges = ranges;
|
|
4748
4787
|
return changed ? 4 /* Viewport */ : 0;
|
|
4749
4788
|
}
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4789
|
+
lineBlockAt(pos) {
|
|
4790
|
+
return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to <= pos)) ||
|
|
4791
|
+
scaleBlock(this.heightMap.lineAt(pos, QueryType.ByPos, this.state.doc, 0, 0), this.scaler);
|
|
4753
4792
|
}
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height, editorTop), QueryType.ByHeight, this.state.doc, editorTop, 0), this.scaler, editorTop);
|
|
4793
|
+
lineBlockAtHeight(height) {
|
|
4794
|
+
return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height), QueryType.ByHeight, this.state.doc, 0, 0), this.scaler);
|
|
4757
4795
|
}
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height, editorTop), this.state.doc, editorTop, 0), this.scaler, editorTop);
|
|
4761
|
-
}
|
|
4762
|
-
forEachLine(from, to, f, editorTop) {
|
|
4763
|
-
editorTop += this.paddingTop;
|
|
4764
|
-
return this.heightMap.forEachLine(from, to, this.state.doc, editorTop, 0, this.scaler.scale == 1 ? f : b => f(scaleBlock(b, this.scaler, editorTop)));
|
|
4796
|
+
elementAtHeight(height) {
|
|
4797
|
+
return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height), this.state.doc, 0, 0), this.scaler);
|
|
4765
4798
|
}
|
|
4766
4799
|
get contentHeight() {
|
|
4767
|
-
return this.
|
|
4768
|
-
}
|
|
4769
|
-
get domHeight() {
|
|
4770
|
-
return this.scaler.toDOM(this.heightMap.height, this.paddingTop);
|
|
4800
|
+
return this.scaler.toDOM(this.heightMap.height) + this.paddingTop + this.paddingBottom;
|
|
4771
4801
|
}
|
|
4772
4802
|
}
|
|
4773
4803
|
class Viewport {
|
|
@@ -4864,36 +4894,34 @@ class BigScaler {
|
|
|
4864
4894
|
base = obj.bottom;
|
|
4865
4895
|
}
|
|
4866
4896
|
}
|
|
4867
|
-
toDOM(n
|
|
4868
|
-
n -= top;
|
|
4897
|
+
toDOM(n) {
|
|
4869
4898
|
for (let i = 0, base = 0, domBase = 0;; i++) {
|
|
4870
4899
|
let vp = i < this.viewports.length ? this.viewports[i] : null;
|
|
4871
4900
|
if (!vp || n < vp.top)
|
|
4872
|
-
return domBase + (n - base) * this.scale
|
|
4901
|
+
return domBase + (n - base) * this.scale;
|
|
4873
4902
|
if (n <= vp.bottom)
|
|
4874
|
-
return vp.domTop + (n - vp.top)
|
|
4903
|
+
return vp.domTop + (n - vp.top);
|
|
4875
4904
|
base = vp.bottom;
|
|
4876
4905
|
domBase = vp.domBottom;
|
|
4877
4906
|
}
|
|
4878
4907
|
}
|
|
4879
|
-
fromDOM(n
|
|
4880
|
-
n -= top;
|
|
4908
|
+
fromDOM(n) {
|
|
4881
4909
|
for (let i = 0, base = 0, domBase = 0;; i++) {
|
|
4882
4910
|
let vp = i < this.viewports.length ? this.viewports[i] : null;
|
|
4883
4911
|
if (!vp || n < vp.domTop)
|
|
4884
|
-
return base + (n - domBase) / this.scale
|
|
4912
|
+
return base + (n - domBase) / this.scale;
|
|
4885
4913
|
if (n <= vp.domBottom)
|
|
4886
|
-
return vp.top + (n - vp.domTop)
|
|
4914
|
+
return vp.top + (n - vp.domTop);
|
|
4887
4915
|
base = vp.bottom;
|
|
4888
4916
|
domBase = vp.domBottom;
|
|
4889
4917
|
}
|
|
4890
4918
|
}
|
|
4891
4919
|
}
|
|
4892
|
-
function scaleBlock(block, scaler
|
|
4920
|
+
function scaleBlock(block, scaler) {
|
|
4893
4921
|
if (scaler.scale == 1)
|
|
4894
4922
|
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
|
|
4923
|
+
let bTop = scaler.toDOM(block.top), bBottom = scaler.toDOM(block.bottom);
|
|
4924
|
+
return new BlockInfo(block.from, block.length, bTop, bBottom - bTop, Array.isArray(block.type) ? block.type.map(b => scaleBlock(b, scaler)) : block.type);
|
|
4897
4925
|
}
|
|
4898
4926
|
|
|
4899
4927
|
const theme = /*@__PURE__*/Facet.define({ combine: strs => strs.join(" ") });
|
|
@@ -5872,11 +5900,11 @@ class EditorView {
|
|
|
5872
5900
|
for (let i = 0;; i++) {
|
|
5873
5901
|
this.updateState = 1 /* Measuring */;
|
|
5874
5902
|
let oldViewport = this.viewport;
|
|
5875
|
-
let changed = this.viewState.measure(this
|
|
5903
|
+
let changed = this.viewState.measure(this);
|
|
5876
5904
|
if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null)
|
|
5877
5905
|
break;
|
|
5878
5906
|
if (i > 5) {
|
|
5879
|
-
console.warn("Viewport failed to stabilize");
|
|
5907
|
+
console.warn(this.measureRequests.length ? "Measure loop restarted more than 5 times" : "Viewport failed to stabilize");
|
|
5880
5908
|
break;
|
|
5881
5909
|
}
|
|
5882
5910
|
let measuring = [];
|
|
@@ -5892,7 +5920,7 @@ class EditorView {
|
|
|
5892
5920
|
return BadMeasure;
|
|
5893
5921
|
}
|
|
5894
5922
|
});
|
|
5895
|
-
let update = new ViewUpdate(this, this.state);
|
|
5923
|
+
let update = new ViewUpdate(this, this.state), redrawn = false;
|
|
5896
5924
|
update.flags |= changed;
|
|
5897
5925
|
if (!updated)
|
|
5898
5926
|
updated = update;
|
|
@@ -5902,13 +5930,15 @@ class EditorView {
|
|
|
5902
5930
|
if (!update.empty) {
|
|
5903
5931
|
this.updatePlugins(update);
|
|
5904
5932
|
this.inputState.update(update);
|
|
5933
|
+
this.updateAttrs();
|
|
5934
|
+
redrawn = this.docView.update(update);
|
|
5905
5935
|
}
|
|
5906
|
-
this.updateAttrs();
|
|
5907
|
-
let redrawn = changed > 0 && this.docView.update(update);
|
|
5908
5936
|
for (let i = 0; i < measuring.length; i++)
|
|
5909
5937
|
if (measured[i] != BadMeasure) {
|
|
5910
5938
|
try {
|
|
5911
|
-
measuring[i]
|
|
5939
|
+
let m = measuring[i];
|
|
5940
|
+
if (m.write)
|
|
5941
|
+
m.write(measured[i], this);
|
|
5912
5942
|
}
|
|
5913
5943
|
catch (e) {
|
|
5914
5944
|
logException(this.state, e);
|
|
@@ -5918,8 +5948,8 @@ class EditorView {
|
|
|
5918
5948
|
this.docView.scrollIntoView(this.viewState.scrollTarget);
|
|
5919
5949
|
this.viewState.scrollTarget = null;
|
|
5920
5950
|
}
|
|
5921
|
-
if (
|
|
5922
|
-
this.docView.updateSelection(
|
|
5951
|
+
if (redrawn)
|
|
5952
|
+
this.docView.updateSelection(true);
|
|
5923
5953
|
if (this.viewport.from == oldViewport.from && this.viewport.to == oldViewport.to && this.measureRequests.length == 0)
|
|
5924
5954
|
break;
|
|
5925
5955
|
}
|
|
@@ -6032,6 +6062,13 @@ class EditorView {
|
|
|
6032
6062
|
return null;
|
|
6033
6063
|
}
|
|
6034
6064
|
/**
|
|
6065
|
+
The top position of the document, in screen coordinates. This
|
|
6066
|
+
may be negative when the editor is scrolled down.
|
|
6067
|
+
*/
|
|
6068
|
+
get documentTop() {
|
|
6069
|
+
return this.contentDOM.getBoundingClientRect().top + this.viewState.paddingTop;
|
|
6070
|
+
}
|
|
6071
|
+
/**
|
|
6035
6072
|
Find the line or block widget at the given vertical position.
|
|
6036
6073
|
|
|
6037
6074
|
By default, this position is interpreted as a screen position,
|
|
@@ -6041,10 +6078,21 @@ class EditorView {
|
|
|
6041
6078
|
position, or a precomputed document top
|
|
6042
6079
|
(`view.contentDOM.getBoundingClientRect().top`) to limit layout
|
|
6043
6080
|
queries.
|
|
6081
|
+
|
|
6082
|
+
*Deprecated: use `blockAtHeight` instead.*
|
|
6044
6083
|
*/
|
|
6045
6084
|
blockAtHeight(height, docTop) {
|
|
6085
|
+
let top = ensureTop(docTop, this);
|
|
6086
|
+
return this.elementAtHeight(height - top).moveY(top);
|
|
6087
|
+
}
|
|
6088
|
+
/**
|
|
6089
|
+
Find the text line or block widget at the given vertical
|
|
6090
|
+
position (which is interpreted as relative to the [top of the
|
|
6091
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop)
|
|
6092
|
+
*/
|
|
6093
|
+
elementAtHeight(height) {
|
|
6046
6094
|
this.readMeasured();
|
|
6047
|
-
return this.viewState.
|
|
6095
|
+
return this.viewState.elementAtHeight(height);
|
|
6048
6096
|
}
|
|
6049
6097
|
/**
|
|
6050
6098
|
Find information for the visual line (see
|
|
@@ -6056,20 +6104,43 @@ class EditorView {
|
|
|
6056
6104
|
Defaults to treating `height` as a screen position. See
|
|
6057
6105
|
[`blockAtHeight`](https://codemirror.net/6/docs/ref/#view.EditorView.blockAtHeight) for the
|
|
6058
6106
|
interpretation of the `docTop` parameter.
|
|
6107
|
+
|
|
6108
|
+
*Deprecated: use `lineBlockAtHeight` instead.*
|
|
6059
6109
|
*/
|
|
6060
6110
|
visualLineAtHeight(height, docTop) {
|
|
6111
|
+
let top = ensureTop(docTop, this);
|
|
6112
|
+
return this.lineBlockAtHeight(height - top).moveY(top);
|
|
6113
|
+
}
|
|
6114
|
+
/**
|
|
6115
|
+
Find the line block (see
|
|
6116
|
+
[`lineBlockAt`](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) at the given
|
|
6117
|
+
height.
|
|
6118
|
+
*/
|
|
6119
|
+
lineBlockAtHeight(height) {
|
|
6061
6120
|
this.readMeasured();
|
|
6062
|
-
return this.viewState.
|
|
6121
|
+
return this.viewState.lineBlockAtHeight(height);
|
|
6063
6122
|
}
|
|
6064
6123
|
/**
|
|
6065
6124
|
Iterate over the height information of the visual lines in the
|
|
6066
6125
|
viewport. The heights of lines are reported relative to the
|
|
6067
6126
|
given document top, which defaults to the screen position of the
|
|
6068
6127
|
document (forcing a layout).
|
|
6128
|
+
|
|
6129
|
+
*Deprecated: use `viewportLineBlocks` instead.*
|
|
6069
6130
|
*/
|
|
6070
6131
|
viewportLines(f, docTop) {
|
|
6071
|
-
let
|
|
6072
|
-
|
|
6132
|
+
let top = ensureTop(docTop, this);
|
|
6133
|
+
for (let line of this.viewportLineBlocks)
|
|
6134
|
+
f(line.moveY(top));
|
|
6135
|
+
}
|
|
6136
|
+
/**
|
|
6137
|
+
Get the extent and vertical position of all [line
|
|
6138
|
+
blocks](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) in the viewport. Positions
|
|
6139
|
+
are relative to the [top of the
|
|
6140
|
+
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop);
|
|
6141
|
+
*/
|
|
6142
|
+
get viewportLineBlocks() {
|
|
6143
|
+
return this.viewState.viewportLines;
|
|
6073
6144
|
}
|
|
6074
6145
|
/**
|
|
6075
6146
|
Find the extent and height of the visual line (a range delimited
|
|
@@ -6080,9 +6151,22 @@ class EditorView {
|
|
|
6080
6151
|
argument, which defaults to 0 for this method. You can pass
|
|
6081
6152
|
`view.contentDOM.getBoundingClientRect().top` here to get screen
|
|
6082
6153
|
coordinates.
|
|
6154
|
+
|
|
6155
|
+
*Deprecated: use `lineBlockAt` instead.*
|
|
6083
6156
|
*/
|
|
6084
6157
|
visualLineAt(pos, docTop = 0) {
|
|
6085
|
-
return this.
|
|
6158
|
+
return this.lineBlockAt(pos).moveY(docTop + this.viewState.paddingTop);
|
|
6159
|
+
}
|
|
6160
|
+
/**
|
|
6161
|
+
Find the line block around the given document position. A line
|
|
6162
|
+
block is a range delimited on both sides by either a
|
|
6163
|
+
non-[hidden](https://codemirror.net/6/docs/ref/#view.Decoration^range) line breaks, or the
|
|
6164
|
+
start/end of the document. It will usually just hold a line of
|
|
6165
|
+
text, but may be broken into multiple textblocks by block
|
|
6166
|
+
widgets.
|
|
6167
|
+
*/
|
|
6168
|
+
lineBlockAt(pos) {
|
|
6169
|
+
return this.viewState.lineBlockAt(pos);
|
|
6086
6170
|
}
|
|
6087
6171
|
/**
|
|
6088
6172
|
The editor's total content height.
|
|
@@ -6415,8 +6499,9 @@ search match).
|
|
|
6415
6499
|
EditorView.announce = /*@__PURE__*/StateEffect.define();
|
|
6416
6500
|
// Maximum line length for which we compute accurate bidi info
|
|
6417
6501
|
const MaxBidiLine = 4096;
|
|
6418
|
-
|
|
6419
|
-
|
|
6502
|
+
// FIXME remove this and its callers on next breaking release
|
|
6503
|
+
function ensureTop(given, view) {
|
|
6504
|
+
return (given == null ? view.contentDOM.getBoundingClientRect().top : given) + view.viewState.paddingTop;
|
|
6420
6505
|
}
|
|
6421
6506
|
let resizeDebounce = -1;
|
|
6422
6507
|
function ensureGlobalHandler() {
|
|
@@ -6767,7 +6852,7 @@ function wrappedLine(view, pos, inside) {
|
|
|
6767
6852
|
type: BlockType.Text };
|
|
6768
6853
|
}
|
|
6769
6854
|
function blockAt(view, pos) {
|
|
6770
|
-
let line = view.
|
|
6855
|
+
let line = view.lineBlockAt(pos);
|
|
6771
6856
|
if (Array.isArray(line.type))
|
|
6772
6857
|
for (let l of line.type) {
|
|
6773
6858
|
if (l.to > pos || l.to == pos && (l.to == line.to || l.type == BlockType.Text))
|
|
@@ -7158,7 +7243,7 @@ const activeLineHighlighter = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
7158
7243
|
for (let r of view.state.selection.ranges) {
|
|
7159
7244
|
if (!r.empty)
|
|
7160
7245
|
return Decoration.none;
|
|
7161
|
-
let line = view.
|
|
7246
|
+
let line = view.lineBlockAt(r.head);
|
|
7162
7247
|
if (line.from > lastLineStart) {
|
|
7163
7248
|
deco.push(lineDeco.range(line.from));
|
|
7164
7249
|
lastLineStart = line.from;
|