prosemirror-view 1.24.0-beta.3 → 1.24.0

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,17 @@
1
+ ## 1.24.0 (2022-05-30)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix an issue where bogus table wrappers could be added when copy-pasting table content nodes within an editor.
6
+
7
+ Fix a crash that could occur when two textblocks were joined in the editor DOM.
8
+
9
+ Treat ctrl-b/f/p/n on macOS similar to arrow key presses, anticipating cursor motion.
10
+
11
+ ### New features
12
+
13
+ Include TypeScript type declarations.
14
+
1
15
  ## 1.23.13 (2022-04-26)
2
16
 
3
17
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -1774,9 +1774,10 @@ var CustomNodeViewDesc = function (_NodeViewDesc2) {
1774
1774
  if (this.dirty == NODE_DIRTY) return false;
1775
1775
 
1776
1776
  if (this.spec.update) {
1777
- var result = this.spec.update(node, outerDeco, innerDeco);
1778
- if (result) this.updateInner(node, outerDeco, innerDeco, view);
1779
- return result;
1777
+ var _result = this.spec.update(node, outerDeco, innerDeco);
1778
+
1779
+ if (_result) this.updateInner(node, outerDeco, innerDeco, view);
1780
+ return _result;
1780
1781
  } else if (!this.contentDOM && !node.isLeaf) {
1781
1782
  return false;
1782
1783
  } else {
@@ -2866,13 +2867,13 @@ function captureKeyDown(view, event) {
2866
2867
  return stopNativeHorizontalDelete(view, 1) || skipIgnoredNodesRight(view);
2867
2868
  } else if (code == 13 || code == 27) {
2868
2869
  return true;
2869
- } else if (code == 37) {
2870
+ } else if (code == 37 || result.mac && code == 66 && mods == "c") {
2870
2871
  return selectHorizontally(view, -1, mods) || skipIgnoredNodesLeft(view);
2871
- } else if (code == 39) {
2872
+ } else if (code == 39 || result.mac && code == 70 && mods == "c") {
2872
2873
  return selectHorizontally(view, 1, mods) || skipIgnoredNodesRight(view);
2873
- } else if (code == 38) {
2874
+ } else if (code == 38 || result.mac && code == 80 && mods == "c") {
2874
2875
  return selectVertically(view, -1, mods) || skipIgnoredNodesLeft(view);
2875
- } else if (code == 40) {
2876
+ } else if (code == 40 || result.mac && code == 78 && mods == "c") {
2876
2877
  return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodesRight(view);
2877
2878
  } else if (mods == (mac ? "m" : "c") && (code == 66 || code == 73 || code == 89 || code == 90)) {
2878
2879
  return true;
@@ -2902,7 +2903,8 @@ function serializeForClipboard(view, slice) {
2902
2903
  document: doc
2903
2904
  }));
2904
2905
  var firstChild = wrap.firstChild,
2905
- needsWrap;
2906
+ needsWrap,
2907
+ wrappers = 0;
2906
2908
 
2907
2909
  while (firstChild && firstChild.nodeType == 1 && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) {
2908
2910
  for (var i = needsWrap.length - 1; i >= 0; i--) {
@@ -2913,17 +2915,13 @@ function serializeForClipboard(view, slice) {
2913
2915
  }
2914
2916
 
2915
2917
  wrap.appendChild(wrapper);
2916
-
2917
- if (needsWrap[i] != "tbody") {
2918
- openStart++;
2919
- openEnd++;
2920
- }
2918
+ wrappers++;
2921
2919
  }
2922
2920
 
2923
2921
  firstChild = wrap.firstChild;
2924
2922
  }
2925
2923
 
2926
- if (firstChild && firstChild.nodeType == 1) firstChild.setAttribute("data-pm-slice", "".concat(openStart, " ").concat(openEnd, " ").concat(JSON.stringify(context)));
2924
+ if (firstChild && firstChild.nodeType == 1) firstChild.setAttribute("data-pm-slice", "".concat(openStart, " ").concat(openEnd).concat(wrappers ? " -".concat(wrappers) : "", " ").concat(JSON.stringify(context)));
2927
2925
  var text = view.someProp("clipboardTextSerializer", function (f) {
2928
2926
  return f(slice);
2929
2927
  }) || slice.content.textBetween(0, slice.content.size, "\n\n");
@@ -2969,7 +2967,10 @@ function parseFromClipboard(view, text, html, plainText, $context) {
2969
2967
  }
2970
2968
 
2971
2969
  var contextNode = dom && dom.querySelector("[data-pm-slice]");
2972
- var sliceData = contextNode && /^(\d+) (\d+) (.*)/.exec(contextNode.getAttribute("data-pm-slice") || "");
2970
+ var sliceData = contextNode && /^(\d+) (\d+)(?: -(\d+))? (.*)/.exec(contextNode.getAttribute("data-pm-slice") || "");
2971
+ if (sliceData && sliceData[3]) for (var i = +sliceData[3]; i > 0 && dom.firstChild; i--) {
2972
+ dom = dom.firstChild;
2973
+ }
2973
2974
 
2974
2975
  if (!slice) {
2975
2976
  var parser = view.someProp("clipboardParser") || view.someProp("domParser") || prosemirrorModel.DOMParser.fromSchema(view.state.schema);
@@ -2986,7 +2987,7 @@ function parseFromClipboard(view, text, html, plainText, $context) {
2986
2987
  }
2987
2988
 
2988
2989
  if (sliceData) {
2989
- slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[3]);
2990
+ slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[4]);
2990
2991
  } else {
2991
2992
  slice = prosemirrorModel.Slice.maxOpen(normalizeSiblings(slice.content, $context), true);
2992
2993
 
@@ -4330,9 +4331,10 @@ var DecorationGroup = function () {
4330
4331
  var found = [];
4331
4332
 
4332
4333
  for (var i = 0; i < this.members.length; i++) {
4333
- var result = this.members[i].forChild(offset, child);
4334
- if (result == empty) continue;
4335
- if (result instanceof DecorationGroup) found = found.concat(result.members);else found.push(result);
4334
+ var _result2 = this.members[i].forChild(offset, child);
4335
+
4336
+ if (_result2 == empty) continue;
4337
+ if (_result2 instanceof DecorationGroup) found = found.concat(_result2.members);else found.push(_result2);
4336
4338
  }
4337
4339
 
4338
4340
  return DecorationGroup.from(found);
@@ -4825,12 +4827,12 @@ var DOMObserver = function () {
4825
4827
 
4826
4828
  if (this.view.editable) {
4827
4829
  for (var i = 0; i < mutations.length; i++) {
4828
- var result = this.registerMutation(mutations[i], added);
4830
+ var _result3 = this.registerMutation(mutations[i], added);
4829
4831
 
4830
- if (result) {
4831
- from = from < 0 ? result.from : Math.min(result.from, from);
4832
- to = to < 0 ? result.to : Math.max(result.to, to);
4833
- if (result.typeOver) typeOver = true;
4832
+ if (_result3) {
4833
+ from = from < 0 ? _result3.from : Math.min(_result3.from, from);
4834
+ to = to < 0 ? _result3.to : Math.max(_result3.to, to);
4835
+ if (_result3.typeOver) typeOver = true;
4834
4836
  }
4835
4837
  }
4836
4838
  }
@@ -5111,7 +5113,8 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
5111
5113
 
5112
5114
  var $from = parse.doc.resolveNoCache(change.start - parse.from);
5113
5115
  var $to = parse.doc.resolveNoCache(change.endB - parse.from);
5114
- var inlineChange = $from.sameParent($to) && $from.parent.inlineContent;
5116
+ var $fromA = doc.resolve(change.start);
5117
+ var inlineChange = $from.sameParent($to) && $from.parent.inlineContent && $fromA.end() >= change.endA;
5115
5118
  var nextSel;
5116
5119
 
5117
5120
  if ((ios && view.input.lastIOSEnter > Date.now() - 225 && (!inlineChange || addedNodes.some(function (n) {
@@ -5144,7 +5147,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
5144
5147
 
5145
5148
  var chFrom = change.start,
5146
5149
  chTo = change.endA;
5147
- var tr, storedMarks, markChange, $from1;
5150
+ var tr, storedMarks, markChange;
5148
5151
 
5149
5152
  if (inlineChange) {
5150
5153
  if ($from.pos == $to.pos) {
@@ -5157,7 +5160,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
5157
5160
 
5158
5161
  tr = view.state.tr["delete"](chFrom, chTo);
5159
5162
  storedMarks = doc.resolve(change.start).marksAcross(doc.resolve(change.endA));
5160
- } else if (change.endA == change.endB && ($from1 = doc.resolve(change.start)) && (markChange = isMarkChange($from.parent.content.cut($from.parentOffset, $to.parentOffset), $from1.parent.content.cut($from1.parentOffset, change.endA - $from1.start())))) {
5163
+ } else if (change.endA == change.endB && (markChange = isMarkChange($from.parent.content.cut($from.parentOffset, $to.parentOffset), $fromA.parent.content.cut($fromA.parentOffset, change.endA - $fromA.start())))) {
5161
5164
  tr = view.state.tr;
5162
5165
  if (markChange.type == "add") tr.addMark(chFrom, chTo, markChange.mark);else tr.removeMark(chFrom, chTo, markChange.mark);
5163
5166
  } else if ($from.parent.child($from.index()).isText && $from.index() == $to.index() - ($to.textOffset ? 0 : 1)) {
package/dist/index.js CHANGED
@@ -2509,16 +2509,16 @@ function captureKeyDown(view, event) {
2509
2509
  else if (code == 13 || code == 27) { // Enter, Esc
2510
2510
  return true;
2511
2511
  }
2512
- else if (code == 37) { // Left arrow
2512
+ else if (code == 37 || (result.mac && code == 66 && mods == "c")) { // Left arrow, Ctrl-b on Mac
2513
2513
  return selectHorizontally(view, -1, mods) || skipIgnoredNodesLeft(view);
2514
2514
  }
2515
- else if (code == 39) { // Right arrow
2515
+ else if (code == 39 || (result.mac && code == 70 && mods == "c")) { // Right arrow, Ctrl-f on Mac
2516
2516
  return selectHorizontally(view, 1, mods) || skipIgnoredNodesRight(view);
2517
2517
  }
2518
- else if (code == 38) { // Up arrow
2518
+ else if (code == 38 || (result.mac && code == 80 && mods == "c")) { // Up arrow, Ctrl-p on Mac
2519
2519
  return selectVertically(view, -1, mods) || skipIgnoredNodesLeft(view);
2520
2520
  }
2521
- else if (code == 40) { // Down arrow
2521
+ else if (code == 40 || (result.mac && code == 78 && mods == "c")) { // Down arrow, Ctrl-n on Mac
2522
2522
  return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodesRight(view);
2523
2523
  }
2524
2524
  else if (mods == (mac ? "m" : "c") &&
@@ -2540,22 +2540,19 @@ function serializeForClipboard(view, slice) {
2540
2540
  let serializer = view.someProp("clipboardSerializer") || DOMSerializer.fromSchema(view.state.schema);
2541
2541
  let doc = detachedDoc(), wrap = doc.createElement("div");
2542
2542
  wrap.appendChild(serializer.serializeFragment(content, { document: doc }));
2543
- let firstChild = wrap.firstChild, needsWrap;
2543
+ let firstChild = wrap.firstChild, needsWrap, wrappers = 0;
2544
2544
  while (firstChild && firstChild.nodeType == 1 && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) {
2545
2545
  for (let i = needsWrap.length - 1; i >= 0; i--) {
2546
2546
  let wrapper = doc.createElement(needsWrap[i]);
2547
2547
  while (wrap.firstChild)
2548
2548
  wrapper.appendChild(wrap.firstChild);
2549
2549
  wrap.appendChild(wrapper);
2550
- if (needsWrap[i] != "tbody") {
2551
- openStart++;
2552
- openEnd++;
2553
- }
2550
+ wrappers++;
2554
2551
  }
2555
2552
  firstChild = wrap.firstChild;
2556
2553
  }
2557
2554
  if (firstChild && firstChild.nodeType == 1)
2558
- firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd} ${JSON.stringify(context)}`);
2555
+ firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd}${wrappers ? ` -${wrappers}` : ""} ${JSON.stringify(context)}`);
2559
2556
  let text = view.someProp("clipboardTextSerializer", f => f(slice)) ||
2560
2557
  slice.content.textBetween(0, slice.content.size, "\n\n");
2561
2558
  return { dom: wrap, text };
@@ -2593,7 +2590,10 @@ function parseFromClipboard(view, text, html, plainText, $context) {
2593
2590
  restoreReplacedSpaces(dom);
2594
2591
  }
2595
2592
  let contextNode = dom && dom.querySelector("[data-pm-slice]");
2596
- let sliceData = contextNode && /^(\d+) (\d+) (.*)/.exec(contextNode.getAttribute("data-pm-slice") || "");
2593
+ let sliceData = contextNode && /^(\d+) (\d+)(?: -(\d+))? (.*)/.exec(contextNode.getAttribute("data-pm-slice") || "");
2594
+ if (sliceData && sliceData[3])
2595
+ for (let i = +sliceData[3]; i > 0 && dom.firstChild; i--)
2596
+ dom = dom.firstChild;
2597
2597
  if (!slice) {
2598
2598
  let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
2599
2599
  slice = parser.parseSlice(dom, {
@@ -2608,7 +2608,7 @@ function parseFromClipboard(view, text, html, plainText, $context) {
2608
2608
  });
2609
2609
  }
2610
2610
  if (sliceData) {
2611
- slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[3]);
2611
+ slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[4]);
2612
2612
  }
2613
2613
  else { // HTML wasn't created by ProseMirror. Make sure top-level siblings are coherent
2614
2614
  slice = Slice.maxOpen(normalizeSiblings(slice.content, $context), true);
@@ -4566,7 +4566,8 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
4566
4566
  }
4567
4567
  let $from = parse.doc.resolveNoCache(change.start - parse.from);
4568
4568
  let $to = parse.doc.resolveNoCache(change.endB - parse.from);
4569
- let inlineChange = $from.sameParent($to) && $from.parent.inlineContent;
4569
+ let $fromA = doc.resolve(change.start);
4570
+ let inlineChange = $from.sameParent($to) && $from.parent.inlineContent && $fromA.end() >= change.endA;
4570
4571
  let nextSel;
4571
4572
  // If this looks like the effect of pressing Enter (or was recorded
4572
4573
  // as being an iOS enter press), just dispatch an Enter key instead.
@@ -4609,7 +4610,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
4609
4610
  }, 20);
4610
4611
  }
4611
4612
  let chFrom = change.start, chTo = change.endA;
4612
- let tr, storedMarks, markChange, $from1;
4613
+ let tr, storedMarks, markChange;
4613
4614
  if (inlineChange) {
4614
4615
  if ($from.pos == $to.pos) { // Deletion
4615
4616
  // IE11 sometimes weirdly moves the DOM selection around after
@@ -4622,8 +4623,8 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
4622
4623
  storedMarks = doc.resolve(change.start).marksAcross(doc.resolve(change.endA));
4623
4624
  }
4624
4625
  else if ( // Adding or removing a mark
4625
- change.endA == change.endB && ($from1 = doc.resolve(change.start)) &&
4626
- (markChange = isMarkChange($from.parent.content.cut($from.parentOffset, $to.parentOffset), $from1.parent.content.cut($from1.parentOffset, change.endA - $from1.start())))) {
4626
+ change.endA == change.endB &&
4627
+ (markChange = isMarkChange($from.parent.content.cut($from.parentOffset, $to.parentOffset), $fromA.parent.content.cut($fromA.parentOffset, change.endA - $fromA.start())))) {
4627
4628
  tr = view.state.tr;
4628
4629
  if (markChange.type == "add")
4629
4630
  tr.addMark(chFrom, chTo, markChange.mark);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-view",
3
- "version": "1.24.0-beta.3",
3
+ "version": "1.24.0",
4
4
  "description": "ProseMirror's view component",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -256,13 +256,13 @@ export function captureKeyDown(view: EditorView, event: KeyboardEvent) {
256
256
  return stopNativeHorizontalDelete(view, 1) || skipIgnoredNodesRight(view)
257
257
  } else if (code == 13 || code == 27) { // Enter, Esc
258
258
  return true
259
- } else if (code == 37) { // Left arrow
259
+ } else if (code == 37 || (result.mac && code == 66 && mods == "c")) { // Left arrow, Ctrl-b on Mac
260
260
  return selectHorizontally(view, -1, mods) || skipIgnoredNodesLeft(view)
261
- } else if (code == 39) { // Right arrow
261
+ } else if (code == 39 || (result.mac && code == 70 && mods == "c")) { // Right arrow, Ctrl-f on Mac
262
262
  return selectHorizontally(view, 1, mods) || skipIgnoredNodesRight(view)
263
- } else if (code == 38) { // Up arrow
263
+ } else if (code == 38 || (result.mac && code == 80 && mods == "c")) { // Up arrow, Ctrl-p on Mac
264
264
  return selectVertically(view, -1, mods) || skipIgnoredNodesLeft(view)
265
- } else if (code == 40) { // Down arrow
265
+ } else if (code == 40 || (result.mac && code == 78 && mods == "c")) { // Down arrow, Ctrl-n on Mac
266
266
  return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodesRight(view)
267
267
  } else if (mods == (browser.mac ? "m" : "c") &&
268
268
  (code == 66 || code == 73 || code == 89 || code == 90)) { // Mod-[biyz]
package/src/clipboard.ts CHANGED
@@ -16,22 +16,20 @@ export function serializeForClipboard(view: EditorView, slice: Slice) {
16
16
  let doc = detachedDoc(), wrap = doc.createElement("div")
17
17
  wrap.appendChild(serializer.serializeFragment(content, {document: doc}))
18
18
 
19
- let firstChild = wrap.firstChild, needsWrap
19
+ let firstChild = wrap.firstChild, needsWrap, wrappers = 0
20
20
  while (firstChild && firstChild.nodeType == 1 && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) {
21
21
  for (let i = needsWrap.length - 1; i >= 0; i--) {
22
22
  let wrapper = doc.createElement(needsWrap[i])
23
23
  while (wrap.firstChild) wrapper.appendChild(wrap.firstChild)
24
24
  wrap.appendChild(wrapper)
25
- if (needsWrap[i] != "tbody") {
26
- openStart++
27
- openEnd++
28
- }
25
+ wrappers++
29
26
  }
30
27
  firstChild = wrap.firstChild
31
28
  }
32
29
 
33
30
  if (firstChild && firstChild.nodeType == 1)
34
- (firstChild as HTMLElement).setAttribute("data-pm-slice", `${openStart} ${openEnd} ${JSON.stringify(context)}`)
31
+ (firstChild as HTMLElement).setAttribute(
32
+ "data-pm-slice", `${openStart} ${openEnd}${wrappers ? ` -${wrappers}` : ""} ${JSON.stringify(context)}`)
35
33
 
36
34
  let text = view.someProp("clipboardTextSerializer", f => f(slice)) ||
37
35
  slice.content.textBetween(0, slice.content.size, "\n\n")
@@ -67,7 +65,10 @@ export function parseFromClipboard(view: EditorView, text: string, html: string
67
65
  }
68
66
 
69
67
  let contextNode = dom && dom.querySelector("[data-pm-slice]")
70
- let sliceData = contextNode && /^(\d+) (\d+) (.*)/.exec(contextNode.getAttribute("data-pm-slice") || "")
68
+ let sliceData = contextNode && /^(\d+) (\d+)(?: -(\d+))? (.*)/.exec(contextNode.getAttribute("data-pm-slice") || "")
69
+ if (sliceData && sliceData[3]) for (let i = +sliceData[3]; i > 0 && dom!.firstChild; i--)
70
+ dom = dom!.firstChild as HTMLElement
71
+
71
72
  if (!slice) {
72
73
  let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser.fromSchema(view.state.schema)
73
74
  slice = parser.parseSlice(dom!, {
@@ -81,7 +82,7 @@ export function parseFromClipboard(view: EditorView, text: string, html: string
81
82
  })
82
83
  }
83
84
  if (sliceData) {
84
- slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[3])
85
+ slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[4])
85
86
  } else { // HTML wasn't created by ProseMirror. Make sure top-level siblings are coherent
86
87
  slice = Slice.maxOpen(normalizeSiblings(slice.content, $context), true)
87
88
  if (slice.openStart || slice.openEnd) {
package/src/domchange.ts CHANGED
@@ -167,7 +167,8 @@ export function readDOMChange(view: EditorView, from: number, to: number, typeOv
167
167
 
168
168
  let $from = parse.doc.resolveNoCache(change.start - parse.from)
169
169
  let $to = parse.doc.resolveNoCache(change.endB - parse.from)
170
- let inlineChange = $from.sameParent($to) && $from.parent.inlineContent
170
+ let $fromA = doc.resolve(change.start)
171
+ let inlineChange = $from.sameParent($to) && $from.parent.inlineContent && $fromA.end() >= change.endA
171
172
  let nextSel
172
173
  // If this looks like the effect of pressing Enter (or was recorded
173
174
  // as being an iOS enter press), just dispatch an Enter key instead.
@@ -213,7 +214,7 @@ export function readDOMChange(view: EditorView, from: number, to: number, typeOv
213
214
 
214
215
  let chFrom = change.start, chTo = change.endA
215
216
 
216
- let tr, storedMarks, markChange, $from1
217
+ let tr, storedMarks, markChange
217
218
  if (inlineChange) {
218
219
  if ($from.pos == $to.pos) { // Deletion
219
220
  // IE11 sometimes weirdly moves the DOM selection around after
@@ -225,9 +226,9 @@ export function readDOMChange(view: EditorView, from: number, to: number, typeOv
225
226
  tr = view.state.tr.delete(chFrom, chTo)
226
227
  storedMarks = doc.resolve(change.start).marksAcross(doc.resolve(change.endA))
227
228
  } else if ( // Adding or removing a mark
228
- change.endA == change.endB && ($from1 = doc.resolve(change.start)) &&
229
+ change.endA == change.endB &&
229
230
  (markChange = isMarkChange($from.parent.content.cut($from.parentOffset, $to.parentOffset),
230
- $from1.parent.content.cut($from1.parentOffset, change.endA - $from1.start())))
231
+ $fromA.parent.content.cut($fromA.parentOffset, change.endA - $fromA.start())))
231
232
  ) {
232
233
  tr = view.state.tr
233
234
  if (markChange.type == "add") tr.addMark(chFrom, chTo, markChange.mark)