prosemirror-view 1.29.0 → 1.29.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.29.2 (2023-01-17)
2
+
3
+ ### Bug fixes
4
+
5
+ Make sure enter key handlers are called on Chrome Android when the cursor is in a position where the native behavior of Enter doesn't change the document.
6
+
7
+ Fix a crash that could occur when starting a composition at the end of a non-inclusive mark.
8
+
9
+ Fix a bug in (vertical) `endOfTextblock` that caused it to return falsely positive results inside textblocks that had a separate `contentDOM`.
10
+
11
+ ## 1.29.1 (2022-11-14)
12
+
13
+ ### Bug fixes
14
+
15
+ Fix a problem when returning decorations from an outer editor from the `decorations` prop.
16
+
1
17
  ## 1.29.0 (2022-10-12)
2
18
 
3
19
  ### Bug fixes
package/README.md CHANGED
@@ -19,7 +19,7 @@ This code is released under an
19
19
  [MIT license](https://github.com/prosemirror/prosemirror/tree/master/LICENSE).
20
20
  There's a [forum](http://discuss.prosemirror.net) for general
21
21
  discussion and support requests, and the
22
- [Github bug tracker](https://github.com/prosemirror/prosemirror/issues)
22
+ [GitHub bug tracker](https://github.com/prosemirror/prosemirror/issues)
23
23
  is the place to report issues.
24
24
 
25
25
  We aim to be an inclusive, welcoming community. To make that explicit,
package/dist/index.cjs CHANGED
@@ -628,7 +628,7 @@ function endOfTextblockVertical(view, state, dir) {
628
628
  if (!nearest) break;
629
629
 
630
630
  if (nearest.node.isBlock) {
631
- dom = nearest.dom;
631
+ dom = nearest.contentDOM || nearest.dom;
632
632
  break;
633
633
  }
634
634
 
@@ -2045,7 +2045,9 @@ var ViewTreeUpdater = function () {
2045
2045
  var found = -1;
2046
2046
 
2047
2047
  for (var i = this.index; i < Math.min(this.index + 3, this.top.children.length); i++) {
2048
- if (this.top.children[i].matchesMark(marks[depth])) {
2048
+ var next = this.top.children[i];
2049
+
2050
+ if (next.matchesMark(marks[depth]) && !this.isLocked(next.dom)) {
2049
2051
  found = i;
2050
2052
  break;
2051
2053
  }
@@ -2132,7 +2134,7 @@ var ViewTreeUpdater = function () {
2132
2134
 
2133
2135
  if (_preMatch != null && _preMatch != index) return false;
2134
2136
  var nextDOM = next.dom;
2135
- var locked = this.lock && (nextDOM == this.lock || nextDOM.nodeType == 1 && nextDOM.contains(this.lock.parentNode)) && !(node.isText && next.node && next.node.isText && next.nodeDOM.nodeValue == node.text && next.dirty != NODE_DIRTY && sameOuterDeco(outerDeco, next.outerDeco));
2137
+ var locked = this.isLocked(nextDOM) && !(node.isText && next.node && next.node.isText && next.nodeDOM.nodeValue == node.text && next.dirty != NODE_DIRTY && sameOuterDeco(outerDeco, next.outerDeco));
2136
2138
 
2137
2139
  if (!locked && next.update(node, outerDeco, innerDeco, view)) {
2138
2140
  this.destroyBetween(this.index, i);
@@ -2201,6 +2203,11 @@ var ViewTreeUpdater = function () {
2201
2203
  this.changed = true;
2202
2204
  }
2203
2205
  }
2206
+ }, {
2207
+ key: "isLocked",
2208
+ value: function isLocked(node) {
2209
+ return this.lock && (node == this.lock || node.nodeType == 1 && node.contains(this.lock.parentNode));
2210
+ }
2204
2211
  }]);
2205
2212
 
2206
2213
  return ViewTreeUpdater;
@@ -3346,7 +3353,7 @@ editHandlers.keypress = function (view, _event) {
3346
3353
 
3347
3354
  if (!(sel instanceof prosemirrorState.TextSelection) || !sel.$from.sameParent(sel.$to)) {
3348
3355
  var text = String.fromCharCode(event.charCode);
3349
- if (!view.someProp("handleTextInput", function (f) {
3356
+ if (!/[\r\n]/.test(text) && !view.someProp("handleTextInput", function (f) {
3350
3357
  return f(view, sel.$from.pos, sel.$to.pos, text);
3351
3358
  })) view.dispatch(view.state.tr.insertText(text).scrollIntoView());
3352
3359
  event.preventDefault();
@@ -4442,7 +4449,11 @@ var DecorationGroup = function () {
4442
4449
  return members[0];
4443
4450
 
4444
4451
  default:
4445
- return new DecorationGroup(members);
4452
+ return new DecorationGroup(members.every(function (m) {
4453
+ return m instanceof DecorationSet;
4454
+ }) ? members : members.reduce(function (r, m) {
4455
+ return r.concat(m instanceof DecorationSet ? m : m.members);
4456
+ }, []));
4446
4457
  }
4447
4458
  }
4448
4459
  }]);
@@ -5156,6 +5167,10 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
5156
5167
  var newSel = selectionFromDOM(view, origin);
5157
5168
 
5158
5169
  if (newSel && !view.state.selection.eq(newSel)) {
5170
+ if (chrome && android && view.input.lastKeyCode === 13 && Date.now() - 100 < view.input.lastKeyCodeTime && view.someProp("handleKeyDown", function (f) {
5171
+ return f(view, keyEvent(13, "Enter"));
5172
+ })) return;
5173
+
5159
5174
  var _tr = view.state.tr.setSelection(newSel);
5160
5175
 
5161
5176
  if (origin == "pointer") _tr.setMeta("pointer", true);else if (origin == "key") _tr.scrollIntoView();
package/dist/index.js CHANGED
@@ -541,7 +541,7 @@ function endOfTextblockVertical(view, state, dir) {
541
541
  if (!nearest)
542
542
  break;
543
543
  if (nearest.node.isBlock) {
544
- dom = nearest.dom;
544
+ dom = nearest.contentDOM || nearest.dom;
545
545
  break;
546
546
  }
547
547
  dom = nearest.dom.parentNode;
@@ -1679,7 +1679,8 @@ class ViewTreeUpdater {
1679
1679
  this.stack.push(this.top, this.index + 1);
1680
1680
  let found = -1;
1681
1681
  for (let i = this.index; i < Math.min(this.index + 3, this.top.children.length); i++) {
1682
- if (this.top.children[i].matchesMark(marks[depth])) {
1682
+ let next = this.top.children[i];
1683
+ if (next.matchesMark(marks[depth]) && !this.isLocked(next.dom)) {
1683
1684
  found = i;
1684
1685
  break;
1685
1686
  }
@@ -1765,7 +1766,7 @@ class ViewTreeUpdater {
1765
1766
  // Can't update if nextDOM is or contains this.lock, except if
1766
1767
  // it's a text node whose content already matches the new text
1767
1768
  // and whose decorations match the new ones.
1768
- let locked = this.lock && (nextDOM == this.lock || nextDOM.nodeType == 1 && nextDOM.contains(this.lock.parentNode)) &&
1769
+ let locked = this.isLocked(nextDOM) &&
1769
1770
  !(node.isText && next.node && next.node.isText && next.nodeDOM.nodeValue == node.text &&
1770
1771
  next.dirty != NODE_DIRTY && sameOuterDeco(outerDeco, next.outerDeco));
1771
1772
  if (!locked && next.update(node, outerDeco, innerDeco, view)) {
@@ -1835,6 +1836,9 @@ class ViewTreeUpdater {
1835
1836
  this.changed = true;
1836
1837
  }
1837
1838
  }
1839
+ isLocked(node) {
1840
+ return this.lock && (node == this.lock || node.nodeType == 1 && node.contains(this.lock.parentNode));
1841
+ }
1838
1842
  }
1839
1843
  // Iterate from the end of the fragment and array of descs to find
1840
1844
  // directly matching ones, in order to avoid overeagerly reusing those
@@ -2921,7 +2925,7 @@ editHandlers.keypress = (view, _event) => {
2921
2925
  let sel = view.state.selection;
2922
2926
  if (!(sel instanceof TextSelection) || !sel.$from.sameParent(sel.$to)) {
2923
2927
  let text = String.fromCharCode(event.charCode);
2924
- if (!view.someProp("handleTextInput", f => f(view, sel.$from.pos, sel.$to.pos, text)))
2928
+ if (!/[\r\n]/.test(text) && !view.someProp("handleTextInput", f => f(view, sel.$from.pos, sel.$to.pos, text)))
2925
2929
  view.dispatch(view.state.tr.insertText(text).scrollIntoView());
2926
2930
  event.preventDefault();
2927
2931
  }
@@ -3976,7 +3980,8 @@ class DecorationGroup {
3976
3980
  switch (members.length) {
3977
3981
  case 0: return empty;
3978
3982
  case 1: return members[0];
3979
- default: return new DecorationGroup(members);
3983
+ default: return new DecorationGroup(members.every(m => m instanceof DecorationSet) ? members :
3984
+ members.reduce((r, m) => r.concat(m instanceof DecorationSet ? m : m.members), []));
3980
3985
  }
3981
3986
  }
3982
3987
  }
@@ -4570,6 +4575,10 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
4570
4575
  let origin = view.input.lastSelectionTime > Date.now() - 50 ? view.input.lastSelectionOrigin : null;
4571
4576
  let newSel = selectionFromDOM(view, origin);
4572
4577
  if (newSel && !view.state.selection.eq(newSel)) {
4578
+ if (chrome && android &&
4579
+ view.input.lastKeyCode === 13 && Date.now() - 100 < view.input.lastKeyCodeTime &&
4580
+ view.someProp("handleKeyDown", f => f(view, keyEvent(13, "Enter"))))
4581
+ return;
4573
4582
  let tr = view.state.tr.setSelection(newSel);
4574
4583
  if (origin == "pointer")
4575
4584
  tr.setMeta("pointer", true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-view",
3
- "version": "1.29.0",
3
+ "version": "1.29.2",
4
4
  "description": "ProseMirror's view component",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
package/src/decoration.ts CHANGED
@@ -528,11 +528,14 @@ class DecorationGroup implements DecorationSource {
528
528
 
529
529
  // Create a group for the given array of decoration sets, or return
530
530
  // a single set when possible.
531
- static from(members: readonly DecorationSet[]): DecorationSet | DecorationGroup {
531
+ static from(members: readonly DecorationSource[]): DecorationSource {
532
532
  switch (members.length) {
533
533
  case 0: return empty
534
534
  case 1: return members[0]
535
- default: return new DecorationGroup(members)
535
+ default: return new DecorationGroup(
536
+ members.every(m => m instanceof DecorationSet) ? members as DecorationSet[] :
537
+ members.reduce((r, m) => r.concat(m instanceof DecorationSet ? m : (m as DecorationGroup).members),
538
+ [] as DecorationSet[]))
536
539
  }
537
540
  }
538
541
  }
@@ -753,8 +756,8 @@ function insertAhead(array: Decoration[], i: number, deco: Decoration) {
753
756
  }
754
757
 
755
758
  // Get the decorations associated with the current props of a view.
756
- export function viewDecorations(view: EditorView): DecorationSet | DecorationGroup {
757
- let found = []
759
+ export function viewDecorations(view: EditorView): DecorationSource {
760
+ let found: DecorationSource[] = []
758
761
  view.someProp("decorations", f => {
759
762
  let result = f(view.state)
760
763
  if (result && result != empty) found.push(result)
package/src/domchange.ts CHANGED
@@ -81,6 +81,10 @@ export function readDOMChange(view: EditorView, from: number, to: number, typeOv
81
81
  let origin = view.input.lastSelectionTime > Date.now() - 50 ? view.input.lastSelectionOrigin : null
82
82
  let newSel = selectionFromDOM(view, origin)
83
83
  if (newSel && !view.state.selection.eq(newSel)) {
84
+ if (browser.chrome && browser.android &&
85
+ view.input.lastKeyCode === 13 && Date.now() - 100 < view.input.lastKeyCodeTime &&
86
+ view.someProp("handleKeyDown", f => f(view, keyEvent(13, "Enter"))))
87
+ return
84
88
  let tr = view.state.tr.setSelection(newSel)
85
89
  if (origin == "pointer") tr.setMeta("pointer", true)
86
90
  else if (origin == "key") tr.scrollIntoView()
package/src/domcoords.ts CHANGED
@@ -413,7 +413,7 @@ function endOfTextblockVertical(view: EditorView, state: EditorState, dir: "up"
413
413
  for (;;) {
414
414
  let nearest = view.docView.nearestDesc(dom, true)
415
415
  if (!nearest) break
416
- if (nearest.node!.isBlock) { dom = nearest.dom; break }
416
+ if (nearest.node!.isBlock) { dom = nearest.contentDOM || nearest.dom; break }
417
417
  dom = nearest.dom.parentNode!
418
418
  }
419
419
  let coords = coordsAtPos(view, $pos.pos, 1)
package/src/input.ts CHANGED
@@ -147,7 +147,7 @@ editHandlers.keypress = (view, _event) => {
147
147
  let sel = view.state.selection
148
148
  if (!(sel instanceof TextSelection) || !sel.$from.sameParent(sel.$to)) {
149
149
  let text = String.fromCharCode(event.charCode)
150
- if (!view.someProp("handleTextInput", f => f(view, sel.$from.pos, sel.$to.pos, text)))
150
+ if (!/[\r\n]/.test(text) && !view.someProp("handleTextInput", f => f(view, sel.$from.pos, sel.$to.pos, text)))
151
151
  view.dispatch(view.state.tr.insertText(text).scrollIntoView())
152
152
  event.preventDefault()
153
153
  }
package/src/viewdesc.ts CHANGED
@@ -1150,7 +1150,8 @@ class ViewTreeUpdater {
1150
1150
  this.stack.push(this.top, this.index + 1)
1151
1151
  let found = -1
1152
1152
  for (let i = this.index; i < Math.min(this.index + 3, this.top.children.length); i++) {
1153
- if (this.top.children[i].matchesMark(marks[depth])) { found = i; break }
1153
+ let next = this.top.children[i]
1154
+ if (next.matchesMark(marks[depth]) && !this.isLocked(next.dom)) { found = i; break }
1154
1155
  }
1155
1156
  if (found > -1) {
1156
1157
  if (found > this.index) {
@@ -1230,7 +1231,7 @@ class ViewTreeUpdater {
1230
1231
  // Can't update if nextDOM is or contains this.lock, except if
1231
1232
  // it's a text node whose content already matches the new text
1232
1233
  // and whose decorations match the new ones.
1233
- let locked = this.lock && (nextDOM == this.lock || nextDOM.nodeType == 1 && nextDOM.contains(this.lock.parentNode)) &&
1234
+ let locked = this.isLocked(nextDOM) &&
1234
1235
  !(node.isText && next.node && next.node.isText && next.nodeDOM.nodeValue == node.text &&
1235
1236
  next.dirty != NODE_DIRTY && sameOuterDeco(outerDeco, next.outerDeco))
1236
1237
  if (!locked && next.update(node, outerDeco, innerDeco, view)) {
@@ -1299,6 +1300,10 @@ class ViewTreeUpdater {
1299
1300
  this.changed = true
1300
1301
  }
1301
1302
  }
1303
+
1304
+ isLocked(node: DOMNode) {
1305
+ return this.lock && (node == this.lock || node.nodeType == 1 && node.contains(this.lock.parentNode))
1306
+ }
1302
1307
  }
1303
1308
 
1304
1309
  // Iterate from the end of the fragment and array of descs to find