@codemirror/view 6.11.2 → 6.11.3

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 CHANGED
@@ -1,3 +1,13 @@
1
+ ## 6.11.3 (2023-05-17)
2
+
3
+ ### Bug fixes
4
+
5
+ Make sure pointer selection respects `EditorView.atomicRanges`.
6
+
7
+ Preserve DOM widgets when their decoration type changes but they otherwise stay in the same place.
8
+
9
+ Fix a bug in `drawSelection` that could lead to invisible or incorrect selections for a blank line below a block widget.
10
+
1
11
  ## 6.11.2 (2023-05-13)
2
12
 
3
13
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -1647,7 +1647,7 @@ class BlockWidgetView extends ContentView {
1647
1647
  }
1648
1648
  domBoundsAround() { return null; }
1649
1649
  become(other) {
1650
- if (other instanceof BlockWidgetView && other.type == this.type &&
1650
+ if (other instanceof BlockWidgetView &&
1651
1651
  other.widget.constructor == this.widget.constructor) {
1652
1652
  if (!other.widget.compare(this.widget))
1653
1653
  this.markDirty(true);
@@ -1655,6 +1655,7 @@ class BlockWidgetView extends ContentView {
1655
1655
  this.prevWidget = this.widget;
1656
1656
  this.widget = other.widget;
1657
1657
  this.length = other.length;
1658
+ this.type = other.type;
1658
1659
  this.breakAfter = other.breakAfter;
1659
1660
  return true;
1660
1661
  }
@@ -2481,6 +2482,7 @@ class DOMReader {
2481
2482
  constructor(points, state$1) {
2482
2483
  this.points = points;
2483
2484
  this.text = "";
2485
+ console.log("make reader");
2484
2486
  this.lineSeparator = state$1.facet(state.EditorState.lineSeparator);
2485
2487
  }
2486
2488
  append(text) {
@@ -2495,6 +2497,7 @@ class DOMReader {
2495
2497
  let parent = start.parentNode;
2496
2498
  for (let cur = start;;) {
2497
2499
  this.findPointBefore(parent, cur);
2500
+ let oldLen = this.text.length;
2498
2501
  this.readNode(cur);
2499
2502
  let next = cur.nextSibling;
2500
2503
  if (next == end)
@@ -2502,7 +2505,7 @@ class DOMReader {
2502
2505
  let view = ContentView.get(cur), nextView = ContentView.get(next);
2503
2506
  if (view && nextView ? view.breakAfter :
2504
2507
  (view ? view.breakAfter : isBlockElement(cur)) ||
2505
- (isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore)))
2508
+ (isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
2506
2509
  this.lineBreak();
2507
2510
  cur = next;
2508
2511
  }
@@ -3451,15 +3454,15 @@ function moveVertically(view, start, forward, distance) {
3451
3454
  return state.EditorSelection.cursor(pos, start.assoc, undefined, goal);
3452
3455
  }
3453
3456
  }
3454
- function skipAtoms(view, oldPos, pos) {
3455
- let atoms = view.state.facet(atomicRanges).map(f => f(view));
3457
+ function skipAtomicRanges(atoms, pos, bias) {
3456
3458
  for (;;) {
3457
- let moved = false;
3459
+ let moved = 0;
3458
3460
  for (let set of atoms) {
3459
- set.between(pos.from - 1, pos.from + 1, (from, to, value) => {
3460
- if (pos.from > from && pos.from < to) {
3461
- pos = oldPos.head > pos.from ? state.EditorSelection.cursor(from, 1) : state.EditorSelection.cursor(to, -1);
3462
- moved = true;
3461
+ set.between(pos - 1, pos + 1, (from, to, value) => {
3462
+ if (pos > from && pos < to) {
3463
+ let side = moved || bias || (pos - from < to - pos ? -1 : 1);
3464
+ pos = side < 0 ? from : to;
3465
+ moved = side;
3463
3466
  }
3464
3467
  });
3465
3468
  }
@@ -3467,6 +3470,10 @@ function skipAtoms(view, oldPos, pos) {
3467
3470
  return pos;
3468
3471
  }
3469
3472
  }
3473
+ function skipAtoms(view, oldPos, pos) {
3474
+ let newPos = skipAtomicRanges(view.state.facet(atomicRanges).map(f => f(view)), pos.from, oldPos.head > pos.from ? -1 : 1);
3475
+ return newPos == pos.from ? pos : state.EditorSelection.cursor(newPos, newPos < pos.from ? 1 : -1);
3476
+ }
3470
3477
 
3471
3478
  // This will also be where dragging info and such goes
3472
3479
  class InputState {
@@ -3716,6 +3723,7 @@ class MouseSelection {
3716
3723
  this.scrolling = -1;
3717
3724
  this.lastEvent = startEvent;
3718
3725
  this.scrollParent = scrollableParent(view.contentDOM);
3726
+ this.atoms = view.state.facet(atomicRanges).map(f => f(view));
3719
3727
  let doc = view.contentDOM.ownerDocument;
3720
3728
  doc.addEventListener("mousemove", this.move = this.move.bind(this));
3721
3729
  doc.addEventListener("mouseup", this.up = this.up.bind(this));
@@ -3789,10 +3797,33 @@ class MouseSelection {
3789
3797
  if (this.dragging === false)
3790
3798
  this.select(this.lastEvent);
3791
3799
  }
3800
+ skipAtoms(sel) {
3801
+ let ranges = null;
3802
+ for (let i = 0; i < sel.ranges.length; i++) {
3803
+ let range = sel.ranges[i], updated = null;
3804
+ if (range.empty) {
3805
+ let pos = skipAtomicRanges(this.atoms, range.from, 0);
3806
+ if (pos != range.from)
3807
+ updated = state.EditorSelection.cursor(pos, -1);
3808
+ }
3809
+ else {
3810
+ let from = skipAtomicRanges(this.atoms, range.from, -1);
3811
+ let to = skipAtomicRanges(this.atoms, range.to, 1);
3812
+ if (from != range.from || to != range.to)
3813
+ updated = state.EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to);
3814
+ }
3815
+ if (updated) {
3816
+ if (!ranges)
3817
+ ranges = sel.ranges.slice();
3818
+ ranges[i] = updated;
3819
+ }
3820
+ }
3821
+ return ranges ? state.EditorSelection.create(ranges, sel.mainIndex) : sel;
3822
+ }
3792
3823
  select(event) {
3793
- let selection = this.style.get(event, this.extend, this.multiple);
3794
- if (this.mustSelect || !selection.eq(this.view.state.selection) ||
3795
- selection.main.assoc != this.view.state.selection.main.assoc)
3824
+ let { view } = this, selection = this.skipAtoms(this.style.get(event, this.extend, this.multiple));
3825
+ if (this.mustSelect || !selection.eq(view.state.selection) ||
3826
+ selection.main.assoc != view.state.selection.main.assoc)
3796
3827
  this.view.dispatch({
3797
3828
  selection,
3798
3829
  userEvent: "select.pointer"
@@ -7718,7 +7749,7 @@ function rectanglesForRange(view, className, range) {
7718
7749
  let top = visualStart ? drawForLine(range.from, null, visualStart) : drawForWidget(startBlock, false);
7719
7750
  let bottom = visualEnd ? drawForLine(null, range.to, visualEnd) : drawForWidget(endBlock, true);
7720
7751
  let between = [];
7721
- if ((visualStart || startBlock).to < (visualEnd || endBlock).from - 1)
7752
+ if ((visualStart || startBlock).to < (visualEnd || endBlock).from - (visualStart && visualEnd ? 1 : 0))
7722
7753
  between.push(piece(leftSide, top.bottom, rightSide, bottom.top));
7723
7754
  else if (top.bottom < bottom.top && view.elementAtHeight((top.bottom + bottom.top) / 2).type == exports.BlockType.Text)
7724
7755
  top.bottom = bottom.top = (top.bottom + bottom.top) / 2;
package/dist/index.js CHANGED
@@ -1642,7 +1642,7 @@ class BlockWidgetView extends ContentView {
1642
1642
  }
1643
1643
  domBoundsAround() { return null; }
1644
1644
  become(other) {
1645
- if (other instanceof BlockWidgetView && other.type == this.type &&
1645
+ if (other instanceof BlockWidgetView &&
1646
1646
  other.widget.constructor == this.widget.constructor) {
1647
1647
  if (!other.widget.compare(this.widget))
1648
1648
  this.markDirty(true);
@@ -1650,6 +1650,7 @@ class BlockWidgetView extends ContentView {
1650
1650
  this.prevWidget = this.widget;
1651
1651
  this.widget = other.widget;
1652
1652
  this.length = other.length;
1653
+ this.type = other.type;
1653
1654
  this.breakAfter = other.breakAfter;
1654
1655
  return true;
1655
1656
  }
@@ -2475,6 +2476,7 @@ class DOMReader {
2475
2476
  constructor(points, state) {
2476
2477
  this.points = points;
2477
2478
  this.text = "";
2479
+ console.log("make reader");
2478
2480
  this.lineSeparator = state.facet(EditorState.lineSeparator);
2479
2481
  }
2480
2482
  append(text) {
@@ -2489,6 +2491,7 @@ class DOMReader {
2489
2491
  let parent = start.parentNode;
2490
2492
  for (let cur = start;;) {
2491
2493
  this.findPointBefore(parent, cur);
2494
+ let oldLen = this.text.length;
2492
2495
  this.readNode(cur);
2493
2496
  let next = cur.nextSibling;
2494
2497
  if (next == end)
@@ -2496,7 +2499,7 @@ class DOMReader {
2496
2499
  let view = ContentView.get(cur), nextView = ContentView.get(next);
2497
2500
  if (view && nextView ? view.breakAfter :
2498
2501
  (view ? view.breakAfter : isBlockElement(cur)) ||
2499
- (isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore)))
2502
+ (isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
2500
2503
  this.lineBreak();
2501
2504
  cur = next;
2502
2505
  }
@@ -3445,15 +3448,15 @@ function moveVertically(view, start, forward, distance) {
3445
3448
  return EditorSelection.cursor(pos, start.assoc, undefined, goal);
3446
3449
  }
3447
3450
  }
3448
- function skipAtoms(view, oldPos, pos) {
3449
- let atoms = view.state.facet(atomicRanges).map(f => f(view));
3451
+ function skipAtomicRanges(atoms, pos, bias) {
3450
3452
  for (;;) {
3451
- let moved = false;
3453
+ let moved = 0;
3452
3454
  for (let set of atoms) {
3453
- set.between(pos.from - 1, pos.from + 1, (from, to, value) => {
3454
- if (pos.from > from && pos.from < to) {
3455
- pos = oldPos.head > pos.from ? EditorSelection.cursor(from, 1) : EditorSelection.cursor(to, -1);
3456
- moved = true;
3455
+ set.between(pos - 1, pos + 1, (from, to, value) => {
3456
+ if (pos > from && pos < to) {
3457
+ let side = moved || bias || (pos - from < to - pos ? -1 : 1);
3458
+ pos = side < 0 ? from : to;
3459
+ moved = side;
3457
3460
  }
3458
3461
  });
3459
3462
  }
@@ -3461,6 +3464,10 @@ function skipAtoms(view, oldPos, pos) {
3461
3464
  return pos;
3462
3465
  }
3463
3466
  }
3467
+ function skipAtoms(view, oldPos, pos) {
3468
+ let newPos = skipAtomicRanges(view.state.facet(atomicRanges).map(f => f(view)), pos.from, oldPos.head > pos.from ? -1 : 1);
3469
+ return newPos == pos.from ? pos : EditorSelection.cursor(newPos, newPos < pos.from ? 1 : -1);
3470
+ }
3464
3471
 
3465
3472
  // This will also be where dragging info and such goes
3466
3473
  class InputState {
@@ -3710,6 +3717,7 @@ class MouseSelection {
3710
3717
  this.scrolling = -1;
3711
3718
  this.lastEvent = startEvent;
3712
3719
  this.scrollParent = scrollableParent(view.contentDOM);
3720
+ this.atoms = view.state.facet(atomicRanges).map(f => f(view));
3713
3721
  let doc = view.contentDOM.ownerDocument;
3714
3722
  doc.addEventListener("mousemove", this.move = this.move.bind(this));
3715
3723
  doc.addEventListener("mouseup", this.up = this.up.bind(this));
@@ -3783,10 +3791,33 @@ class MouseSelection {
3783
3791
  if (this.dragging === false)
3784
3792
  this.select(this.lastEvent);
3785
3793
  }
3794
+ skipAtoms(sel) {
3795
+ let ranges = null;
3796
+ for (let i = 0; i < sel.ranges.length; i++) {
3797
+ let range = sel.ranges[i], updated = null;
3798
+ if (range.empty) {
3799
+ let pos = skipAtomicRanges(this.atoms, range.from, 0);
3800
+ if (pos != range.from)
3801
+ updated = EditorSelection.cursor(pos, -1);
3802
+ }
3803
+ else {
3804
+ let from = skipAtomicRanges(this.atoms, range.from, -1);
3805
+ let to = skipAtomicRanges(this.atoms, range.to, 1);
3806
+ if (from != range.from || to != range.to)
3807
+ updated = EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to);
3808
+ }
3809
+ if (updated) {
3810
+ if (!ranges)
3811
+ ranges = sel.ranges.slice();
3812
+ ranges[i] = updated;
3813
+ }
3814
+ }
3815
+ return ranges ? EditorSelection.create(ranges, sel.mainIndex) : sel;
3816
+ }
3786
3817
  select(event) {
3787
- let selection = this.style.get(event, this.extend, this.multiple);
3788
- if (this.mustSelect || !selection.eq(this.view.state.selection) ||
3789
- selection.main.assoc != this.view.state.selection.main.assoc)
3818
+ let { view } = this, selection = this.skipAtoms(this.style.get(event, this.extend, this.multiple));
3819
+ if (this.mustSelect || !selection.eq(view.state.selection) ||
3820
+ selection.main.assoc != view.state.selection.main.assoc)
3790
3821
  this.view.dispatch({
3791
3822
  selection,
3792
3823
  userEvent: "select.pointer"
@@ -7711,7 +7742,7 @@ function rectanglesForRange(view, className, range) {
7711
7742
  let top = visualStart ? drawForLine(range.from, null, visualStart) : drawForWidget(startBlock, false);
7712
7743
  let bottom = visualEnd ? drawForLine(null, range.to, visualEnd) : drawForWidget(endBlock, true);
7713
7744
  let between = [];
7714
- if ((visualStart || startBlock).to < (visualEnd || endBlock).from - 1)
7745
+ if ((visualStart || startBlock).to < (visualEnd || endBlock).from - (visualStart && visualEnd ? 1 : 0))
7715
7746
  between.push(piece(leftSide, top.bottom, rightSide, bottom.top));
7716
7747
  else if (top.bottom < bottom.top && view.elementAtHeight((top.bottom + bottom.top) / 2).type == BlockType.Text)
7717
7748
  top.bottom = bottom.top = (top.bottom + bottom.top) / 2;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "6.11.2",
3
+ "version": "6.11.3",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",