@codemirror/view 6.43.12 → 6.43.13
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 +10 -0
- package/dist/index.cjs +63 -30
- package/dist/index.d.cts +2 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.js +63 -30
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## 6.43.13 (2026-09-22)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Make `coordsAtPos` (and thus also the drawn cursor) return the outside of the line when the queried side points out of the line and there is non-dominant-direction text at that side.
|
|
6
|
+
|
|
7
|
+
`visualLineSide`, which is now deprecated because it doesn't do anything non-trivial, now just returns the logical line side, since that is actually the more correct thing to do when moving to the start or end of line.
|
|
8
|
+
|
|
9
|
+
`moveVisually` now uses positions at the logical start/end of the line to represent the first/last position in the line when the text at that side isn't int he line's dominant text direction.
|
|
10
|
+
|
|
1
11
|
## 6.43.12 (2026-09-15)
|
|
2
12
|
|
|
3
13
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -1273,10 +1273,12 @@ let movedOver = "";
|
|
|
1273
1273
|
// This implementation moves strictly visually, without concern for a
|
|
1274
1274
|
// traversal visiting every logical position in the string. It will
|
|
1275
1275
|
// still do so for simple input, but situations like multiple isolates
|
|
1276
|
-
// with the same level next to each other
|
|
1277
|
-
// main dir at the end of the line, will make some positions
|
|
1276
|
+
// with the same level next to each other will make some positions
|
|
1278
1277
|
// unreachable with this motion. Each visible cursor position will
|
|
1279
|
-
// correspond to the lower-level bidi span that touches it
|
|
1278
|
+
// correspond to the lower-level bidi span that touches it, except
|
|
1279
|
+
// positions at start/end of line, when the text there isn't in the
|
|
1280
|
+
// dominant direction, which will use a cursor at the start/end with
|
|
1281
|
+
// an an assoc pointing out of the line instead.
|
|
1280
1282
|
//
|
|
1281
1283
|
// The alternative would be to solve an order globally for a given
|
|
1282
1284
|
// line, making sure that it includes every position, but that would
|
|
@@ -1285,8 +1287,22 @@ let movedOver = "";
|
|
|
1285
1287
|
// people. (And would generally be a lot more complicated.)
|
|
1286
1288
|
function moveVisually(line, order, dir, start, forward) {
|
|
1287
1289
|
var _a;
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
+
if (!line.length)
|
|
1291
|
+
return null;
|
|
1292
|
+
let startIndex = start.head - line.from, spanI;
|
|
1293
|
+
if (start.head == line.from && start.assoc < 0) { // Start of line.
|
|
1294
|
+
if (!forward)
|
|
1295
|
+
return null;
|
|
1296
|
+
startIndex = order[spanI = 0].side(false, dir);
|
|
1297
|
+
}
|
|
1298
|
+
else if (start.head == line.to && start.assoc > 0) { // End of line
|
|
1299
|
+
if (forward)
|
|
1300
|
+
return null;
|
|
1301
|
+
startIndex = order[spanI = order.length - 1].side(true, dir);
|
|
1302
|
+
}
|
|
1303
|
+
else {
|
|
1304
|
+
spanI = BidiSpan.find(order, startIndex, (_a = start.bidiLevel) !== null && _a !== void 0 ? _a : -1, start.assoc);
|
|
1305
|
+
}
|
|
1290
1306
|
let span = order[spanI], spanEnd = span.side(forward, dir);
|
|
1291
1307
|
// End of span
|
|
1292
1308
|
if (startIndex == spanEnd) {
|
|
@@ -1302,8 +1318,13 @@ function moveVisually(line, order, dir, start, forward) {
|
|
|
1302
1318
|
nextIndex = spanEnd;
|
|
1303
1319
|
movedOver = line.text.slice(Math.min(startIndex, nextIndex), Math.max(startIndex, nextIndex));
|
|
1304
1320
|
let nextSpan = spanI == (forward ? order.length - 1 : 0) ? null : order[spanI + (forward ? 1 : -1)];
|
|
1305
|
-
if (
|
|
1306
|
-
|
|
1321
|
+
if (nextIndex == spanEnd) {
|
|
1322
|
+
// End of line
|
|
1323
|
+
if (!nextSpan)
|
|
1324
|
+
return forward ? state.EditorSelection.cursor(line.to, 1) : state.EditorSelection.cursor(line.from, -1);
|
|
1325
|
+
if (nextSpan.level + (forward ? 0 : 1) < span.level)
|
|
1326
|
+
return state.EditorSelection.cursor(nextSpan.side(!forward, dir) + line.from, nextSpan.forward(forward, dir) ? 1 : -1, nextSpan.level);
|
|
1327
|
+
}
|
|
1307
1328
|
return state.EditorSelection.cursor(nextIndex + line.from, span.forward(forward, dir) ? -1 : 1, span.level);
|
|
1308
1329
|
}
|
|
1309
1330
|
function autoDirection(text, from, to) {
|
|
@@ -3678,9 +3699,6 @@ function moveToLineBoundary(view, start, forward, includeWrap) {
|
|
|
3678
3699
|
if (pos != null)
|
|
3679
3700
|
return state.EditorSelection.cursor(pos, forward ? -1 : 1);
|
|
3680
3701
|
}
|
|
3681
|
-
let line = view.state.doc.lineAt(start.head);
|
|
3682
|
-
if (forward ? line.to == block.to : line.from == block.from)
|
|
3683
|
-
return view.visualLineSide(line, forward);
|
|
3684
3702
|
return state.EditorSelection.cursor(forward ? block.to : block.from, forward ? -1 : 1);
|
|
3685
3703
|
}
|
|
3686
3704
|
function moveByChar(view, start, forward, by) {
|
|
@@ -3694,7 +3712,7 @@ function moveByChar(view, start, forward, by) {
|
|
|
3694
3712
|
char = "\n";
|
|
3695
3713
|
line = view.state.doc.line(line.number + (forward ? 1 : -1));
|
|
3696
3714
|
spans = view.bidiSpans(line);
|
|
3697
|
-
next =
|
|
3715
|
+
next = forward ? state.EditorSelection.cursor(line.from, -1) : state.EditorSelection.cursor(line.to, 1);
|
|
3698
3716
|
}
|
|
3699
3717
|
if (!check) {
|
|
3700
3718
|
if (!by)
|
|
@@ -4482,7 +4500,9 @@ function selectionFromPoints(points, base) {
|
|
|
4482
4500
|
if (points.length == 0)
|
|
4483
4501
|
return null;
|
|
4484
4502
|
let anchor = points[0].pos, head = points.length == 2 ? points[1].pos : anchor;
|
|
4485
|
-
return anchor
|
|
4503
|
+
return anchor < 0 || head < 0 ? null
|
|
4504
|
+
: anchor == head ? state.EditorSelection.create([state.EditorSelection.cursor(head + base, -1)])
|
|
4505
|
+
: state.EditorSelection.single(anchor + base, head + base);
|
|
4486
4506
|
}
|
|
4487
4507
|
function sameSelPos(selection, range) {
|
|
4488
4508
|
return range.head == selection.main.head && range.anchor == selection.main.anchor;
|
|
@@ -4634,8 +4654,9 @@ class InputState {
|
|
|
4634
4654
|
if (mods.shiftKey && browser.ios && !/^(off|none)$/.test(this.view.contentDOM.autocapitalize) &&
|
|
4635
4655
|
iosVirtualKeyboardOpen(this.view.win))
|
|
4636
4656
|
mods.shiftKey = false;
|
|
4637
|
-
this.pendingIOSKey = { key: event.key, keyCode: event.keyCode, mods };
|
|
4638
|
-
setTimeout(() => this.
|
|
4657
|
+
let pending = this.pendingIOSKey = { key: event.key, keyCode: event.keyCode, mods };
|
|
4658
|
+
setTimeout(() => { if (this.pendingIOSKey == pending)
|
|
4659
|
+
this.flushIOSKey(); }, 50);
|
|
4639
4660
|
return true;
|
|
4640
4661
|
}
|
|
4641
4662
|
if (event.keyCode != 229)
|
|
@@ -4924,14 +4945,14 @@ function doPaste(view, input) {
|
|
|
4924
4945
|
lastLine = line.from;
|
|
4925
4946
|
let insert = state$1.toText((byLine ? text.line(i++).text : input) + state$1.lineBreak);
|
|
4926
4947
|
return { changes: { from: line.from, insert },
|
|
4927
|
-
range: state.EditorSelection.cursor(range.from + insert.length) };
|
|
4948
|
+
range: state.EditorSelection.cursor(range.from + insert.length, -1) };
|
|
4928
4949
|
});
|
|
4929
4950
|
}
|
|
4930
4951
|
else if (byLine) {
|
|
4931
4952
|
changes = state$1.changeByRange(range => {
|
|
4932
4953
|
let line = text.line(i++);
|
|
4933
4954
|
return { changes: { from: range.from, to: range.to, insert: line.text },
|
|
4934
|
-
range: state.EditorSelection.cursor(range.from + line.length) };
|
|
4955
|
+
range: state.EditorSelection.cursor(range.from + line.length, -1) };
|
|
4935
4956
|
});
|
|
4936
4957
|
}
|
|
4937
4958
|
else {
|
|
@@ -5628,13 +5649,13 @@ class HeightMap {
|
|
|
5628
5649
|
after += next.size;
|
|
5629
5650
|
}
|
|
5630
5651
|
}
|
|
5631
|
-
let brk =
|
|
5652
|
+
let brk = false;
|
|
5632
5653
|
if (nodes[i - 1] == null) {
|
|
5633
|
-
brk =
|
|
5654
|
+
brk = true;
|
|
5634
5655
|
i--;
|
|
5635
5656
|
}
|
|
5636
5657
|
else if (nodes[i] == null) {
|
|
5637
|
-
brk =
|
|
5658
|
+
brk = true;
|
|
5638
5659
|
j++;
|
|
5639
5660
|
}
|
|
5640
5661
|
return new HeightMapBranch(HeightMap.of(nodes.slice(0, i)), brk, HeightMap.of(nodes.slice(j)));
|
|
@@ -5863,12 +5884,14 @@ class HeightMapGap extends HeightMap {
|
|
|
5863
5884
|
}
|
|
5864
5885
|
class HeightMapBranch extends HeightMap {
|
|
5865
5886
|
constructor(left, brk, right) {
|
|
5866
|
-
super(left.length + brk + right.length, left.height + right.height, brk | (left.outdated || right.outdated ? 2 /* Flag.Outdated */ : 0));
|
|
5887
|
+
super(left.length + (brk ? 1 : 0) + right.length, left.height + right.height, (brk ? 1 /* Flag.Break */ : 0) | (left.outdated || right.outdated ? 2 /* Flag.Outdated */ : 0));
|
|
5867
5888
|
this.left = left;
|
|
5868
5889
|
this.right = right;
|
|
5869
5890
|
this.size = left.size + right.size;
|
|
5870
5891
|
}
|
|
5871
|
-
|
|
5892
|
+
// Returns 1 if there is a line break between this.left and
|
|
5893
|
+
// this.right, 0 otherwise.
|
|
5894
|
+
get break() { return (this.flags & 1 /* Flag.Break */); }
|
|
5872
5895
|
blockAt(height, oracle, top, offset) {
|
|
5873
5896
|
let mid = top + this.left.height;
|
|
5874
5897
|
return height < mid ? this.left.blockAt(height, oracle, top, offset)
|
|
@@ -5898,11 +5921,11 @@ class HeightMapBranch extends HeightMap {
|
|
|
5898
5921
|
else {
|
|
5899
5922
|
let mid = this.lineAt(rightOffset, QueryType.ByPos, oracle, top, offset);
|
|
5900
5923
|
if (from < mid.from)
|
|
5901
|
-
this.left.forEachLine(from, mid.from - 1, oracle, top, offset, f);
|
|
5924
|
+
this.left.forEachLine(from, Math.min(to, mid.from - 1), oracle, top, offset, f);
|
|
5902
5925
|
if (mid.to >= from && mid.from <= to)
|
|
5903
5926
|
f(mid);
|
|
5904
5927
|
if (to > mid.to)
|
|
5905
|
-
this.right.forEachLine(mid.to + 1, to, oracle, rightTop, rightOffset, f);
|
|
5928
|
+
this.right.forEachLine(Math.max(from, mid.to + 1), to, oracle, rightTop, rightOffset, f);
|
|
5906
5929
|
}
|
|
5907
5930
|
}
|
|
5908
5931
|
replace(from, to, nodes) {
|
|
@@ -8471,15 +8494,11 @@ class EditorView {
|
|
|
8471
8494
|
return skipAtoms(this, start, moveByChar(this, start, forward, initial => byGroup(this, start.head, initial)));
|
|
8472
8495
|
}
|
|
8473
8496
|
/**
|
|
8474
|
-
Get the cursor position visually at the start
|
|
8475
|
-
|
|
8476
|
-
start or end (which is simply at `line.from`/`line.to`) if text
|
|
8477
|
-
at the start or end goes against the line's base text direction.
|
|
8497
|
+
**\[DEPRECATED]** Get the cursor position visually at the start
|
|
8498
|
+
or end of a line.
|
|
8478
8499
|
*/
|
|
8479
8500
|
visualLineSide(line, end) {
|
|
8480
|
-
|
|
8481
|
-
let span = order[end ? order.length - 1 : 0];
|
|
8482
|
-
return state.EditorSelection.cursor(span.side(end, dir) + line.from, span.forward(!end, dir) ? 1 : -1);
|
|
8501
|
+
return end ? state.EditorSelection.cursor(line.to, 1) : state.EditorSelection.cursor(line.from, -1);
|
|
8483
8502
|
}
|
|
8484
8503
|
/**
|
|
8485
8504
|
Move to the next line boundary in the given direction. If
|
|
@@ -8548,6 +8567,20 @@ class EditorView {
|
|
|
8548
8567
|
this.readMeasured();
|
|
8549
8568
|
let line = this.state.doc.lineAt(pos), order = this.bidiSpans(line);
|
|
8550
8569
|
let span = order[BidiSpan.find(order, pos - line.from, -1, side)];
|
|
8570
|
+
// For positions at start/end of line, if the side points out of
|
|
8571
|
+
// the line and the text there isn't in the dominant dir, return
|
|
8572
|
+
// the position of the outermost character on the line.
|
|
8573
|
+
if (line.length && (pos == line.from && side < 0 || pos == line.to && side > 0) &&
|
|
8574
|
+
span.dir != this.textDirectionAt(line.from)) {
|
|
8575
|
+
if (pos == line.to) {
|
|
8576
|
+
pos = line.from + span.from;
|
|
8577
|
+
side = 1;
|
|
8578
|
+
}
|
|
8579
|
+
else {
|
|
8580
|
+
pos = line.from + span.to;
|
|
8581
|
+
side = -1;
|
|
8582
|
+
}
|
|
8583
|
+
}
|
|
8551
8584
|
return this.docView.coordsAt(pos, side, span.dir == exports.Direction.RTL);
|
|
8552
8585
|
}
|
|
8553
8586
|
/**
|
package/dist/index.d.cts
CHANGED
|
@@ -959,10 +959,8 @@ declare class EditorView {
|
|
|
959
959
|
*/
|
|
960
960
|
moveByGroup(start: SelectionRange, forward: boolean): SelectionRange;
|
|
961
961
|
/**
|
|
962
|
-
Get the cursor position visually at the start
|
|
963
|
-
|
|
964
|
-
start or end (which is simply at `line.from`/`line.to`) if text
|
|
965
|
-
at the start or end goes against the line's base text direction.
|
|
962
|
+
**\[DEPRECATED]** Get the cursor position visually at the start
|
|
963
|
+
or end of a line.
|
|
966
964
|
*/
|
|
967
965
|
visualLineSide(line: Line, end: boolean): SelectionRange;
|
|
968
966
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -959,10 +959,8 @@ declare class EditorView {
|
|
|
959
959
|
*/
|
|
960
960
|
moveByGroup(start: SelectionRange, forward: boolean): SelectionRange;
|
|
961
961
|
/**
|
|
962
|
-
Get the cursor position visually at the start
|
|
963
|
-
|
|
964
|
-
start or end (which is simply at `line.from`/`line.to`) if text
|
|
965
|
-
at the start or end goes against the line's base text direction.
|
|
962
|
+
**\[DEPRECATED]** Get the cursor position visually at the start
|
|
963
|
+
or end of a line.
|
|
966
964
|
*/
|
|
967
965
|
visualLineSide(line: Line, end: boolean): SelectionRange;
|
|
968
966
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1269,10 +1269,12 @@ let movedOver = "";
|
|
|
1269
1269
|
// This implementation moves strictly visually, without concern for a
|
|
1270
1270
|
// traversal visiting every logical position in the string. It will
|
|
1271
1271
|
// still do so for simple input, but situations like multiple isolates
|
|
1272
|
-
// with the same level next to each other
|
|
1273
|
-
// main dir at the end of the line, will make some positions
|
|
1272
|
+
// with the same level next to each other will make some positions
|
|
1274
1273
|
// unreachable with this motion. Each visible cursor position will
|
|
1275
|
-
// correspond to the lower-level bidi span that touches it
|
|
1274
|
+
// correspond to the lower-level bidi span that touches it, except
|
|
1275
|
+
// positions at start/end of line, when the text there isn't in the
|
|
1276
|
+
// dominant direction, which will use a cursor at the start/end with
|
|
1277
|
+
// an an assoc pointing out of the line instead.
|
|
1276
1278
|
//
|
|
1277
1279
|
// The alternative would be to solve an order globally for a given
|
|
1278
1280
|
// line, making sure that it includes every position, but that would
|
|
@@ -1281,8 +1283,22 @@ let movedOver = "";
|
|
|
1281
1283
|
// people. (And would generally be a lot more complicated.)
|
|
1282
1284
|
function moveVisually(line, order, dir, start, forward) {
|
|
1283
1285
|
var _a;
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
+
if (!line.length)
|
|
1287
|
+
return null;
|
|
1288
|
+
let startIndex = start.head - line.from, spanI;
|
|
1289
|
+
if (start.head == line.from && start.assoc < 0) { // Start of line.
|
|
1290
|
+
if (!forward)
|
|
1291
|
+
return null;
|
|
1292
|
+
startIndex = order[spanI = 0].side(false, dir);
|
|
1293
|
+
}
|
|
1294
|
+
else if (start.head == line.to && start.assoc > 0) { // End of line
|
|
1295
|
+
if (forward)
|
|
1296
|
+
return null;
|
|
1297
|
+
startIndex = order[spanI = order.length - 1].side(true, dir);
|
|
1298
|
+
}
|
|
1299
|
+
else {
|
|
1300
|
+
spanI = BidiSpan.find(order, startIndex, (_a = start.bidiLevel) !== null && _a !== void 0 ? _a : -1, start.assoc);
|
|
1301
|
+
}
|
|
1286
1302
|
let span = order[spanI], spanEnd = span.side(forward, dir);
|
|
1287
1303
|
// End of span
|
|
1288
1304
|
if (startIndex == spanEnd) {
|
|
@@ -1298,8 +1314,13 @@ function moveVisually(line, order, dir, start, forward) {
|
|
|
1298
1314
|
nextIndex = spanEnd;
|
|
1299
1315
|
movedOver = line.text.slice(Math.min(startIndex, nextIndex), Math.max(startIndex, nextIndex));
|
|
1300
1316
|
let nextSpan = spanI == (forward ? order.length - 1 : 0) ? null : order[spanI + (forward ? 1 : -1)];
|
|
1301
|
-
if (
|
|
1302
|
-
|
|
1317
|
+
if (nextIndex == spanEnd) {
|
|
1318
|
+
// End of line
|
|
1319
|
+
if (!nextSpan)
|
|
1320
|
+
return forward ? EditorSelection.cursor(line.to, 1) : EditorSelection.cursor(line.from, -1);
|
|
1321
|
+
if (nextSpan.level + (forward ? 0 : 1) < span.level)
|
|
1322
|
+
return EditorSelection.cursor(nextSpan.side(!forward, dir) + line.from, nextSpan.forward(forward, dir) ? 1 : -1, nextSpan.level);
|
|
1323
|
+
}
|
|
1303
1324
|
return EditorSelection.cursor(nextIndex + line.from, span.forward(forward, dir) ? -1 : 1, span.level);
|
|
1304
1325
|
}
|
|
1305
1326
|
function autoDirection(text, from, to) {
|
|
@@ -3674,9 +3695,6 @@ function moveToLineBoundary(view, start, forward, includeWrap) {
|
|
|
3674
3695
|
if (pos != null)
|
|
3675
3696
|
return EditorSelection.cursor(pos, forward ? -1 : 1);
|
|
3676
3697
|
}
|
|
3677
|
-
let line = view.state.doc.lineAt(start.head);
|
|
3678
|
-
if (forward ? line.to == block.to : line.from == block.from)
|
|
3679
|
-
return view.visualLineSide(line, forward);
|
|
3680
3698
|
return EditorSelection.cursor(forward ? block.to : block.from, forward ? -1 : 1);
|
|
3681
3699
|
}
|
|
3682
3700
|
function moveByChar(view, start, forward, by) {
|
|
@@ -3690,7 +3708,7 @@ function moveByChar(view, start, forward, by) {
|
|
|
3690
3708
|
char = "\n";
|
|
3691
3709
|
line = view.state.doc.line(line.number + (forward ? 1 : -1));
|
|
3692
3710
|
spans = view.bidiSpans(line);
|
|
3693
|
-
next =
|
|
3711
|
+
next = forward ? EditorSelection.cursor(line.from, -1) : EditorSelection.cursor(line.to, 1);
|
|
3694
3712
|
}
|
|
3695
3713
|
if (!check) {
|
|
3696
3714
|
if (!by)
|
|
@@ -4478,7 +4496,9 @@ function selectionFromPoints(points, base) {
|
|
|
4478
4496
|
if (points.length == 0)
|
|
4479
4497
|
return null;
|
|
4480
4498
|
let anchor = points[0].pos, head = points.length == 2 ? points[1].pos : anchor;
|
|
4481
|
-
return anchor
|
|
4499
|
+
return anchor < 0 || head < 0 ? null
|
|
4500
|
+
: anchor == head ? EditorSelection.create([EditorSelection.cursor(head + base, -1)])
|
|
4501
|
+
: EditorSelection.single(anchor + base, head + base);
|
|
4482
4502
|
}
|
|
4483
4503
|
function sameSelPos(selection, range) {
|
|
4484
4504
|
return range.head == selection.main.head && range.anchor == selection.main.anchor;
|
|
@@ -4630,8 +4650,9 @@ class InputState {
|
|
|
4630
4650
|
if (mods.shiftKey && browser.ios && !/^(off|none)$/.test(this.view.contentDOM.autocapitalize) &&
|
|
4631
4651
|
iosVirtualKeyboardOpen(this.view.win))
|
|
4632
4652
|
mods.shiftKey = false;
|
|
4633
|
-
this.pendingIOSKey = { key: event.key, keyCode: event.keyCode, mods };
|
|
4634
|
-
setTimeout(() => this.
|
|
4653
|
+
let pending = this.pendingIOSKey = { key: event.key, keyCode: event.keyCode, mods };
|
|
4654
|
+
setTimeout(() => { if (this.pendingIOSKey == pending)
|
|
4655
|
+
this.flushIOSKey(); }, 50);
|
|
4635
4656
|
return true;
|
|
4636
4657
|
}
|
|
4637
4658
|
if (event.keyCode != 229)
|
|
@@ -4920,14 +4941,14 @@ function doPaste(view, input) {
|
|
|
4920
4941
|
lastLine = line.from;
|
|
4921
4942
|
let insert = state.toText((byLine ? text.line(i++).text : input) + state.lineBreak);
|
|
4922
4943
|
return { changes: { from: line.from, insert },
|
|
4923
|
-
range: EditorSelection.cursor(range.from + insert.length) };
|
|
4944
|
+
range: EditorSelection.cursor(range.from + insert.length, -1) };
|
|
4924
4945
|
});
|
|
4925
4946
|
}
|
|
4926
4947
|
else if (byLine) {
|
|
4927
4948
|
changes = state.changeByRange(range => {
|
|
4928
4949
|
let line = text.line(i++);
|
|
4929
4950
|
return { changes: { from: range.from, to: range.to, insert: line.text },
|
|
4930
|
-
range: EditorSelection.cursor(range.from + line.length) };
|
|
4951
|
+
range: EditorSelection.cursor(range.from + line.length, -1) };
|
|
4931
4952
|
});
|
|
4932
4953
|
}
|
|
4933
4954
|
else {
|
|
@@ -5623,13 +5644,13 @@ class HeightMap {
|
|
|
5623
5644
|
after += next.size;
|
|
5624
5645
|
}
|
|
5625
5646
|
}
|
|
5626
|
-
let brk =
|
|
5647
|
+
let brk = false;
|
|
5627
5648
|
if (nodes[i - 1] == null) {
|
|
5628
|
-
brk =
|
|
5649
|
+
brk = true;
|
|
5629
5650
|
i--;
|
|
5630
5651
|
}
|
|
5631
5652
|
else if (nodes[i] == null) {
|
|
5632
|
-
brk =
|
|
5653
|
+
brk = true;
|
|
5633
5654
|
j++;
|
|
5634
5655
|
}
|
|
5635
5656
|
return new HeightMapBranch(HeightMap.of(nodes.slice(0, i)), brk, HeightMap.of(nodes.slice(j)));
|
|
@@ -5858,12 +5879,14 @@ class HeightMapGap extends HeightMap {
|
|
|
5858
5879
|
}
|
|
5859
5880
|
class HeightMapBranch extends HeightMap {
|
|
5860
5881
|
constructor(left, brk, right) {
|
|
5861
|
-
super(left.length + brk + right.length, left.height + right.height, brk | (left.outdated || right.outdated ? 2 /* Flag.Outdated */ : 0));
|
|
5882
|
+
super(left.length + (brk ? 1 : 0) + right.length, left.height + right.height, (brk ? 1 /* Flag.Break */ : 0) | (left.outdated || right.outdated ? 2 /* Flag.Outdated */ : 0));
|
|
5862
5883
|
this.left = left;
|
|
5863
5884
|
this.right = right;
|
|
5864
5885
|
this.size = left.size + right.size;
|
|
5865
5886
|
}
|
|
5866
|
-
|
|
5887
|
+
// Returns 1 if there is a line break between this.left and
|
|
5888
|
+
// this.right, 0 otherwise.
|
|
5889
|
+
get break() { return (this.flags & 1 /* Flag.Break */); }
|
|
5867
5890
|
blockAt(height, oracle, top, offset) {
|
|
5868
5891
|
let mid = top + this.left.height;
|
|
5869
5892
|
return height < mid ? this.left.blockAt(height, oracle, top, offset)
|
|
@@ -5893,11 +5916,11 @@ class HeightMapBranch extends HeightMap {
|
|
|
5893
5916
|
else {
|
|
5894
5917
|
let mid = this.lineAt(rightOffset, QueryType.ByPos, oracle, top, offset);
|
|
5895
5918
|
if (from < mid.from)
|
|
5896
|
-
this.left.forEachLine(from, mid.from - 1, oracle, top, offset, f);
|
|
5919
|
+
this.left.forEachLine(from, Math.min(to, mid.from - 1), oracle, top, offset, f);
|
|
5897
5920
|
if (mid.to >= from && mid.from <= to)
|
|
5898
5921
|
f(mid);
|
|
5899
5922
|
if (to > mid.to)
|
|
5900
|
-
this.right.forEachLine(mid.to + 1, to, oracle, rightTop, rightOffset, f);
|
|
5923
|
+
this.right.forEachLine(Math.max(from, mid.to + 1), to, oracle, rightTop, rightOffset, f);
|
|
5901
5924
|
}
|
|
5902
5925
|
}
|
|
5903
5926
|
replace(from, to, nodes) {
|
|
@@ -8466,15 +8489,11 @@ class EditorView {
|
|
|
8466
8489
|
return skipAtoms(this, start, moveByChar(this, start, forward, initial => byGroup(this, start.head, initial)));
|
|
8467
8490
|
}
|
|
8468
8491
|
/**
|
|
8469
|
-
Get the cursor position visually at the start
|
|
8470
|
-
|
|
8471
|
-
start or end (which is simply at `line.from`/`line.to`) if text
|
|
8472
|
-
at the start or end goes against the line's base text direction.
|
|
8492
|
+
**\[DEPRECATED]** Get the cursor position visually at the start
|
|
8493
|
+
or end of a line.
|
|
8473
8494
|
*/
|
|
8474
8495
|
visualLineSide(line, end) {
|
|
8475
|
-
|
|
8476
|
-
let span = order[end ? order.length - 1 : 0];
|
|
8477
|
-
return EditorSelection.cursor(span.side(end, dir) + line.from, span.forward(!end, dir) ? 1 : -1);
|
|
8496
|
+
return end ? EditorSelection.cursor(line.to, 1) : EditorSelection.cursor(line.from, -1);
|
|
8478
8497
|
}
|
|
8479
8498
|
/**
|
|
8480
8499
|
Move to the next line boundary in the given direction. If
|
|
@@ -8543,6 +8562,20 @@ class EditorView {
|
|
|
8543
8562
|
this.readMeasured();
|
|
8544
8563
|
let line = this.state.doc.lineAt(pos), order = this.bidiSpans(line);
|
|
8545
8564
|
let span = order[BidiSpan.find(order, pos - line.from, -1, side)];
|
|
8565
|
+
// For positions at start/end of line, if the side points out of
|
|
8566
|
+
// the line and the text there isn't in the dominant dir, return
|
|
8567
|
+
// the position of the outermost character on the line.
|
|
8568
|
+
if (line.length && (pos == line.from && side < 0 || pos == line.to && side > 0) &&
|
|
8569
|
+
span.dir != this.textDirectionAt(line.from)) {
|
|
8570
|
+
if (pos == line.to) {
|
|
8571
|
+
pos = line.from + span.from;
|
|
8572
|
+
side = 1;
|
|
8573
|
+
}
|
|
8574
|
+
else {
|
|
8575
|
+
pos = line.from + span.to;
|
|
8576
|
+
side = -1;
|
|
8577
|
+
}
|
|
8578
|
+
}
|
|
8546
8579
|
return this.docView.coordsAt(pos, side, span.dir == Direction.RTL);
|
|
8547
8580
|
}
|
|
8548
8581
|
/**
|