prosemirror-view 1.37.0 → 1.37.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,19 @@
1
+ ## 1.37.2 (2025-01-22)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix a bug that caused `EditorView.nodeDOM` to sometimes not return a DOM node when querying a node next to a widget.
6
+
7
+ Fix an issue where an editor would, when scrolling the selection into view, try to do so even if the selection wasn't in that editor.
8
+
9
+ ## 1.37.1 (2024-12-11)
10
+
11
+ ### Bug fixes
12
+
13
+ Fix an issue where `display: content` elements could break `posAtCoords`.
14
+
15
+ Work around an issue with Chrome reporting the selection incorrectly during composition.
16
+
1
17
  ## 1.37.0 (2024-11-23)
2
18
 
3
19
  ### Bug fixes
@@ -2060,18 +2076,14 @@ Transactions that update the selection because of mouse or touch input now get a
2060
2076
 
2061
2077
  ## 0.16.0 (2016-12-23)
2062
2078
 
2063
- ### Bug fixes
2064
-
2065
- Solve problem where setting a node selection would trigger a DOM read, leading to the selection being reset.
2066
-
2067
- ## 0.16.0 (2016-12-23)
2068
-
2069
2079
  ### Breaking changes
2070
2080
 
2071
2081
  The `spellcheck`, `label`, and `class` props are now replaced by an [`attributes` prop](https://prosemirror.net/docs/ref/version/0.16.0.html#view.EditorProps.attributes).
2072
2082
 
2073
2083
  ### Bug fixes
2074
2084
 
2085
+ Solve problem where setting a node selection would trigger a DOM read, leading to the selection being reset.
2086
+
2075
2087
  Ignoring/aborting an action should no longer lead to the DOM being stuck in an outdated state.
2076
2088
 
2077
2089
  Typing at the end of a textblock which ends in a non-text node now actually works.
package/dist/index.cjs CHANGED
@@ -389,10 +389,10 @@ function posFromCaret(view, node, offset, coords) {
389
389
  var outsideBlock = -1;
390
390
  for (var cur = node, sawBlock = false;;) {
391
391
  if (cur == view.dom) break;
392
- var desc = view.docView.nearestDesc(cur, true);
392
+ var desc = view.docView.nearestDesc(cur, true),
393
+ rect = void 0;
393
394
  if (!desc) return null;
394
- if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM)) {
395
- var rect = desc.dom.getBoundingClientRect();
395
+ if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM) && ((rect = desc.dom.getBoundingClientRect()).width || rect.height)) {
396
396
  if (desc.node.isBlock && desc.parent) {
397
397
  if (!sawBlock && rect.left > coords.left || rect.top > coords.top) outsideBlock = desc.posBefore;else if (!sawBlock && rect.right < coords.left || rect.bottom < coords.top) outsideBlock = desc.posAfter;
398
398
  sawBlock = true;
@@ -810,7 +810,15 @@ var ViewDesc = function () {
810
810
  var child = this.children[i],
811
811
  end = offset + child.size;
812
812
  if (offset == pos && end != offset) {
813
- while (!child.border && child.children.length) child = child.children[0];
813
+ while (!child.border && child.children.length) {
814
+ for (var _i = 0; _i < child.children.length; _i++) {
815
+ var inner = child.children[_i];
816
+ if (inner.size) {
817
+ child = inner;
818
+ break;
819
+ }
820
+ }
821
+ }
814
822
  return child;
815
823
  }
816
824
  if (pos < end) return child.descAt(pos - offset - child.border);
@@ -1700,7 +1708,7 @@ function patchAttributes(dom, prev, cur) {
1700
1708
  var prevList = prev["class"] ? prev["class"].split(" ").filter(Boolean) : [];
1701
1709
  var curList = cur["class"] ? cur["class"].split(" ").filter(Boolean) : [];
1702
1710
  for (var i = 0; i < prevList.length; i++) if (curList.indexOf(prevList[i]) == -1) dom.classList.remove(prevList[i]);
1703
- for (var _i = 0; _i < curList.length; _i++) if (prevList.indexOf(curList[_i]) == -1) dom.classList.add(curList[_i]);
1711
+ for (var _i2 = 0; _i2 < curList.length; _i2++) if (prevList.indexOf(curList[_i2]) == -1) dom.classList.add(curList[_i2]);
1704
1712
  if (dom.classList.length == 0) dom.removeAttribute("class");
1705
1713
  }
1706
1714
  if (prev.style != cur.style) {
@@ -2020,7 +2028,7 @@ function iterDeco(parent, deco, onWidget, onNode) {
2020
2028
  if (widget) {
2021
2029
  if (widgets) {
2022
2030
  widgets.sort(compareSide);
2023
- for (var _i2 = 0; _i2 < widgets.length; _i2++) onWidget(widgets[_i2], parentIndex, !!restNode);
2031
+ for (var _i3 = 0; _i3 < widgets.length; _i3++) onWidget(widgets[_i3], parentIndex, !!restNode);
2024
2032
  } else {
2025
2033
  onWidget(widget, parentIndex, !!restNode);
2026
2034
  }
@@ -2037,13 +2045,13 @@ function iterDeco(parent, deco, onWidget, onNode) {
2037
2045
  } else {
2038
2046
  break;
2039
2047
  }
2040
- for (var _i3 = 0; _i3 < active.length; _i3++) if (active[_i3].to <= offset) active.splice(_i3--, 1);
2048
+ for (var _i4 = 0; _i4 < active.length; _i4++) if (active[_i4].to <= offset) active.splice(_i4--, 1);
2041
2049
  while (decoIndex < locals.length && locals[decoIndex].from <= offset && locals[decoIndex].to > offset) active.push(locals[decoIndex++]);
2042
2050
  var end = offset + _child.nodeSize;
2043
2051
  if (_child.isText) {
2044
2052
  var cutAt = end;
2045
2053
  if (decoIndex < locals.length && locals[decoIndex].from < cutAt) cutAt = locals[decoIndex].from;
2046
- for (var _i4 = 0; _i4 < active.length; _i4++) if (active[_i4].to < cutAt) cutAt = active[_i4].to;
2054
+ for (var _i5 = 0; _i5 < active.length; _i5++) if (active[_i5].to < cutAt) cutAt = active[_i5].to;
2047
2055
  if (cutAt < end) {
2048
2056
  restNode = _child.cut(cutAt - offset);
2049
2057
  _child = _child.cut(0, cutAt - offset);
@@ -2874,7 +2882,7 @@ var InputState = _createClass(function InputState() {
2874
2882
  this.lastIOSEnterFallbackTimeout = -1;
2875
2883
  this.lastFocus = 0;
2876
2884
  this.lastTouch = 0;
2877
- this.lastAndroidDelete = 0;
2885
+ this.lastChromeDelete = 0;
2878
2886
  this.composing = false;
2879
2887
  this.compositionNode = null;
2880
2888
  this.composingTimeout = -1;
@@ -3717,10 +3725,10 @@ var DecorationSet = function () {
3717
3725
  var span = this.local[i];
3718
3726
  if (span.from <= end && span.to >= start && (!predicate || predicate(span.spec))) result.push(span.copy(span.from + offset, span.to + offset));
3719
3727
  }
3720
- for (var _i5 = 0; _i5 < this.children.length; _i5 += 3) {
3721
- if (this.children[_i5] < end && this.children[_i5 + 1] > start) {
3722
- var childOff = this.children[_i5] + 1;
3723
- this.children[_i5 + 2].findInner(start - childOff, end - childOff, result, offset + childOff, predicate);
3728
+ for (var _i6 = 0; _i6 < this.children.length; _i6 += 3) {
3729
+ if (this.children[_i6] < end && this.children[_i6 + 1] > start) {
3730
+ var childOff = this.children[_i6] + 1;
3731
+ this.children[_i6 + 2].findInner(start - childOff, end - childOff, result, offset + childOff, predicate);
3724
3732
  }
3725
3733
  }
3726
3734
  }
@@ -3797,7 +3805,7 @@ var DecorationSet = function () {
3797
3805
  i -= 3;
3798
3806
  }
3799
3807
  }
3800
- if (local.length) for (var _i6 = 0, _span; _i6 < decorations.length; _i6++) if (_span = decorations[_i6]) {
3808
+ if (local.length) for (var _i7 = 0, _span; _i7 < decorations.length; _i7++) if (_span = decorations[_i7]) {
3801
3809
  for (var _j2 = 0; _j2 < local.length; _j2++) if (local[_j2].eq(_span, offset)) {
3802
3810
  if (local == this.local) local = this.local.slice();
3803
3811
  local.splice(_j2--, 1);
@@ -3818,8 +3826,8 @@ var DecorationSet = function () {
3818
3826
  }
3819
3827
  var start = offset + 1,
3820
3828
  end = start + node.content.size;
3821
- for (var _i7 = 0; _i7 < this.local.length; _i7++) {
3822
- var dec = this.local[_i7];
3829
+ for (var _i8 = 0; _i8 < this.local.length; _i8++) {
3830
+ var dec = this.local[_i8];
3823
3831
  if (dec.from < end && dec.to > start && dec.type instanceof InlineType) {
3824
3832
  var from = Math.max(start, dec.from) - start,
3825
3833
  to = Math.min(end, dec.to) - start;
@@ -3838,7 +3846,7 @@ var DecorationSet = function () {
3838
3846
  if (this == other) return true;
3839
3847
  if (!(other instanceof DecorationSet) || this.local.length != other.local.length || this.children.length != other.children.length) return false;
3840
3848
  for (var i = 0; i < this.local.length; i++) if (!this.local[i].eq(other.local[i])) return false;
3841
- for (var _i8 = 0; _i8 < this.children.length; _i8 += 3) if (this.children[_i8] != other.children[_i8] || this.children[_i8 + 1] != other.children[_i8 + 1] || !this.children[_i8 + 2].eq(other.children[_i8 + 2])) return false;
3849
+ for (var _i9 = 0; _i9 < this.children.length; _i9 += 3) if (this.children[_i9] != other.children[_i9] || this.children[_i9 + 1] != other.children[_i9 + 1] || !this.children[_i9 + 2].eq(other.children[_i9 + 2])) return false;
3842
3850
  return true;
3843
3851
  }
3844
3852
  }, {
@@ -3955,15 +3963,15 @@ function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, op
3955
3963
  var moved = 0;
3956
3964
  mapping.maps[i].forEach(function (oldStart, oldEnd, newStart, newEnd) {
3957
3965
  var dSize = newEnd - newStart - (oldEnd - oldStart);
3958
- for (var _i12 = 0; _i12 < children.length; _i12 += 3) {
3959
- var end = children[_i12 + 1];
3966
+ for (var _i13 = 0; _i13 < children.length; _i13 += 3) {
3967
+ var end = children[_i13 + 1];
3960
3968
  if (end < 0 || oldStart > end + _baseOffset - moved) continue;
3961
- var start = children[_i12] + _baseOffset - moved;
3969
+ var start = children[_i13] + _baseOffset - moved;
3962
3970
  if (oldEnd >= start) {
3963
- children[_i12 + 1] = oldStart <= start ? -2 : -1;
3971
+ children[_i13 + 1] = oldStart <= start ? -2 : -1;
3964
3972
  } else if (oldStart >= _baseOffset && dSize) {
3965
- children[_i12] += dSize;
3966
- children[_i12 + 1] += dSize;
3973
+ children[_i13] += dSize;
3974
+ children[_i13 + 1] += dSize;
3967
3975
  }
3968
3976
  }
3969
3977
  moved += dSize;
@@ -3975,32 +3983,32 @@ function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, op
3975
3983
  _loop4(baseOffset);
3976
3984
  }
3977
3985
  var mustRebuild = false;
3978
- for (var _i9 = 0; _i9 < children.length; _i9 += 3) if (children[_i9 + 1] < 0) {
3979
- if (children[_i9 + 1] == -2) {
3986
+ for (var _i10 = 0; _i10 < children.length; _i10 += 3) if (children[_i10 + 1] < 0) {
3987
+ if (children[_i10 + 1] == -2) {
3980
3988
  mustRebuild = true;
3981
- children[_i9 + 1] = -1;
3989
+ children[_i10 + 1] = -1;
3982
3990
  continue;
3983
3991
  }
3984
- var from = mapping.map(oldChildren[_i9] + oldOffset),
3992
+ var from = mapping.map(oldChildren[_i10] + oldOffset),
3985
3993
  fromLocal = from - offset;
3986
3994
  if (fromLocal < 0 || fromLocal >= node.content.size) {
3987
3995
  mustRebuild = true;
3988
3996
  continue;
3989
3997
  }
3990
- var to = mapping.map(oldChildren[_i9 + 1] + oldOffset, -1),
3998
+ var to = mapping.map(oldChildren[_i10 + 1] + oldOffset, -1),
3991
3999
  toLocal = to - offset;
3992
4000
  var _node$content$findInd2 = node.content.findIndex(fromLocal),
3993
4001
  index = _node$content$findInd2.index,
3994
4002
  childOffset = _node$content$findInd2.offset;
3995
4003
  var childNode = node.maybeChild(index);
3996
4004
  if (childNode && childOffset == fromLocal && childOffset + childNode.nodeSize == toLocal) {
3997
- var mapped = children[_i9 + 2].mapInner(mapping, childNode, from + 1, oldChildren[_i9] + oldOffset + 1, options);
4005
+ var mapped = children[_i10 + 2].mapInner(mapping, childNode, from + 1, oldChildren[_i10] + oldOffset + 1, options);
3998
4006
  if (mapped != empty) {
3999
- children[_i9] = fromLocal;
4000
- children[_i9 + 1] = toLocal;
4001
- children[_i9 + 2] = mapped;
4007
+ children[_i10] = fromLocal;
4008
+ children[_i10 + 1] = toLocal;
4009
+ children[_i10 + 2] = mapped;
4002
4010
  } else {
4003
- children[_i9 + 1] = -2;
4011
+ children[_i10 + 1] = -2;
4004
4012
  mustRebuild = true;
4005
4013
  }
4006
4014
  } else {
@@ -4011,14 +4019,14 @@ function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, op
4011
4019
  var decorations = mapAndGatherRemainingDecorations(children, oldChildren, newLocal, mapping, offset, oldOffset, options);
4012
4020
  var built = buildTree(decorations, node, 0, options);
4013
4021
  newLocal = built.local;
4014
- for (var _i10 = 0; _i10 < children.length; _i10 += 3) if (children[_i10 + 1] < 0) {
4015
- children.splice(_i10, 3);
4016
- _i10 -= 3;
4022
+ for (var _i11 = 0; _i11 < children.length; _i11 += 3) if (children[_i11 + 1] < 0) {
4023
+ children.splice(_i11, 3);
4024
+ _i11 -= 3;
4017
4025
  }
4018
- for (var _i11 = 0, j = 0; _i11 < built.children.length; _i11 += 3) {
4019
- var _from2 = built.children[_i11];
4026
+ for (var _i12 = 0, j = 0; _i12 < built.children.length; _i12 += 3) {
4027
+ var _from2 = built.children[_i12];
4020
4028
  while (j < children.length && children[j] < _from2) j += 3;
4021
- children.splice(j, 0, built.children[_i11], built.children[_i11 + 1], built.children[_i11 + 2]);
4029
+ children.splice(j, 0, built.children[_i12], built.children[_i12 + 1], built.children[_i12 + 2]);
4022
4030
  }
4023
4031
  }
4024
4032
  return new DecorationSet(newLocal.sort(byPos), children);
@@ -4038,7 +4046,7 @@ function mapAndGatherRemainingDecorations(children, oldChildren, decorations, ma
4038
4046
  var mapped = set.local[i].map(mapping, offset, oldOffset);
4039
4047
  if (mapped) decorations.push(mapped);else if (options.onRemove) options.onRemove(set.local[i].spec);
4040
4048
  }
4041
- for (var _i13 = 0; _i13 < set.children.length; _i13 += 3) gather(set.children[_i13 + 2], set.children[_i13] + oldOffset + 1);
4049
+ for (var _i14 = 0; _i14 < set.children.length; _i14 += 3) gather(set.children[_i14 + 2], set.children[_i14] + oldOffset + 1);
4042
4050
  }
4043
4051
  for (var i = 0; i < children.length; i += 3) if (children[i + 1] == -1) gather(children[i + 2], oldChildren[i] + oldOffset + 1);
4044
4052
  return decorations;
@@ -4392,8 +4400,8 @@ var DOMObserver = function () {
4392
4400
  var prev = mut.previousSibling,
4393
4401
  next = mut.nextSibling;
4394
4402
  if (ie && ie_version <= 11 && mut.addedNodes.length) {
4395
- for (var _i14 = 0; _i14 < mut.addedNodes.length; _i14++) {
4396
- var _mut$addedNodes$_i = mut.addedNodes[_i14],
4403
+ for (var _i15 = 0; _i15 < mut.addedNodes.length; _i15++) {
4404
+ var _mut$addedNodes$_i = mut.addedNodes[_i15],
4397
4405
  previousSibling = _mut$addedNodes$_i.previousSibling,
4398
4406
  nextSibling = _mut$addedNodes$_i.nextSibling;
4399
4407
  if (!previousSibling || Array.prototype.indexOf.call(mut.addedNodes, previousSibling) < 0) prev = previousSibling;
@@ -4661,7 +4669,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
4661
4669
  if (android && chrome) view.domObserver.suppressSelectionUpdates();
4662
4670
  return;
4663
4671
  }
4664
- if (chrome && android && change.endB == change.start) view.input.lastAndroidDelete = Date.now();
4672
+ if (chrome && change.endB == change.start) view.input.lastChromeDelete = Date.now();
4665
4673
  if (android && !inlineChange && $from.start() != $to.start() && $to.parentOffset == 0 && $from.depth == $to.depth && parse.sel && parse.sel.anchor == parse.sel.head && parse.sel.head == change.endA) {
4666
4674
  change.endB -= 2;
4667
4675
  $to = parse.doc.resolveNoCache(change.endB - parse.from);
@@ -4698,7 +4706,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
4698
4706
  if (!tr) tr = view.state.tr.replace(chFrom, chTo, parse.doc.slice(change.start - parse.from, change.endB - parse.from));
4699
4707
  if (parse.sel) {
4700
4708
  var _sel3 = resolveSelection(view, tr.doc, parse.sel);
4701
- if (_sel3 && !(chrome && android && view.composing && _sel3.empty && (change.start != change.endB || view.input.lastAndroidDelete < Date.now() - 100) && (_sel3.head == chFrom || _sel3.head == tr.mapping.map(chTo) - 1) || ie && _sel3.empty && _sel3.head == chFrom)) tr.setSelection(_sel3);
4709
+ if (_sel3 && !(chrome && view.composing && _sel3.empty && (change.start != change.endB || view.input.lastChromeDelete < Date.now() - 100) && (_sel3.head == chFrom || _sel3.head == tr.mapping.map(chTo) - 1) || ie && _sel3.empty && _sel3.head == chFrom)) tr.setSelection(_sel3);
4702
4710
  }
4703
4711
  if (storedMarks) tr.ensureMarks(storedMarks);
4704
4712
  if (compositionID) tr.setMeta("composition", compositionID);
@@ -4717,7 +4725,7 @@ function isMarkChange(cur, prev) {
4717
4725
  mark,
4718
4726
  update;
4719
4727
  for (var i = 0; i < prevMarks.length; i++) added = prevMarks[i].removeFromSet(added);
4720
- for (var _i15 = 0; _i15 < curMarks.length; _i15++) removed = curMarks[_i15].removeFromSet(removed);
4728
+ for (var _i16 = 0; _i16 < curMarks.length; _i16++) removed = curMarks[_i16].removeFromSet(removed);
4721
4729
  if (added.length == 1 && removed.length == 0) {
4722
4730
  mark = added[0];
4723
4731
  type = "add";
@@ -4734,7 +4742,7 @@ function isMarkChange(cur, prev) {
4734
4742
  return null;
4735
4743
  }
4736
4744
  var updated = [];
4737
- for (var _i16 = 0; _i16 < prev.childCount; _i16++) updated.push(update(prev.child(_i16)));
4745
+ for (var _i17 = 0; _i17 < prev.childCount; _i17++) updated.push(update(prev.child(_i17)));
4738
4746
  if (prosemirrorModel.Fragment.from(updated).eq(cur)) return {
4739
4747
  mark: mark,
4740
4748
  type: type
@@ -4952,7 +4960,7 @@ var EditorView = function () {
4952
4960
  value: function scrollToSelection() {
4953
4961
  var _this16 = this;
4954
4962
  var startDOM = this.domSelectionRange().focusNode;
4955
- if (this.someProp("handleScrollToSelection", function (f) {
4963
+ if (!startDOM || !this.dom.contains(startDOM.nodeType == 1 ? startDOM : startDOM.parentNode)) ;else if (this.someProp("handleScrollToSelection", function (f) {
4956
4964
  return f(_this16);
4957
4965
  })) ;else if (this.state.selection instanceof prosemirrorState.NodeSelection) {
4958
4966
  var target = this.docView.domAfterPos(this.state.selection.from);
@@ -4977,13 +4985,13 @@ var EditorView = function () {
4977
4985
  var plugin = this.directPlugins[i];
4978
4986
  if (plugin.spec.view) this.pluginViews.push(plugin.spec.view(this));
4979
4987
  }
4980
- for (var _i17 = 0; _i17 < this.state.plugins.length; _i17++) {
4981
- var _plugin = this.state.plugins[_i17];
4988
+ for (var _i18 = 0; _i18 < this.state.plugins.length; _i18++) {
4989
+ var _plugin = this.state.plugins[_i18];
4982
4990
  if (_plugin.spec.view) this.pluginViews.push(_plugin.spec.view(this));
4983
4991
  }
4984
4992
  } else {
4985
- for (var _i18 = 0; _i18 < this.pluginViews.length; _i18++) {
4986
- var pluginView = this.pluginViews[_i18];
4993
+ for (var _i19 = 0; _i19 < this.pluginViews.length; _i19++) {
4994
+ var pluginView = this.pluginViews[_i19];
4987
4995
  if (pluginView.update) pluginView.update(this, prevState);
4988
4996
  }
4989
4997
  }
@@ -5013,8 +5021,8 @@ var EditorView = function () {
5013
5021
  if (_prop != null && (value = f ? f(_prop) : _prop)) return value;
5014
5022
  }
5015
5023
  var plugins = this.state.plugins;
5016
- if (plugins) for (var _i19 = 0; _i19 < plugins.length; _i19++) {
5017
- var _prop2 = plugins[_i19].props[propName];
5024
+ if (plugins) for (var _i20 = 0; _i20 < plugins.length; _i20++) {
5025
+ var _prop2 = plugins[_i20].props[propName];
5018
5026
  if (_prop2 != null && (value = f ? f(_prop2) : _prop2)) return value;
5019
5027
  }
5020
5028
  }
package/dist/index.js CHANGED
@@ -396,11 +396,12 @@ function posFromCaret(view, node, offset, coords) {
396
396
  for (let cur = node, sawBlock = false;;) {
397
397
  if (cur == view.dom)
398
398
  break;
399
- let desc = view.docView.nearestDesc(cur, true);
399
+ let desc = view.docView.nearestDesc(cur, true), rect;
400
400
  if (!desc)
401
401
  return null;
402
- if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM)) {
403
- let rect = desc.dom.getBoundingClientRect();
402
+ if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM) &&
403
+ // Ignore elements with zero-size bounding rectangles
404
+ ((rect = desc.dom.getBoundingClientRect()).width || rect.height)) {
404
405
  if (desc.node.isBlock && desc.parent) {
405
406
  // Only apply the horizontal test to the innermost block. Vertical for any parent.
406
407
  if (!sawBlock && rect.left > coords.left || rect.top > coords.top)
@@ -884,8 +885,15 @@ class ViewDesc {
884
885
  for (let i = 0, offset = 0; i < this.children.length; i++) {
885
886
  let child = this.children[i], end = offset + child.size;
886
887
  if (offset == pos && end != offset) {
887
- while (!child.border && child.children.length)
888
- child = child.children[0];
888
+ while (!child.border && child.children.length) {
889
+ for (let i = 0; i < child.children.length; i++) {
890
+ let inner = child.children[i];
891
+ if (inner.size) {
892
+ child = inner;
893
+ break;
894
+ }
895
+ }
896
+ }
889
897
  return child;
890
898
  }
891
899
  if (pos < end)
@@ -3042,7 +3050,7 @@ class InputState {
3042
3050
  this.lastIOSEnterFallbackTimeout = -1;
3043
3051
  this.lastFocus = 0;
3044
3052
  this.lastTouch = 0;
3045
- this.lastAndroidDelete = 0;
3053
+ this.lastChromeDelete = 0;
3046
3054
  this.composing = false;
3047
3055
  this.compositionNode = null;
3048
3056
  this.composingTimeout = -1;
@@ -5020,11 +5028,11 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
5020
5028
  view.domObserver.suppressSelectionUpdates(); // #820
5021
5029
  return;
5022
5030
  }
5023
- // Chrome Android will occasionally, during composition, delete the
5031
+ // Chrome will occasionally, during composition, delete the
5024
5032
  // entire composition and then immediately insert it again. This is
5025
5033
  // used to detect that situation.
5026
- if (chrome && android && change.endB == change.start)
5027
- view.input.lastAndroidDelete = Date.now();
5034
+ if (chrome && change.endB == change.start)
5035
+ view.input.lastChromeDelete = Date.now();
5028
5036
  // This tries to detect Android virtual keyboard
5029
5037
  // enter-and-pick-suggestion action. That sometimes (see issue
5030
5038
  // #1059) first fires a DOM mutation, before moving the selection to
@@ -5075,13 +5083,13 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
5075
5083
  tr = view.state.tr.replace(chFrom, chTo, parse.doc.slice(change.start - parse.from, change.endB - parse.from));
5076
5084
  if (parse.sel) {
5077
5085
  let sel = resolveSelection(view, tr.doc, parse.sel);
5078
- // Chrome Android will sometimes, during composition, report the
5086
+ // Chrome will sometimes, during composition, report the
5079
5087
  // selection in the wrong place. If it looks like that is
5080
5088
  // happening, don't update the selection.
5081
5089
  // Edge just doesn't move the cursor forward when you start typing
5082
5090
  // in an empty block or between br nodes.
5083
- if (sel && !(chrome && android && view.composing && sel.empty &&
5084
- (change.start != change.endB || view.input.lastAndroidDelete < Date.now() - 100) &&
5091
+ if (sel && !(chrome && view.composing && sel.empty &&
5092
+ (change.start != change.endB || view.input.lastChromeDelete < Date.now() - 100) &&
5085
5093
  (sel.head == chFrom || sel.head == tr.mapping.map(chTo) - 1) ||
5086
5094
  ie && sel.empty && sel.head == chFrom))
5087
5095
  tr.setSelection(sel);
@@ -5431,7 +5439,8 @@ class EditorView {
5431
5439
  */
5432
5440
  scrollToSelection() {
5433
5441
  let startDOM = this.domSelectionRange().focusNode;
5434
- if (this.someProp("handleScrollToSelection", f => f(this))) ;
5442
+ if (!startDOM || !this.dom.contains(startDOM.nodeType == 1 ? startDOM : startDOM.parentNode)) ;
5443
+ else if (this.someProp("handleScrollToSelection", f => f(this))) ;
5435
5444
  else if (this.state.selection instanceof NodeSelection) {
5436
5445
  let target = this.docView.domAfterPos(this.state.selection.from);
5437
5446
  if (target.nodeType == 1)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-view",
3
- "version": "1.37.0",
3
+ "version": "1.37.2",
4
4
  "description": "ProseMirror's view component",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
package/src/domchange.ts CHANGED
@@ -196,11 +196,11 @@ export function readDOMChange(view: EditorView, from: number, to: number, typeOv
196
196
  return
197
197
  }
198
198
 
199
- // Chrome Android will occasionally, during composition, delete the
199
+ // Chrome will occasionally, during composition, delete the
200
200
  // entire composition and then immediately insert it again. This is
201
201
  // used to detect that situation.
202
- if (browser.chrome && browser.android && change.endB == change.start)
203
- view.input.lastAndroidDelete = Date.now()
202
+ if (browser.chrome && change.endB == change.start)
203
+ view.input.lastChromeDelete = Date.now()
204
204
 
205
205
  // This tries to detect Android virtual keyboard
206
206
  // enter-and-pick-suggestion action. That sometimes (see issue
@@ -252,13 +252,13 @@ export function readDOMChange(view: EditorView, from: number, to: number, typeOv
252
252
  tr = view.state.tr.replace(chFrom, chTo, parse.doc.slice(change.start - parse.from, change.endB - parse.from))
253
253
  if (parse.sel) {
254
254
  let sel = resolveSelection(view, tr.doc, parse.sel)
255
- // Chrome Android will sometimes, during composition, report the
255
+ // Chrome will sometimes, during composition, report the
256
256
  // selection in the wrong place. If it looks like that is
257
257
  // happening, don't update the selection.
258
258
  // Edge just doesn't move the cursor forward when you start typing
259
259
  // in an empty block or between br nodes.
260
- if (sel && !(browser.chrome && browser.android && view.composing && sel.empty &&
261
- (change.start != change.endB || view.input.lastAndroidDelete < Date.now() - 100) &&
260
+ if (sel && !(browser.chrome && view.composing && sel.empty &&
261
+ (change.start != change.endB || view.input.lastChromeDelete < Date.now() - 100) &&
262
262
  (sel.head == chFrom || sel.head == tr.mapping.map(chTo) - 1) ||
263
263
  browser.ie && sel.empty && sel.head == chFrom))
264
264
  tr.setSelection(sel)
package/src/domcoords.ts CHANGED
@@ -225,10 +225,11 @@ function posFromCaret(view: EditorView, node: Node, offset: number, coords: {top
225
225
  let outsideBlock = -1
226
226
  for (let cur = node, sawBlock = false;;) {
227
227
  if (cur == view.dom) break
228
- let desc = view.docView.nearestDesc(cur, true)
228
+ let desc = view.docView.nearestDesc(cur, true), rect
229
229
  if (!desc) return null
230
- if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM)) {
231
- let rect = (desc.dom as HTMLElement).getBoundingClientRect()
230
+ if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM) &&
231
+ // Ignore elements with zero-size bounding rectangles
232
+ ((rect = (desc.dom as HTMLElement).getBoundingClientRect()).width || rect.height)) {
232
233
  if (desc.node.isBlock && desc.parent) {
233
234
  // Only apply the horizontal test to the innermost block. Vertical for any parent.
234
235
  if (!sawBlock && rect.left > coords.left || rect.top > coords.top) outsideBlock = desc.posBefore
package/src/index.ts CHANGED
@@ -235,8 +235,10 @@ export class EditorView {
235
235
 
236
236
  /// @internal
237
237
  scrollToSelection() {
238
- let startDOM = this.domSelectionRange().focusNode!
239
- if (this.someProp("handleScrollToSelection", f => f(this))) {
238
+ let startDOM = this.domSelectionRange().focusNode
239
+ if (!startDOM || !this.dom.contains(startDOM.nodeType == 1 ? startDOM : startDOM.parentNode)) {
240
+ // Ignore selections outside the editor
241
+ } else if (this.someProp("handleScrollToSelection", f => f(this))) {
240
242
  // Handled
241
243
  } else if (this.state.selection instanceof NodeSelection) {
242
244
  let target = this.docView.domAfterPos(this.state.selection.from)
package/src/input.ts CHANGED
@@ -28,7 +28,7 @@ export class InputState {
28
28
  lastIOSEnterFallbackTimeout = -1
29
29
  lastFocus = 0
30
30
  lastTouch = 0
31
- lastAndroidDelete = 0
31
+ lastChromeDelete = 0
32
32
  composing = false
33
33
  compositionNode: Text | null = null
34
34
  composingTimeout = -1
package/src/viewdesc.ts CHANGED
@@ -289,7 +289,12 @@ export class ViewDesc {
289
289
  for (let i = 0, offset = 0; i < this.children.length; i++) {
290
290
  let child = this.children[i], end = offset + child.size
291
291
  if (offset == pos && end != offset) {
292
- while (!child.border && child.children.length) child = child.children[0]
292
+ while (!child.border && child.children.length) {
293
+ for (let i = 0; i < child.children.length; i++) {
294
+ let inner = child.children[i]
295
+ if (inner.size) { child = inner; break }
296
+ }
297
+ }
293
298
  return child
294
299
  }
295
300
  if (pos < end) return child.descAt(pos - offset - child.border)