prosemirror-view 1.31.8 → 1.32.1

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 CHANGED
@@ -1,3 +1,23 @@
1
+ ## 1.32.1 (2023-10-13)
2
+
3
+ ### Bug fixes
4
+
5
+ Work around a Chrome issue where it didn't draw a selection for inline leaf nodes when selecting across them.
6
+
7
+ Override the native behavior when shift-selecting horizontally across non-text inline nodes, since most browsers behave poorly here.
8
+
9
+ ## 1.32.0 (2023-09-27)
10
+
11
+ ### Bug fixes
12
+
13
+ Work around an issue on Chrome where, when clicking above the right side of an uneditable node, the cursor would be put after the node.
14
+
15
+ Fix a bug that could corrupt the composition when it occurs next to text identical to the composed characters.
16
+
17
+ ### New features
18
+
19
+ The new `EditorView.updateRoot` method can be used to make the editor update its DOM root when it is moved to a new document or shadow tree.
20
+
1
21
  ## 1.31.8 (2023-09-12)
2
22
 
3
23
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -513,6 +513,8 @@ function _posAtCoords(view, coords) {
513
513
  }
514
514
  }
515
515
 
516
+ var prev;
517
+ if (webkit && offset && node.nodeType == 1 && (prev = node.childNodes[offset - 1]).nodeType == 1 && prev.contentEditable == "false" && prev.getBoundingClientRect().top >= coords.top) offset--;
516
518
  if (node == view.dom && offset == node.childNodes.length - 1 && node.lastChild.nodeType == 1 && coords.top > node.lastChild.getBoundingClientRect().bottom) pos = view.state.doc.content.size;else if (offset == 0 || node.nodeType != 1 || node.childNodes[offset - 1].nodeName != "BR") pos = posFromCaret(view, node, offset, coords);
517
519
  }
518
520
 
@@ -2479,6 +2481,7 @@ function findTextInFragment(frag, text, from, to) {
2479
2481
  }
2480
2482
 
