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/CHANGELOG.md +34 -0
- package/dist/index.es.js +126 -54
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +126 -54
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/clipboard.js +19 -1
- package/src/input.js +22 -19
- package/src/viewdesc.js +88 -32
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
|
-
|
|
969
|
-
|
|
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 =
|
|
1298
|
-
var
|
|
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
|
-
//
|
|
1311
|
-
|
|
1312
|
-
updater.findNodeMatch(child, outerDeco, innerDeco, i)
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
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 (
|
|
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.
|
|
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
|
|
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
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
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
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
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")).
|
|
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 (
|
|
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 (
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
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 (
|
|
3856
|
-
|
|
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);
|