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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-view",
3
- "version": "1.23.0",
3
+ "version": "1.23.4",
4
4
  "description": "ProseMirror's view component",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.es.js",
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) return {ignore: true}
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.mouseDown.delayedSelectionSync = true
47
- view.domObserver.setCurSelection()
48
- return
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.children)
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 children = this.top.children, found = -1
1156
- if (index >= this.preMatch.index) {
1157
- for (let i = this.index; i < children.length; i++) {
1158
- if (this.preMatch.matched.get(children[i]) == index) {
1159
- if (children[i].matchesNode(node, outerDeco, innerDeco)) found = i
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 + 1); i < e; 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, descs) {
1284
- let fI = frag.childCount, dI = descs.length, matched = new Map
1285
- for (; fI > 0 && dI > 0; dI--) {
1286
- let desc = descs[dI - 1], node = desc.node
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
  }