prosemirror-view 1.31.7 → 1.31.8

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,13 @@
1
+ ## 1.31.8 (2023-09-12)
2
+
3
+ ### Bug fixes
4
+
5
+ Fix a bug that broke arrow motion near uneditable nodes on Chrome in some situations.
6
+
7
+ Fix an issue that broke backspace at the end of a textblock that ended in a newline on Chrome.
8
+
9
+ Fix a crash in the way inline decorations that ended right after a node end position were drawn.
10
+
1
11
  ## 1.31.7 (2023-07-28)
2
12
 
3
13
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -32,10 +32,6 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
32
32
 
33
33
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
34
34
 
35
- Object.defineProperty(exports, '__esModule', {
36
- value: true
37
- });
38
-
39
35
  var prosemirrorState = require('prosemirror-state');
40
36
 
41
37
  var prosemirrorModel = require('prosemirror-model');
@@ -2190,9 +2186,13 @@ var ViewTreeUpdater = function () {
2190
2186
  return true;
2191
2187
  } else if (!locked && (updated = this.recreateWrapper(next, node, outerDeco, innerDeco, view, pos))) {
2192
2188
  this.top.children[this.index] = updated;
2193
- updated.dirty = CONTENT_DIRTY;
2194
- updated.updateChildren(view, pos + 1);
2195
- updated.dirty = NOT_DIRTY;
2189
+
2190
+ if (updated.contentDOM) {
2191
+ updated.dirty = CONTENT_DIRTY;
2192
+ updated.updateChildren(view, pos + 1);
2193
+ updated.dirty = NOT_DIRTY;
2194
+ }
2195
+
2196
2196
  this.changed = true;
2197
2197
  this.index++;
2198
2198
  return true;
@@ -2209,25 +2209,27 @@ var ViewTreeUpdater = function () {
2209
2209
  value: function recreateWrapper(next, node, outerDeco, innerDeco, view, pos) {
2210
2210
  if (next.dirty || node.isAtom || !next.children.length || !next.node.content.eq(node.content)) return null;
2211
2211
  var wrapper = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos);
2212
- if (!wrapper.contentDOM) return null;
2213
- wrapper.children = next.children;
2214
- next.children = [];
2215
- next.destroy();
2216
2212
 
2217
- var _iterator = _createForOfIteratorHelper(wrapper.children),
2218
- _step;
2213
+ if (wrapper.contentDOM) {
2214
+ wrapper.children = next.children;
2215
+ next.children = [];
2216
+
2217
+ var _iterator = _createForOfIteratorHelper(wrapper.children),
2218
+ _step;
2219
2219
 
2220
- try {
2221
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
2222
- var ch = _step.value;
2223
- ch.parent = wrapper;
2220
+ try {
2221
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
2222
+ var ch = _step.value;
2223
+ ch.parent = wrapper;
2224
+ }
2225
+ } catch (err) {
2226
+ _iterator.e(err);
2227
+ } finally {
2228
+ _iterator.f();
2224
2229
  }
2225
- } catch (err) {
2226
- _iterator.e(err);
2227
- } finally {
2228
- _iterator.f();
2229
2230
  }
2230
2231
 
2232
+ next.destroy();
2231
2233
  return wrapper;
2232
2234
  }
2233
2235
  }, {
@@ -2364,14 +2366,18 @@ function iterDeco(parent, deco, onWidget, onNode) {
2364
2366
  restNode = null;
2365
2367
 
2366
2368
  for (var parentIndex = 0;;) {
2367
- if (decoIndex < locals.length && locals[decoIndex].to == offset) {
2368
- var widget = locals[decoIndex++],
2369
- widgets = void 0;
2369
+ var widget = void 0,
2370
+ widgets = void 0;
2371
+
2372
+ while (decoIndex < locals.length && locals[decoIndex].to == offset) {
2373
+ var next = locals[decoIndex++];
2370
2374
 
2371
- while (decoIndex < locals.length && locals[decoIndex].to == offset) {
2372
- (widgets || (widgets = [widget])).push(locals[decoIndex++]);
2375
+ if (next.widget) {
2376
+ if (!widget) widget = next;else (widgets || (widgets = [widget])).push(next);
2373
2377
  }
2378
+ }
2374
2379
 
2380
+ if (widget) {
2375
2381
  if (widgets) {
2376
2382
  widgets.sort(compareSide);
2377
2383
 
@@ -2773,10 +2779,10 @@ function nodeLen(node) {
2773
2779
  return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
2774
2780
  }
2775
2781
 
2776
- function isIgnorable(dom) {
2782
+ function isIgnorable(dom, dir) {
2777
2783
  if (dom.contentEditable == "false") return true;
2778
2784
  var desc = dom.pmViewDesc;
2779
- return desc && desc.size == 0 && (dom.nextSibling || dom.nodeName != "BR");
2785
+ return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR");
2780
2786
  }
2781
2787
 
2782
2788
  function skipIgnoredNodes(view, dir) {
@@ -2791,7 +2797,7 @@ function skipIgnoredNodesBefore(view) {
2791
2797
  var moveNode,
2792
2798
  moveOffset,
2793
2799
  force = false;
2794
- if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset])) force = true;
2800
+ if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset], -1)) force = true;
2795
2801
 
2796
2802
  for (;;) {
2797
2803
  if (offset > 0) {
@@ -2800,7 +2806,7 @@ function skipIgnoredNodesBefore(view) {
2800
2806
  } else {
2801
2807
  var before = node.childNodes[offset - 1];
2802
2808
 
2803
- if (isIgnorable(before)) {
2809
+ if (isIgnorable(before, -1)) {
2804
2810
  moveNode = node;
2805
2811
  moveOffset = --offset;
2806
2812
  } else if (before.nodeType == 3) {
@@ -2813,7 +2819,7 @@ function skipIgnoredNodesBefore(view) {
2813
2819
  } else {
2814
2820
  var prev = node.previousSibling;
2815
2821
 
2816
- while (prev && isIgnorable(prev)) {
2822
+ while (prev && isIgnorable(prev, -1)) {
2817
2823
  moveNode = node.parentNode;
2818
2824
  moveOffset = domIndex(prev);
2819
2825
  prev = prev.previousSibling;
@@ -2846,7 +2852,7 @@ function skipIgnoredNodesAfter(view) {
2846
2852
  if (node.nodeType != 1) break;
2847
2853
  var after = node.childNodes[offset];
2848
2854
 
2849
- if (isIgnorable(after)) {
2855
+ if (isIgnorable(after, 1)) {
2850
2856
  moveNode = node;
2851
2857
  moveOffset = ++offset;
2852
2858
  } else break;
@@ -2855,7 +2861,7 @@ function skipIgnoredNodesAfter(view) {
2855
2861
  } else {
2856
2862
  var next = node.nextSibling;
2857
2863
 
2858
- while (next && isIgnorable(next)) {
2864
+ while (next && isIgnorable(next, 1)) {
2859
2865
  moveNode = next.parentNode;
2860
2866
  moveOffset = domIndex(next) + 1;
2861
2867
  next = next.nextSibling;
@@ -2888,8 +2894,10 @@ function textNodeAfter(node, offset) {
2888
2894
  }
2889
2895
 
2890
2896
  while (node && offset < node.childNodes.length) {
2891
- node = node.childNodes[offset];
2892
- if (node.nodeType == 3) return node;
2897
+ var next = node.childNodes[offset];
2898
+ if (next.nodeType == 3) return next;
2899
+ if (next.nodeType == 1 && next.contentEditable == "false") break;
2900
+ node = next;
2893
2901
  offset = 0;
2894
2902
  }
2895
2903
  }
@@ -2901,8 +2909,10 @@ function textNodeBefore(node, offset) {
2901
2909
  }
2902
2910
 
2903
2911
  while (node && offset) {
2904
- node = node.childNodes[offset - 1];
2905
- if (node.nodeType == 3) return node;
2912
+ var next = node.childNodes[offset - 1];
2913
+ if (next.nodeType == 3) return next;
2914
+ if (next.nodeType == 1 && next.contentEditable == "false") break;
2915
+ node = next;
2906
2916
  offset = node.childNodes.length;
2907
2917
  }
2908
2918
  }
@@ -3059,7 +3069,7 @@ function captureKeyDown(view, event) {
3059
3069
  } else if (code == 38 || mac && code == 80 && mods == "c") {
3060
3070
  return selectVertically(view, -1, mods) || skipIgnoredNodes(view, -1);
3061
3071
  } else if (code == 40 || mac && code == 78 && mods == "c") {
3062
- return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodesAfter(view);
3072
+ return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodes(view, 1);
3063
3073
  } else if (mods == (mac ? "m" : "c") && (code == 66 || code == 73 || code == 89 || code == 90)) {
3064
3074
  return true;
3065
3075
  }
@@ -4296,6 +4306,11 @@ var Decoration = function () {
4296
4306
  get: function get() {
4297
4307
  return this.type instanceof InlineType;
4298
4308
  }
4309
+ }, {
4310
+ key: "widget",
4311
+ get: function get() {
4312
+ return this.type instanceof WidgetType;
4313
+ }
4299
4314
  }], [{
4300
4315
  key: "widget",
4301
4316
  value: function widget(pos, toDOM, spec) {
package/dist/index.d.cts CHANGED
@@ -2,9 +2,9 @@ import { EditorState, Transaction, Selection, Plugin } from 'prosemirror-state';
2
2
  import { Mark, Node, ParseRule, Slice, ResolvedPos, DOMParser, DOMSerializer } from 'prosemirror-model';
3
3
  import { Mapping } from 'prosemirror-transform';
4
4
 
5
- declare type DOMNode = InstanceType<typeof window.Node>;
5
+ type DOMNode = InstanceType<typeof window.Node>;
6
6
 
7
- declare type WidgetConstructor = ((view: EditorView, getPos: () => number | undefined) => DOMNode) | DOMNode;
7
+ type WidgetConstructor = ((view: EditorView, getPos: () => number | undefined) => DOMNode) | DOMNode;
8
8
  /**
9
9
  Decoration objects can be provided to the view through the
10
10
  [`decorations` prop](https://prosemirror.net/docs/ref/#view.EditorProps.decorations). They come in
@@ -125,7 +125,7 @@ A set of attributes to add to a decorated node. Most properties
125
125
  simply directly correspond to DOM attributes of the same name,
126
126
  which will be set to the property's value. These are exceptions:
127
127
  */
128
- declare type DecorationAttrs = {
128
+ type DecorationAttrs = {
129
129
  /**
130
130
  When non-null, the target node is wrapped in a DOM element of
131
131
  this type (and the other attributes are applied to this element).
@@ -166,7 +166,8 @@ updates create a new value.
166
166
  declare class DecorationSet implements DecorationSource {
167
167
  /**
168
168
  Create a set of decorations, using the structure of the given
169
- document.
169
+ document. This will consume (modify) the `decorations` array, so
170
+ you must make a copy if you want need to preserve that.
170
171
  */
171
172
  static create(doc: Node, decorations: Decoration[]): DecorationSet;
172
173
  /**
@@ -193,8 +194,9 @@ declare class DecorationSet implements DecorationSource {
193
194
  }): DecorationSet;
194
195
  /**
195
196
  Add the given array of decorations to the ones in the set,
196
- producing a new set. Needs access to the current document to
197
- create the appropriate tree structure.
197
+ producing a new set. Consumes the `decorations` array. Needs
198
+ access to the current document to create the appropriate tree
199
+ structure.
198
200
  */
199
201
  add(doc: Node, decorations: Decoration[]): DecorationSet;
200
202
  private addInner;
@@ -356,7 +358,7 @@ declare class NodeViewDesc extends ViewDesc {
356
358
  parseRule(): ParseRule | null;
357
359
  matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
358
360
  get size(): number;
359
- get border(): 1 | 0;
361
+ get border(): 0 | 1;
360
362
  updateChildren(view: EditorView, pos: number): void;
361
363
  localCompositionInfo(view: EditorView, pos: number): {
362
364
  node: Text;
@@ -604,12 +606,12 @@ declare class EditorView {
604
606
  The type of function [provided](https://prosemirror.net/docs/ref/#view.EditorProps.nodeViews) to
605
607
  create [node views](https://prosemirror.net/docs/ref/#view.NodeView).
606
608
  */
607
- declare type NodeViewConstructor = (node: Node, view: EditorView, getPos: () => number | undefined, decorations: readonly Decoration[], innerDecorations: DecorationSource) => NodeView;
609
+ type NodeViewConstructor = (node: Node, view: EditorView, getPos: () => number | undefined, decorations: readonly Decoration[], innerDecorations: DecorationSource) => NodeView;
608
610
  /**
609
611
  The function types [used](https://prosemirror.net/docs/ref/#view.EditorProps.markViews) to create
610
612
  mark views.
611
613
  */
612
- declare type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) => {
614
+ type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) => {
613
615
  dom: HTMLElement;
614
616
  contentDOM?: HTMLElement;
615
617
  };
package/dist/index.d.ts CHANGED
@@ -2,9 +2,9 @@ import { EditorState, Transaction, Selection, Plugin } from 'prosemirror-state';
2
2
  import { Mark, Node, ParseRule, Slice, ResolvedPos, DOMParser, DOMSerializer } from 'prosemirror-model';
3
3
  import { Mapping } from 'prosemirror-transform';
4
4
 
5
- declare type DOMNode = InstanceType<typeof window.Node>;
5
+ type DOMNode = InstanceType<typeof window.Node>;
6
6
 
7
- declare type WidgetConstructor = ((view: EditorView, getPos: () => number | undefined) => DOMNode) | DOMNode;
7
+ type WidgetConstructor = ((view: EditorView, getPos: () => number | undefined) => DOMNode) | DOMNode;
8
8
  /**
9
9
  Decoration objects can be provided to the view through the
10
10
  [`decorations` prop](https://prosemirror.net/docs/ref/#view.EditorProps.decorations). They come in
@@ -125,7 +125,7 @@ A set of attributes to add to a decorated node. Most properties
125
125
  simply directly correspond to DOM attributes of the same name,
126
126
  which will be set to the property's value. These are exceptions:
127
127
  */
128
- declare type DecorationAttrs = {
128
+ type DecorationAttrs = {
129
129
  /**
130
130
  When non-null, the target node is wrapped in a DOM element of
131
131
  this type (and the other attributes are applied to this element).
@@ -166,7 +166,8 @@ updates create a new value.
166
166
  declare class DecorationSet implements DecorationSource {
167
167
  /**
168
168
  Create a set of decorations, using the structure of the given
169
- document.
169
+ document. This will consume (modify) the `decorations` array, so
170
+ you must make a copy if you want need to preserve that.
170
171
  */
171
172
  static create(doc: Node, decorations: Decoration[]): DecorationSet;
172
173
  /**
@@ -193,8 +194,9 @@ declare class DecorationSet implements DecorationSource {
193
194
  }): DecorationSet;
194
195
  /**
195
196
  Add the given array of decorations to the ones in the set,
196
- producing a new set. Needs access to the current document to
197
- create the appropriate tree structure.
197
+ producing a new set. Consumes the `decorations` array. Needs
198
+ access to the current document to create the appropriate tree
199
+ structure.
198
200
  */
199
201
  add(doc: Node, decorations: Decoration[]): DecorationSet;
200
202
  private addInner;
@@ -356,7 +358,7 @@ declare class NodeViewDesc extends ViewDesc {
356
358
  parseRule(): ParseRule | null;
357
359
  matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
358
360
  get size(): number;
359
- get border(): 1 | 0;
361
+ get border(): 0 | 1;
360
362
  updateChildren(view: EditorView, pos: number): void;
361
363
  localCompositionInfo(view: EditorView, pos: number): {
362
364
  node: Text;
@@ -604,12 +606,12 @@ declare class EditorView {
604
606
  The type of function [provided](https://prosemirror.net/docs/ref/#view.EditorProps.nodeViews) to
605
607
  create [node views](https://prosemirror.net/docs/ref/#view.NodeView).
606
608
  */
607
- declare type NodeViewConstructor = (node: Node, view: EditorView, getPos: () => number | undefined, decorations: readonly Decoration[], innerDecorations: DecorationSource) => NodeView;
609
+ type NodeViewConstructor = (node: Node, view: EditorView, getPos: () => number | undefined, decorations: readonly Decoration[], innerDecorations: DecorationSource) => NodeView;
608
610
  /**
609
611
  The function types [used](https://prosemirror.net/docs/ref/#view.EditorProps.markViews) to create
610
612
  mark views.
611
613
  */
612
- declare type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) => {
614
+ type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) => {
613
615
  dom: HTMLElement;
614
616
  contentDOM?: HTMLElement;
615
617
  };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { TextSelection, NodeSelection, Selection, AllSelection } from 'prosemirror-state';
1
+ import { TextSelection, NodeSelection, AllSelection, Selection } from 'prosemirror-state';
2
2
  import { DOMSerializer, Fragment, Mark, Slice, DOMParser } from 'prosemirror-model';
3
3
  import { dropPoint } from 'prosemirror-transform';
4
4
 
@@ -1810,9 +1810,11 @@ class ViewTreeUpdater {
1810
1810
  }
1811
1811
  else if (!locked && (updated = this.recreateWrapper(next, node, outerDeco, innerDeco, view, pos))) {
1812
1812
  this.top.children[this.index] = updated;
1813
- updated.dirty = CONTENT_DIRTY;
1814
- updated.updateChildren(view, pos + 1);
1815
- updated.dirty = NOT_DIRTY;
1813
+ if (updated.contentDOM) {
1814
+ updated.dirty = CONTENT_DIRTY;
1815
+ updated.updateChildren(view, pos + 1);
1816
+ updated.dirty = NOT_DIRTY;
1817
+ }
1816
1818
  this.changed = true;
1817
1819
  this.index++;
1818
1820
  return true;
@@ -1829,13 +1831,13 @@ class ViewTreeUpdater {
1829
1831
  !next.node.content.eq(node.content))
1830
1832
  return null;
1831
1833
  let wrapper = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos);
1832
- if (!wrapper.contentDOM)
1833
- return null;
1834
- wrapper.children = next.children;
1835
- next.children = [];
1834
+ if (wrapper.contentDOM) {
1835
+ wrapper.children = next.children;
1836
+ next.children = [];
1837
+ for (let ch of wrapper.children)
1838
+ ch.parent = wrapper;
1839
+ }
1836
1840
  next.destroy();
1837
- for (let ch of wrapper.children)
1838
- ch.parent = wrapper;
1839
1841
  return wrapper;
1840
1842
  }
1841
1843
  // Insert the node as a newly created node desc.
@@ -1963,10 +1965,17 @@ function iterDeco(parent, deco, onWidget, onNode) {
1963
1965
  }
1964
1966
  let decoIndex = 0, active = [], restNode = null;
1965
1967
  for (let parentIndex = 0;;) {
1966
- if (decoIndex < locals.length && locals[decoIndex].to == offset) {
1967
- let widget = locals[decoIndex++], widgets;
1968
- while (decoIndex < locals.length && locals[decoIndex].to == offset)
1969
- (widgets || (widgets = [widget])).push(locals[decoIndex++]);
1968
+ let widget, widgets;
1969
+ while (decoIndex < locals.length && locals[decoIndex].to == offset) {
1970
+ let next = locals[decoIndex++];
1971
+ if (next.widget) {
1972
+ if (!widget)
1973
+ widget = next;
1974
+ else
1975
+ (widgets || (widgets = [widget])).push(next);
1976
+ }
1977
+ }
1978
+ if (widget) {
1970
1979
  if (widgets) {
1971
1980
  widgets.sort(compareSide);
1972
1981
  for (let i = 0; i < widgets.length; i++)
@@ -2355,11 +2364,11 @@ function selectHorizontally(view, dir, mods) {
2355
2364
  function nodeLen(node) {
2356
2365
  return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
2357
2366
  }
2358
- function isIgnorable(dom) {
2367
+ function isIgnorable(dom, dir) {
2359
2368
  if (dom.contentEditable == "false")
2360
2369
  return true;
2361
2370
  let desc = dom.pmViewDesc;
2362
- return desc && desc.size == 0 && (dom.nextSibling || dom.nodeName != "BR");
2371
+ return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR");
2363
2372
  }
2364
2373
  function skipIgnoredNodes(view, dir) {
2365
2374
  return dir < 0 ? skipIgnoredNodesBefore(view) : skipIgnoredNodesAfter(view);
@@ -2375,7 +2384,7 @@ function skipIgnoredNodesBefore(view) {
2375
2384
  // Gecko will do odd things when the selection is directly in front
2376
2385
  // of a non-editable node, so in that case, move it into the next
2377
2386
  // node if possible. Issue prosemirror/prosemirror#832.
2378
- if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset]))
2387
+ if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset], -1))
2379
2388
  force = true;
2380
2389
  for (;;) {
2381
2390
  if (offset > 0) {
@@ -2384,7 +2393,7 @@ function skipIgnoredNodesBefore(view) {
2384
2393
  }
2385
2394
  else {
2386
2395
  let before = node.childNodes[offset - 1];
2387
- if (isIgnorable(before)) {
2396
+ if (isIgnorable(before, -1)) {
2388
2397
  moveNode = node;
2389
2398
  moveOffset = --offset;
2390
2399
  }
@@ -2401,7 +2410,7 @@ function skipIgnoredNodesBefore(view) {
2401
2410
  }
2402
2411
  else {
2403
2412
  let prev = node.previousSibling;
2404
- while (prev && isIgnorable(prev)) {
2413
+ while (prev && isIgnorable(prev, -1)) {
2405
2414
  moveNode = node.parentNode;
2406
2415
  moveOffset = domIndex(prev);
2407
2416
  prev = prev.previousSibling;
@@ -2437,7 +2446,7 @@ function skipIgnoredNodesAfter(view) {
2437
2446
  if (node.nodeType != 1)
2438
2447
  break;
2439
2448
  let after = node.childNodes[offset];
2440
- if (isIgnorable(after)) {
2449
+ if (isIgnorable(after, 1)) {
2441
2450
  moveNode = node;
2442
2451
  moveOffset = ++offset;
2443
2452
  }
@@ -2449,7 +2458,7 @@ function skipIgnoredNodesAfter(view) {
2449
2458
  }
2450
2459
  else {
2451
2460
  let next = node.nextSibling;
2452
- while (next && isIgnorable(next)) {
2461
+ while (next && isIgnorable(next, 1)) {
2453
2462
  moveNode = next.parentNode;
2454
2463
  moveOffset = domIndex(next) + 1;
2455
2464
  next = next.nextSibling;
@@ -2480,9 +2489,12 @@ function textNodeAfter(node, offset) {
2480
2489
  node = node.parentNode;
2481
2490
  }
2482
2491
  while (node && offset < node.childNodes.length) {
2483
- node = node.childNodes[offset];
2484
- if (node.nodeType == 3)
2485
- return node;
2492
+ let next = node.childNodes[offset];
2493
+ if (next.nodeType == 3)
2494
+ return next;
2495
+ if (next.nodeType == 1 && next.contentEditable == "false")
2496
+ break;
2497
+ node = next;
2486
2498
  offset = 0;
2487
2499
  }
2488
2500
  }
@@ -2492,9 +2504,12 @@ function textNodeBefore(node, offset) {
2492
2504
  node = node.parentNode;
2493
2505
  }
2494
2506
  while (node && offset) {
2495
- node = node.childNodes[offset - 1];
2496
- if (node.nodeType == 3)
2497
- return node;
2507
+ let next = node.childNodes[offset - 1];
2508
+ if (next.nodeType == 3)
2509
+ return next;
2510
+ if (next.nodeType == 1 && next.contentEditable == "false")
2511
+ break;
2512
+ node = next;
2498
2513
  offset = node.childNodes.length;
2499
2514
  }
2500
2515
  }
@@ -2656,7 +2671,7 @@ function captureKeyDown(view, event) {
2656
2671
  return selectVertically(view, -1, mods) || skipIgnoredNodes(view, -1);
2657
2672
  }
2658
2673
  else if (code == 40 || (mac && code == 78 && mods == "c")) { // Down arrow, Ctrl-n on Mac
2659
- return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodesAfter(view);
2674
+ return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodes(view, 1);
2660
2675
  }
2661
2676
  else if (mods == (mac ? "m" : "c") &&
2662
2677
  (code == 66 || code == 73 || code == 89 || code == 90)) { // Mod-[biyz]
@@ -3814,6 +3829,10 @@ class Decoration {
3814
3829
  @internal
3815
3830
  */
3816
3831
  get inline() { return this.type instanceof InlineType; }
3832
+ /**
3833
+ @internal
3834
+ */
3835
+ get widget() { return this.type instanceof WidgetType; }
3817
3836
  }
3818
3837
  const none = [], noSpec = {};
3819
3838
  /**
@@ -3832,7 +3851,8 @@ class DecorationSet {
3832
3851
  }
3833
3852
  /**
3834
3853
  Create a set of decorations, using the structure of the given
3835
- document.
3854
+ document. This will consume (modify) the `decorations` array, so
3855
+ you must make a copy if you want need to preserve that.
3836
3856
  */
3837
3857
  static create(doc, decorations) {
3838
3858
  return decorations.length ? buildTree(decorations, doc, 0, noSpec) : empty;
@@ -3891,8 +3911,9 @@ class DecorationSet {
3891
3911
  }
3892
3912
  /**
3893
3913
  Add the given array of decorations to the ones in the set,
3894
- producing a new set. Needs access to the current document to
3895
- create the appropriate tree structure.
3914
+ producing a new set. Consumes the `decorations` array. Needs
3915
+ access to the current document to create the appropriate tree
3916
+ structure.
3896
3917
  */
3897
3918
  add(doc, decorations) {
3898
3919
  if (!decorations.length)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-view",
3
- "version": "1.31.7",
3
+ "version": "1.31.8",
4
4
  "description": "ProseMirror's view component",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -54,10 +54,10 @@ function nodeLen(node: Node) {
54
54
  return node.nodeType == 3 ? node.nodeValue!.length : node.childNodes.length
55
55
  }
56
56
 
57
- function isIgnorable(dom: Node) {
57
+ function isIgnorable(dom: Node, dir: number) {
58
58
  if ((dom as HTMLElement).contentEditable == "false") return true
59
59
  let desc = dom.pmViewDesc
60
- return desc && desc.size == 0 && (dom.nextSibling || dom.nodeName != "BR")
60
+ return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR")
61
61
  }
62
62
 
63
63
  function skipIgnoredNodes(view: EditorView, dir: number) {
@@ -74,14 +74,14 @@ function skipIgnoredNodesBefore(view: EditorView) {
74
74
  // Gecko will do odd things when the selection is directly in front
75
75
  // of a non-editable node, so in that case, move it into the next
76
76
  // node if possible. Issue prosemirror/prosemirror#832.
77
- if (browser.gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset])) force = true
77
+ if (browser.gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset], -1)) force = true
78
78
  for (;;) {
79
79
  if (offset > 0) {
80
80
  if (node.nodeType != 1) {
81
81
  break
82
82
  } else {
83
83
  let before = node.childNodes[offset - 1]
84
- if (isIgnorable(before)) {
84
+ if (isIgnorable(before, -1)) {
85
85
  moveNode = node
86
86
  moveOffset = --offset
87
87
  } else if (before.nodeType == 3) {
@@ -93,7 +93,7 @@ function skipIgnoredNodesBefore(view: EditorView) {
93
93
  break
94
94
  } else {
95
95
  let prev = node.previousSibling
96
- while (prev && isIgnorable(prev)) {
96
+ while (prev && isIgnorable(prev, -1)) {
97
97
  moveNode = node.parentNode
98
98
  moveOffset = domIndex(prev)
99
99
  prev = prev.previousSibling
@@ -124,7 +124,7 @@ function skipIgnoredNodesAfter(view: EditorView) {
124
124
  if (offset < len) {
125
125
  if (node.nodeType != 1) break
126
126
  let after = node.childNodes[offset]
127
- if (isIgnorable(after)) {
127
+ if (isIgnorable(after, 1)) {
128
128
  moveNode = node
129
129
  moveOffset = ++offset
130
130
  }
@@ -133,7 +133,7 @@ function skipIgnoredNodesAfter(view: EditorView) {
133
133
  break
134
134
  } else {
135
135
  let next = node.nextSibling
136
- while (next && isIgnorable(next)) {
136
+ while (next && isIgnorable(next, 1)) {
137
137
  moveNode = next.parentNode
138
138
  moveOffset = domIndex(next) + 1
139
139
  next = next.nextSibling
@@ -163,8 +163,10 @@ function textNodeAfter(node: Node | null, offset: number): Text | undefined {
163
163
  node = node.parentNode
164
164
  }
165
165
  while (node && offset < node.childNodes.length) {
166
- node = node.childNodes[offset]
167
- if (node.nodeType == 3) return node as Text
166
+ let next = node.childNodes[offset]
167
+ if (next.nodeType == 3) return next as Text
168
+ if (next.nodeType == 1 && (next as HTMLElement).contentEditable == "false") break
169
+ node = next
168
170
  offset = 0
169
171
  }
170
172
  }
@@ -175,8 +177,10 @@ function textNodeBefore(node: Node | null, offset: number): Text | undefined {
175
177
  node = node.parentNode
176
178
  }
177
179
  while (node && offset) {
178
- node = node.childNodes[offset - 1]
179
- if (node.nodeType == 3) return node as Text
180
+ let next = node.childNodes[offset - 1]
181
+ if (next.nodeType == 3) return next as Text
182
+ if (next.nodeType == 1 && (next as HTMLElement).contentEditable == "false") break
183
+ node = next
180
184
  offset = node.childNodes.length
181
185
  }
182
186
  }
@@ -327,7 +331,7 @@ export function captureKeyDown(view: EditorView, event: KeyboardEvent) {
327
331
  } else if (code == 38 || (browser.mac && code == 80 && mods == "c")) { // Up arrow, Ctrl-p on Mac
328
332
  return selectVertically(view, -1, mods) || skipIgnoredNodes(view, -1)
329
333
  } else if (code == 40 || (browser.mac && code == 78 && mods == "c")) { // Down arrow, Ctrl-n on Mac
330
- return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodesAfter(view)
334
+ return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodes(view, 1)
331
335
  } else if (mods == (browser.mac ? "m" : "c") &&
332
336
  (code == 66 || code == 73 || code == 89 || code == 90)) { // Mod-[biyz]
333
337
  return true
package/src/decoration.ts CHANGED
@@ -223,6 +223,9 @@ export class Decoration {
223
223
 
224
224
  /// @internal
225
225
  get inline() { return this.type instanceof InlineType }
226
+
227
+ /// @internal
228
+ get widget() { return this.type instanceof WidgetType }
226
229
  }
227
230
 
228
231
  /// A set of attributes to add to a decorated node. Most properties
@@ -278,7 +281,8 @@ export class DecorationSet implements DecorationSource {
278
281
  }
279
282
 
280
283
  /// Create a set of decorations, using the structure of the given
281
- /// document.
284
+ /// document. This will consume (modify) the `decorations` array, so
285
+ /// you must make a copy if you want need to preserve that.
282
286
  static create(doc: Node, decorations: Decoration[]) {
283
287
  return decorations.length ? buildTree(decorations, doc, 0, noSpec) : empty
284
288
  }
@@ -302,7 +306,7 @@ export class DecorationSet implements DecorationSource {
302
306
  result.push(span.copy(span.from + offset, span.to + offset))
303
307
  }
304
308
  for (let i = 0; i < this.children.length; i += 3) {
305
- if (this.children[i] < end && this.children[i + 1] > start) {
309
+ if ((this.children[i] as number) < end && (this.children[i + 1] as number) > start) {
306
310
  let childOff = (this.children[i] as number) + 1
307
311
  ;(this.children[i + 2] as DecorationSet).findInner(start - childOff, end - childOff,
308
312
  result, offset + childOff, predicate)
@@ -340,8 +344,9 @@ export class DecorationSet implements DecorationSource {
340
344
  }
341
345
 
342
346
  /// Add the given array of decorations to the ones in the set,
343
- /// producing a new set. Needs access to the current document to
344
- /// create the appropriate tree structure.
347
+ /// producing a new set. Consumes the `decorations` array. Needs
348
+ /// access to the current document to create the appropriate tree
349
+ /// structure.
345
350
  add(doc: Node, decorations: Decoration[]) {
346
351
  if (!decorations.length) return this
347
352
  if (this == empty) return DecorationSet.create(doc, decorations)
@@ -355,7 +360,7 @@ export class DecorationSet implements DecorationSource {
355
360
  if (!(found = takeSpansForNode(decorations, childNode, baseOffset))) return
356
361
 
357
362
  if (!children) children = this.children.slice()
358
- while (childIndex < children.length && children[childIndex] < childOffset) childIndex += 3
363
+ while (childIndex < children.length && (children[childIndex] as number) < childOffset) childIndex += 3
359
364
  if (children[childIndex] == childOffset)
360
365
  children[childIndex + 2] = (children[childIndex + 2] as DecorationSet).addInner(childNode, found, baseOffset + 1)
361
366
  else
@@ -414,7 +419,7 @@ export class DecorationSet implements DecorationSource {
414
419
  if (node.isLeaf) return DecorationSet.empty
415
420
 
416
421
  let child, local: Decoration[] | undefined
417
- for (let i = 0; i < this.children.length; i += 3) if (this.children[i] >= offset) {
422
+ for (let i = 0; i < this.children.length; i += 3) if ((this.children[i] as number) >= offset) {
418
423
  if (this.children[i] == offset) child = this.children[i + 2] as DecorationSet
419
424
  break
420
425
  }
@@ -576,7 +581,7 @@ function mapChildren(
576
581
  // Find the child nodes that still correspond to a single node,
577
582
  // recursively call mapInner on them and update their positions.
578
583
  let mustRebuild = false
579
- for (let i = 0; i < children.length; i += 3) if (children[i + 1] < 0) { // Touched nodes
584
+ for (let i = 0; i < children.length; i += 3) if ((children[i + 1] as number) < 0) { // Touched nodes
580
585
  if (children[i + 1] == -2) {
581
586
  mustRebuild = true
582
587
  children[i + 1] = -1
@@ -613,7 +618,7 @@ function mapChildren(
613
618
  offset, oldOffset, options)
614
619
  let built = buildTree(decorations, node, 0, options)
615
620
  newLocal = built.local as Decoration[]
616
- for (let i = 0; i < children.length; i += 3) if (children[i + 1] < 0) {
621
+ for (let i = 0; i < children.length; i += 3) if ((children[i + 1] as number) < 0) {
617
622
  children.splice(i, 3)
618
623
  i -= 3
619
624
  }
package/src/viewdesc.ts CHANGED
@@ -387,7 +387,7 @@ export class ViewDesc {
387
387
  brKludge = !!(offset && node.nodeValue![offset - 1] == "\n")
388
388
  // Issue #1128
389
389
  if (brKludge && offset == node.nodeValue!.length) {
390
- for (let scan: DOMNode | null = node, after; scan; scan = scan.parentNode) {
390
+ for (let scan: DOMNode | null = node, after; scan; scan = scan.parentNode) {
391
391
  if (after = scan.nextSibling) {
392
392
  if (after.nodeName == "BR")
393
393
  anchorDOM = headDOM = {node: after.parentNode!, offset: domIndex(after) + 1}
@@ -1244,9 +1244,11 @@ class ViewTreeUpdater {
1244
1244
  return true
1245
1245
  } else if (!locked && (updated = this.recreateWrapper(next, node, outerDeco, innerDeco, view, pos))) {
1246
1246
  this.top.children[this.index] = updated
1247
- updated.dirty = CONTENT_DIRTY
1248
- updated.updateChildren(view, pos + 1)
1249
- updated.dirty = NOT_DIRTY
1247
+ if (updated.contentDOM) {
1248
+ updated.dirty = CONTENT_DIRTY
1249
+ updated.updateChildren(view, pos + 1)
1250
+ updated.dirty = NOT_DIRTY
1251
+ }
1250
1252
  this.changed = true
1251
1253
  this.index++
1252
1254
  return true
@@ -1264,12 +1266,12 @@ class ViewTreeUpdater {
1264
1266
  if (next.dirty || node.isAtom || !next.children.length ||
1265
1267
  !next.node.content.eq(node.content)) return null
1266
1268
  let wrapper = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos)
1267
- if (!wrapper.contentDOM) return null
1268
- wrapper.children = next.children
1269
- next.children = []
1269
+ if (wrapper.contentDOM) {
1270
+ wrapper.children = next.children
1271
+ next.children = []
1272
+ for (let ch of wrapper.children) ch.parent = wrapper
1273
+ }
1270
1274
  next.destroy()
1271
- for (let ch of wrapper.children) ch.parent = wrapper
1272
-
1273
1275
  return wrapper
1274
1276
  }
1275
1277
 
@@ -1403,10 +1405,15 @@ function iterDeco(
1403
1405
 
1404
1406
  let decoIndex = 0, active = [], restNode = null
1405
1407
  for (let parentIndex = 0;;) {
1406
- if (decoIndex < locals.length && locals[decoIndex].to == offset) {
1407
- let widget = locals[decoIndex++], widgets
1408
- while (decoIndex < locals.length && locals[decoIndex].to == offset)
1409
- (widgets || (widgets = [widget])).push(locals[decoIndex++])
1408
+ let widget, widgets
1409
+ while (decoIndex < locals.length && locals[decoIndex].to == offset) {
1410
+ let next = locals[decoIndex++]
1411
+ if (next.widget) {
1412
+ if (!widget) widget = next
1413
+ else (widgets || (widgets = [widget])).push(next)
1414
+ }
1415
+ }
1416
+ if (widget) {
1410
1417
  if (widgets) {
1411
1418
  widgets.sort(compareSide)
1412
1419
  for (let i = 0; i < widgets.length; i++) onWidget(widgets[i], parentIndex, !!restNode)