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/package.json
CHANGED
package/src/clipboard.js
CHANGED
|
@@ -73,7 +73,8 @@ export function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
73
73
|
preserveWhitespace: !!(asText || sliceData),
|
|
74
74
|
context: $context,
|
|
75
75
|
ruleFromNode(dom) {
|
|
76
|
-
if (dom.nodeName == "BR" && !dom.nextSibling
|
|
76
|
+
if (dom.nodeName == "BR" && !dom.nextSibling &&
|
|
77
|
+
dom.parentNode && !inlineParents.test(dom.parentNode.nodeName)) return {ignore: true}
|
|
77
78
|
}
|
|
78
79
|
})
|
|
79
80
|
}
|
|
@@ -95,6 +96,8 @@ export function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
95
96
|
return slice
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
const 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
|
|
100
|
+
|
|
98
101
|
// Takes a slice parsed with parseSlice, which means there hasn't been
|
|
99
102
|
// any content-expression checking done on the top nodes, tries to
|
|
100
103
|
// find a parent node in the current context that might fit the nodes,
|
package/src/input.js
CHANGED
|
@@ -100,9 +100,14 @@ export function dispatchEvent(view, event) {
|
|
|
100
100
|
editHandlers.keydown = (view, event) => {
|
|
101
101
|
view.shiftKey = event.keyCode == 16 || event.shiftKey
|
|
102
102
|
if (inOrNearComposition(view, event)) return
|
|
103
|
-
if (event.keyCode != 229) view.domObserver.forceFlush()
|
|
104
103
|
view.lastKeyCode = event.keyCode
|
|
105
104
|
view.lastKeyCodeTime = Date.now()
|
|
105
|
+
// Suppress enter key events on Chrome Android, because those tend
|
|
106
|
+
// to be part of a confused sequence of composition events fired,
|
|
107
|
+
// and handling them eagerly tends to corrupt the input.
|
|
108
|
+
if (browser.android && browser.chrome && event.keyCode == 13) return
|
|
109
|
+
if (event.keyCode != 229) view.domObserver.forceFlush()
|
|
110
|
+
|
|
106
111
|
// On iOS, if we preventDefault enter key presses, the virtual
|
|
107
112
|
// keyboard gets confused. So the hack here is to set a flag that
|
|
108
113
|
// makes the DOM change code recognize that what just happens should
|
|
@@ -477,6 +482,7 @@ function timestampFromCustomEvent() {
|
|
|
477
482
|
}
|
|
478
483
|
|
|
479
484
|
export function endComposition(view, forceUpdate) {
|
|
485
|
+
if (browser.android && view.domObserver.flushingSoon >= 0) return
|
|
480
486
|
view.domObserver.forceFlush()
|
|
481
487
|
clearComposition(view)
|
|
482
488
|
if (forceUpdate || view.docView.dirty) {
|
|
@@ -564,6 +570,11 @@ function doPaste(view, text, html, e) {
|
|
|
564
570
|
}
|
|
565
571
|
|
|
566
572
|
editHandlers.paste = (view, e) => {
|
|
573
|
+
// Handling paste from JavaScript during composition is very poorly
|
|
574
|
+
// handled by browsers, so as a dodgy but preferable kludge, we just
|
|
575
|
+
// let the browser do its native thing there, except on Android,
|
|
576
|
+
// where the editor is almost always composing.
|
|
577
|
+
if (view.composing && !browser.android) return
|
|
567
578
|
let data = brokenClipboardAPI ? null : e.clipboardData
|
|
568
579
|
if (data && doPaste(view, data.getData("text/plain"), data.getData("text/html"), e)) e.preventDefault()
|
|
569
580
|
else capturePaste(view, e)
|
|
@@ -696,6 +707,7 @@ handlers.beforeinput = (view, event) => {
|
|
|
696
707
|
// Very specific hack to deal with backspace sometimes failing on
|
|
697
708
|
// Chrome Android when after an uneditable node.
|
|
698
709
|
if (browser.chrome && browser.android && event.inputType == "deleteContentBackward") {
|
|
710
|
+
view.domObserver.flushSoon()
|
|
699
711
|
let {domChangeCount} = view
|
|
700
712
|
setTimeout(() => {
|
|
701
713
|
if (view.domChangeCount != domChangeCount) return // Event already had some effect
|
package/src/selection.js
CHANGED
|
@@ -43,9 +43,13 @@ export function selectionToDOM(view, force) {
|
|
|
43
43
|
if (!editorOwnsSelection(view)) return
|
|
44
44
|
|
|
45
45
|
if (!force && view.mouseDown && view.mouseDown.allowDefault) {
|
|
46
|
-
view.
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
let domSel = view.root.getSelection(), curSel = view.domObserver.currentSelection
|
|
47
|
+
if (domSel.anchorNode && isEquivalentPosition(domSel.anchorNode, domSel.anchorOffset,
|
|
48
|
+
curSel.anchorNode, curSel.anchorOffset)) {
|
|
49
|
+
view.mouseDown.delayedSelectionSync = true
|
|
50
|
+
view.domObserver.setCurSelection()
|
|
51
|
+
return
|
|
52
|
+
}
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
view.domObserver.disconnectSelection()
|
package/src/viewdesc.js
CHANGED
|
@@ -1091,7 +1091,7 @@ class ViewTreeUpdater {
|
|
|
1091
1091
|
// Tracks whether anything was changed
|
|
1092
1092
|
this.changed = false
|
|
1093
1093
|
|
|
1094
|
-
this.preMatch = preMatch(top.node.content, top
|
|
1094
|
+
this.preMatch = preMatch(top.node.content, top)
|
|
1095
1095
|
}
|
|
1096
1096
|
|
|
1097
1097
|
// Destroy and remove the children between the given indices in
|
|
@@ -1152,17 +1152,14 @@ class ViewTreeUpdater {
|
|
|
1152
1152
|
// Try to find a node desc matching the given data. Skip over it and
|
|
1153
1153
|
// return true when successful.
|
|
1154
1154
|
findNodeMatch(node, outerDeco, innerDeco, index) {
|
|
1155
|
-
let
|
|
1156
|
-
if (index >= this.preMatch.index
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
break
|
|
1161
|
-
}
|
|
1162
|
-
}
|
|
1155
|
+
let found = -1, targetDesc
|
|
1156
|
+
if (index >= this.preMatch.index &&
|
|
1157
|
+
(targetDesc = this.preMatch.matches[index - this.preMatch.index]).parent == this.top &&
|
|
1158
|
+
targetDesc.matchesNode(node, outerDeco, innerDeco)) {
|
|
1159
|
+
found = this.top.children.indexOf(targetDesc, this.index)
|
|
1163
1160
|
} else {
|
|
1164
|
-
for (let i = this.index, e = Math.min(children.length, i +
|
|
1165
|
-
let child = children[i]
|
|
1161
|
+
for (let i = this.index, e = Math.min(this.top.children.length, i + 5); i < e; i++) {
|
|
1162
|
+
let child = this.top.children[i]
|
|
1166
1163
|
if (child.matchesNode(node, outerDeco, innerDeco) && !this.preMatch.matched.has(child)) {
|
|
1167
1164
|
found = i
|
|
1168
1165
|
break
|
|
@@ -1274,22 +1271,44 @@ class ViewTreeUpdater {
|
|
|
1274
1271
|
}
|
|
1275
1272
|
}
|
|
1276
1273
|
|
|
1277
|
-
// : (Fragment, [ViewDesc]) → {index: number, matched: Map<ViewDesc, number
|
|
1274
|
+
// : (Fragment, [ViewDesc]) → {index: number, matched: Map<ViewDesc, number>, matches: ViewDesc[]}
|
|
1278
1275
|
// Iterate from the end of the fragment and array of descs to find
|
|
1279
1276
|
// directly matching ones, in order to avoid overeagerly reusing those
|
|
1280
1277
|
// for other nodes. Returns the fragment index of the first node that
|
|
1281
1278
|
// is part of the sequence of matched nodes at the end of the
|
|
1282
1279
|
// fragment.
|
|
1283
|
-
function preMatch(frag,
|
|
1284
|
-
let
|
|
1285
|
-
|
|
1286
|
-
|
|
1280
|
+
function preMatch(frag, parentDesc) {
|
|
1281
|
+
let curDesc = parentDesc, descI = curDesc.children.length
|
|
1282
|
+
let fI = frag.childCount, matched = new Map, matches = []
|
|
1283
|
+
outer: while (fI > 0) {
|
|
1284
|
+
let desc
|
|
1285
|
+
for (;;) {
|
|
1286
|
+
if (descI) {
|
|
1287
|
+
let next = curDesc.children[descI - 1]
|
|
1288
|
+
if (next instanceof MarkViewDesc) {
|
|
1289
|
+
curDesc = next
|
|
1290
|
+
descI = next.children.length
|
|
1291
|
+
} else {
|
|
1292
|
+
desc = next
|
|
1293
|
+
descI--
|
|
1294
|
+
break
|
|
1295
|
+
}
|
|
1296
|
+
} else if (curDesc == parentDesc) {
|
|
1297
|
+
break outer
|
|
1298
|
+
} else {
|
|
1299
|
+
// FIXME
|
|
1300
|
+
descI = curDesc.parent.children.indexOf(curDesc)
|
|
1301
|
+
curDesc = curDesc.parent
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
let node = desc.node
|
|
1287
1305
|
if (!node) continue
|
|
1288
1306
|
if (node != frag.child(fI - 1)) break
|
|
1289
1307
|
--fI
|
|
1290
1308
|
matched.set(desc, fI)
|
|
1309
|
+
matches.push(desc)
|
|
1291
1310
|
}
|
|
1292
|
-
return {index: fI, matched}
|
|
1311
|
+
return {index: fI, matched, matches: matches.reverse()}
|
|
1293
1312
|
}
|
|
1294
1313
|
|
|
1295
1314
|
function compareSide(a, b) { return a.type.side - b.type.side }
|
|
@@ -1403,8 +1422,8 @@ function findTextInFragment(frag, text, from, to) {
|
|
|
1403
1422
|
if (!next.isText) break
|
|
1404
1423
|
str += next.text
|
|
1405
1424
|
}
|
|
1406
|
-
if (pos >= from) {
|
|
1407
|
-
let found = str.lastIndexOf(text, to - childStart)
|
|
1425
|
+
if (pos >= from && childStart < to) {
|
|
1426
|
+
let found = str.lastIndexOf(text, to - childStart - 1)
|
|
1408
1427
|
if (found >= 0 && found + text.length + childStart >= from)
|
|
1409
1428
|
return childStart + found
|
|
1410
1429
|
}
|