prosemirror-view 1.33.8 → 1.33.10

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,21 @@
1
+ ## 1.33.10 (2024-08-13)
2
+
3
+ ### Bug fixes
4
+
5
+ Prevent triple clicks and clicks on atom nodes from dispatching a selection update when the new selection is equal to the current selection.
6
+
7
+ Don't crash when `window.getSelection()` returns null.
8
+
9
+ Create a cursor wrapper when starting a composition with a selection that spans mark boundaries, to avoid odd DOM forms created by Chrome in such a situation.
10
+
11
+ ## 1.33.9 (2024-07-18)
12
+
13
+ ### Bug fixes
14
+
15
+ Fix an issue where dragging an image on Chrome versions before 121 failed to put the image file in the clipboard data.
16
+
17
+ Enable cross-site scripting protection hack when rendering nodes and marks inside the editor.
18
+
1
19
  ## 1.33.8 (2024-06-11)
2
20
 
3
21
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -603,6 +603,7 @@ function endOfTextblockHorizontal(view, state, dir) {
603
603
  atStart = !offset,
604
604
  atEnd = offset == $head.parent.content.size;
605
605
  var sel = view.domSelection();
606
+ if (!sel) return $head.pos == $head.start() || $head.pos == $head.end();
606
607
  if (!maybeRTL.test($head.parent.textContent) || !sel.modify) return dir == "left" || dir == "backward" ? atStart : atEnd;
607
608
  return withFlushedState(view, state, function () {
608
609
  var _view$domSelectionRan = view.domSelectionRange(),
@@ -1216,7 +1217,7 @@ var MarkViewDesc = function (_ViewDesc3) {
1216
1217
  value: function create(parent, mark, inline, view) {
1217
1218
  var custom = view.nodeViews[mark.type.name];
1218
1219
  var spec = custom && custom(mark, view, inline);
1219
- if (!spec || !spec.dom) spec = prosemirrorModel.DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline));
1220
+ if (!spec || !spec.dom) spec = prosemirrorModel.DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline), null, mark.attrs);
1220
1221
  return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom);
1221
1222
  }
1222
1223
  }]);
