prosemirror-view 1.23.1 → 1.23.5
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 +65 -27
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +65 -27
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/clipboard.js +4 -1
- package/src/domchange.js +1 -1
- package/src/input.js +13 -1
- package/src/selection.js +7 -3
- package/src/viewdesc.js +39 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## 1.23.5 (2021-12-27)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Use the `whitespace` node prop where appropriate.
|
|
6
|
+
|
|
7
|
+
## 1.23.4 (2021-12-22)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Improve the way the editor handles the mess of events produced when pressing Enter before a word that was just typed on Chrome + GBoard.
|
|
12
|
+
|
|
13
|
+
Fix an issue where compositions right before another instance of the composed text could cause the editor to crash.
|
|
14
|
+
|
|
15
|
+
Fix an issue where, if decorations changed during a pointer drag selection, the selection anchor might move around inappropriately.
|
|
16
|
+
|
|
17
|
+
## 1.23.3 (2021-11-26)
|
|
18
|
+
|
|
19
|
+
### Bug fixes
|
|
20
|
+
|
|
21
|
+
The clipboard parser will no longer drop trailing `<br>` nodes that appear in an inline parent element.
|
|
22
|
+
|
|
23
|
+
## 1.23.2 (2021-11-19)
|
|
24
|
+
|
|
25
|
+
### Bug fixes
|
|
26
|
+
|
|
27
|
+
Avoid some unnecessary node redraws when marks are present in sibling nodes.
|
|
28
|
+
|
|
1
29
|
## 1.23.1 (2021-11-15)
|
|
2
30
|
|
|
3
31
|
### Bug fixes
|
package/dist/index.es.js
CHANGED
|
@@ -1290,7 +1290,7 @@ var NodeViewDesc = /*@__PURE__*/(function (ViewDesc) {
|
|
|
1290
1290
|
// attrs in the dom, that won't be picked up. Not entirely sure
|
|
1291
1291
|
// whether this is a problem
|
|
1292
1292
|
var rule = {node: this.node.type.name, attrs: this.node.attrs};
|
|
1293
|
-
if (this.node.type.
|
|
1293
|
+
if (this.node.type.whitespace == "pre") { rule.preserveWhitespace = "full"; }
|
|
1294
1294
|
if (this.contentDOM && !this.contentLost) { rule.contentElement = this.contentDOM; }
|
|
1295
1295
|
else { rule.getContent = function () { return this$1.contentDOM ? Fragment.empty : this$1.node.content; }; }
|
|
1296
1296
|
return rule
|
|
@@ -1747,7 +1747,7 @@ var ViewTreeUpdater = function ViewTreeUpdater(top, lockedNode) {
|
|
|
1747
1747
|
// Tracks whether anything was changed
|
|
1748
1748
|
this.changed = false;
|
|
1749
1749
|
|
|
1750
|
-
this.preMatch = preMatch(top.node.content, top
|
|
1750
|
+
this.preMatch = preMatch(top.node.content, top);
|
|
1751
1751
|
};
|
|
1752
1752
|
|
|
1753
1753
|
// Destroy and remove the children between the given indices in
|
|
@@ -1808,19 +1808,16 @@ ViewTreeUpdater.prototype.syncToMarks = function syncToMarks (marks, inline, vie
|
|
|
1808
1808
|
// Try to find a node desc matching the given data. Skip over it and
|
|
1809
1809
|
// return true when successful.
|
|
1810
1810
|
ViewTreeUpdater.prototype.findNodeMatch = function findNodeMatch (node, outerDeco, innerDeco, index) {
|
|
1811
|
-
var
|
|
1812
|
-
if (index >= this.preMatch.index
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
break
|
|
1817
|
-
}
|
|
1818
|
-
}
|
|
1811
|
+
var found = -1, targetDesc;
|
|
1812
|
+
if (index >= this.preMatch.index &&
|
|
1813
|
+
(targetDesc = this.preMatch.matches[index - this.preMatch.index]).parent == this.top &&
|
|
1814
|
+
targetDesc.matchesNode(node, outerDeco, innerDeco)) {
|
|
1815
|
+
found = this.top.children.indexOf(targetDesc, this.index);
|
|
1819
1816
|
} else {
|
|
1820
|
-
for (var i
|
|
1821
|
-
var child = children[i
|
|
1817
|
+
for (var i = this.index, e = Math.min(this.top.children.length, i + 5); i < e; i++) {
|
|
1818
|
+
var child = this.top.children[i];
|
|
1822
1819
|
if (child.matchesNode(node, outerDeco, innerDeco) && !this.preMatch.matched.has(child)) {
|
|
1823
|
-
found = i
|
|
1820
|
+
found = i;
|
|
1824
1821
|
break
|
|
1825
1822
|
}
|
|
1826
1823
|
}
|
|
@@ -1929,22 +1926,44 @@ ViewTreeUpdater.prototype.addHackNode = function addHackNode (nodeName) {
|
|
|
1929
1926
|
}
|
|
1930
1927
|
};
|
|
1931
1928
|
|
|
1932
|
-
// : (Fragment, [ViewDesc]) → {index: number, matched: Map<ViewDesc, number
|
|
1929
|
+
// : (Fragment, [ViewDesc]) → {index: number, matched: Map<ViewDesc, number>, matches: ViewDesc[]}
|
|
1933
1930
|
// Iterate from the end of the fragment and array of descs to find
|
|
1934
1931
|
// directly matching ones, in order to avoid overeagerly reusing those
|
|
1935
1932
|
// for other nodes. Returns the fragment index of the first node that
|
|
1936
1933
|
// is part of the sequence of matched nodes at the end of the
|
|
1937
1934
|
// fragment.
|
|
1938
|
-
function preMatch(frag,
|
|
1939
|
-
var
|
|
1940
|
-
|
|
1941
|
-
|
|
1935
|
+
function preMatch(frag, parentDesc) {
|
|
1936
|
+
var curDesc = parentDesc, descI = curDesc.children.length;
|
|
1937
|
+
var fI = frag.childCount, matched = new Map, matches = [];
|
|
1938
|
+
outer: while (fI > 0) {
|
|
1939
|
+
var desc = (void 0);
|
|
1940
|
+
for (;;) {
|
|
1941
|
+
if (descI) {
|
|
1942
|
+
var next = curDesc.children[descI - 1];
|
|
1943
|
+
if (next instanceof MarkViewDesc) {
|
|
1944
|
+
curDesc = next;
|
|
1945
|
+
descI = next.children.length;
|
|
1946
|
+
} else {
|
|
1947
|
+
desc = next;
|
|
1948
|
+
descI--;
|
|
1949
|
+
break
|
|
1950
|
+
}
|
|
1951
|
+
} else if (curDesc == parentDesc) {
|
|
1952
|
+
break outer
|
|
1953
|
+
} else {
|
|
1954
|
+
// FIXME
|
|
1955
|
+
descI = curDesc.parent.children.indexOf(curDesc);
|
|
1956
|
+
curDesc = curDesc.parent;
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
var node = desc.node;
|
|
1942
1960
|
if (!node) { continue }
|
|
1943
1961
|
if (node != frag.child(fI - 1)) { break }
|
|
1944
1962
|
--fI;
|
|
1945
1963
|
matched.set(desc, fI);
|
|
1964
|
+
matches.push(desc);
|
|
1946
1965
|
}
|
|
1947
|
-
return {index: fI, matched: matched}
|
|
1966
|
+
return {index: fI, matched: matched, matches: matches.reverse()}
|
|
1948
1967
|
}
|
|
1949
1968
|
|
|
1950
1969
|
function compareSide(a, b) { return a.type.side - b.type.side }
|
|
@@ -2058,8 +2077,8 @@ function findTextInFragment(frag, text, from, to) {
|
|
|
2058
2077
|
if (!next.isText) { break }
|
|
2059
2078
|
str += next.text;
|
|
2060
2079
|
}
|
|
2061
|
-
if (pos >= from) {
|
|
2062
|
-
var found = str.lastIndexOf(text, to - childStart);
|
|
2080
|
+
if (pos >= from && childStart < to) {
|
|
2081
|
+
var found = str.lastIndexOf(text, to - childStart - 1);
|
|
2063
2082
|
if (found >= 0 && found + text.length + childStart >= from)
|
|
2064
2083
|
{ return childStart + found }
|
|
2065
2084
|
}
|
|
@@ -2130,9 +2149,13 @@ function selectionToDOM(view, force) {
|
|
|
2130
2149
|
if (!editorOwnsSelection(view)) { return }
|
|
2131
2150
|
|
|
2132
2151
|
if (!force && view.mouseDown && view.mouseDown.allowDefault) {
|
|
2133
|
-
view.
|
|
2134
|
-
|
|
2135
|
-
|
|
2152
|
+
var domSel = view.root.getSelection(), curSel = view.domObserver.currentSelection;
|
|
2153
|
+
if (domSel.anchorNode && isEquivalentPosition(domSel.anchorNode, domSel.anchorOffset,
|
|
2154
|
+
curSel.anchorNode, curSel.anchorOffset)) {
|
|
2155
|
+
view.mouseDown.delayedSelectionSync = true;
|
|
2156
|
+
view.domObserver.setCurSelection();
|
|
2157
|
+
return
|
|
2158
|
+
}
|
|
2136
2159
|
}
|
|
2137
2160
|
|
|
2138
2161
|
view.domObserver.disconnectSelection();
|
|
@@ -2597,7 +2620,7 @@ function parseBetween(view, from_, to_) {
|
|
|
2597
2620
|
topOpen: true,
|
|
2598
2621
|
from: fromOffset,
|
|
2599
2622
|
to: toOffset,
|
|
2600
|
-
preserveWhitespace: $from.parent.type.
|
|
2623
|
+
preserveWhitespace: $from.parent.type.whitespace == "pre" ? "full" : true,
|
|
2601
2624
|
editableContent: true,
|
|
2602
2625
|
findPositions: find,
|
|
2603
2626
|
ruleFromNode: ruleFromNode,
|
|
@@ -2979,7 +3002,8 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
2979
3002
|
preserveWhitespace: !!(asText || sliceData),
|
|
2980
3003
|
context: $context,
|
|
2981
3004
|
ruleFromNode: function ruleFromNode(dom) {
|
|
2982
|
-
if (dom.nodeName == "BR" && !dom.nextSibling
|
|
3005
|
+
if (dom.nodeName == "BR" && !dom.nextSibling &&
|
|
3006
|
+
dom.parentNode && !inlineParents.test(dom.parentNode.nodeName)) { return {ignore: true} }
|
|
2983
3007
|
}
|
|
2984
3008
|
});
|
|
2985
3009
|
}
|
|
@@ -3001,6 +3025,8 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
3001
3025
|
return slice
|
|
3002
3026
|
}
|
|
3003
3027
|
|
|
3028
|
+
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;
|
|
3029
|
+
|
|
3004
3030
|
// Takes a slice parsed with parseSlice, which means there hasn't been
|
|
3005
3031
|
// any content-expression checking done on the top nodes, tries to
|
|
3006
3032
|
// find a parent node in the current context that might fit the nodes,
|
|
@@ -3481,9 +3507,14 @@ function dispatchEvent(view, event) {
|
|
|
3481
3507
|
editHandlers.keydown = function (view, event) {
|
|
3482
3508
|
view.shiftKey = event.keyCode == 16 || event.shiftKey;
|
|
3483
3509
|
if (inOrNearComposition(view, event)) { return }
|
|
3484
|
-
if (event.keyCode != 229) { view.domObserver.forceFlush(); }
|
|
3485
3510
|
view.lastKeyCode = event.keyCode;
|
|
3486
3511
|
view.lastKeyCodeTime = Date.now();
|
|
3512
|
+
// Suppress enter key events on Chrome Android, because those tend
|
|
3513
|
+
// to be part of a confused sequence of composition events fired,
|
|
3514
|
+
// and handling them eagerly tends to corrupt the input.
|
|
3515
|
+
if (result.android && result.chrome && event.keyCode == 13) { return }
|
|
3516
|
+
if (event.keyCode != 229) { view.domObserver.forceFlush(); }
|
|
3517
|
+
|
|
3487
3518
|
// On iOS, if we preventDefault enter key presses, the virtual
|
|
3488
3519
|
// keyboard gets confused. So the hack here is to set a flag that
|
|
3489
3520
|
// makes the DOM change code recognize that what just happens should
|
|
@@ -3868,6 +3899,7 @@ function timestampFromCustomEvent() {
|
|
|
3868
3899
|
}
|
|
3869
3900
|
|
|
3870
3901
|
function endComposition(view, forceUpdate) {
|
|
3902
|
+
if (result.android && view.domObserver.flushingSoon >= 0) { return }
|
|
3871
3903
|
view.domObserver.forceFlush();
|
|
3872
3904
|
clearComposition(view);
|
|
3873
3905
|
if (forceUpdate || view.docView.dirty) {
|
|
@@ -3958,6 +3990,11 @@ function doPaste(view, text, html, e) {
|
|
|
3958
3990
|
}
|
|
3959
3991
|
|
|
3960
3992
|
editHandlers.paste = function (view, e) {
|
|
3993
|
+
// Handling paste from JavaScript during composition is very poorly
|
|
3994
|
+
// handled by browsers, so as a dodgy but preferable kludge, we just
|
|
3995
|
+
// let the browser do its native thing there, except on Android,
|
|
3996
|
+
// where the editor is almost always composing.
|
|
3997
|
+
if (view.composing && !result.android) { return }
|
|
3961
3998
|
var data = brokenClipboardAPI ? null : e.clipboardData;
|
|
3962
3999
|
if (data && doPaste(view, data.getData("text/plain"), data.getData("text/html"), e)) { e.preventDefault(); }
|
|
3963
4000
|
else { capturePaste(view, e); }
|
|
@@ -4089,6 +4126,7 @@ handlers.beforeinput = function (view, event) {
|
|
|
4089
4126
|
// Very specific hack to deal with backspace sometimes failing on
|
|
4090
4127
|
// Chrome Android when after an uneditable node.
|
|
4091
4128
|
if (result.chrome && result.android && event.inputType == "deleteContentBackward") {
|
|
4129
|
+
view.domObserver.flushSoon();
|
|
4092
4130
|
var domChangeCount = view.domChangeCount;
|
|
4093
4131
|
setTimeout(function () {
|
|
4094
4132
|
if (view.domChangeCount != domChangeCount) { return } // Event already had some effect
|