prosemirror-view 1.23.0 → 1.23.4
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 +28 -0
- package/dist/index.es.js +63 -25
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +63 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/clipboard.js +4 -1
- package/src/input.js +13 -1
- package/src/selection.js +7 -3
- package/src/viewdesc.js +38 -19
package/dist/index.js
CHANGED
|
@@ -1751,7 +1751,7 @@ var ViewTreeUpdater = function ViewTreeUpdater(top, lockedNode) {
|
|
|
1751
1751
|
// Tracks whether anything was changed
|
|
1752
1752
|
this.changed = false;
|
|
1753
1753
|
|
|
1754
|
-
this.preMatch = preMatch(top.node.content, top
|
|
1754
|
+
this.preMatch = preMatch(top.node.content, top);
|
|
1755
1755
|
};
|
|
1756
1756
|
|
|
1757
1757
|
// Destroy and remove the children between the given indices in
|
|
@@ -1812,19 +1812,16 @@ ViewTreeUpdater.prototype.syncToMarks = function syncToMarks (marks, inline, vie
|
|
|
1812
1812
|
// Try to find a node desc matching the given data. Skip over it and
|
|
1813
1813
|
// return true when successful.
|
|
1814
1814
|
ViewTreeUpdater.prototype.findNodeMatch = function findNodeMatch (node, outerDeco, innerDeco, index) {
|
|
1815
|
-
var
|
|
1816
|
-
if (index >= this.preMatch.index
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
break
|
|
1821
|
-
}
|
|
1822
|
-
}
|
|
1815
|
+
var found = -1, targetDesc;
|
|
1816
|
+
if (index >= this.preMatch.index &&
|
|
1817
|
+
(targetDesc = this.preMatch.matches[index - this.preMatch.index]).parent == this.top &&
|
|
1818
|
+
targetDesc.matchesNode(node, outerDeco, innerDeco)) {
|
|
1819
|
+
found = this.top.children.indexOf(targetDesc, this.index);
|
|
1823
1820
|
} else {
|
|
1824
|
-
for (var i
|
|
1825
|
-
var child = children[i
|
|
1821
|
+
for (var i = this.index, e = Math.min(this.top.children.length, i + 5); i < e; i++) {
|
|
1822
|
+
var child = this.top.children[i];
|
|
1826
1823
|
if (child.matchesNode(node, outerDeco, innerDeco) && !this.preMatch.matched.has(child)) {
|
|
1827
|
-
found = i
|
|
1824
|
+
found = i;
|
|
1828
1825
|
break
|
|
1829
1826
|
}
|
|
1830
1827
|
}
|
|
@@ -1933,22 +1930,44 @@ ViewTreeUpdater.prototype.addHackNode = function addHackNode (nodeName) {
|
|
|
1933
1930
|
}
|
|
1934
1931
|
};
|
|
1935
1932
|
|
|
1936
|
-
// : (Fragment, [ViewDesc]) → {index: number, matched: Map<ViewDesc, number
|
|
1933
|
+
// : (Fragment, [ViewDesc]) → {index: number, matched: Map<ViewDesc, number>, matches: ViewDesc[]}
|
|
1937
1934
|
// Iterate from the end of the fragment and array of descs to find
|
|
1938
1935
|
// directly matching ones, in order to avoid overeagerly reusing those
|
|
1939
1936
|
// for other nodes. Returns the fragment index of the first node that
|
|
1940
1937
|
// is part of the sequence of matched nodes at the end of the
|
|
1941
1938
|
// fragment.
|
|
1942
|
-
function preMatch(frag,
|
|
1943
|
-
var
|
|
1944
|
-
|
|
1945
|
-
|
|
1939
|
+
function preMatch(frag, parentDesc) {
|
|
1940
|
+
var curDesc = parentDesc, descI = curDesc.children.length;
|
|
1941
|
+
var fI = frag.childCount, matched = new Map, matches = [];
|
|
1942
|
+
outer: while (fI > 0) {
|
|
1943
|
+
var desc = (void 0);
|
|
1944
|
+
for (;;) {
|
|
1945
|
+
if (descI) {
|
|
1946
|
+
var next = curDesc.children[descI - 1];
|
|
1947
|
+
if (next instanceof MarkViewDesc) {
|
|
1948
|
+
curDesc = next;
|
|
1949
|
+
descI = next.children.length;
|
|
1950
|
+
} else {
|
|
1951
|
+
desc = next;
|
|
1952
|
+
descI--;
|
|
1953
|
+
break
|
|
1954
|
+
}
|
|
1955
|
+
} else if (curDesc == parentDesc) {
|
|
1956
|
+
break outer
|
|
1957
|
+
} else {
|
|
1958
|
+
// FIXME
|
|
1959
|
+
descI = curDesc.parent.children.indexOf(curDesc);
|
|
1960
|
+
curDesc = curDesc.parent;
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
var node = desc.node;
|
|
1946
1964
|
if (!node) { continue }
|
|
1947
1965
|
if (node != frag.child(fI - 1)) { break }
|
|
1948
1966
|
--fI;
|
|
1949
1967
|
matched.set(desc, fI);
|
|
1968
|
+
matches.push(desc);
|
|
1950
1969
|
}
|
|
1951
|
-
return {index: fI, matched: matched}
|
|
1970
|
+
return {index: fI, matched: matched, matches: matches.reverse()}
|
|
1952
1971
|
}
|
|
1953
1972
|
|
|
1954
1973
|
function compareSide(a, b) { return a.type.side - b.type.side }
|
|
@@ -2062,8 +2081,8 @@ function findTextInFragment(frag, text, from, to) {
|
|
|
2062
2081
|
if (!next.isText) { break }
|
|
2063
2082
|
str += next.text;
|
|
2064
2083
|
}
|
|
2065
|
-
if (pos >= from) {
|
|
2066
|
-
var found = str.lastIndexOf(text, to - childStart);
|
|
2084
|
+
if (pos >= from && childStart < to) {
|
|
2085
|
+
var found = str.lastIndexOf(text, to - childStart - 1);
|
|
2067
2086
|
if (found >= 0 && found + text.length + childStart >= from)
|
|
2068
2087
|
{ return childStart + found }
|
|
2069
2088
|
}
|
|
@@ -2134,9 +2153,13 @@ function selectionToDOM(view, force) {
|
|
|
2134
2153
|
if (!editorOwnsSelection(view)) { return }
|
|
2135
2154
|
|
|
2136
2155
|
if (!force && view.mouseDown && view.mouseDown.allowDefault) {
|
|
2137
|
-
view.
|
|
2138
|
-
|
|
2139
|
-
|
|
2156
|
+
var domSel = view.root.getSelection(), curSel = view.domObserver.currentSelection;
|
|
2157
|
+
if (domSel.anchorNode && isEquivalentPosition(domSel.anchorNode, domSel.anchorOffset,
|
|
2158
|
+
curSel.anchorNode, curSel.anchorOffset)) {
|
|
2159
|
+
view.mouseDown.delayedSelectionSync = true;
|
|
2160
|
+
view.domObserver.setCurSelection();
|
|
2161
|
+
return
|
|
2162
|
+
}
|
|
2140
2163
|
}
|
|
2141
2164
|
|
|
2142
2165
|
view.domObserver.disconnectSelection();
|
|
@@ -2983,7 +3006,8 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
2983
3006
|
preserveWhitespace: !!(asText || sliceData),
|
|
2984
3007
|
context: $context,
|
|
2985
3008
|
ruleFromNode: function ruleFromNode(dom) {
|
|
2986
|
-
if (dom.nodeName == "BR" && !dom.nextSibling
|
|
3009
|
+
if (dom.nodeName == "BR" && !dom.nextSibling &&
|
|
3010
|
+
dom.parentNode && !inlineParents.test(dom.parentNode.nodeName)) { return {ignore: true} }
|
|
2987
3011
|
}
|
|
2988
3012
|
});
|
|
2989
3013
|
}
|
|
@@ -3005,6 +3029,8 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
3005
3029
|
return slice
|
|
3006
3030
|
}
|
|
3007
3031
|
|
|
3032
|
+
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;
|
|
3033
|
+
|
|
3008
3034
|
// Takes a slice parsed with parseSlice, which means there hasn't been
|
|
3009
3035
|
// any content-expression checking done on the top nodes, tries to
|
|
3010
3036
|
// find a parent node in the current context that might fit the nodes,
|
|
@@ -3485,9 +3511,14 @@ function dispatchEvent(view, event) {
|
|
|
3485
3511
|
editHandlers.keydown = function (view, event) {
|
|
3486
3512
|
view.shiftKey = event.keyCode == 16 || event.shiftKey;
|
|
3487
3513
|
if (inOrNearComposition(view, event)) { return }
|
|
3488
|
-
if (event.keyCode != 229) { view.domObserver.forceFlush(); }
|
|
3489
3514
|
view.lastKeyCode = event.keyCode;
|
|
3490
3515
|
view.lastKeyCodeTime = Date.now();
|
|
3516
|
+
// Suppress enter key events on Chrome Android, because those tend
|
|
3517
|
+
// to be part of a confused sequence of composition events fired,
|
|
3518
|
+
// and handling them eagerly tends to corrupt the input.
|
|
3519
|
+
if (result.android && result.chrome && event.keyCode == 13) { return }
|
|
3520
|
+
if (event.keyCode != 229) { view.domObserver.forceFlush(); }
|
|
3521
|
+
|
|
3491
3522
|
// On iOS, if we preventDefault enter key presses, the virtual
|
|
3492
3523
|
// keyboard gets confused. So the hack here is to set a flag that
|
|
3493
3524
|
// makes the DOM change code recognize that what just happens should
|
|
@@ -3872,6 +3903,7 @@ function timestampFromCustomEvent() {
|
|
|
3872
3903
|
}
|
|
3873
3904
|
|
|
3874
3905
|
function endComposition(view, forceUpdate) {
|
|
3906
|
+
if (result.android && view.domObserver.flushingSoon >= 0) { return }
|
|
3875
3907
|
view.domObserver.forceFlush();
|
|
3876
3908
|
clearComposition(view);
|
|
3877
3909
|
if (forceUpdate || view.docView.dirty) {
|
|
@@ -3962,6 +3994,11 @@ function doPaste(view, text, html, e) {
|
|
|
3962
3994
|
}
|
|
3963
3995
|
|
|
3964
3996
|
editHandlers.paste = function (view, e) {
|
|
3997
|
+
// Handling paste from JavaScript during composition is very poorly
|
|
3998
|
+
// handled by browsers, so as a dodgy but preferable kludge, we just
|
|
3999
|
+
// let the browser do its native thing there, except on Android,
|
|
4000
|
+
// where the editor is almost always composing.
|
|
4001
|
+
if (view.composing && !result.android) { return }
|
|
3965
4002
|
var data = brokenClipboardAPI ? null : e.clipboardData;
|
|
3966
4003
|
if (data && doPaste(view, data.getData("text/plain"), data.getData("text/html"), e)) { e.preventDefault(); }
|
|
3967
4004
|
else { capturePaste(view, e); }
|
|
@@ -4093,6 +4130,7 @@ handlers.beforeinput = function (view, event) {
|
|
|
4093
4130
|
// Very specific hack to deal with backspace sometimes failing on
|
|
4094
4131
|
// Chrome Android when after an uneditable node.
|
|
4095
4132
|
if (result.chrome && result.android && event.inputType == "deleteContentBackward") {
|
|
4133
|
+
view.domObserver.flushSoon();
|
|
4096
4134
|
var domChangeCount = view.domChangeCount;
|
|
4097
4135
|
setTimeout(function () {
|
|
4098
4136
|
if (view.domChangeCount != domChangeCount) { return } // Event already had some effect
|