prosemirror-view 1.18.10 → 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 +10 -0
- package/dist/index.es.js +69 -21
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +69 -21
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/clipboard.js +19 -1
- package/src/viewdesc.js +55 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## 1.18.11 (2021-07-22)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Work around an issue where Chrome and Safari will replace some spaces with non-breaking spaces when putting HTML on the clipboard.
|
|
6
|
+
|
|
7
|
+
When pasting as plain text (shift-mod-v) apply the marks at the selection to the inserted content.
|
|
8
|
+
|
|
9
|
+
Fix flaky behavior when starting a composition with a selection that spans multiple blocks.
|
|
10
|
+
|
|
1
11
|
## 1.18.10 (2021-07-15)
|
|
2
12
|
|
|
3
13
|
### Bug fixes
|
package/dist/index.es.js
CHANGED
|
@@ -1039,7 +1039,7 @@ ViewDesc.prototype.markDirty = function markDirty (from, to) {
|
|
|
1039
1039
|
else { child.markDirty(from - startInside, to - startInside); }
|
|
1040
1040
|
return
|
|
1041
1041
|
} else {
|
|
1042
|
-
child.dirty = NODE_DIRTY;
|
|
1042
|
+
child.dirty = child.dom == child.contentDOM && child.dom.parentNode == this.contentDOM ? CONTENT_DIRTY : NODE_DIRTY;
|
|
1043
1043
|
}
|
|
1044
1044
|
}
|
|
1045
1045
|
offset = end;
|
|
@@ -1298,8 +1298,10 @@ var NodeViewDesc = /*@__PURE__*/(function (ViewDesc) {
|
|
|
1298
1298
|
var this$1 = this;
|
|
1299
1299
|
|
|
1300
1300
|
var inline = this.node.inlineContent, off = pos;
|
|
1301
|
-
var composition =
|
|
1302
|
-
var
|
|
1301
|
+
var composition = view.composing && this.localCompositionInfo(view, pos);
|
|
1302
|
+
var localComposition = composition && composition.pos > -1 ? composition : null;
|
|
1303
|
+
var compositionInChild = composition && composition.pos < 0;
|
|
1304
|
+
var updater = new ViewTreeUpdater(this, localComposition && localComposition.node);
|
|
1303
1305
|
iterDeco(this.node, this.innerDeco, function (widget, i, insideNode) {
|
|
1304
1306
|
if (widget.spec.marks)
|
|
1305
1307
|
{ updater.syncToMarks(widget.spec.marks, inline, view); }
|
|
@@ -1311,13 +1313,15 @@ var NodeViewDesc = /*@__PURE__*/(function (ViewDesc) {
|
|
|
1311
1313
|
}, function (child, outerDeco, innerDeco, i) {
|
|
1312
1314
|
// Make sure the wrapping mark descs match the node's marks.
|
|
1313
1315
|
updater.syncToMarks(child.marks, inline, view);
|
|
1314
|
-
//
|
|
1315
|
-
|
|
1316
|
-
updater.findNodeMatch(child, outerDeco, innerDeco, i)
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1316
|
+
// Try several strategies for drawing this node
|
|
1317
|
+
var compIndex;
|
|
1318
|
+
if (updater.findNodeMatch(child, outerDeco, innerDeco, i)) ; else if (compositionInChild && view.state.selection.from > off &&
|
|
1319
|
+
view.state.selection.to < off + child.nodeSize &&
|
|
1320
|
+
(compIndex = updater.findIndexWithChild(composition.node)) > -1 &&
|
|
1321
|
+
updater.updateNodeAt(child, outerDeco, innerDeco, compIndex, view)) ; else if (updater.updateNextNode(child, outerDeco, innerDeco, view, i)) ; else {
|
|
1322
|
+
// Add it as a new view
|
|
1320
1323
|
updater.addNode(child, outerDeco, innerDeco, view, off);
|
|
1324
|
+
}
|
|
1321
1325
|
off += child.nodeSize;
|
|
1322
1326
|
});
|
|
1323
1327
|
// Drop all remaining descs after the current position.
|
|
@@ -1328,16 +1332,15 @@ var NodeViewDesc = /*@__PURE__*/(function (ViewDesc) {
|
|
|
1328
1332
|
// Sync the DOM if anything changed
|
|
1329
1333
|
if (updater.changed || this.dirty == CONTENT_DIRTY) {
|
|
1330
1334
|
// May have to protect focused DOM from being changed if a composition is active
|
|
1331
|
-
if (
|
|
1335
|
+
if (localComposition) { this.protectLocalComposition(view, localComposition); }
|
|
1332
1336
|
renderDescs(this.contentDOM, this.children, view);
|
|
1333
1337
|
if (result.ios) { iosHacks(this.dom); }
|
|
1334
1338
|
}
|
|
1335
1339
|
};
|
|
1336
1340
|
|
|
1337
|
-
NodeViewDesc.prototype.
|
|
1341
|
+
NodeViewDesc.prototype.localCompositionInfo = function localCompositionInfo (view, pos) {
|
|
1338
1342
|
// Only do something if both the selection and a focused text node
|
|
1339
|
-
// are inside of this node
|
|
1340
|
-
// view that's a child of this view
|
|
1343
|
+
// are inside of this node
|
|
1341
1344
|
var ref = view.state.selection;
|
|
1342
1345
|
var from = ref.from;
|
|
1343
1346
|
var to = ref.to;
|
|
@@ -1346,13 +1349,16 @@ var NodeViewDesc = /*@__PURE__*/(function (ViewDesc) {
|
|
|
1346
1349
|
var textNode = nearbyTextNode(sel.focusNode, sel.focusOffset);
|
|
1347
1350
|
if (!textNode || !this.dom.contains(textNode.parentNode)) { return }
|
|
1348
1351
|
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1352
|
+
if (this.node.inlineContent) {
|
|
1353
|
+
// Find the text in the focused node in the node, stop if it's not
|
|
1354
|
+
// there (may have been modified through other means, in which
|
|
1355
|
+
// case it should overwritten)
|
|
1356
|
+
var text = textNode.nodeValue;
|
|
1357
|
+
var textPos = findTextInFragment(this.node.content, text, from - pos, to - pos);
|
|
1358
|
+
return textPos < 0 ? null : {node: textNode, pos: textPos, text: text}
|
|
1359
|
+
} else {
|
|
1360
|
+
return {node: textNode, pos: -1}
|
|
1361
|
+
}
|
|
1356
1362
|
};
|
|
1357
1363
|
|
|
1358
1364
|
NodeViewDesc.prototype.protectLocalComposition = function protectLocalComposition (view, ref) {
|
|
@@ -1805,6 +1811,29 @@ ViewTreeUpdater.prototype.findNodeMatch = function findNodeMatch (node, outerDec
|
|
|
1805
1811
|
return true
|
|
1806
1812
|
};
|
|
1807
1813
|
|
|
1814
|
+
ViewTreeUpdater.prototype.updateNodeAt = function updateNodeAt (node, outerDeco, innerDeco, index, view) {
|
|
1815
|
+
var child = this.top.children[index];
|
|
1816
|
+
if (!child.update(node, outerDeco, innerDeco, view)) { return false }
|
|
1817
|
+
this.destroyBetween(this.index, index);
|
|
1818
|
+
this.index = index + 1;
|
|
1819
|
+
return true
|
|
1820
|
+
};
|
|
1821
|
+
|
|
1822
|
+
ViewTreeUpdater.prototype.findIndexWithChild = function findIndexWithChild (domNode) {
|
|
1823
|
+
for (;;) {
|
|
1824
|
+
var parent = domNode.parentNode;
|
|
1825
|
+
if (!parent) { return -1 }
|
|
1826
|
+
if (parent == this.top.contentDOM) {
|
|
1827
|
+
var desc = domNode.pmViewDesc;
|
|
1828
|
+
if (desc) { for (var i = this.index; i < this.top.children.length; i++) {
|
|
1829
|
+
if (this.top.children[i] == desc) { return i }
|
|
1830
|
+
} }
|
|
1831
|
+
return -1
|
|
1832
|
+
}
|
|
1833
|
+
domNode = parent;
|
|
1834
|
+
}
|
|
1835
|
+
};
|
|
1836
|
+
|
|
1808
1837
|
// : (Node, [Decoration], DecorationSource, EditorView, Fragment, number) → bool
|
|
1809
1838
|
// Try to update the next node, if any, to the given data. Checks
|
|
1810
1839
|
// pre-matches to avoid overwriting nodes that could still be used.
|
|
@@ -2894,14 +2923,19 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
2894
2923
|
if (parsed) {
|
|
2895
2924
|
slice = parsed;
|
|
2896
2925
|
} else {
|
|
2926
|
+
var marks = $context.marks();
|
|
2927
|
+
var ref = view.state;
|
|
2928
|
+
var schema = ref.schema;
|
|
2929
|
+
var serializer = DOMSerializer.fromSchema(schema);
|
|
2897
2930
|
dom = document.createElement("div");
|
|
2898
2931
|
text.trim().split(/(?:\r\n?|\n)+/).forEach(function (block) {
|
|
2899
|
-
dom.appendChild(document.createElement("p")).
|
|
2932
|
+
dom.appendChild(document.createElement("p")).appendChild(serializer.serializeNode(schema.text(block, marks)));
|
|
2900
2933
|
});
|
|
2901
2934
|
}
|
|
2902
2935
|
} else {
|
|
2903
2936
|
view.someProp("transformPastedHTML", function (f) { html = f(html); });
|
|
2904
2937
|
dom = readHTML(html);
|
|
2938
|
+
if (result.webkit) { restoreReplacedSpaces(dom); }
|
|
2905
2939
|
}
|
|
2906
2940
|
|
|
2907
2941
|
var contextNode = dom && dom.querySelector("[data-pm-slice]");
|
|
@@ -3034,6 +3068,20 @@ function readHTML(html) {
|
|
|
3034
3068
|
return elt
|
|
3035
3069
|
}
|
|
3036
3070
|
|
|
3071
|
+
// Webkit browsers do some hard-to-predict replacement of regular
|
|
3072
|
+
// spaces with non-breaking spaces when putting content on the
|
|
3073
|
+
// clipboard. This tries to convert such non-breaking spaces (which
|
|
3074
|
+
// will be wrapped in a plain span on Chrome, a span with class
|
|
3075
|
+
// Apple-converted-space on Safari) back to regular spaces.
|
|
3076
|
+
function restoreReplacedSpaces(dom) {
|
|
3077
|
+
var nodes = dom.querySelectorAll(result.chrome ? "span:not([class]):not([style])" : "span.Apple-converted-space");
|
|
3078
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
3079
|
+
var node = nodes[i];
|
|
3080
|
+
if (node.childNodes.length == 1 && node.textContent == "\u00a0" && node.parentNode)
|
|
3081
|
+
{ node.parentNode.replaceChild(dom.ownerDocument.createTextNode(" "), node); }
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
|
|
3037
3085
|
function addContext(slice, context) {
|
|
3038
3086
|
if (!slice.size) { return slice }
|
|
3039
3087
|
var schema = slice.content.firstChild.type.schema, array;
|