prosemirror-view 1.27.0 → 1.27.1

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
+ ## 1.27.1 (2022-08-16)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix a bug in `DecorationSet.map` that could cause invalid mapping when step maps contain multiple replaced ranges.
6
+
7
+ Make sure that when the editor receives focus via tab or calling `.focus()` on its DOM element, the existing selection is restored.
8
+
9
+ Avoid collapsing of whitespace in Firefox when the editor doesn't have `white-space` set to `pre-wrap`.
10
+
1
11
  ## 1.27.0 (2022-07-20)
2
12
 
3
13
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -531,7 +531,7 @@ function _coordsAtPos(view, pos, side) {
531
531
  to++;
532
532
  }
533
533
 
534
- return flattenV(singleRect(textRange(node, from, to), takeSide), takeSide < 0);
534
+ return flattenV(singleRect(textRange(node, from, to), 1), takeSide < 0);
535
535
  }
536
536
  }
537
537
 
@@ -1462,7 +1462,7 @@ var NodeViewDesc = function (_ViewDesc4) {
1462
1462
  var composition = view.composing ? this.localCompositionInfo(view, pos) : null;
1463
1463
  var localComposition = composition && composition.pos > -1 ? composition : null;
1464
1464
  var compositionInChild = composition && composition.pos < 0;
1465
- var updater = new ViewTreeUpdater(this, localComposition && localComposition.node);
1465
+ var updater = new ViewTreeUpdater(this, localComposition && localComposition.node, view);
1466
1466
  iterDeco(this.node, this.innerDeco, function (widget, i, insideNode) {
1467
1467
  if (widget.spec.marks) updater.syncToMarks(widget.spec.marks, inline, view);else if (widget.type.side >= 0 && !insideNode) updater.syncToMarks(i == _this6.node.childCount ? prosemirrorModel.Mark.none : _this6.node.child(i).marks, inline, view);
1468
1468
  updater.placeWidget(widget, view, off);
@@ -1974,10 +1974,11 @@ function rm(dom) {
1974
1974
  }
1975
1975
 
1976
1976
  var ViewTreeUpdater = function () {
1977
- function ViewTreeUpdater(top, lock) {
1977
+ function ViewTreeUpdater(top, lock, view) {
1978
1978
  _classCallCheck(this, ViewTreeUpdater);
1979
1979
 
1980
1980
  this.lock = lock;
1981
+ this.view = view;
1981
1982
  this.index = 0;
1982
1983
  this.stack = [];
1983
1984
  this.changed = false;
@@ -2158,7 +2159,7 @@ var ViewTreeUpdater = function () {
2158
2159
  lastChild = parent.children[parent.children.length - 1];
2159
2160
  }
2160
2161
 
2161
- if (!lastChild || !(lastChild instanceof TextViewDesc) || /\n$/.test(lastChild.node.text)) {
2162
+ if (!lastChild || !(lastChild instanceof TextViewDesc) || /\n$/.test(lastChild.node.text) || this.view.requiresGeckoHackNode && /\s$/.test(lastChild.node.text)) {
2162
2163
  if ((safari || chrome) && lastChild && lastChild.dom.contentEditable == "false") this.addHackNode("IMG", parent);
2163
2164
  this.addHackNode("BR", this.top);
2164
2165
  }
@@ -3164,6 +3165,10 @@ function addContext(slice, context) {
3164
3165
 
3165
3166
  var handlers = {};
3166
3167
  var editHandlers = {};
3168
+ var passiveHandlers = {
3169
+ touchstart: true,
3170
+ touchmove: true
3171
+ };
3167
3172
 
3168
3173
  var InputState = _createClass(function InputState() {
3169
3174
  _classCallCheck(this, InputState);
@@ -3182,6 +3187,8 @@ var InputState = _createClass(function InputState() {
3182
3187
  this.lastSelectionTime = 0;
3183
3188
  this.lastIOSEnter = 0;
3184
3189
  this.lastIOSEnterFallbackTimeout = -1;
3190
+ this.lastFocus = 0;
3191
+ this.lastTouch = 0;
3185
3192
  this.lastAndroidDelete = 0;
3186
3193
  this.composing = false;
3187
3194
  this.composingTimeout = -1;
@@ -3197,7 +3204,9 @@ function initInput(view) {
3197
3204
  var handler = handlers[event];
3198
3205
  view.dom.addEventListener(event, view.input.eventHandlers[event] = function (event) {
3199
3206
  if (eventBelongsToView(view, event) && !runCustomHandler(view, event) && (view.editable || !(event.type in editHandlers))) handler(view, event);
3200
- });
3207
+ }, passiveHandlers[event] ? {
3208
+ passive: true
3209
+ } : undefined);
3201
3210
  };
3202
3211
 
3203
3212
  for (var event in handlers) {
@@ -3571,11 +3580,17 @@ var MouseDown = function () {
3571
3580
  return MouseDown;
3572
3581
  }();
3573
3582
 
3574
- handlers.touchdown = function (view) {
3583
+ handlers.touchstart = function (view) {
3584
+ view.input.lastTouch = Date.now();
3575
3585
  forceDOMFlush(view);
3576
3586
  setSelectionOrigin(view, "pointer");
3577
3587
  };
3578
3588
 
3589
+ handlers.touchmove = function (view) {
3590
+ view.input.lastTouch = Date.now();
3591
+ setSelectionOrigin(view, "pointer");
3592
+ };
3593
+
3579
3594
  handlers.contextmenu = function (view) {
3580
3595
  return forceDOMFlush(view);
3581
3596
  };
@@ -3813,7 +3828,6 @@ editHandlers.drop = function (view, _event) {
3813
3828
  var eventPos = view.posAtCoords(eventCoords(event));
3814
3829
  if (!eventPos) return;
3815
3830
  var $mouse = view.state.doc.resolve(eventPos.pos);
3816
- if (!$mouse) return;
3817
3831
  var slice = dragging && dragging.slice;
3818
3832
 
3819
3833
  if (slice) {
@@ -3861,6 +3875,8 @@ editHandlers.drop = function (view, _event) {
3861
3875
  };
3862
3876
 
3863
3877
  handlers.focus = function (view) {
3878
+ view.input.lastFocus = Date.now();
3879
+
3864
3880
  if (!view.focused) {
3865
3881
  view.domObserver.stop();
3866
3882
  view.dom.classList.add("ProseMirror-focused");
@@ -4400,24 +4416,30 @@ var DecorationGroup = function () {
4400
4416
  function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, options) {
4401
4417
  var children = oldChildren.slice();
4402
4418
 
4403
- var shift = function shift(oldStart, oldEnd, newStart, newEnd) {
4404
- for (var i = 0; i < children.length; i += 3) {
4405
- var end = children[i + 1],
4406
- dSize = void 0;
4407
- if (end < 0 || oldStart > end + oldOffset) continue;
4408
- var start = children[i] + oldOffset;
4409
-
4410
- if (oldEnd >= start) {
4411
- children[i + 1] = oldStart <= start ? -2 : -1;
4412
- } else if (newStart >= offset && (dSize = newEnd - newStart - (oldEnd - oldStart))) {
4413
- children[i] += dSize;
4414
- children[i + 1] += dSize;
4419
+ var _loop4 = function _loop4(i) {
4420
+ var moved = 0;
4421
+ mapping.maps[i].forEach(function (oldStart, oldEnd, newStart, newEnd) {
4422
+ var dSize = newEnd - newStart - (oldEnd - oldStart);
4423
+
4424
+ for (var _i12 = 0; _i12 < children.length; _i12 += 3) {
4425
+ var end = children[_i12 + 1];
4426
+ if (end < 0 || oldStart > end + oldOffset - moved) continue;
4427
+ var start = children[_i12] + oldOffset - moved;
4428
+
4429
+ if (oldEnd >= start) {
4430
+ children[_i12 + 1] = oldStart <= start ? -2 : -1;
4431
+ } else if (newStart >= offset && dSize) {
4432
+ children[_i12] += dSize;
4433
+ children[_i12 + 1] += dSize;
4434
+ }
4415
4435
  }
4416
- }
4436
+
4437
+ moved += dSize;
4438
+ });
4417
4439
  };
4418
4440
 
4419
4441
  for (var i = 0; i < mapping.maps.length; i++) {
4420
- mapping.maps[i].forEach(shift);
4442
+ _loop4(i);
4421
4443
  }
4422
4444
 
4423
4445
  var mustRebuild = false;
@@ -4509,8 +4531,8 @@ function mapAndGatherRemainingDecorations(children, oldChildren, decorations, ma
4509
4531
  if (mapped) decorations.push(mapped);else if (options.onRemove) options.onRemove(set.local[i].spec);
4510
4532
  }
4511
4533
 
4512
- for (var _i12 = 0; _i12 < set.children.length; _i12 += 3) {
4513
- gather(set.children[_i12 + 2], set.children[_i12] + oldOffset + 1);
4534
+ for (var _i13 = 0; _i13 < set.children.length; _i13 += 3) {
4535
+ gather(set.children[_i13 + 2], set.children[_i13] + oldOffset + 1);
4514
4536
  }
4515
4537
  }
4516
4538
 
@@ -4816,7 +4838,8 @@ var DOMObserver = function () {
4816
4838
  }, {
4817
4839
  key: "flush",
4818
4840
  value: function flush() {
4819
- if (!this.view.docView || this.flushingSoon > -1) return;
4841
+ var view = this.view;
4842
+ if (!view.docView || this.flushingSoon > -1) return;
4820
4843
  var mutations = this.observer ? this.observer.takeRecords() : [];
4821
4844
 
4822
4845
  if (this.queue.length) {
@@ -4824,14 +4847,14 @@ var DOMObserver = function () {
4824
4847
  this.queue.length = 0;
4825
4848
  }
4826
4849
 
4827
- var sel = this.view.domSelection();
4828
- var newSel = !this.suppressingSelectionUpdates && !this.currentSelection.eq(sel) && hasFocusAndSelection(this.view) && !this.ignoreSelectionChange(sel);
4850
+ var sel = view.domSelection();
4851
+ var newSel = !this.suppressingSelectionUpdates && !this.currentSelection.eq(sel) && hasFocusAndSelection(view) && !this.ignoreSelectionChange(sel);
4829
4852
  var from = -1,
4830
4853
  to = -1,
4831
4854
  typeOver = false,
4832
4855
  added = [];
4833
4856
 
4834
- if (this.view.editable) {
4857
+ if (view.editable) {
4835
4858
  for (var i = 0; i < mutations.length; i++) {
4836
4859
  var result = this.registerMutation(mutations[i], added);
4837
4860
 
@@ -4855,14 +4878,21 @@ var DOMObserver = function () {
4855
4878
  }
4856
4879
  }
4857
4880
 
4858
- if (from > -1 || newSel) {
4881
+ var readSel = null;
4882
+
4883
+ if (from < 0 && newSel && view.input.lastFocus > Date.now() - 200 && view.input.lastTouch < Date.now() - 300 && selectionCollapsed(sel) && (readSel = selectionFromDOM(view)) && readSel.eq(prosemirrorState.Selection.near(view.state.doc.resolve(0), 1))) {
4884
+ view.input.lastFocus = 0;
4885
+ selectionToDOM(view);
4886
+ this.currentSelection.set(sel);
4887
+ view.scrollToSelection();
4888
+ } else if (from > -1 || newSel) {
4859
4889
  if (from > -1) {
4860
- this.view.docView.markDirty(from, to);
4861
- checkCSS(this.view);
4890
+ view.docView.markDirty(from, to);
4891
+ checkCSS(view);
4862
4892
  }
4863
4893
 
4864
4894
  this.handleDOMChange(from, to, typeOver, added);
4865
- if (this.view.docView && this.view.docView.dirty) this.view.updateState(this.view.state);else if (!this.currentSelection.eq(sel)) selectionToDOM(this.view);
4895
+ if (view.docView && view.docView.dirty) view.updateState(view.state);else if (!this.currentSelection.eq(sel)) selectionToDOM(view);
4866
4896
  this.currentSelection.set(sel);
4867
4897
  }
4868
4898
  }
@@ -4887,8 +4917,8 @@ var DOMObserver = function () {
4887
4917
  next = mut.nextSibling;
4888
4918
 
4889
4919
  if (ie && ie_version <= 11 && mut.addedNodes.length) {
4890
- for (var _i13 = 0; _i13 < mut.addedNodes.length; _i13++) {
4891
- var _mut$addedNodes$_i = mut.addedNodes[_i13],
4920
+ for (var _i14 = 0; _i14 < mut.addedNodes.length; _i14++) {
4921
+ var _mut$addedNodes$_i = mut.addedNodes[_i14],
4892
4922
  previousSibling = _mut$addedNodes$_i.previousSibling,
4893
4923
  nextSibling = _mut$addedNodes$_i.nextSibling;
4894
4924
  if (!previousSibling || Array.prototype.indexOf.call(mut.addedNodes, previousSibling) < 0) prev = previousSibling;
@@ -4922,12 +4952,19 @@ var DOMObserver = function () {
4922
4952
  return DOMObserver;
4923
4953
  }();
4924
4954
 
4925
- var cssChecked = false;
4955
+ var cssChecked = new WeakMap();
4956
+ var cssCheckWarned = false;
4926
4957
 
4927
4958
  function checkCSS(view) {
4928
- if (cssChecked) return;
4929
- cssChecked = true;
4930
- if (getComputedStyle(view.dom).whiteSpace == "normal") console["warn"]("ProseMirror expects the CSS white-space property to be set, preferably to 'pre-wrap'. It is recommended to load style/prosemirror.css from the prosemirror-view package.");
4959
+ if (cssChecked.has(view)) return;
4960
+ cssChecked.set(view, null);
4961
+
4962
+ if (['normal', 'nowrap', 'pre-line'].indexOf(getComputedStyle(view.dom).whiteSpace) !== -1) {
4963
+ view.requiresGeckoHackNode = gecko;
4964
+ if (cssCheckWarned) return;
4965
+ console["warn"]("ProseMirror expects the CSS white-space property to be set, preferably to 'pre-wrap'. It is recommended to load style/prosemirror.css from the prosemirror-view package.");
4966
+ cssCheckWarned = true;
4967
+ }
4931
4968
  }
4932
4969
 
4933
4970
  function parseBetween(view, from_, to_) {
@@ -5209,8 +5246,8 @@ function isMarkChange(cur, prev) {
5209
5246
  added = prevMarks[i].removeFromSet(added);
5210
5247
  }
5211
5248
 
5212
- for (var _i14 = 0; _i14 < curMarks.length; _i14++) {
5213
- removed = curMarks[_i14].removeFromSet(removed);
5249
+ for (var _i15 = 0; _i15 < curMarks.length; _i15++) {
5250
+ removed = curMarks[_i15].removeFromSet(removed);
5214
5251
  }
5215
5252
 
5216
5253
  if (added.length == 1 && removed.length == 0) {
@@ -5233,8 +5270,8 @@ function isMarkChange(cur, prev) {
5233
5270
 
5234
5271
  var updated = [];
5235
5272
 
5236
- for (var _i15 = 0; _i15 < prev.childCount; _i15++) {
5237
- updated.push(update(prev.child(_i15)));
5273
+ for (var _i16 = 0; _i16 < prev.childCount; _i16++) {
5274
+ updated.push(update(prev.child(_i16)));
5238
5275
  }
5239
5276
 
5240
5277
  if (prosemirrorModel.Fragment.from(updated).eq(cur)) return {
@@ -5327,6 +5364,7 @@ var EditorView = function () {
5327
5364
  this.input = new InputState();
5328
5365
  this.prevDirectPlugins = [];
5329
5366
  this.pluginViews = [];
5367
+ this.requiresGeckoHackNode = false;
5330
5368
  this.dragging = null;
5331
5369
  this._props = props;
5332
5370
  this.state = props.state;
@@ -5410,8 +5448,6 @@ var EditorView = function () {
5410
5448
  }, {
5411
5449
  key: "updateStateInner",
5412
5450
  value: function updateStateInner(state, reconfigured) {
5413
- var _this16 = this;
5414
-
5415
5451
  var prev = this.state,
5416
5452
  redraw = false,
5417
5453
  updateSel = false;
@@ -5474,19 +5510,26 @@ var EditorView = function () {
5474
5510
  if (scroll == "reset") {
5475
5511
  this.dom.scrollTop = 0;
5476
5512
  } else if (scroll == "to selection") {
5477
- var startDOM = this.domSelection().focusNode;
5478
- if (this.someProp("handleScrollToSelection", function (f) {
5479
- return f(_this16);
5480
- })) ;else if (state.selection instanceof prosemirrorState.NodeSelection) {
5481
- var target = this.docView.domAfterPos(state.selection.from);
5482
- if (target.nodeType == 1) scrollRectIntoView(this, target.getBoundingClientRect(), startDOM);
5483
- } else {
5484
- scrollRectIntoView(this, this.coordsAtPos(state.selection.head, 1), startDOM);
5485
- }
5513
+ this.scrollToSelection();
5486
5514
  } else if (oldScrollPos) {
5487
5515
  resetScrollPos(oldScrollPos);
5488
5516
  }
5489
5517
  }
5518
+ }, {
5519
+ key: "scrollToSelection",
5520
+ value: function scrollToSelection() {
5521
+ var _this16 = this;
5522
+
5523
+ var startDOM = this.domSelection().focusNode;
5524
+ if (this.someProp("handleScrollToSelection", function (f) {
5525
+ return f(_this16);
5526
+ })) ;else if (this.state.selection instanceof prosemirrorState.NodeSelection) {
5527
+ var target = this.docView.domAfterPos(this.state.selection.from);
5528
+ if (target.nodeType == 1) scrollRectIntoView(this, target.getBoundingClientRect(), startDOM);
5529
+ } else {
5530
+ scrollRectIntoView(this, this.coordsAtPos(this.state.selection.head, 1), startDOM);
5531
+ }
5532
+ }
5490
5533
  }, {
5491
5534
  key: "destroyPluginViews",
5492
5535
  value: function destroyPluginViews() {
@@ -5508,13 +5551,13 @@ var EditorView = function () {
5508
5551
  if (plugin.spec.view) this.pluginViews.push(plugin.spec.view(this));
5509
5552
  }
5510
5553
 
5511
- for (var _i16 = 0; _i16 < this.state.plugins.length; _i16++) {
5512
- var _plugin = this.state.plugins[_i16];
5554
+ for (var _i17 = 0; _i17 < this.state.plugins.length; _i17++) {
5555
+ var _plugin = this.state.plugins[_i17];
5513
5556
  if (_plugin.spec.view) this.pluginViews.push(_plugin.spec.view(this));
5514
5557
  }
5515
5558
  } else {
5516
- for (var _i17 = 0; _i17 < this.pluginViews.length; _i17++) {
5517
- var pluginView = this.pluginViews[_i17];
5559
+ for (var _i18 = 0; _i18 < this.pluginViews.length; _i18++) {
5560
+ var pluginView = this.pluginViews[_i18];
5518
5561
  if (pluginView.update) pluginView.update(this, prevState);
5519
5562
  }
5520
5563
  }
@@ -5532,8 +5575,8 @@ var EditorView = function () {
5532
5575
  }
5533
5576
 
5534
5577
  var plugins = this.state.plugins;
5535
- if (plugins) for (var _i18 = 0; _i18 < plugins.length; _i18++) {
5536
- var _prop2 = plugins[_i18].props[propName];
5578
+ if (plugins) for (var _i19 = 0; _i19 < plugins.length; _i19++) {
5579
+ var _prop2 = plugins[_i19].props[propName];
5537
5580
  if (_prop2 != null && (value = f ? f(_prop2) : _prop2)) return value;
5538
5581
  }
5539
5582
  }
@@ -5558,7 +5601,7 @@ var EditorView = function () {
5558
5601
  var cached = this._root;
5559
5602
 
5560
5603
  if (cached == null) {
5561
- var _loop4 = function _loop4(search) {
5604
+ var _loop5 = function _loop5(search) {
5562
5605
  if (search.nodeType == 9 || search.nodeType == 11 && search.host) {
5563
5606
  if (!search.getSelection) Object.getPrototypeOf(search).getSelection = function () {
5564
5607
  return search.ownerDocument.getSelection();
@@ -5570,7 +5613,7 @@ var EditorView = function () {
5570
5613
  };
5571
5614
 
5572
5615
  for (var search = this.dom.parentNode; search; search = search.parentNode) {
5573
- var _ret3 = _loop4(search);
5616
+ var _ret3 = _loop5(search);
5574
5617
 
5575
5618
  if (_typeof(_ret3) === "object") return _ret3.v;
5576
5619
  }
package/dist/index.d.ts CHANGED
@@ -696,8 +696,8 @@ interface EditorProps<P = any> {
696
696
  */
697
697
  clipboardTextParser?: (this: P, text: string, $context: ResolvedPos, plain: boolean) => Slice;
698
698
  /**
699
- Can be used to transform pasted content before it is applied to
700
- the document.
699
+ Can be used to transform pasted or dragged-and-dropped content
700
+ before it is applied to the document.
701
701
  */
702
702
  transformPasted?: (this: P, slice: Slice) => Slice;
703
703
  /**
package/dist/index.js CHANGED
@@ -458,7 +458,7 @@ function coordsAtPos(view, pos, side) {
458
458
  else {
459
459
  to++;
460
460
  }
461
- return flattenV(singleRect(textRange(node, from, to), takeSide), takeSide < 0);
461
+ return flattenV(singleRect(textRange(node, from, to), 1), takeSide < 0);
462
462
  }
463
463
  }
464
464
  let $dom = view.state.doc.resolve(pos - (atom || 0));
@@ -1242,7 +1242,7 @@ class NodeViewDesc extends ViewDesc {
1242
1242
  let composition = view.composing ? this.localCompositionInfo(view, pos) : null;
1243
1243
  let localComposition = composition && composition.pos > -1 ? composition : null;
1244
1244
  let compositionInChild = composition && composition.pos < 0;
1245
- let updater = new ViewTreeUpdater(this, localComposition && localComposition.node);
1245
+ let updater = new ViewTreeUpdater(this, localComposition && localComposition.node, view);
1246
1246
  iterDeco(this.node, this.innerDeco, (widget, i, insideNode) => {
1247
1247
  if (widget.spec.marks)
1248
1248
  updater.syncToMarks(widget.spec.marks, inline, view);
@@ -1624,8 +1624,9 @@ function rm(dom) {
1624
1624
  // Helper class for incrementally updating a tree of mark descs and
1625
1625
  // the widget and node descs inside of them.
1626
1626
  class ViewTreeUpdater {
1627
- constructor(top, lock) {
1627
+ constructor(top, lock, view) {
1628
1628
  this.lock = lock;
1629
+ this.view = view;
1629
1630
  // Index into `this.top`'s child array, represents the current
1630
1631
  // update position.
1631
1632
  this.index = 0;
@@ -1799,7 +1800,8 @@ class ViewTreeUpdater {
1799
1800
  }
1800
1801
  if (!lastChild || // Empty textblock
1801
1802
  !(lastChild instanceof TextViewDesc) ||
1802
- /\n$/.test(lastChild.node.text)) {
1803
+ /\n$/.test(lastChild.node.text) ||
1804
+ (this.view.requiresGeckoHackNode && /\s$/.test(lastChild.node.text))) {
1803
1805
  // Avoid bugs in Safari's cursor drawing (#1165) and Chrome's mouse selection (#1152)
1804
1806
  if ((safari || chrome) && lastChild && lastChild.dom.contentEditable == "false")
1805
1807
  this.addHackNode("IMG", parent);
@@ -2772,7 +2774,8 @@ function addContext(slice, context) {
2772
2774
  // A collection of DOM events that occur within the editor, and callback functions
2773
2775
  // to invoke when the event fires.
2774
2776
  const handlers = {};
2775
- let editHandlers = {};
2777
+ const editHandlers = {};
2778
+ const passiveHandlers = { touchstart: true, touchmove: true };
2776
2779
  class InputState {
2777
2780
  constructor() {
2778
2781
  this.shiftKey = false;
@@ -2784,6 +2787,8 @@ class InputState {
2784
2787
  this.lastSelectionTime = 0;
2785
2788
  this.lastIOSEnter = 0;
2786
2789
  this.lastIOSEnterFallbackTimeout = -1;
2790
+ this.lastFocus = 0;
2791
+ this.lastTouch = 0;
2787
2792
  this.lastAndroidDelete = 0;
2788
2793
  this.composing = false;
2789
2794
  this.composingTimeout = -1;
@@ -2801,7 +2806,7 @@ function initInput(view) {
2801
2806
  if (eventBelongsToView(view, event) && !runCustomHandler(view, event) &&
2802
2807
  (view.editable || !(event.type in editHandlers)))
2803
2808
  handler(view, event);
2804
- });
2809
+ }, passiveHandlers[event] ? { passive: true } : undefined);
2805
2810
  }
2806
2811
  // On Safari, for reasons beyond my understanding, adding an input
2807
2812
  // event handler makes an issue where the composition vanishes when
@@ -3141,10 +3146,15 @@ class MouseDown {
3141
3146
  this.done();
3142
3147
  }
3143
3148
  }
3144
- handlers.touchdown = view => {
3149
+ handlers.touchstart = view => {
3150
+ view.input.lastTouch = Date.now();
3145
3151
  forceDOMFlush(view);
3146
3152
  setSelectionOrigin(view, "pointer");
3147
3153
  };
3154
+ handlers.touchmove = view => {
3155
+ view.input.lastTouch = Date.now();
3156
+ setSelectionOrigin(view, "pointer");
3157
+ };
3148
3158
  handlers.contextmenu = view => forceDOMFlush(view);
3149
3159
  function inOrNearComposition(view, event) {
3150
3160
  if (view.composing)
@@ -3396,8 +3406,6 @@ editHandlers.drop = (view, _event) => {
3396
3406
  if (!eventPos)
3397
3407
  return;
3398
3408
  let $mouse = view.state.doc.resolve(eventPos.pos);
3399
- if (!$mouse)
3400
- return;
3401
3409
  let slice = dragging && dragging.slice;
3402
3410
  if (slice) {
3403
3411
  view.someProp("transformPasted", f => { slice = f(slice); });
@@ -3442,6 +3450,7 @@ editHandlers.drop = (view, _event) => {
3442
3450
  view.dispatch(tr.setMeta("uiEvent", "drop"));
3443
3451
  };
3444
3452
  handlers.focus = view => {
3453
+ view.input.lastFocus = Date.now();
3445
3454
  if (!view.focused) {
3446
3455
  view.domObserver.stop();
3447
3456
  view.dom.classList.add("ProseMirror-focused");
@@ -3956,23 +3965,26 @@ function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, op
3956
3965
  let children = oldChildren.slice();
3957
3966
  // Mark the children that are directly touched by changes, and
3958
3967
  // move those that are after the changes.
3959
- let shift = (oldStart, oldEnd, newStart, newEnd) => {
3960
- for (let i = 0; i < children.length; i += 3) {
3961
- let end = children[i + 1], dSize;
3962
- if (end < 0 || oldStart > end + oldOffset)
3963
- continue;
3964
- let start = children[i] + oldOffset;
3965
- if (oldEnd >= start) {
3966
- children[i + 1] = oldStart <= start ? -2 : -1;
3967
- }
3968
- else if (newStart >= offset && (dSize = (newEnd - newStart) - (oldEnd - oldStart))) {
3969
- children[i] += dSize;
3970
- children[i + 1] += dSize;
3968
+ for (let i = 0; i < mapping.maps.length; i++) {
3969
+ let moved = 0;
3970
+ mapping.maps[i].forEach((oldStart, oldEnd, newStart, newEnd) => {
3971
+ let dSize = (newEnd - newStart) - (oldEnd - oldStart);
3972
+ for (let i = 0; i < children.length; i += 3) {
3973
+ let end = children[i + 1];
3974
+ if (end < 0 || oldStart > end + oldOffset - moved)
3975
+ continue;
3976
+ let start = children[i] + oldOffset - moved;
3977
+ if (oldEnd >= start) {
3978
+ children[i + 1] = oldStart <= start ? -2 : -1;
3979
+ }
3980
+ else if (newStart >= offset && dSize) {
3981
+ children[i] += dSize;
3982
+ children[i + 1] += dSize;
3983
+ }
3971
3984
  }
3972
- }
3973
- };
3974
- for (let i = 0; i < mapping.maps.length; i++)
3975
- mapping.maps[i].forEach(shift);
3985
+ moved += dSize;
3986
+ });
3987
+ }
3976
3988
  // Find the child nodes that still correspond to a single node,
3977
3989
  // recursively call mapInner on them and update their positions.
3978
3990
  let mustRebuild = false;
@@ -4300,17 +4312,18 @@ class DOMObserver {
4300
4312
  }
4301
4313
  }
4302
4314
  flush() {
4303
- if (!this.view.docView || this.flushingSoon > -1)
4315
+ let { view } = this;
4316
+ if (!view.docView || this.flushingSoon > -1)
4304
4317
  return;
4305
4318
  let mutations = this.observer ? this.observer.takeRecords() : [];
4306
4319
  if (this.queue.length) {
4307
4320
  mutations = this.queue.concat(mutations);
4308
4321
  this.queue.length = 0;
4309
4322
  }
4310
- let sel = this.view.domSelection();
4311
- let newSel = !this.suppressingSelectionUpdates && !this.currentSelection.eq(sel) && hasFocusAndSelection(this.view) && !this.ignoreSelectionChange(sel);
4323
+ let sel = view.domSelection();
4324
+ let newSel = !this.suppressingSelectionUpdates && !this.currentSelection.eq(sel) && hasFocusAndSelection(view) && !this.ignoreSelectionChange(sel);
4312
4325
  let from = -1, to = -1, typeOver = false, added = [];
4313
- if (this.view.editable) {
4326
+ if (view.editable) {
4314
4327
  for (let i = 0; i < mutations.length; i++) {
4315
4328
  let result = this.registerMutation(mutations[i], added);
4316
4329
  if (result) {
@@ -4331,16 +4344,29 @@ class DOMObserver {
4331
4344
  a.remove();
4332
4345
  }
4333
4346
  }
4334
- if (from > -1 || newSel) {
4347
+ let readSel = null;
4348
+ // If it looks like the browser has reset the selection to the
4349
+ // start of the document after focus, restore the selection from
4350
+ // the state
4351
+ if (from < 0 && newSel && view.input.lastFocus > Date.now() - 200 &&
4352
+ view.input.lastTouch < Date.now() - 300 &&
4353
+ selectionCollapsed(sel) && (readSel = selectionFromDOM(view)) &&
4354
+ readSel.eq(Selection.near(view.state.doc.resolve(0), 1))) {
4355
+ view.input.lastFocus = 0;
4356
+ selectionToDOM(view);
4357
+ this.currentSelection.set(sel);
4358
+ view.scrollToSelection();
4359
+ }
4360
+ else if (from > -1 || newSel) {
4335
4361
  if (from > -1) {
4336
- this.view.docView.markDirty(from, to);
4337
- checkCSS(this.view);
4362
+ view.docView.markDirty(from, to);
4363
+ checkCSS(view);
4338
4364
  }
4339
4365
  this.handleDOMChange(from, to, typeOver, added);
4340
- if (this.view.docView && this.view.docView.dirty)
4341
- this.view.updateState(this.view.state);
4366
+ if (view.docView && view.docView.dirty)
4367
+ view.updateState(view.state);
4342
4368
  else if (!this.currentSelection.eq(sel))
4343
- selectionToDOM(this.view);
4369
+ selectionToDOM(view);
4344
4370
  this.currentSelection.set(sel);
4345
4371
  }
4346
4372
  }
@@ -4397,13 +4423,19 @@ class DOMObserver {
4397
4423
  }
4398
4424
  }
4399
4425
  }
4400
- let cssChecked = false;
4426
+ let cssChecked = new WeakMap();
4427
+ let cssCheckWarned = false;
4401
4428
  function checkCSS(view) {
4402
- if (cssChecked)
4429
+ if (cssChecked.has(view))
4403
4430
  return;
4404
- cssChecked = true;
4405
- if (getComputedStyle(view.dom).whiteSpace == "normal")
4431
+ cssChecked.set(view, null);
4432
+ if (['normal', 'nowrap', 'pre-line'].indexOf(getComputedStyle(view.dom).whiteSpace) !== -1) {
4433
+ view.requiresGeckoHackNode = gecko;
4434
+ if (cssCheckWarned)
4435
+ return;
4406
4436
  console["warn"]("ProseMirror expects the CSS white-space property to be set, preferably to 'pre-wrap'. It is recommended to load style/prosemirror.css from the prosemirror-view package.");
4437
+ cssCheckWarned = true;
4438
+ }
4407
4439
  }
4408
4440
 
4409
4441
  // Note that all referencing and parsing is done with the
@@ -4810,6 +4842,12 @@ class EditorView {
4810
4842
  this.prevDirectPlugins = [];
4811
4843
  this.pluginViews = [];
4812
4844
  /**
4845
+ Holds `true` when a hack node is needed in Firefox to prevent the
4846
+ [space is eaten issue](https://github.com/ProseMirror/prosemirror/issues/651)
4847
+ @internal
4848
+ */
4849
+ this.requiresGeckoHackNode = false;
4850
+ /**
4813
4851
  When editor content is being dragged, this object contains
4814
4852
  information about the dragged slice and whether it is being
4815
4853
  copied or moved. At any other time, it is null.
@@ -4960,21 +4998,27 @@ class EditorView {
4960
4998
  this.dom.scrollTop = 0;
4961
4999
  }
4962
5000
  else if (scroll == "to selection") {
4963
- let startDOM = this.domSelection().focusNode;
4964
- if (this.someProp("handleScrollToSelection", f => f(this))) ;
4965
- else if (state.selection instanceof NodeSelection) {
4966
- let target = this.docView.domAfterPos(state.selection.from);
4967
- if (target.nodeType == 1)
4968
- scrollRectIntoView(this, target.getBoundingClientRect(), startDOM);
4969
- }
4970
- else {
4971
- scrollRectIntoView(this, this.coordsAtPos(state.selection.head, 1), startDOM);
4972
- }
5001
+ this.scrollToSelection();
4973
5002
  }
4974
5003
  else if (oldScrollPos) {
4975
5004
  resetScrollPos(oldScrollPos);
4976
5005
  }
4977
5006
  }
5007
+ /**
5008
+ @internal
5009
+ */
5010
+ scrollToSelection() {
5011
+ let startDOM = this.domSelection().focusNode;
5012
+ if (this.someProp("handleScrollToSelection", f => f(this))) ;
5013
+ else if (this.state.selection instanceof NodeSelection) {
5014
+ let target = this.docView.domAfterPos(this.state.selection.from);
5015
+ if (target.nodeType == 1)
5016
+ scrollRectIntoView(this, target.getBoundingClientRect(), startDOM);
5017
+ }
5018
+ else {
5019
+ scrollRectIntoView(this, this.coordsAtPos(this.state.selection.head, 1), startDOM);
5020
+ }
5021
+ }
4978
5022
  destroyPluginViews() {
4979
5023
  let view;
4980
5024
  while (view = this.pluginViews.pop())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-view",
3
- "version": "1.27.0",
3
+ "version": "1.27.1",
4
4
  "description": "ProseMirror's view component",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",