2481
2483
  if (pos >= from) {
2484
+ if (pos >= to && str.slice(to - text.length - childStart, to - childStart) == text) return to - text.length;
2482
2485
  var found = childStart < to ? str.lastIndexOf(text, to - childStart - 1) : -1;
2483
2486
  if (found >= 0 && found + text.length + childStart >= from) return childStart + found;
2484
2487
  if (from == to && str.length >= to + text.length - childStart && str.slice(to - childStart, to - childStart + text.length) == text) return to;
@@ -2743,24 +2746,31 @@ function selectHorizontally(view, dir, mods) {
2743
2746
  var sel = view.state.selection;
2744
2747
 
2745
2748
  if (sel instanceof prosemirrorState.TextSelection) {
2746
- if (!sel.empty || mods.indexOf("s") > -1) {
2749
+ if (mods.indexOf("s") > -1) {
2750
+ var $head = sel.$head,
2751
+ node = $head.textOffset ? null : dir < 0 ? $head.nodeBefore : $head.nodeAfter;
2752
+ if (!node || node.isText || !node.isLeaf) return false;
2753
+ var $newHead = view.state.doc.resolve($head.pos + node.nodeSize * (dir < 0 ? -1 : 1));
2754
+ return apply(view, new prosemirrorState.TextSelection(sel.$anchor, $newHead));
2755
+ } else if (!sel.empty) {
2747
2756
  return false;
2748
2757
  } else if (view.endOfTextblock(dir > 0 ? "forward" : "backward")) {
2749
2758
  var next = moveSelectionBlock(view.state, dir);
2750
2759
  if (next && next instanceof prosemirrorState.NodeSelection) return apply(view, next);
2751
2760
  return false;
2752
2761
  } else if (!(mac && mods.indexOf("m") > -1)) {
2753
- var $head = sel.$head,
2754
- node = $head.textOffset ? null : dir < 0 ? $head.nodeBefore : $head.nodeAfter,
2762
+ var _$head = sel.$head,
2763
+ _node = _$head.textOffset ? null : dir < 0 ? _$head.nodeBefore : _$head.nodeAfter,
2755
2764
  desc;
2756
- if (!node || node.isText) return false;
2757
- var nodePos = dir < 0 ? $head.pos - node.nodeSize : $head.pos;
2758
- if (!(node.isAtom || (desc = view.docView.descAt(nodePos)) && !desc.contentDOM)) return false;
2759
2765
 
2760
- if (prosemirrorState.NodeSelection.isSelectable(node)) {
2761
- return apply(view, new prosemirrorState.NodeSelection(dir < 0 ? view.state.doc.resolve($head.pos - node.nodeSize) : $head));
2766
+ if (!_node || _node.isText) return false;
2767
+ var nodePos = dir < 0 ? _$head.pos - _node.nodeSize : _$head.pos;
2768
+ if (!(_node.isAtom || (desc = view.docView.descAt(nodePos)) && !desc.contentDOM)) return false;
2769
+
2770
+ if (prosemirrorState.NodeSelection.isSelectable(_node)) {
2771
+ return apply(view, new prosemirrorState.NodeSelection(dir < 0 ? view.state.doc.resolve(_$head.pos - _node.nodeSize) : _$head));
2762
2772
  } else if (webkit) {
2763
- return apply(view, new prosemirrorState.TextSelection(view.state.doc.resolve(dir < 0 ? nodePos : nodePos + node.nodeSize)));
2773
+ return apply(view, new prosemirrorState.TextSelection(view.state.doc.resolve(dir < 0 ? nodePos : nodePos + _node.nodeSize)));
2764
2774
  } else {
2765
2775
  return false;
2766
2776
  }
@@ -2780,7 +2790,6 @@ function nodeLen(node) {
2780
2790
  }
2781
2791
 
2782
2792
  function isIgnorable(dom, dir) {
2783
- if (dom.contentEditable == "false") return true;
2784
2793
  var desc = dom.pmViewDesc;
2785
2794
  return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR");
2786
2795
  }
@@ -3203,7 +3212,7 @@ function parseFromClipboard(view, text, html, plainText, $context) {
3203
3212
 
3204
3213
  for (var node = slice.content.firstChild; openStart < slice.openStart && !node.type.spec.isolating; openStart++, node = node.firstChild) {}
3205
3214
 
3206
- for (var _node = slice.content.lastChild; openEnd < slice.openEnd && !_node.type.spec.isolating; openEnd++, _node = _node.lastChild) {}
3215
+ for (var _node2 = slice.content.lastChild; openEnd < slice.openEnd && !_node2.type.spec.isolating; openEnd++, _node2 = _node2.lastChild) {}
3207
3216
 
3208
3217
  slice = closeSlice(slice, openStart, openEnd);
3209
3218
  }
@@ -5943,6 +5952,11 @@ var EditorView = function () {
5943
5952
 
5944
5953
  return cached || document;
5945
5954
  }
5955
+ }, {
5956
+ key: "updateRoot",
5957
+ value: function updateRoot() {
5958
+ this._root = null;
5959
+ }
5946
5960
  }, {
5947
5961
  key: "posAtCoords",
5948
5962
  value: function posAtCoords(coords) {
package/dist/index.d.cts CHANGED
@@ -492,6 +492,11 @@ declare class EditorView {
492
492
  */
493
493
  get root(): Document | ShadowRoot;
494
494
  /**
495
+ When an existing editor view is moved to a new document or
496
+ shadow tree, call this to make it recompute its root.
497
+ */
498
+ updateRoot(): void;
499
+ /**
495
500
  Given a pair of viewport coordinates, return the document
496
501
  position that corresponds to them. May return null if the given
497
502
  coordinates aren't inside of the editor. When an object is
package/dist/index.d.ts CHANGED
@@ -492,6 +492,11 @@ declare class EditorView {
492
492
  */
493
493
  get root(): Document | ShadowRoot;
494
494
  /**
495
+ When an existing editor view is moved to a new document or
496
+ shadow tree, call this to make it recompute its root.
497
+ */
498
+ updateRoot(): void;
499
+ /**
495
500
  Given a pair of viewport coordinates, return the document
496
501
  position that corresponds to them. May return null if the given
497
502
  coordinates aren't inside of the editor. When an object is
package/dist/index.js CHANGED
@@ -426,6 +426,11 @@ function posAtCoords(view, coords) {
426
426
  offset++;
427
427
  }
428
428
  }
429
+ let prev;
430
+ // When clicking above the right side of an uneditable node, Chrome will report a cursor position after that node.
431
+ if (webkit && offset && node.nodeType == 1 && (prev = node.childNodes[offset - 1]).nodeType == 1 &&
432
+ prev.contentEditable == "false" && prev.getBoundingClientRect().top >= coords.top)
433
+ offset--;
429
434
  // Suspiciously specific kludge to work around caret*FromPoint
430
435
  // never returning a position at the end of the document
431
436
  if (node == view.dom && offset == node.childNodes.length - 1 && node.lastChild.nodeType == 1 &&
@@ -2068,6 +2073,8 @@ function findTextInFragment(frag, text, from, to) {
2068
2073
  str += next.text;
2069
2074
  }
2070
2075
  if (pos >= from) {
2076
+ if (pos >= to && str.slice(to - text.length - childStart, to - childStart) == text)
2077
+ return to - text.length;
2071
2078
  let found = childStart < to ? str.lastIndexOf(text, to - childStart - 1) : -1;
2072
2079
  if (found >= 0 && found + text.length + childStart >= from)
2073
2080
  return childStart + found;
@@ -2321,7 +2328,14 @@ function apply(view, sel) {
2321
2328
  function selectHorizontally(view, dir, mods) {
2322
2329
  let sel = view.state.selection;
2323
2330
  if (sel instanceof TextSelection) {
2324
- if (!sel.empty || mods.indexOf("s") > -1) {
2331
+ if (mods.indexOf("s") > -1) {
2332
+ let { $head } = sel, node = $head.textOffset ? null : dir < 0 ? $head.nodeBefore : $head.nodeAfter;
2333
+ if (!node || node.isText || !node.isLeaf)
2334
+ return false;
2335
+ let $newHead = view.state.doc.resolve($head.pos + node.nodeSize * (dir < 0 ? -1 : 1));
2336
+ return apply(view, new TextSelection(sel.$anchor, $newHead));
2337
+ }
2338
+ else if (!sel.empty) {
2325
2339
  return false;
2326
2340
  }
2327
2341
  else if (view.endOfTextblock(dir > 0 ? "forward" : "backward")) {
@@ -2365,8 +2379,6 @@ function nodeLen(node) {
2365
2379
  return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
2366
2380
  }
2367
2381
  function isIgnorable(dom, dir) {
2368
- if (dom.contentEditable == "false")
2369
- return true;
2370
2382
  let desc = dom.pmViewDesc;
2371
2383
  return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR");
2372
2384
  }
@@ -5354,6 +5366,13 @@ class EditorView {
5354
5366
  return cached || document;
5355
5367
  }
5356
5368
  /**
5369
+ When an existing editor view is moved to a new document or
5370
+ shadow tree, call this to make it recompute its root.
5371
+ */
5372
+ updateRoot() {
5373
+ this._root = null;
5374
+ }
5375
+ /**
5357
5376
  Given a pair of viewport coordinates, return the document
5358
5377
  position that corresponds to them. May return null if the given
5359
5378
  coordinates aren't inside of the editor. When an object is
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-view",
3
- "version": "1.31.8",
3
+ "version": "1.32.1",
4
4
  "description": "ProseMirror's view component",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -19,7 +19,12 @@ function apply(view: EditorView, sel: Selection) {
19
19
  function selectHorizontally(view: EditorView, dir: number, mods: string) {
20
20
  let sel = view.state.selection
21
21
  if (sel instanceof TextSelection) {
22
- if (!sel.empty || mods.indexOf("s") > -1) {
22
+ if (mods.indexOf("s") > -1) {
23
+ let {$head} = sel, node = $head.textOffset ? null : dir < 0 ? $head.nodeBefore : $head.nodeAfter
24
+ if (!node || node.isText || !node.isLeaf) return false
25
+ let $newHead = view.state.doc.resolve($head.pos + node.nodeSize * (dir < 0 ? -1 : 1))
26
+ return apply(view, new TextSelection(sel.$anchor, $newHead))
27
+ } else if (!sel.empty) {
23
28
  return false
24
29
  } else if (view.endOfTextblock(dir > 0 ? "forward" : "backward")) {
25
30
  let next = moveSelectionBlock(view.state, dir)
@@ -55,7 +60,6 @@ function nodeLen(node: Node) {
55
60
  }
56
61
 
57
62
  function isIgnorable(dom: Node, dir: number) {
58
- if ((dom as HTMLElement).contentEditable == "false") return true
59
63
  let desc = dom.pmViewDesc
60
64
  return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR")
61
65
  }
package/src/domcoords.ts CHANGED
@@ -294,6 +294,11 @@ export function posAtCoords(view: EditorView, coords: {top: number, left: number
294
294
  offset++
295
295
  }
296
296
  }
297
+ let prev
298
+ // When clicking above the right side of an uneditable node, Chrome will report a cursor position after that node.
299
+ if (browser.webkit && offset && node.nodeType == 1 && (prev = node.childNodes[offset - 1]).nodeType == 1 &&
300
+ (prev as HTMLElement).contentEditable == "false" && (prev as HTMLElement).getBoundingClientRect().top >= coords.top)
301
+ offset--
297
302
  // Suspiciously specific kludge to work around caret*FromPoint
298
303
  // never returning a position at the end of the document
299
304
  if (node == view.dom && offset == node.childNodes.length - 1 && node.lastChild!.nodeType == 1 &&
package/src/index.ts CHANGED
@@ -339,6 +339,12 @@ export class EditorView {
339
339
  return cached || document
340
340
  }
341
341
 
342
+ /// When an existing editor view is moved to a new document or
343
+ /// shadow tree, call this to make it recompute its root.
344
+ updateRoot() {
345
+ this._root = null
346
+ }
347
+
342
348
  /// Given a pair of viewport coordinates, return the document
343
349
  /// position that corresponds to them. May return null if the given
344
350
  /// coordinates aren't inside of the editor. When an object is
package/src/viewdesc.ts CHANGED
@@ -1499,6 +1499,8 @@ function findTextInFragment(frag: Fragment, text: string, from: number, to: numb
1499
1499
  str += next.text
1500
1500
  }
1501
1501
  if (pos >= from) {
1502
+ if (pos >= to && str.slice(to - text.length - childStart, to - childStart) == text)
1503
+ return to - text.length
1502
1504
  let found = childStart < to ? str.lastIndexOf(text, to - childStart - 1) : -1
1503
1505
  if (found >= 0 && found + text.length + childStart >= from)
1504
1506
  return childStart + found
@@ -23,6 +23,9 @@
23
23
  .ProseMirror-hideselection *::-moz-selection { background: transparent; }
24
24
  .ProseMirror-hideselection { caret-color: transparent; }
25
25
 
26
+ /* See https://github.com/ProseMirror/prosemirror/issues/1421#issuecomment-1759320191 */
27
+ .ProseMirror [draggable][contenteditable=false] { user-select: text }
28
+
26
29
  .ProseMirror-selectednode {
27
30
  outline: 2px solid #8cf;
28
31
  }