@codemirror/view 6.39.0 → 6.39.2

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,15 @@
1
+ ## 6.39.2 (2025-12-09)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix an issue where `moveVertially` was sometimes unable to escape lines with thick borders or padding.
6
+
7
+ ## 6.39.1 (2025-12-09)
8
+
9
+ ### Bug fixes
10
+
11
+ Restore a workaround for a Chrome selection bug that had regressed in the previous release.
12
+
1
13
  ## 6.39.0 (2025-12-08)
2
14
 
3
15
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -1729,7 +1729,7 @@ class Tile {
1729
1729
  isText() { return false; }
1730
1730
  isBlock() { return false; }
1731
1731
  get domAttrs() { return null; }
1732
- sync() {
1732
+ sync(track) {
1733
1733
  this.flags |= 2 /* TileFlag.Synced */;
1734
1734
  if (this.flags & 4 /* TileFlag.AttrsDirty */) {
1735
1735
  this.flags &= ~4 /* TileFlag.AttrsDirty */;
@@ -1801,16 +1801,19 @@ class CompositeTile extends Tile {
1801
1801
  this.children.push(child);
1802
1802
  child.parent = this;
1803
1803
  }
1804
- sync() {
1804
+ sync(track) {
1805
1805
  if (this.flags & 2 /* TileFlag.Synced */)
1806
1806
  return;
1807
- super.sync();
1807
+ super.sync(track);
1808
1808
  let parent = this.dom, prev = null, next;
1809
+ let tracking = (track === null || track === void 0 ? void 0 : track.node) == parent ? track : null;
1809
1810
  let length = 0;
1810
1811
  for (let child of this.children) {
1811
- child.sync();
1812
+ child.sync(track);
1812
1813
  length += child.length + child.breakAfter;
1813
1814
  next = prev ? prev.nextSibling : parent.firstChild;
1815
+ if (tracking && next != child.dom)
1816
+ tracking.written = true;
1814
1817
  if (child.dom.parentNode == parent) {
1815
1818
  while (next && next != child.dom)
1816
1819
  next = rm$1(next);
@@ -1821,6 +1824,8 @@ class CompositeTile extends Tile {
1821
1824
  prev = child.dom;
1822
1825
  }
1823
1826
  next = prev ? prev.nextSibling : parent.firstChild;
1827
+ if (tracking && next)
1828
+ tracking.written = true;
1824
1829
  while (next)
1825
1830
  next = rm$1(next);
1826
1831
  this.length = length;
@@ -2029,12 +2034,15 @@ class TextTile extends Tile {
2029
2034
  super(dom, text.length);
2030
2035
  this.text = text;
2031
2036
  }
2032
- sync() {
2037
+ sync(track) {
2033
2038
  if (this.flags & 2 /* TileFlag.Synced */)
2034
2039
  return;
2035
- super.sync();
2036
- if (this.dom.nodeValue != this.text)
2040
+ super.sync(track);
2041
+ if (this.dom.nodeValue != this.text) {
2042
+ if (track && track.node == this.dom)
2043
+ track.written = true;
2037
2044
  this.dom.nodeValue = this.text;
2045
+ }
2038
2046
  }
2039
2047
  isText() { return true; }
2040
2048
  toString() { return JSON.stringify(this.text); }
@@ -2939,8 +2947,8 @@ class DocView {
2939
2947
  // selection from the one it displays (issue #218). This tries
2940
2948
  // to detect that situation.
2941
2949
  let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
2942
- this.tile.sync();
2943
- if (track && (track.written || observer.selectionRange.focusNode != track.node))
2950
+ this.tile.sync(track);
2951
+ if (track && (track.written || observer.selectionRange.focusNode != track.node || !this.tile.dom.contains(track.node)))
2944
2952
  this.forceSelection = true;
2945
2953
  this.tile.dom.style.height = "";
2946
2954
  });
@@ -3699,15 +3707,22 @@ function posAtCoords(view, coords, precise, scanY) {
3699
3707
  let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
3700
3708
  let { x, y } = coords, yOffset = y - docTop, block;
3701
3709
  // First find the block at the given Y position, if any. If scanY is
3702
- // given (used for vertical cursor motion), try to skip widgets.
3710
+ // given (used for vertical cursor motion), try to skip widgets and
3711
+ // line padding.
3703
3712
  for (;;) {
3704
3713
  if (yOffset < 0)
3705
3714
  return new PosAssoc(0, 1);
3706
3715
  if (yOffset > view.viewState.docHeight)
3707
3716
  return new PosAssoc(view.state.doc.length, -1);
3708
3717
  block = view.elementAtHeight(yOffset);
3709
- if (scanY == null || block.type == exports.BlockType.Text)
3718
+ if (scanY == null)
3710
3719
  break;
3720
+ if (block.type == exports.BlockType.Text) {
3721
+ // Check whether we aren't landing the top/bottom padding of the line
3722
+ let rect = view.docView.coordsAt(scanY < 0 ? block.from : block.to, scanY);
3723
+ if (rect && (scanY < 0 ? rect.top <= yOffset + docTop : rect.bottom >= yOffset + docTop))
3724
+ break;
3725
+ }
3711
3726
  let halfLine = view.viewState.heightOracle.textHeight / 2;
3712
3727
  yOffset = scanY > 0 ? block.bottom + halfLine : block.top - halfLine;
3713
3728
  }
package/dist/index.js CHANGED
@@ -1725,7 +1725,7 @@ class Tile {
1725
1725
  isText() { return false; }
1726
1726
  isBlock() { return false; }
1727
1727
  get domAttrs() { return null; }
1728
- sync() {
1728
+ sync(track) {
1729
1729
  this.flags |= 2 /* TileFlag.Synced */;
1730
1730
  if (this.flags & 4 /* TileFlag.AttrsDirty */) {
1731
1731
  this.flags &= ~4 /* TileFlag.AttrsDirty */;
@@ -1797,16 +1797,19 @@ class CompositeTile extends Tile {
1797
1797
  this.children.push(child);
1798
1798
  child.parent = this;
1799
1799
  }
1800
- sync() {
1800
+ sync(track) {
1801
1801
  if (this.flags & 2 /* TileFlag.Synced */)
1802
1802
  return;
1803
- super.sync();
1803
+ super.sync(track);
1804
1804
  let parent = this.dom, prev = null, next;
1805
+ let tracking = (track === null || track === void 0 ? void 0 : track.node) == parent ? track : null;
1805
1806
  let length = 0;
1806
1807
  for (let child of this.children) {
1807
- child.sync();
1808
+ child.sync(track);
1808
1809
  length += child.length + child.breakAfter;
1809
1810
  next = prev ? prev.nextSibling : parent.firstChild;
1811
+ if (tracking && next != child.dom)
1812
+ tracking.written = true;
1810
1813
  if (child.dom.parentNode == parent) {
1811
1814
  while (next && next != child.dom)
1812
1815
  next = rm$1(next);
@@ -1817,6 +1820,8 @@ class CompositeTile extends Tile {
1817
1820
  prev = child.dom;
1818
1821
  }
1819
1822
  next = prev ? prev.nextSibling : parent.firstChild;
1823
+ if (tracking && next)
1824
+ tracking.written = true;
1820
1825
  while (next)
1821
1826
  next = rm$1(next);
1822
1827
  this.length = length;
@@ -2025,12 +2030,15 @@ class TextTile extends Tile {
2025
2030
  super(dom, text.length);
2026
2031
  this.text = text;
2027
2032
  }
2028
- sync() {
2033
+ sync(track) {
2029
2034
  if (this.flags & 2 /* TileFlag.Synced */)
2030
2035
  return;
2031
- super.sync();
2032
- if (this.dom.nodeValue != this.text)
2036
+ super.sync(track);
2037
+ if (this.dom.nodeValue != this.text) {
2038
+ if (track && track.node == this.dom)
2039
+ track.written = true;
2033
2040
  this.dom.nodeValue = this.text;
2041
+ }
2034
2042
  }
2035
2043
  isText() { return true; }
2036
2044
  toString() { return JSON.stringify(this.text); }
@@ -2935,8 +2943,8 @@ class DocView {
2935
2943
  // selection from the one it displays (issue #218). This tries
2936
2944
  // to detect that situation.
2937
2945
  let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
2938
- this.tile.sync();
2939
- if (track && (track.written || observer.selectionRange.focusNode != track.node))
2946
+ this.tile.sync(track);
2947
+ if (track && (track.written || observer.selectionRange.focusNode != track.node || !this.tile.dom.contains(track.node)))
2940
2948
  this.forceSelection = true;
2941
2949
  this.tile.dom.style.height = "";
2942
2950
  });
@@ -3695,15 +3703,22 @@ function posAtCoords(view, coords, precise, scanY) {
3695
3703
  let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
3696
3704
  let { x, y } = coords, yOffset = y - docTop, block;
3697
3705
  // First find the block at the given Y position, if any. If scanY is
3698
- // given (used for vertical cursor motion), try to skip widgets.
3706
+ // given (used for vertical cursor motion), try to skip widgets and
3707
+ // line padding.
3699
3708
  for (;;) {
3700
3709
  if (yOffset < 0)
3701
3710
  return new PosAssoc(0, 1);
3702
3711
  if (yOffset > view.viewState.docHeight)
3703
3712
  return new PosAssoc(view.state.doc.length, -1);
3704
3713
  block = view.elementAtHeight(yOffset);
3705
- if (scanY == null || block.type == BlockType.Text)
3714
+ if (scanY == null)
3706
3715
  break;
3716
+ if (block.type == BlockType.Text) {
3717
+ // Check whether we aren't landing the top/bottom padding of the line
3718
+ let rect = view.docView.coordsAt(scanY < 0 ? block.from : block.to, scanY);
3719
+ if (rect && (scanY < 0 ? rect.top <= yOffset + docTop : rect.bottom >= yOffset + docTop))
3720
+ break;
3721
+ }
3707
3722
  let halfLine = view.viewState.heightOracle.textHeight / 2;
3708
3723
  yOffset = scanY > 0 ? block.bottom + halfLine : block.top - halfLine;
3709
3724
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "6.39.0",
3
+ "version": "6.39.2",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",