prosemirror-view 1.23.2 → 1.23.6

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,35 @@
1
+ ## 1.23.6 (2022-01-13)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix an issue that could cause pieces of DOM to not be synchronized with the document after some kind of changes around marks.
6
+
7
+ Fix a bug where marks rendered with nested elements would in some situations suppress new input.
8
+
9
+ Disable Chrome-specific drag-selection workaround in non-Chrome browsers because it affected table cell selection in Safari.
10
+
11
+ ## 1.23.5 (2021-12-27)
12
+
13
+ ### Bug fixes
14
+
15
+ Use the `whitespace` node prop where appropriate.
16
+
17
+ ## 1.23.4 (2021-12-22)
18
+
19
+ ### Bug fixes
20
+
21
+ Improve the way the editor handles the mess of events produced when pressing Enter before a word that was just typed on Chrome + GBoard.
22
+
23
+ Fix an issue where compositions right before another instance of the composed text could cause the editor to crash.
24
+
25
+ Fix an issue where, if decorations changed during a pointer drag selection, the selection anchor might move around inappropriately.
26
+
27
+ ## 1.23.3 (2021-11-26)
28
+
29
+ ### Bug fixes
30
+
31
+ The clipboard parser will no longer drop trailing `<br>` nodes that appear in an inline parent element.
32
+
1
33
  ## 1.23.2 (2021-11-19)
2
34
 
3
35
  ### Bug fixes
package/dist/index.es.js CHANGED
@@ -1051,7 +1051,8 @@ ViewDesc.prototype.markDirty = function markDirty (from, to) {
1051
1051
  else { child.markDirty(from - startInside, to - startInside); }
1052
1052
  return
1053
1053
  } else {
1054
- child.dirty = child.dom == child.contentDOM && child.dom.parentNode == this.contentDOM ? CONTENT_DIRTY : NODE_DIRTY;
1054
+ child.dirty = child.dom == child.contentDOM && child.dom.parentNode == this.contentDOM && !child.children.length
1055
+ ? CONTENT_DIRTY : NODE_DIRTY;
1055
1056
  }
1056
1057
  }
1057
1058
  offset = end;
@@ -1189,7 +1190,10 @@ var MarkViewDesc = /*@__PURE__*/(function (ViewDesc) {
1189
1190
  return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom)
1190
1191
  };
1191
1192
 
1192
- MarkViewDesc.prototype.parseRule = function parseRule () { return {mark: this.mark.type.name, attrs: this.mark.attrs, contentElement: this.contentDOM} };
1193
+ MarkViewDesc.prototype.parseRule = function parseRule () {
1194
+ if ((this.dirty & NODE_DIRTY) || this.mark.type.spec.reparseInView) { return null }
1195
+ return {mark: this.mark.type.name, attrs: this.mark.attrs, contentElement: this.contentDOM}
1196
+ };
1193
1197
 
1194
1198
  MarkViewDesc.prototype.matchesMark = function matchesMark (mark) { return this.dirty != NODE_DIRTY && this.mark.eq(mark) };
1195
1199
 