@@ -1415,9 +1416,9 @@ var NodeViewDesc = function (_ViewDesc4) {
1415
1416
  if (node.isText) {
1416
1417
  if (!dom) dom = document.createTextNode(node.text);else if (dom.nodeType != 3) throw new RangeError("Text must be rendered as a DOM text node");
1417
1418
  } else if (!dom) {
1418
- var _prosemirrorModel$DOM = prosemirrorModel.DOMSerializer.renderSpec(document, node.type.spec.toDOM(node));
1419
- dom = _prosemirrorModel$DOM.dom;
1420
- contentDOM = _prosemirrorModel$DOM.contentDOM;
1419
+ var _spec = prosemirrorModel.DOMSerializer.renderSpec(document, node.type.spec.toDOM(node), null, node.attrs);
1420
+ dom = _spec.dom;
1421
+ contentDOM = _spec.contentDOM;
1421
1422
  }
1422
1423
  if (!contentDOM && !node.isText && dom.nodeName != "BR") {
1423
1424
  if (!dom.hasAttribute("contenteditable")) dom.contentEditable = "false";
@@ -2214,10 +2215,17 @@ function removeClassOnSelectionChange(view) {
2214
2215
  function selectCursorWrapper(view) {
2215
2216
  var domSel = view.domSelection(),
2216
2217
  range = document.createRange();
2218
+ if (!domSel) return;
2217
2219
  var node = view.cursorWrapper.dom,
2218
2220
  img = node.nodeName == "IMG";
2219
- if (img) range.setEnd(node.parentNode, domIndex(node) + 1);else range.setEnd(node, 0);
2220
- range.collapse(false);
2221
+ if (img) range.setStart(node.parentNode, domIndex(node) + 1);else range.setStart(node, 0);
2222
+ var sel = view.state.selection;
2223
+ if (sel.empty) {
2224
+ range.collapse(true);
2225
+ } else {
2226
+ var end = view.domAtPos(sel.to);
2227
+ range.setEnd(end.node, end.offset);
2228
+ }
2221
2229
  domSel.removeAllRanges();
2222
2230
  domSel.addRange(range);
2223
2231
  if (!img && !view.state.selection.visible && ie && ie_version <= 11) {
@@ -2449,6 +2457,7 @@ function setSelFocus(view, node, offset) {
2449
2457
  }
2450
2458
  }
2451
2459
  var sel = view.domSelection();
2460
+ if (!sel) return;
2452
2461
  if (selectionCollapsed(sel)) {
2453
2462
  var range = document.createRange();
2454
2463
  range.setEnd(node, offset);
@@ -2969,6 +2978,7 @@ function runHandlerOnContext(view, propName, pos, inside, event) {
2969
2978
  }
2970
2979
  function updateSelection(view, selection, origin) {
2971
2980
  if (!view.focused) view.focus();
2981
+ if (view.state.selection.eq(selection)) return;
2972
2982
  var tr = view.state.tr.setSelection(selection);
2973
2983
  if (origin == "pointer") tr.setMeta("pointer", true);
2974
2984
  view.dispatch(tr);
@@ -3187,8 +3197,8 @@ editHandlers.compositionstart = editHandlers.compositionupdate = function (view)
3187
3197
  if (!view.composing) {
3188
3198
  view.domObserver.flush();
3189
3199
  var state = view.state,
3190
- $pos = state.selection.$from;
3191
- if (state.selection.empty && (state.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some(function (m) {
3200
+ $pos = state.selection.$to;
3201
+ if (state.selection instanceof prosemirrorState.TextSelection && (state.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some(function (m) {
3192
3202
  return m.type.spec.inclusive === false;
3193
3203
  }))) {
3194
3204
  view.markCursor = view.state.storedMarks || $pos.marks();
@@ -3202,7 +3212,8 @@ editHandlers.compositionstart = editHandlers.compositionupdate = function (view)
3202
3212
  var before = offset < 0 ? node.lastChild : node.childNodes[offset - 1];
3203
3213
  if (!before) break;
3204
3214
  if (before.nodeType == 3) {
3205
- view.domSelection().collapse(before, before.nodeValue.length);
3215
+ var _sel = view.domSelection();
3216
+ if (_sel) _sel.collapse(before, before.nodeValue.length);
3206
3217
  break;
3207
3218
  } else {
3208
3219
  node = before;
@@ -3380,7 +3391,7 @@ handlers.dragstart = function (view, _event) {
3380
3391
  dom = _serializeForClipboar2.dom,
3381
3392
  text = _serializeForClipboar2.text,
3382
3393
  slice = _serializeForClipboar2.slice;
3383
- event.dataTransfer.clearData();
3394
+ if (!event.dataTransfer.files.length || !chrome || chrome_version > 120) event.dataTransfer.clearData();
3384
3395
  event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
3385
3396
  event.dataTransfer.effectAllowed = "copyMove";
3386
3397
  if (!brokenClipboardAPI) event.dataTransfer.setData("text/plain", text);
@@ -4562,9 +4573,9 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
4562
4573
  };
4563
4574
  } else {
4564
4575
  if (parse.sel) {
4565
- var _sel = resolveSelection(view, view.state.doc, parse.sel);
4566
- if (_sel && !_sel.eq(view.state.selection)) {
4567
- var _tr2 = view.state.tr.setSelection(_sel);
4576
+ var _sel2 = resolveSelection(view, view.state.doc, parse.sel);
4577
+ if (_sel2 && !_sel2.eq(view.state.selection)) {
4578
+ var _tr2 = view.state.tr.setSelection(_sel2);
4568
4579
  if (compositionID) _tr2.setMeta("composition", compositionID);
4569
4580
  view.dispatch(_tr2);
4570
4581
  }
@@ -4641,8 +4652,8 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
4641
4652
  }
4642
4653
  if (!tr) tr = view.state.tr.replace(chFrom, chTo, parse.doc.slice(change.start - parse.from, change.endB - parse.from));
4643
4654
  if (parse.sel) {
4644
- var _sel2 = resolveSelection(view, tr.doc, parse.sel);
4645
- if (_sel2 && !(chrome && android && view.composing && _sel2.empty && (change.start != change.endB || view.input.lastAndroidDelete < Date.now() - 100) && (_sel2.head == chFrom || _sel2.head == tr.mapping.map(chTo) - 1) || ie && _sel2.empty && _sel2.head == chFrom)) tr.setSelection(_sel2);
4655
+ var _sel3 = resolveSelection(view, tr.doc, parse.sel);
4656
+ if (_sel3 && !(chrome && android && view.composing && _sel3.empty && (change.start != change.endB || view.input.lastAndroidDelete < Date.now() - 100) && (_sel3.head == chFrom || _sel3.head == tr.mapping.map(chTo) - 1) || ie && _sel3.empty && _sel3.head == chFrom)) tr.setSelection(_sel3);
4646
4657
  }
4647
4658
  if (storedMarks) tr.ensureMarks(storedMarks);
4648
4659
  if (compositionID) tr.setMeta("composition", compositionID);
@@ -5096,6 +5107,12 @@ var EditorView = function () {
5096
5107
  key: "domSelectionRange",
5097
5108
  value: function domSelectionRange() {
5098
5109
  var sel = this.domSelection();
5110
+ if (!sel) return {
5111
+ focusNode: null,
5112
+ focusOffset: 0,
5113
+ anchorNode: null,
5114
+ anchorOffset: 0
5115
+ };
5099
5116
  return safari && this.root.nodeType === 11 && deepActiveElement(this.dom.ownerDocument) == this.dom && safariShadowSelectionRange(this, sel) || sel;
5100
5117
  }
5101
5118
  }, {
@@ -5127,7 +5144,7 @@ function updateCursorWrapper(view) {
5127
5144
  dom.setAttribute("alt", "");
5128
5145
  view.cursorWrapper = {
5129
5146
  dom: dom,
5130
- deco: Decoration.widget(view.state.selection.head, dom, {
5147
+ deco: Decoration.widget(view.state.selection.from, dom, {
5131
5148
  raw: true,
5132
5149
  marks: view.markCursor
5133
5150
  })
package/dist/index.js CHANGED
@@ -659,6 +659,8 @@ function endOfTextblockHorizontal(view, state, dir) {
659
659
  return false;
660
660
  let offset = $head.parentOffset, atStart = !offset, atEnd = offset == $head.parent.content.size;
661
661
  let sel = view.domSelection();
662
+ if (!sel)
663
+ return $head.pos == $head.start() || $head.pos == $head.end();
662
664
  // If the textblock is all LTR, or the browser doesn't support
663
665
  // Selection.modify (Edge), fall back to a primitive approach
664
666
  if (!maybeRTL.test($head.parent.textContent) || !sel.modify)
@@ -1195,7 +1197,7 @@ class MarkViewDesc extends ViewDesc {
1195
1197
  let custom = view.nodeViews[mark.type.name];
1196
1198
  let spec = custom && custom(mark, view, inline);
1197
1199
  if (!spec || !spec.dom)
1198
- spec = DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline));
1200
+ spec = DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline), null, mark.attrs);
1199
1201
  return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom);
1200
1202
  }
1201
1203
  parseRule() {
@@ -1267,7 +1269,8 @@ class NodeViewDesc extends ViewDesc {
1267
1269
  throw new RangeError("Text must be rendered as a DOM text node");
1268
1270
  }
1269
1271
  else if (!dom) {
1270
- ({ dom, contentDOM } = DOMSerializer.renderSpec(document, node.type.spec.toDOM(node)));
1272
+ let spec = DOMSerializer.renderSpec(document, node.type.spec.toDOM(node), null, node.attrs);
1273
+ ({ dom, contentDOM } = spec);
1271
1274
  }
1272
1275
  if (!contentDOM && !node.isText && dom.nodeName != "BR") { // Chrome gets confused by <br contenteditable=false>
1273
1276
  if (!dom.hasAttribute("contenteditable"))
@@ -2280,12 +2283,21 @@ function removeClassOnSelectionChange(view) {
2280
2283
  }
2281
2284
  function selectCursorWrapper(view) {
2282
2285
  let domSel = view.domSelection(), range = document.createRange();
2286
+ if (!domSel)
2287
+ return;
2283
2288
  let node = view.cursorWrapper.dom, img = node.nodeName == "IMG";
2284
2289
  if (img)
2285
- range.setEnd(node.parentNode, domIndex(node) + 1);
2290
+ range.setStart(node.parentNode, domIndex(node) + 1);
2286
2291
  else
2287
- range.setEnd(node, 0);
2288
- range.collapse(false);
2292
+ range.setStart(node, 0);
2293
+ let sel = view.state.selection;
2294
+ if (sel.empty) {
2295
+ range.collapse(true);
2296
+ }
2297
+ else {
2298
+ let end = view.domAtPos(sel.to);
2299
+ range.setEnd(end.node, end.offset);
2300
+ }
2289
2301
  domSel.removeAllRanges();
2290
2302
  domSel.addRange(range);
2291
2303
  // Kludge to kill 'control selection' in IE11 when selecting an
@@ -2573,6 +2585,8 @@ function setSelFocus(view, node, offset) {
2573
2585
  }
2574
2586
  }
2575
2587
  let sel = view.domSelection();
2588
+ if (!sel)
2589
+ return;
2576
2590
  if (selectionCollapsed(sel)) {
2577
2591
  let range = document.createRange();
2578
2592
  range.setEnd(node, offset);
@@ -3139,6 +3153,8 @@ function runHandlerOnContext(view, propName, pos, inside, event) {
3139
3153
  function updateSelection(view, selection, origin) {
3140
3154
  if (!view.focused)
3141
3155
  view.focus();
3156
+ if (view.state.selection.eq(selection))
3157
+ return;
3142
3158
  let tr = view.state.tr.setSelection(selection);
3143
3159
  if (origin == "pointer")
3144
3160
  tr.setMeta("pointer", true);
@@ -3393,8 +3409,8 @@ const timeoutComposition = android ? 5000 : -1;
3393
3409
  editHandlers.compositionstart = editHandlers.compositionupdate = view => {
3394
3410
  if (!view.composing) {
3395
3411
  view.domObserver.flush();
3396
- let { state } = view, $pos = state.selection.$from;
3397
- if (state.selection.empty &&
3412
+ let { state } = view, $pos = state.selection.$to;
3413
+ if (state.selection instanceof TextSelection &&
3398
3414
  (state.storedMarks ||
3399
3415
  (!$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some(m => m.type.spec.inclusive === false)))) {
3400
3416
  // Need to wrap the cursor in mark nodes different from the ones in the DOM context
@@ -3414,7 +3430,9 @@ editHandlers.compositionstart = editHandlers.compositionupdate = view => {
3414
3430
  if (!before)
3415
3431
  break;
3416
3432
  if (before.nodeType == 3) {
3417
- view.domSelection().collapse(before, before.nodeValue.length);
3433
+ let sel = view.domSelection();
3434
+ if (sel)
3435
+ sel.collapse(before, before.nodeValue.length);
3418
3436
  break;
3419
3437
  }
3420
3438
  else {
@@ -3631,7 +3649,9 @@ handlers.dragstart = (view, _event) => {
3631
3649
  }
3632
3650
  let draggedSlice = (node || view.state.selection).content();
3633
3651
  let { dom, text, slice } = serializeForClipboard(view, draggedSlice);
3634
- event.dataTransfer.clearData();
3652
+ // Pre-120 Chrome versions clear files when calling `clearData` (#1472)
3653
+ if (!event.dataTransfer.files.length || !chrome || chrome_version > 120)
3654
+ event.dataTransfer.clearData();
3635
3655
  event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
3636
3656
  // See https://github.com/ProseMirror/prosemirror/issues/1156
3637
3657
  event.dataTransfer.effectAllowed = "copyMove";
@@ -5643,6 +5663,8 @@ class EditorView {
5643
5663
  */
5644
5664
  domSelectionRange() {
5645
5665
  let sel = this.domSelection();
5666
+ if (!sel)
5667
+ return { focusNode: null, focusOffset: 0, anchorNode: null, anchorOffset: 0 };
5646
5668
  return safari && this.root.nodeType === 11 &&
5647
5669
  deepActiveElement(this.dom.ownerDocument) == this.dom && safariShadowSelectionRange(this, sel) || sel;
5648
5670
  }
@@ -5680,7 +5702,7 @@ function updateCursorWrapper(view) {
5680
5702
  dom.className = "ProseMirror-separator";
5681
5703
  dom.setAttribute("mark-placeholder", "true");
5682
5704
  dom.setAttribute("alt", "");
5683
- view.cursorWrapper = { dom, deco: Decoration.widget(view.state.selection.head, dom, { raw: true, marks: view.markCursor }) };
5705
+ view.cursorWrapper = { dom, deco: Decoration.widget(view.state.selection.from, dom, { raw: true, marks: view.markCursor }) };
5684
5706
  }
5685
5707
  else {
5686
5708
  view.cursorWrapper = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prosemirror-view",
3
- "version": "1.33.8",
3
+ "version": "1.33.10",
4
4
  "description": "ProseMirror's view component",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -202,6 +202,7 @@ function setSelFocus(view: EditorView, node: Node, offset: number) {
202
202
  }
203
203
 
204
204
  let sel = view.domSelection()
205
+ if (!sel) return
205
206
  if (selectionCollapsed(sel)) {
206
207
  let range = document.createRange()
207
208
  range.setEnd(node, offset)
package/src/domcoords.ts CHANGED
@@ -465,7 +465,8 @@ function endOfTextblockHorizontal(view: EditorView, state: EditorState, dir: "le
465
465
  let {$head} = state.selection
466
466
  if (!$head.parent.isTextblock) return false
467
467
  let offset = $head.parentOffset, atStart = !offset, atEnd = offset == $head.parent.content.size
468
- let sel = view.domSelection()
468
+ let sel: Selection = view.domSelection()!
469
+ if (!sel) return $head.pos == $head.start() || $head.pos == $head.end()
469
470
  // If the textblock is all LTR, or the browser doesn't support
470
471
  // Selection.modify (Edge), fall back to a primitive approach
471
472
  if (!maybeRTL.test($head.parent.textContent) || !(sel as any).modify)
package/src/index.ts CHANGED
@@ -489,13 +489,14 @@ export class EditorView {
489
489
  /// @internal
490
490
  domSelectionRange(): DOMSelectionRange {
491
491
  let sel = this.domSelection()
492
+ if (!sel) return {focusNode: null, focusOffset: 0, anchorNode: null, anchorOffset: 0}
492
493
  return browser.safari && this.root.nodeType === 11 &&
493
494
  deepActiveElement(this.dom.ownerDocument) == this.dom && safariShadowSelectionRange(this, sel) || sel
494
495
  }
495
496
 
496
497
  /// @internal
497
- domSelection(): DOMSelection {
498
- return (this.root as Document).getSelection()!
498
+ domSelection(): DOMSelection | null {
499
+ return (this.root as Document).getSelection()
499
500
  }
500
501
  }
501
502
 
@@ -526,7 +527,7 @@ function updateCursorWrapper(view: EditorView) {
526
527
  dom.className = "ProseMirror-separator"
527
528
  dom.setAttribute("mark-placeholder", "true")
528
529
  dom.setAttribute("alt", "")
529
- view.cursorWrapper = {dom, deco: Decoration.widget(view.state.selection.head,
530
+ view.cursorWrapper = {dom, deco: Decoration.widget(view.state.selection.from,
530
531
  dom, {raw: true, marks: view.markCursor} as any)}
531
532
  } else {
532
533
  view.cursorWrapper = null
package/src/input.ts CHANGED
@@ -183,6 +183,7 @@ function runHandlerOnContext(
183
183
 
184
184
  function updateSelection(view: EditorView, selection: Selection, origin: string) {
185
185
  if (!view.focused) view.focus()
186
+ if (view.state.selection.eq(selection)) return
186
187
  let tr = view.state.tr.setSelection(selection)
187
188
  if (origin == "pointer") tr.setMeta("pointer", true)
188
189
  view.dispatch(tr)
@@ -453,8 +454,8 @@ const timeoutComposition = browser.android ? 5000 : -1
453
454
  editHandlers.compositionstart = editHandlers.compositionupdate = view => {
454
455
  if (!view.composing) {
455
456
  view.domObserver.flush()
456
- let {state} = view, $pos = state.selection.$from
457
- if (state.selection.empty &&
457
+ let {state} = view, $pos = state.selection.$to
458
+ if (state.selection instanceof TextSelection &&
458
459
  (state.storedMarks ||
459
460
  (!$pos.textOffset && $pos.parentOffset && $pos.nodeBefore!.marks.some(m => m.type.spec.inclusive === false)))) {
460
461
  // Need to wrap the cursor in mark nodes different from the ones in the DOM context
@@ -472,7 +473,8 @@ editHandlers.compositionstart = editHandlers.compositionupdate = view => {
472
473
  let before = offset < 0 ? node.lastChild : node.childNodes[offset - 1]
473
474
  if (!before) break
474
475
  if (before.nodeType == 3) {
475
- view.domSelection().collapse(before, before.nodeValue!.length)
476
+ let sel = view.domSelection()
477
+ if (sel) sel.collapse(before, before.nodeValue!.length)
476
478
  break
477
479
  } else {
478
480
  node = before
@@ -677,7 +679,9 @@ handlers.dragstart = (view, _event) => {
677
679
  }
678
680
  let draggedSlice = (node || view.state.selection).content()
679
681
  let {dom, text, slice} = serializeForClipboard(view, draggedSlice)
680
- event.dataTransfer.clearData()
682
+ // Pre-120 Chrome versions clear files when calling `clearData` (#1472)
683
+ if (!event.dataTransfer.files.length || !browser.chrome || browser.chrome_version > 120)
684
+ event.dataTransfer.clearData()
681
685
  event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML)
682
686
  // See https://github.com/ProseMirror/prosemirror/issues/1156
683
687
  event.dataTransfer.effectAllowed = "copyMove"
package/src/selection.ts CHANGED
@@ -136,10 +136,17 @@ function removeClassOnSelectionChange(view: EditorView) {
136
136
 
137
137
  function selectCursorWrapper(view: EditorView) {
138
138
  let domSel = view.domSelection(), range = document.createRange()
139
+ if (!domSel) return
139
140
  let node = view.cursorWrapper!.dom, img = node.nodeName == "IMG"
140
- if (img) range.setEnd(node.parentNode!, domIndex(node) + 1)
141
- else range.setEnd(node, 0)
142
- range.collapse(false)
141
+ if (img) range.setStart(node.parentNode!, domIndex(node) + 1)
142
+ else range.setStart(node, 0)
143
+ let sel = view.state.selection
144
+ if (sel.empty) {
145
+ range.collapse(true)
146
+ } else {
147
+ let end = view.domAtPos(sel.to)
148
+ range.setEnd(end.node, end.offset)
149
+ }
143
150
  domSel.removeAllRanges()
144
151
  domSel.addRange(range)
145
152
  // Kludge to kill 'control selection' in IE11 when selecting an
package/src/viewdesc.ts CHANGED
@@ -572,7 +572,7 @@ class MarkViewDesc extends ViewDesc {
572
572
  let custom = view.nodeViews[mark.type.name]
573
573
  let spec: {dom: HTMLElement, contentDOM?: HTMLElement} = custom && (custom as any)(mark, view, inline)
574
574
  if (!spec || !spec.dom)
575
- spec = DOMSerializer.renderSpec(document, mark.type.spec.toDOM!(mark, inline)) as any
575
+ spec = (DOMSerializer.renderSpec as any)(document, mark.type.spec.toDOM!(mark, inline), null, mark.attrs) as any
576
576
  return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom as HTMLElement)
577
577
  }
578
578
 
@@ -647,7 +647,8 @@ export class NodeViewDesc extends ViewDesc {
647
647
  if (!dom) dom = document.createTextNode(node.text!)
648
648
  else if (dom.nodeType != 3) throw new RangeError("Text must be rendered as a DOM text node")
649
649
  } else if (!dom) {
650
- ;({dom, contentDOM} = DOMSerializer.renderSpec(document, node.type.spec.toDOM!(node)))
650
+ let spec = (DOMSerializer.renderSpec as any)(document, node.type.spec.toDOM!(node), null, node.attrs)
651
+ ;({dom, contentDOM} = spec as {dom: DOMNode, contentDOM?: HTMLElement})
651
652
  }
652
653
  if (!contentDOM && !node.isText && dom.nodeName != "BR") { // Chrome gets confused by <br contenteditable=false>
653
654
  if (!(dom as HTMLElement).hasAttribute("contenteditable")) (dom as HTMLElement).contentEditable = "false"