prosemirror-view 1.18.7 → 1.18.11

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/dist/index.js CHANGED
@@ -698,7 +698,7 @@ var prototypeAccessors = { beforePosition: { configurable: true },size: { config
698
698
  ViewDesc.prototype.matchesWidget = function matchesWidget () { return false };
699
699
  ViewDesc.prototype.matchesMark = function matchesMark () { return false };
700
700
  ViewDesc.prototype.matchesNode = function matchesNode () { return false };
701
- ViewDesc.prototype.matchesHack = function matchesHack () { return false };
701
+ ViewDesc.prototype.matchesHack = function matchesHack (_nodeName) { return false };
702
702
 
703
703
  prototypeAccessors.beforePosition.get = function () { return false };
704
704
 
@@ -964,9 +964,17 @@ ViewDesc.prototype.setSelection = function setSelection (anchor, head, root, for
964
964
  if (node.nodeType == 3) {
965
965
  brKludge = offset$1 && node.nodeValue[offset$1 - 1] == "\n";
966
966
  // Issue #1128
967
- if (brKludge && offset$1 == node.nodeValue.length &&
968
- node.nextSibling && node.nextSibling.nodeName == "BR")
969
- { anchorDOM = headDOM = {node: node.parentNode, offset: domIndex(node) + 1}; }
967
+ if (brKludge && offset$1 == node.nodeValue.length) {
968
+ for (var scan = node, after = (void 0); scan; scan = scan.parentNode) {
969
+ if (after = scan.nextSibling) {
970
+ if (after.nodeName == "BR")
971
+ { anchorDOM = headDOM = {node: after.parentNode, offset: domIndex(after) + 1}; }
972
+ break
973
+ }
974
+ var desc = scan.pmViewDesc;
975
+ if (desc && desc.node && desc.node.isBlock) { break }
976
+ }
977
+ }
970
978
  } else {
971
979
  var prev = node.childNodes[offset$1 - 1];
972
980
  brKludge = prev && (prev.nodeName == "BR" || prev.contentEditable == "false");
@@ -975,8 +983,8 @@ ViewDesc.prototype.setSelection = function setSelection (anchor, head, root, for
975
983
  // Firefox can act strangely when the selection is in front of an
976
984
  // uneditable node. See #1163 and https://bugzilla.mozilla.org/show_bug.cgi?id=1709536
977
985
  if (result.gecko && domSel.focusNode && domSel.focusNode != headDOM.node && domSel.focusNode.nodeType == 1) {
978
- var after = domSel.focusNode.childNodes[domSel.focusOffset];
979
- if (after && after.contentEditable == "false") { force = true; }
986
+ var after$1 = domSel.focusNode.childNodes[domSel.focusOffset];
987
+ if (after$1 && after$1.contentEditable == "false") { force = true; }
980
988
  }
981
989
 
982
990
  if (!(force || brKludge && result.safari) &&
@@ -1035,7 +1043,7 @@ ViewDesc.prototype.markDirty = function markDirty (from, to) {
1035
1043
  else { child.markDirty(from - startInside, to - startInside); }
1036
1044
  return
1037
1045
  } else {
1038
- child.dirty = NODE_DIRTY;
1046
+ child.dirty = child.dom == child.contentDOM && child.dom.parentNode == this.contentDOM ? CONTENT_DIRTY : NODE_DIRTY;
1039
1047
  }
1040
1048
  }
1041
1049
  offset = end;
@@ -1294,8 +1302,10 @@ var NodeViewDesc = /*@__PURE__*/(function (ViewDesc) {
1294
1302
  var this$1 = this;
1295
1303
 
1296
1304
  var inline = this.node.inlineContent, off = pos;
1297
- var composition = inline && view.composing && this.localCompositionNode(view, pos);
1298
- var updater = new ViewTreeUpdater(this, composition && composition.node);
1305
+ var composition = view.composing && this.localCompositionInfo(view, pos);
1306
+ var localComposition = composition && composition.pos > -1 ? composition : null;
1307
+ var compositionInChild = composition && composition.pos < 0;
1308
+ var updater = new ViewTreeUpdater(this, localComposition && localComposition.node);
1299
1309
  iterDeco(this.node, this.innerDeco, function (widget, i, insideNode) {
1300
1310
  if (widget.spec.marks)
1301
1311
  { updater.syncToMarks(widget.spec.marks, inline, view); }
@@ -1307,13 +1317,15 @@ var NodeViewDesc = /*@__PURE__*/(function (ViewDesc) {
1307
1317
  }, function (child, outerDeco, innerDeco, i) {
1308
1318
  // Make sure the wrapping mark descs match the node's marks.
1309
1319
  updater.syncToMarks(child.marks, inline, view);
1310
- // Either find an existing desc that exactly matches this node,
1311
- // and drop the descs before it.
1312
- updater.findNodeMatch(child, outerDeco, innerDeco, i) ||
1313
- // Or try updating the next desc to reflect this node.
1314
- updater.updateNextNode(child, outerDeco, innerDeco, view, i) ||
1315
- // Or just add it as a new desc.
1320
+ // Try several strategies for drawing this node
1321
+ var compIndex;
1322
+ if (updater.findNodeMatch(child, outerDeco, innerDeco, i)) ; else if (compositionInChild && view.state.selection.from > off &&
1323
+ view.state.selection.to < off + child.nodeSize &&
1324
+ (compIndex = updater.findIndexWithChild(composition.node)) > -1 &&
1325
+ updater.updateNodeAt(child, outerDeco, innerDeco, compIndex, view)) ; else if (updater.updateNextNode(child, outerDeco, innerDeco, view, i)) ; else {
1326
+ // Add it as a new view
1316
1327
  updater.addNode(child, outerDeco, innerDeco, view, off);
1328
+ }
1317
1329
  off += child.nodeSize;
1318
1330
  });
1319
1331
  // Drop all remaining descs after the current position.
@@ -1324,16 +1336,15 @@ var NodeViewDesc = /*@__PURE__*/(function (ViewDesc) {
1324
1336
  // Sync the DOM if anything changed
1325
1337
  if (updater.changed || this.dirty == CONTENT_DIRTY) {
1326
1338
  // May have to protect focused DOM from being changed if a composition is active
1327
- if (composition) { this.protectLocalComposition(view, composition); }
1339
+ if (localComposition) { this.protectLocalComposition(view, localComposition); }
1328
1340
  renderDescs(this.contentDOM, this.children, view);
1329
1341
  if (result.ios) { iosHacks(this.dom); }
1330
1342
  }
1331
1343
  };
1332
1344
 
1333
- NodeViewDesc.prototype.localCompositionNode = function localCompositionNode (view, pos) {
1345
+ NodeViewDesc.prototype.localCompositionInfo = function localCompositionInfo (view, pos) {
1334
1346
  // Only do something if both the selection and a focused text node
1335
- // are inside of this node, and the node isn't already part of a
1336
- // view that's a child of this view
1347
+ // are inside of this node
1337
1348
  var ref = view.state.selection;
1338
1349
  var from = ref.from;
1339
1350
  var to = ref.to;
@@ -1342,13 +1353,16 @@ var NodeViewDesc = /*@__PURE__*/(function (ViewDesc) {
1342
1353
  var textNode = nearbyTextNode(sel.focusNode, sel.focusOffset);
1343
1354
  if (!textNode || !this.dom.contains(textNode.parentNode)) { return }
1344
1355
 
1345
- // Find the text in the focused node in the node, stop if it's not
1346
- // there (may have been modified through other means, in which
1347
- // case it should overwritten)
1348
- var text = textNode.nodeValue;
1349
- var textPos = findTextInFragment(this.node.content, text, from - pos, to - pos);
1350
-
1351
- return textPos < 0 ? null : {node: textNode, pos: textPos, text: text}
1356
+ if (this.node.inlineContent) {
1357
+ // Find the text in the focused node in the node, stop if it's not
1358
+ // there (may have been modified through other means, in which
1359
+ // case it should overwritten)
1360
+ var text = textNode.nodeValue;
1361
+ var textPos = findTextInFragment(this.node.content, text, from - pos, to - pos);
1362
+ return textPos < 0 ? null : {node: textNode, pos: textPos, text: text}
1363
+ } else {
1364
+ return {node: textNode, pos: -1}
1365
+ }
1352
1366
  };
1353
1367
 
1354
1368
  NodeViewDesc.prototype.protectLocalComposition = function protectLocalComposition (view, ref) {
@@ -1486,6 +1500,12 @@ var TextViewDesc = /*@__PURE__*/(function (NodeViewDesc) {
1486
1500
  return new TextViewDesc(this.parent, node, this.outerDeco, this.innerDeco, dom, dom, view)
1487
1501
  };
1488
1502
 
1503
+ TextViewDesc.prototype.markDirty = function markDirty (from, to) {
1504
+ NodeViewDesc.prototype.markDirty.call(this, from, to);
1505
+ if (this.dom != this.nodeDOM && (from == 0 || to == this.nodeDOM.nodeValue.length))
1506
+ { this.dirty = NODE_DIRTY; }
1507
+ };
1508
+
1489
1509
  prototypeAccessors$4.domAtom.get = function () { return false };
1490
1510
 
1491
1511
  Object.defineProperties( TextViewDesc.prototype, prototypeAccessors$4 );
@@ -1507,7 +1527,7 @@ var TrailingHackViewDesc = /*@__PURE__*/(function (ViewDesc) {
1507
1527
  var prototypeAccessors$5 = { domAtom: { configurable: true } };
1508
1528
 
1509
1529
  TrailingHackViewDesc.prototype.parseRule = function parseRule () { return {ignore: true} };
1510
- TrailingHackViewDesc.prototype.matchesHack = function matchesHack () { return this.dirty == NOT_DIRTY };
1530
+ TrailingHackViewDesc.prototype.matchesHack = function matchesHack (nodeName) { return this.dirty == NOT_DIRTY && this.dom.nodeName == nodeName };
1511
1531
  prototypeAccessors$5.domAtom.get = function () { return true };
1512
1532
 
1513
1533
  Object.defineProperties( TrailingHackViewDesc.prototype, prototypeAccessors$5 );
@@ -1795,6 +1815,29 @@ ViewTreeUpdater.prototype.findNodeMatch = function findNodeMatch (node, outerDec
1795
1815
  return true
1796
1816
  };
1797
1817
 
1818
+ ViewTreeUpdater.prototype.updateNodeAt = function updateNodeAt (node, outerDeco, innerDeco, index, view) {
1819
+ var child = this.top.children[index];
1820
+ if (!child.update(node, outerDeco, innerDeco, view)) { return false }
1821
+ this.destroyBetween(this.index, index);
1822
+ this.index = index + 1;
1823
+ return true
1824
+ };
1825
+
1826
+ ViewTreeUpdater.prototype.findIndexWithChild = function findIndexWithChild (domNode) {
1827
+ for (;;) {
1828
+ var parent = domNode.parentNode;
1829
+ if (!parent) { return -1 }
1830
+ if (parent == this.top.contentDOM) {
1831
+ var desc = domNode.pmViewDesc;
1832
+ if (desc) { for (var i = this.index; i < this.top.children.length; i++) {
1833
+ if (this.top.children[i] == desc) { return i }
1834
+ } }
1835
+ return -1
1836
+ }
1837
+ domNode = parent;
1838
+ }
1839
+ };
1840
+
1798
1841
  // : (Node, [Decoration], DecorationSource, EditorView, Fragment, number) → bool
1799
1842
  // Try to update the next node, if any, to the given data. Checks
1800
1843
  // pre-matches to avoid overwriting nodes that could still be used.
@@ -1851,13 +1894,20 @@ ViewTreeUpdater.prototype.addTextblockHacks = function addTextblockHacks () {
1851
1894
  if (!lastChild || // Empty textblock
1852
1895
  !(lastChild instanceof TextViewDesc) ||
1853
1896
  /\n$/.test(lastChild.node.text)) {
1854
- if (this.index < this.top.children.length && this.top.children[this.index].matchesHack()) {
1855
- this.index++;
1856
- } else {
1857
- var dom = document.createElement("br");
1858
- this.top.children.splice(this.index++, 0, new TrailingHackViewDesc(this.top, nothing, dom, null));
1859
- this.changed = true;
1860
- }
1897
+ // Avoid a bug in Safari's cursor drawing (#1165)
1898
+ if (result.safari && lastChild && lastChild.dom.contentEditable == "false")
1899
+ { this.addHackNode("IMG"); }
1900
+ this.addHackNode("BR");
1901
+ }
1902
+ };
1903
+
1904
+ ViewTreeUpdater.prototype.addHackNode = function addHackNode (nodeName) {
1905
+ if (this.index < this.top.children.length && this.top.children[this.index].matchesHack(nodeName)) {
1906
+ this.index++;
1907
+ } else {
1908
+ var dom = document.createElement(nodeName);
1909
+ this.top.children.splice(this.index++, 0, new TrailingHackViewDesc(this.top, nothing, dom, null));
1910
+ this.changed = true;
1861
1911
  }
1862
1912
  };
1863
1913
 
@@ -2877,14 +2927,19 @@ function parseFromClipboard(view, text, html, plainText, $context) {
2877
2927
  if (parsed) {
2878
2928
  slice = parsed;
2879
2929
  } else {
2930
+ var marks = $context.marks();
2931
+ var ref = view.state;
2932
+ var schema = ref.schema;
2933
+ var serializer = prosemirrorModel.DOMSerializer.fromSchema(schema);
2880
2934
  dom = document.createElement("div");
2881
2935
  text.trim().split(/(?:\r\n?|\n)+/).forEach(function (block) {
2882
- dom.appendChild(document.createElement("p")).textContent = block;
2936
+ dom.appendChild(document.createElement("p")).appendChild(serializer.serializeNode(schema.text(block, marks)));
2883
2937
  });
2884
2938
  }
2885
2939
  } else {
2886
2940
  view.someProp("transformPastedHTML", function (f) { html = f(html); });
2887
2941
  dom = readHTML(html);
2942
+ if (result.webkit) { restoreReplacedSpaces(dom); }
2888
2943
  }
2889
2944
 
2890
2945
  var contextNode = dom && dom.querySelector("[data-pm-slice]");
@@ -3017,6 +3072,20 @@ function readHTML(html) {
3017
3072
  return elt
3018
3073
  }
3019
3074
 
3075
+ // Webkit browsers do some hard-to-predict replacement of regular
3076
+ // spaces with non-breaking spaces when putting content on the
3077
+ // clipboard. This tries to convert such non-breaking spaces (which
3078
+ // will be wrapped in a plain span on Chrome, a span with class
3079
+ // Apple-converted-space on Safari) back to regular spaces.
3080
+ function restoreReplacedSpaces(dom) {
3081
+ var nodes = dom.querySelectorAll(result.chrome ? "span:not([class]):not([style])" : "span.Apple-converted-space");
3082
+ for (var i = 0; i < nodes.length; i++) {
3083
+ var node = nodes[i];
3084
+ if (node.childNodes.length == 1 && node.textContent == "\u00a0" && node.parentNode)
3085
+ { node.parentNode.replaceChild(dom.ownerDocument.createTextNode(" "), node); }
3086
+ }
3087
+ }
3088
+
3020
3089
  function addContext(slice, context) {
3021
3090
  if (!slice.size) { return slice }
3022
3091
  var schema = slice.content.firstChild.type.schema, array;
@@ -3368,7 +3437,7 @@ function dispatchEvent(view, event) {
3368
3437
  editHandlers.keydown = function (view, event) {
3369
3438
  view.shiftKey = event.keyCode == 16 || event.shiftKey;
3370
3439
  if (inOrNearComposition(view, event)) { return }
3371
- view.domObserver.forceFlush();
3440
+ if (event.keyCode != 229) { view.domObserver.forceFlush(); }
3372
3441
  view.lastKeyCode = event.keyCode;
3373
3442
  view.lastKeyCodeTime = Date.now();
3374
3443
  // On iOS, if we preventDefault enter key presses, the virtual
@@ -3494,10 +3563,11 @@ function handleDoubleClick(view, pos, inside, event) {
3494
3563
  function handleTripleClick(view, pos, inside, event) {
3495
3564
  return runHandlerOnContext(view, "handleTripleClickOn", pos, inside, event) ||
3496
3565
  view.someProp("handleTripleClick", function (f) { return f(view, pos, event); }) ||
3497
- defaultTripleClick(view, inside)
3566
+ defaultTripleClick(view, inside, event)
3498
3567
  }
3499
3568
 
3500
- function defaultTripleClick(view, inside) {
3569
+ function defaultTripleClick(view, inside, event) {
3570
+ if (event.button != 0) { return false }
3501
3571
  var doc = view.state.doc;
3502
3572
  if (inside == -1) {
3503
3573
  if (doc.inlineContent) {
@@ -3579,7 +3649,8 @@ var MouseDown = function MouseDown(view, pos, event, flushed) {
3579
3649
 
3580
3650
  var ref = view.state;
3581
3651
  var selection = ref.selection;
3582
- if (targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
3652
+ if (event.button == 0 &&
3653
+ targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
3583
3654
  selection instanceof prosemirrorState.NodeSelection && selection.from <= targetPos && selection.to > targetPos)
3584
3655
  { this.mightDrag = {node: targetNode,
3585
3656
  pos: targetPos,
@@ -3626,19 +3697,20 @@ MouseDown.prototype.up = function up (event) {
3626
3697
  setSelectionOrigin(this.view, "pointer");
3627
3698
  } else if (handleSingleClick(this.view, pos.pos, pos.inside, event, this.selectNode)) {
3628
3699
  event.preventDefault();
3629
- } else if (this.flushed ||
3630
- // Safari ignores clicks on draggable elements
3631
- (result.safari && this.mightDrag && !this.mightDrag.node.isAtom) ||
3632
- // Chrome will sometimes treat a node selection as a
3633
- // cursor, but still report that the node is selected
3634
- // when asked through getSelection. You'll then get a
3635
- // situation where clicking at the point where that
3636
- // (hidden) cursor is doesn't change the selection, and
3637
- // thus doesn't get a reaction from ProseMirror. This
3638
- // works around that.
3639
- (result.chrome && !(this.view.state.selection instanceof prosemirrorState.TextSelection) &&
3640
- Math.min(Math.abs(pos.pos - this.view.state.selection.from),
3641
- Math.abs(pos.pos - this.view.state.selection.to)) <= 2)) {
3700
+ } else if (event.button == 0 &&
3701
+ (this.flushed ||
3702
+ // Safari ignores clicks on draggable elements
3703
+ (result.safari && this.mightDrag && !this.mightDrag.node.isAtom) ||
3704
+ // Chrome will sometimes treat a node selection as a
3705
+ // cursor, but still report that the node is selected
3706
+ // when asked through getSelection. You'll then get a
3707
+ // situation where clicking at the point where that
3708
+ // (hidden) cursor is doesn't change the selection, and
3709
+ // thus doesn't get a reaction from ProseMirror. This
3710
+ // works around that.
3711
+ (result.chrome && !(this.view.state.selection instanceof prosemirrorState.TextSelection) &&
3712
+ Math.min(Math.abs(pos.pos - this.view.state.selection.from),
3713
+ Math.abs(pos.pos - this.view.state.selection.to)) <= 2))) {
3642
3714
  updateSelection(this.view, prosemirrorState.Selection.near(this.view.state.doc.resolve(pos.pos)), "pointer");
3643
3715
  event.preventDefault();
3644
3716
  } else {
@@ -3852,8 +3924,8 @@ handlers.dragstart = function (view, e) {
3852
3924
  view.dispatch(view.state.tr.setSelection(prosemirrorState.NodeSelection.create(view.state.doc, mouseDown.mightDrag.pos)));
3853
3925
  } else if (e.target && e.target.nodeType == 1) {
3854
3926
  var desc = view.docView.nearestDesc(e.target, true);
3855
- if (!desc || !desc.node.type.spec.draggable || desc == view.docView) { return }
3856
- view.dispatch(view.state.tr.setSelection(prosemirrorState.NodeSelection.create(view.state.doc, desc.posBefore)));
3927
+ if (desc && desc.node.type.spec.draggable && desc != view.docView)
3928
+ { view.dispatch(view.state.tr.setSelection(prosemirrorState.NodeSelection.create(view.state.doc, desc.posBefore))); }
3857
3929
  }
3858
3930
  var slice = view.state.selection.content();
3859
3931
  var ref = serializeForClipboard(view, slice);