@@ -1290,7 +1294,7 @@ var NodeViewDesc = /*@__PURE__*/(function (ViewDesc) {
1290
1294
  // attrs in the dom, that won't be picked up. Not entirely sure
1291
1295
  // whether this is a problem
1292
1296
  var rule = {node: this.node.type.name, attrs: this.node.attrs};
1293
- if (this.node.type.spec.code) { rule.preserveWhitespace = "full"; }
1297
+ if (this.node.type.whitespace == "pre") { rule.preserveWhitespace = "full"; }
1294
1298
  if (this.contentDOM && !this.contentLost) { rule.contentElement = this.contentDOM; }
1295
1299
  else { rule.getContent = function () { return this$1.contentDOM ? Fragment.empty : this$1.node.content; }; }
1296
1300
  return rule
@@ -2077,8 +2081,8 @@ function findTextInFragment(frag, text, from, to) {
2077
2081
  if (!next.isText) { break }
2078
2082
  str += next.text;
2079
2083
  }
2080
- if (pos >= from) {
2081
- var found = str.lastIndexOf(text, to - childStart);
2084
+ if (pos >= from && childStart < to) {
2085
+ var found = str.lastIndexOf(text, to - childStart - 1);
2082
2086
  if (found >= 0 && found + text.length + childStart >= from)
2083
2087
  { return childStart + found }
2084
2088
  }
@@ -2148,10 +2152,17 @@ function selectionToDOM(view, force) {
2148
2152
 
2149
2153
  if (!editorOwnsSelection(view)) { return }
2150
2154
 
2151
- if (!force && view.mouseDown && view.mouseDown.allowDefault) {
2152
- view.mouseDown.delayedSelectionSync = true;
2153
- view.domObserver.setCurSelection();
2154
- return
2155
+ // The delayed drag selection causes issues with Cell Selections
2156
+ // in Safari. And the drag selection delay is to workarond issues
2157
+ // which only present in Chrome.
2158
+ if (!force && view.mouseDown && view.mouseDown.allowDefault && result.chrome) {
2159
+ var domSel = view.root.getSelection(), curSel = view.domObserver.currentSelection;
2160
+ if (domSel.anchorNode && isEquivalentPosition(domSel.anchorNode, domSel.anchorOffset,
2161
+ curSel.anchorNode, curSel.anchorOffset)) {
2162
+ view.mouseDown.delayedSelectionSync = true;
2163
+ view.domObserver.setCurSelection();
2164
+ return
2165
+ }
2155
2166
  }
2156
2167
 
2157
2168
  view.domObserver.disconnectSelection();
@@ -2616,7 +2627,7 @@ function parseBetween(view, from_, to_) {
2616
2627
  topOpen: true,
2617
2628
  from: fromOffset,
2618
2629
  to: toOffset,
2619
- preserveWhitespace: $from.parent.type.spec.code ? "full" : true,
2630
+ preserveWhitespace: $from.parent.type.whitespace == "pre" ? "full" : true,
2620
2631
  editableContent: true,
2621
2632
  findPositions: find,
2622
2633
  ruleFromNode: ruleFromNode,
@@ -2998,7 +3009,8 @@ function parseFromClipboard(view, text, html, plainText, $context) {
2998
3009
  preserveWhitespace: !!(asText || sliceData),
2999
3010
  context: $context,
3000
3011
  ruleFromNode: function ruleFromNode(dom) {
3001
- if (dom.nodeName == "BR" && !dom.nextSibling) { return {ignore: true} }
3012
+ if (dom.nodeName == "BR" && !dom.nextSibling &&
3013
+ dom.parentNode && !inlineParents.test(dom.parentNode.nodeName)) { return {ignore: true} }
3002
3014
  }
3003
3015
  });
3004
3016
  }
@@ -3020,6 +3032,8 @@ function parseFromClipboard(view, text, html, plainText, $context) {
3020
3032
  return slice
3021
3033
  }
3022
3034
 
3035
+ var inlineParents = /^(a|abbr|acronym|b|cite|code|del|em|i|ins|kbd|label|output|q|ruby|s|samp|span|strong|sub|sup|time|u|tt|var)$/i;
3036
+
3023
3037
  // Takes a slice parsed with parseSlice, which means there hasn't been
3024
3038
  // any content-expression checking done on the top nodes, tries to
3025
3039
  // find a parent node in the current context that might fit the nodes,
@@ -3500,9 +3514,14 @@ function dispatchEvent(view, event) {
3500
3514
  editHandlers.keydown = function (view, event) {
3501
3515
  view.shiftKey = event.keyCode == 16 || event.shiftKey;
3502
3516
  if (inOrNearComposition(view, event)) { return }
3503
- if (event.keyCode != 229) { view.domObserver.forceFlush(); }
3504
3517
  view.lastKeyCode = event.keyCode;
3505
3518
  view.lastKeyCodeTime = Date.now();
3519
+ // Suppress enter key events on Chrome Android, because those tend
3520
+ // to be part of a confused sequence of composition events fired,
3521
+ // and handling them eagerly tends to corrupt the input.
3522
+ if (result.android && result.chrome && event.keyCode == 13) { return }
3523
+ if (event.keyCode != 229) { view.domObserver.forceFlush(); }
3524
+
3506
3525
  // On iOS, if we preventDefault enter key presses, the virtual
3507
3526
  // keyboard gets confused. So the hack here is to set a flag that
3508
3527
  // makes the DOM change code recognize that what just happens should
@@ -3887,6 +3906,7 @@ function timestampFromCustomEvent() {
3887
3906
  }
3888
3907
 
3889
3908
  function endComposition(view, forceUpdate) {
3909
+ if (result.android && view.domObserver.flushingSoon >= 0) { return }
3890
3910
  view.domObserver.forceFlush();
3891
3911
  clearComposition(view);
3892
3912
  if (forceUpdate || view.docView.dirty) {
@@ -3977,6 +3997,11 @@ function doPaste(view, text, html, e) {
3977
3997
  }
3978
3998
 
3979
3999
  editHandlers.paste = function (view, e) {
4000
+ // Handling paste from JavaScript during composition is very poorly
4001
+ // handled by browsers, so as a dodgy but preferable kludge, we just
4002
+ // let the browser do its native thing there, except on Android,
4003
+ // where the editor is almost always composing.
4004
+ if (view.composing && !result.android) { return }
3980
4005
  var data = brokenClipboardAPI ? null : e.clipboardData;
3981
4006
  if (data && doPaste(view, data.getData("text/plain"), data.getData("text/html"), e)) { e.preventDefault(); }
3982
4007
  else { capturePaste(view, e); }
@@ -4108,6 +4133,7 @@ handlers.beforeinput = function (view, event) {
4108
4133
  // Very specific hack to deal with backspace sometimes failing on
4109
4134
  // Chrome Android when after an uneditable node.
4110
4135
  if (result.chrome && result.android && event.inputType == "deleteContentBackward") {
4136
+ view.domObserver.flushSoon();
4111
4137
  var domChangeCount = view.domChangeCount;
4112
4138
  setTimeout(function () {
4113
4139
  if (view.domChangeCount != domChangeCount) { return } // Event already had some effect