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 +18 -0
- package/dist/index.cjs +33 -16
- package/dist/index.js +32 -10
- package/package.json +1 -1
- package/src/capturekeys.ts +1 -0
- package/src/domcoords.ts +2 -1
- package/src/index.ts +4 -3
- package/src/input.ts +8 -4
- package/src/selection.ts +10 -3
- package/src/viewdesc.ts +3 -2
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
|
|
1419
|
-
dom =
|
|
1420
|
-
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.
|
|
2220
|
-
|
|
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.$
|
|
3191
|
-
if (state.selection.
|
|
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()
|
|
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
|
|
4566
|
-
if (
|
|
4567
|
-
var _tr2 = view.state.tr.setSelection(
|
|
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
|
|
4645
|
-
if (
|
|
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.
|
|
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
|
-
|
|
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.
|
|
2290
|
+
range.setStart(node.parentNode, domIndex(node) + 1);
|
|
2286
2291
|
else
|
|
2287
|
-
range.
|
|
2288
|
-
|
|
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.$
|
|
3397
|
-
if (state.selection
|
|
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()
|
|
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
|
-
|
|
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.
|
|
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
package/src/capturekeys.ts
CHANGED
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.
|
|
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.$
|
|
457
|
-
if (state.selection
|
|
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()
|
|
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
|
-
|
|
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.
|
|
141
|
-
else range.
|
|
142
|
-
|
|
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
|
-
|
|
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"
|