prosemirror-view 1.41.7 → 1.41.9
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 -2
- package/CONTRIBUTING.md +19 -19
- package/README.md +3 -3
- package/dist/index.cjs +164 -96
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +105 -64
- package/package.json +3 -3
- package/src/domchange.ts +3 -13
- package/src/domobserver.ts +4 -1
- package/src/index.ts +4 -3
- package/src/input.ts +94 -39
- package/src/selection.ts +6 -6
- package/src/viewdesc.ts +8 -8
- package/style/prosemirror.css +1 -1
package/dist/index.js
CHANGED
|
@@ -2244,14 +2244,14 @@ function selectionToDOM(view, force = false) {
|
|
|
2244
2244
|
syncNodeSelection(view, sel);
|
|
2245
2245
|
if (!editorOwnsSelection(view))
|
|
2246
2246
|
return;
|
|
2247
|
-
//
|
|
2248
|
-
//
|
|
2249
|
-
|
|
2250
|
-
if (!force &&
|
|
2247
|
+
// Need to delay selection normalization during a native selection
|
|
2248
|
+
// drag on Chrome, or it will cause further dragging to glitch.
|
|
2249
|
+
let mouseDown = view.input.mouseDown;
|
|
2250
|
+
if (!force && chrome && mouseDown) {
|
|
2251
2251
|
let domSel = view.domSelectionRange(), curSel = view.domObserver.currentSelection;
|
|
2252
2252
|
if (domSel.anchorNode && curSel.anchorNode &&
|
|
2253
|
-
isEquivalentPosition(domSel.anchorNode, domSel.anchorOffset, curSel.anchorNode, curSel.anchorOffset)
|
|
2254
|
-
|
|
2253
|
+
isEquivalentPosition(domSel.anchorNode, domSel.anchorOffset, curSel.anchorNode, curSel.anchorOffset) &&
|
|
2254
|
+
mouseDown.delaySelUpdate()) {
|
|
2255
2255
|
view.domObserver.setCurSelection();
|
|
2256
2256
|
return;
|
|
2257
2257
|
}
|
|
@@ -3103,6 +3103,8 @@ function setSelectionOrigin(view, origin) {
|
|
|
3103
3103
|
view.input.lastSelectionTime = Date.now();
|
|
3104
3104
|
}
|
|
3105
3105
|
function destroyInput(view) {
|
|
3106
|
+
if (view.input.mouseDown)
|
|
3107
|
+
view.input.mouseDown.done();
|
|
3106
3108
|
view.domObserver.stop();
|
|
3107
3109
|
for (let type in view.input.eventHandlers)
|
|
3108
3110
|
view.dom.removeEventListener(type, view.input.eventHandlers[type]);
|
|
@@ -3141,7 +3143,7 @@ function dispatchEvent(view, event) {
|
|
|
3141
3143
|
editHandlers.keydown = (view, _event) => {
|
|
3142
3144
|
let event = _event;
|
|
3143
3145
|
view.input.shiftKey = event.keyCode == 16 || event.shiftKey;
|
|
3144
|
-
if (inOrNearComposition(view
|
|
3146
|
+
if (inOrNearComposition(view))
|
|
3145
3147
|
return;
|
|
3146
3148
|
view.input.lastKeyCode = event.keyCode;
|
|
3147
3149
|
view.input.lastKeyCodeTime = Date.now();
|
|
@@ -3179,7 +3181,7 @@ editHandlers.keyup = (view, event) => {
|
|
|
3179
3181
|
};
|
|
3180
3182
|
editHandlers.keypress = (view, _event) => {
|
|
3181
3183
|
let event = _event;
|
|
3182
|
-
if (inOrNearComposition(view
|
|
3184
|
+
if (inOrNearComposition(view) || !event.charCode ||
|
|
3183
3185
|
event.ctrlKey && !event.altKey || mac && event.metaKey)
|
|
3184
3186
|
return;
|
|
3185
3187
|
if (view.someProp("handleKeyPress", f => f(view, event))) {
|
|
@@ -3274,26 +3276,28 @@ function handleTripleClick(view, pos, inside, event) {
|
|
|
3274
3276
|
function defaultTripleClick(view, inside, event) {
|
|
3275
3277
|
if (event.button != 0)
|
|
3276
3278
|
return false;
|
|
3277
|
-
let doc = view.state.doc;
|
|
3278
|
-
if (
|
|
3279
|
-
if (doc.inlineContent) {
|
|
3280
|
-
updateSelection(view, TextSelection.create(doc, 0, doc.content.size), "pointer");
|
|
3281
|
-
return true;
|
|
3282
|
-
}
|
|
3279
|
+
let selection = selectionForTripleClick(view, inside, true), doc = view.state.doc;
|
|
3280
|
+
if (!selection)
|
|
3283
3281
|
return false;
|
|
3284
|
-
|
|
3282
|
+
updateSelection(view, selection, "pointer");
|
|
3283
|
+
if (selection instanceof TextSelection && doc.eq(view.state.doc))
|
|
3284
|
+
view.input.mouseDown = new TripleClickDrag(view, selection);
|
|
3285
|
+
return true;
|
|
3286
|
+
}
|
|
3287
|
+
function selectionForTripleClick(view, inside, selectNodes) {
|
|
3288
|
+
let doc = view.state.doc;
|
|
3289
|
+
if (inside == -1)
|
|
3290
|
+
return doc.inlineContent ? TextSelection.create(doc, 0, doc.content.size) : null;
|
|
3285
3291
|
let $pos = doc.resolve(inside);
|
|
3286
3292
|
for (let i = $pos.depth + 1; i > 0; i--) {
|
|
3287
3293
|
let node = i > $pos.depth ? $pos.nodeAfter : $pos.node(i);
|
|
3288
3294
|
let nodePos = $pos.before(i);
|
|
3289
3295
|
if (node.inlineContent)
|
|
3290
|
-
|
|
3291
|
-
else if (NodeSelection.isSelectable(node))
|
|
3292
|
-
|
|
3293
|
-
else
|
|
3294
|
-
continue;
|
|
3295
|
-
return true;
|
|
3296
|
+
return TextSelection.create(doc, nodePos + 1, nodePos + 1 + node.content.size);
|
|
3297
|
+
else if (selectNodes && NodeSelection.isSelectable(node))
|
|
3298
|
+
return NodeSelection.create(doc, nodePos);
|
|
3296
3299
|
}
|
|
3300
|
+
return null;
|
|
3297
3301
|
}
|
|
3298
3302
|
function forceDOMFlush(view) {
|
|
3299
3303
|
return endComposition(view);
|
|
@@ -3312,13 +3316,13 @@ handlers.mousedown = (view, _event) => {
|
|
|
3312
3316
|
type = "tripleClick";
|
|
3313
3317
|
}
|
|
3314
3318
|
view.input.lastClick = { time: now, x: event.clientX, y: event.clientY, type, button: event.button };
|
|
3319
|
+
if (view.input.mouseDown)
|
|
3320
|
+
view.input.mouseDown.done();
|
|
3315
3321
|
let pos = view.posAtCoords(eventCoords(event));
|
|
3316
3322
|
if (!pos)
|
|
3317
3323
|
return;
|
|
3318
3324
|
if (type == "singleClick") {
|
|
3319
|
-
|
|
3320
|
-
view.input.mouseDown.done();
|
|
3321
|
-
view.input.mouseDown = new MouseDown(view, pos, event, !!flushed);
|
|
3325
|
+
view.input.mouseDown = new LeftMouseDown(view, pos, event, !!flushed);
|
|
3322
3326
|
}
|
|
3323
3327
|
else if ((type == "doubleClick" ? handleDoubleClick : handleTripleClick)(view, pos.pos, pos.inside, event)) {
|
|
3324
3328
|
event.preventDefault();
|
|
@@ -3328,13 +3332,34 @@ handlers.mousedown = (view, _event) => {
|
|
|
3328
3332
|
}
|
|
3329
3333
|
};
|
|
3330
3334
|
class MouseDown {
|
|
3331
|
-
constructor(view
|
|
3335
|
+
constructor(view) {
|
|
3332
3336
|
this.view = view;
|
|
3337
|
+
this.mightDrag = null;
|
|
3338
|
+
view.root.addEventListener("mouseup", this.up = this.up.bind(this));
|
|
3339
|
+
view.root.addEventListener("mousemove", this.move = this.move.bind(this));
|
|
3340
|
+
}
|
|
3341
|
+
up(event) {
|
|
3342
|
+
this.done();
|
|
3343
|
+
}
|
|
3344
|
+
move(event) {
|
|
3345
|
+
if (event.buttons == 0)
|
|
3346
|
+
this.done();
|
|
3347
|
+
}
|
|
3348
|
+
done() {
|
|
3349
|
+
this.view.root.removeEventListener("mouseup", this.up);
|
|
3350
|
+
this.view.root.removeEventListener("mousemove", this.move);
|
|
3351
|
+
if (this.view.input.mouseDown == this)
|
|
3352
|
+
this.view.input.mouseDown = null;
|
|
3353
|
+
}
|
|
3354
|
+
delaySelUpdate() { return false; }
|
|
3355
|
+
}
|
|
3356
|
+
class LeftMouseDown extends MouseDown {
|
|
3357
|
+
constructor(view, pos, event, flushed) {
|
|
3358
|
+
super(view);
|
|
3333
3359
|
this.pos = pos;
|
|
3334
3360
|
this.event = event;
|
|
3335
3361
|
this.flushed = flushed;
|
|
3336
3362
|
this.delayedSelectionSync = false;
|
|
3337
|
-
this.mightDrag = null;
|
|
3338
3363
|
this.startDoc = view.state.doc;
|
|
3339
3364
|
this.selectNode = !!event[selectNodeModifier];
|
|
3340
3365
|
this.allowDefault = event.shiftKey;
|
|
@@ -3353,8 +3378,8 @@ class MouseDown {
|
|
|
3353
3378
|
this.target = targetDesc && targetDesc.nodeDOM.nodeType == 1 ? targetDesc.nodeDOM : null;
|
|
3354
3379
|
let { selection } = view.state;
|
|
3355
3380
|
if (event.button == 0 &&
|
|
3356
|
-
targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
|
|
3357
|
-
|
|
3381
|
+
(targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
|
|
3382
|
+
selection instanceof NodeSelection && selection.from <= targetPos && selection.to > targetPos))
|
|
3358
3383
|
this.mightDrag = {
|
|
3359
3384
|
node: targetNode,
|
|
3360
3385
|
pos: targetPos,
|
|
@@ -3372,13 +3397,10 @@ class MouseDown {
|
|
|
3372
3397
|
}, 20);
|
|
3373
3398
|
this.view.domObserver.start();
|
|
3374
3399
|
}
|
|
3375
|
-
view.root.addEventListener("mouseup", this.up = this.up.bind(this));
|
|
3376
|
-
view.root.addEventListener("mousemove", this.move = this.move.bind(this));
|
|
3377
3400
|
setSelectionOrigin(view, "pointer");
|
|
3378
3401
|
}
|
|
3379
3402
|
done() {
|
|
3380
|
-
|
|
3381
|
-
this.view.root.removeEventListener("mousemove", this.move);
|
|
3403
|
+
super.done();
|
|
3382
3404
|
if (this.mightDrag && this.target) {
|
|
3383
3405
|
this.view.domObserver.stop();
|
|
3384
3406
|
if (this.mightDrag.addAttr)
|
|
@@ -3388,8 +3410,10 @@ class MouseDown {
|
|
|
3388
3410
|
this.view.domObserver.start();
|
|
3389
3411
|
}
|
|
3390
3412
|
if (this.delayedSelectionSync)
|
|
3391
|
-
setTimeout(() =>
|
|
3392
|
-
|
|
3413
|
+
setTimeout(() => {
|
|
3414
|
+
if (!this.view.isDestroyed)
|
|
3415
|
+
selectionToDOM(this.view);
|
|
3416
|
+
});
|
|
3393
3417
|
}
|
|
3394
3418
|
up(event) {
|
|
3395
3419
|
this.done();
|
|
@@ -3428,14 +3452,41 @@ class MouseDown {
|
|
|
3428
3452
|
move(event) {
|
|
3429
3453
|
this.updateAllowDefault(event);
|
|
3430
3454
|
setSelectionOrigin(this.view, "pointer");
|
|
3431
|
-
|
|
3432
|
-
this.done();
|
|
3455
|
+
super.move(event);
|
|
3433
3456
|
}
|
|
3434
3457
|
updateAllowDefault(event) {
|
|
3435
3458
|
if (!this.allowDefault && (Math.abs(this.event.x - event.clientX) > 4 ||
|
|
3436
3459
|
Math.abs(this.event.y - event.clientY) > 4))
|
|
3437
3460
|
this.allowDefault = true;
|
|
3438
3461
|
}
|
|
3462
|
+
delaySelUpdate() {
|
|
3463
|
+
if (!this.allowDefault)
|
|
3464
|
+
return false;
|
|
3465
|
+
this.delayedSelectionSync = true;
|
|
3466
|
+
return true;
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
class TripleClickDrag extends MouseDown {
|
|
3470
|
+
constructor(view, startSelection) {
|
|
3471
|
+
super(view);
|
|
3472
|
+
this.startSelection = startSelection;
|
|
3473
|
+
this.startDoc = view.state.doc;
|
|
3474
|
+
}
|
|
3475
|
+
move(event) {
|
|
3476
|
+
if (event.buttons == 0 || this.view.isDestroyed || !this.view.state.doc.eq(this.startDoc)) {
|
|
3477
|
+
this.done();
|
|
3478
|
+
return;
|
|
3479
|
+
}
|
|
3480
|
+
event.preventDefault();
|
|
3481
|
+
setSelectionOrigin(this.view, "pointer");
|
|
3482
|
+
let pos = this.view.posAtCoords(eventCoords(event));
|
|
3483
|
+
let target = pos && selectionForTripleClick(this.view, pos.inside, false);
|
|
3484
|
+
if (!target)
|
|
3485
|
+
return;
|
|
3486
|
+
let { doc } = this.view.state, start = this.startSelection;
|
|
3487
|
+
let [anchor, head] = target.from < start.from ? [start.to, target.from] : [start.from, target.to];
|
|
3488
|
+
updateSelection(this.view, TextSelection.create(doc, anchor, head), "pointer");
|
|
3489
|
+
}
|
|
3439
3490
|
}
|
|
3440
3491
|
handlers.touchstart = view => {
|
|
3441
3492
|
view.input.lastTouch = Date.now();
|
|
@@ -3460,7 +3511,7 @@ function inOrNearComposition(view, event) {
|
|
|
3460
3511
|
// This guards against the case where compositionend is triggered without the keyboard
|
|
3461
3512
|
// (e.g. character confirmation may be done with the mouse), and keydown is triggered
|
|
3462
3513
|
// afterwards- we wouldn't want to ignore the keydown event in this case.
|
|
3463
|
-
if (safari && Math.abs(
|
|
3514
|
+
if (safari && Math.abs(Date.now() - view.input.compositionEndedAt) < 500) {
|
|
3464
3515
|
view.input.compositionEndedAt = -2e8;
|
|
3465
3516
|
return true;
|
|
3466
3517
|
}
|
|
@@ -3519,7 +3570,7 @@ function selectionBeforeUneditable(view) {
|
|
|
3519
3570
|
editHandlers.compositionend = (view, event) => {
|
|
3520
3571
|
if (view.composing) {
|
|
3521
3572
|
view.input.composing = false;
|
|
3522
|
-
view.input.compositionEndedAt =
|
|
3573
|
+
view.input.compositionEndedAt = Date.now();
|
|
3523
3574
|
view.input.compositionPendingChanges = view.domObserver.pendingRecords().length ? view.input.compositionID : 0;
|
|
3524
3575
|
view.input.compositionNode = null;
|
|
3525
3576
|
if (view.input.badSafariComposition)
|
|
@@ -3538,7 +3589,7 @@ function scheduleComposeEnd(view, delay) {
|
|
|
3538
3589
|
function clearComposition(view) {
|
|
3539
3590
|
if (view.composing) {
|
|
3540
3591
|
view.input.composing = false;
|
|
3541
|
-
view.input.compositionEndedAt =
|
|
3592
|
+
view.input.compositionEndedAt = Date.now();
|
|
3542
3593
|
}
|
|
3543
3594
|
while (view.input.compositionNodes.length > 0)
|
|
3544
3595
|
view.input.compositionNodes.pop().markParentsDirty();
|
|
@@ -3564,11 +3615,6 @@ function findCompositionNode(view) {
|
|
|
3564
3615
|
}
|
|
3565
3616
|
return textBefore || textAfter;
|
|
3566
3617
|
}
|
|
3567
|
-
function timestampFromCustomEvent() {
|
|
3568
|
-
let event = document.createEvent("Event");
|
|
3569
|
-
event.initEvent("event", true, true);
|
|
3570
|
-
return event.timeStamp;
|
|
3571
|
-
}
|
|
3572
3618
|
/**
|
|
3573
3619
|
@internal
|
|
3574
3620
|
*/
|
|
@@ -3703,8 +3749,9 @@ class Dragging {
|
|
|
3703
3749
|
}
|
|
3704
3750
|
const dragCopyModifier = mac ? "altKey" : "ctrlKey";
|
|
3705
3751
|
function dragMoves(view, event) {
|
|
3706
|
-
let
|
|
3707
|
-
|
|
3752
|
+
let copy;
|
|
3753
|
+
view.someProp("dragCopies", test => { copy = copy || test(event); });
|
|
3754
|
+
return copy != null ? !copy : !event[dragCopyModifier];
|
|
3708
3755
|
}
|
|
3709
3756
|
handlers.dragstart = (view, _event) => {
|
|
3710
3757
|
let event = _event;
|
|
@@ -3731,7 +3778,7 @@ handlers.dragstart = (view, _event) => {
|
|
|
3731
3778
|
if (!event.dataTransfer.files.length || !chrome || chrome_version > 120)
|
|
3732
3779
|
event.dataTransfer.clearData();
|
|
3733
3780
|
event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
|
|
3734
|
-
// See https://
|
|
3781
|
+
// See https://code.haverbeke.berlin/prosemirror/prosemirror/issues/1156
|
|
3735
3782
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
3736
3783
|
if (!brokenClipboardAPI)
|
|
3737
3784
|
event.dataTransfer.setData("text/plain", text);
|
|
@@ -4724,7 +4771,10 @@ class DOMObserver {
|
|
|
4724
4771
|
}
|
|
4725
4772
|
}
|
|
4726
4773
|
}
|
|
4727
|
-
if (added.some(n => n.nodeName == "BR") &&
|
|
4774
|
+
if (added.some(n => n.nodeName == "BR") &&
|
|
4775
|
+
(view.input.lastKeyCode == 8 || view.input.lastKeyCode == 46 ||
|
|
4776
|
+
chrome && (view.composing || view.input.compositionEndedAt > Date.now() - 50) &&
|
|
4777
|
+
mutations.some(m => m.type == "childList" && m.removedNodes.length))) {
|
|
4728
4778
|
// Browsers sometimes insert a bogus break node if you
|
|
4729
4779
|
// backspace out the last bit of text before an inline-flex node (#1552)
|
|
4730
4780
|
for (let node of added)
|
|
@@ -5280,38 +5330,28 @@ function skipClosingAndOpening($pos, fromEnd, mayOpen) {
|
|
|
5280
5330
|
return end;
|
|
5281
5331
|
}
|
|
5282
5332
|
function findDiff(a, b, pos, preferredPos, preferredSide) {
|
|
5283
|
-
let start = a.findDiffStart(b, pos);
|
|
5333
|
+
let start = a.findDiffStart(b, pos), lenA = pos + a.size, lenB = pos + b.size;
|
|
5284
5334
|
if (start == null)
|
|
5285
5335
|
return null;
|
|
5286
|
-
let { a: endA, b: endB } = a.findDiffEnd(b,
|
|
5336
|
+
let { a: endA, b: endB } = a.findDiffEnd(b, lenA, lenB);
|
|
5287
5337
|
if (preferredSide == "end") {
|
|
5288
5338
|
let adjust = Math.max(0, start - Math.min(endA, endB));
|
|
5289
5339
|
preferredPos -= endA + adjust - start;
|
|
5290
5340
|
}
|
|
5291
|
-
if (endA < start &&
|
|
5341
|
+
if (endA < start && lenA < lenB) {
|
|
5292
5342
|
let move = preferredPos <= start && preferredPos >= endA ? start - preferredPos : 0;
|
|
5293
5343
|
start -= move;
|
|
5294
|
-
if (start && start < b.size && isSurrogatePair(b.textBetween(start - 1, start + 1)))
|
|
5295
|
-
start += move ? 1 : -1;
|
|
5296
5344
|
endB = start + (endB - endA);
|
|
5297
5345
|
endA = start;
|
|
5298
5346
|
}
|
|
5299
5347
|
else if (endB < start) {
|
|
5300
5348
|
let move = preferredPos <= start && preferredPos >= endB ? start - preferredPos : 0;
|
|
5301
5349
|
start -= move;
|
|
5302
|
-
if (start && start < a.size && isSurrogatePair(a.textBetween(start - 1, start + 1)))
|
|
5303
|
-
start += move ? 1 : -1;
|
|
5304
5350
|
endA = start + (endA - endB);
|
|
5305
5351
|
endB = start;
|
|
5306
5352
|
}
|
|
5307
5353
|
return { start, endA, endB };
|
|
5308
5354
|
}
|
|
5309
|
-
function isSurrogatePair(str) {
|
|
5310
|
-
if (str.length != 2)
|
|
5311
|
-
return false;
|
|
5312
|
-
let a = str.charCodeAt(0), b = str.charCodeAt(1);
|
|
5313
|
-
return a >= 0xDC00 && a <= 0xDFFF && b >= 0xD800 && b <= 0xDBFF;
|
|
5314
|
-
}
|
|
5315
5355
|
|
|
5316
5356
|
/**
|
|
5317
5357
|
@internal
|
|
@@ -5365,7 +5405,7 @@ class EditorView {
|
|
|
5365
5405
|
this.pluginViews = [];
|
|
5366
5406
|
/**
|
|
5367
5407
|
Holds `true` when a hack node is needed in Firefox to prevent the
|
|
5368
|
-
[space is eaten issue](https://
|
|
5408
|
+
[space is eaten issue](https://code.haverbeke.berlin/prosemirror/prosemirror/issues/651)
|
|
5369
5409
|
@internal
|
|
5370
5410
|
*/
|
|
5371
5411
|
this.requiresGeckoHackNode = false;
|
|
@@ -5512,9 +5552,10 @@ class EditorView {
|
|
|
5512
5552
|
// a DOM selection change and the "selectionchange" event for it
|
|
5513
5553
|
// can cause a spurious DOM selection update, disrupting mouse
|
|
5514
5554
|
// drag selection.
|
|
5555
|
+
let mouseDown = this.input.mouseDown;
|
|
5515
5556
|
if (forceSelUpdate ||
|
|
5516
|
-
!(
|
|
5517
|
-
anchorInRightPlace(this))) {
|
|
5557
|
+
!(mouseDown && this.domObserver.currentSelection.eq(this.domSelectionRange()) &&
|
|
5558
|
+
anchorInRightPlace(this) && mouseDown.delaySelUpdate())) {
|
|
5518
5559
|
selectionToDOM(this, forceSelUpdate);
|
|
5519
5560
|
}
|
|
5520
5561
|
else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prosemirror-view",
|
|
3
|
-
"version": "1.41.
|
|
3
|
+
"version": "1.41.9",
|
|
4
4
|
"description": "ProseMirror's view component",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
],
|
|
26
26
|
"repository": {
|
|
27
27
|
"type": "git",
|
|
28
|
-
"url": "git://
|
|
28
|
+
"url": "git+https://code.haverbeke.berlin/prosemirror/prosemirror-view.git"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"prosemirror-model": "^1.
|
|
31
|
+
"prosemirror-model": "^1.25.8",
|
|
32
32
|
"prosemirror-state": "^1.0.0",
|
|
33
33
|
"prosemirror-transform": "^1.1.0"
|
|
34
34
|
},
|
package/src/domchange.ts
CHANGED
|
@@ -351,33 +351,23 @@ function skipClosingAndOpening($pos: ResolvedPos, fromEnd: boolean, mayOpen: boo
|
|
|
351
351
|
}
|
|
352
352
|
|
|
353
353
|
function findDiff(a: Fragment, b: Fragment, pos: number, preferredPos: number, preferredSide: "start" | "end") {
|
|
354
|
-
let start = a.findDiffStart(b, pos)
|
|
354
|
+
let start = a.findDiffStart(b, pos), lenA = pos + a.size, lenB = pos + b.size
|
|
355
355
|
if (start == null) return null
|
|
356
|
-
let {a: endA, b: endB} = a.findDiffEnd(b,
|
|
356
|
+
let {a: endA, b: endB} = a.findDiffEnd(b, lenA, lenB)!
|
|
357
357
|
if (preferredSide == "end") {
|
|
358
358
|
let adjust = Math.max(0, start - Math.min(endA, endB))
|
|
359
359
|
preferredPos -= endA + adjust - start
|
|
360
360
|
}
|
|
361
|
-
if (endA < start &&
|
|
361
|
+
if (endA < start && lenA < lenB) {
|
|
362
362
|
let move = preferredPos <= start && preferredPos >= endA ? start - preferredPos : 0
|
|
363
363
|
start -= move
|
|
364
|
-
if (start && start < b.size && isSurrogatePair(b.textBetween(start - 1, start + 1)))
|
|
365
|
-
start += move ? 1 : -1
|
|
366
364
|
endB = start + (endB - endA)
|
|
367
365
|
endA = start
|
|
368
366
|
} else if (endB < start) {
|
|
369
367
|
let move = preferredPos <= start && preferredPos >= endB ? start - preferredPos : 0
|
|
370
368
|
start -= move
|
|
371
|
-
if (start && start < a.size && isSurrogatePair(a.textBetween(start - 1, start + 1)))
|
|
372
|
-
start += move ? 1 : -1
|
|
373
369
|
endA = start + (endA - endB)
|
|
374
370
|
endB = start
|
|
375
371
|
}
|
|
376
372
|
return {start, endA, endB}
|
|
377
373
|
}
|
|
378
|
-
|
|
379
|
-
function isSurrogatePair(str: string) {
|
|
380
|
-
if (str.length != 2) return false
|
|
381
|
-
let a = str.charCodeAt(0), b = str.charCodeAt(1)
|
|
382
|
-
return a >= 0xDC00 && a <= 0xDFFF && b >= 0xD800 && b <= 0xDBFF
|
|
383
|
-
}
|
package/src/domobserver.ts
CHANGED
|
@@ -192,7 +192,10 @@ export class DOMObserver {
|
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
if (added.some(n => n.nodeName == "BR") &&
|
|
195
|
+
if (added.some(n => n.nodeName == "BR") &&
|
|
196
|
+
(view.input.lastKeyCode == 8 || view.input.lastKeyCode == 46 ||
|
|
197
|
+
browser.chrome && (view.composing || view.input.compositionEndedAt > Date.now() - 50) &&
|
|
198
|
+
mutations.some(m => m.type == "childList" && m.removedNodes.length))) {
|
|
196
199
|
// Browsers sometimes insert a bogus break node if you
|
|
197
200
|
// backspace out the last bit of text before an inline-flex node (#1552)
|
|
198
201
|
for (let node of added) if (node.nodeName == "BR" && node.parentNode) {
|
package/src/index.ts
CHANGED
|
@@ -54,7 +54,7 @@ export class EditorView {
|
|
|
54
54
|
/// @internal
|
|
55
55
|
declare domObserver: DOMObserver
|
|
56
56
|
/// Holds `true` when a hack node is needed in Firefox to prevent the
|
|
57
|
-
/// [space is eaten issue](https://
|
|
57
|
+
/// [space is eaten issue](https://code.haverbeke.berlin/prosemirror/prosemirror/issues/651)
|
|
58
58
|
/// @internal
|
|
59
59
|
requiresGeckoHackNode: boolean = false
|
|
60
60
|
|
|
@@ -208,9 +208,10 @@ export class EditorView {
|
|
|
208
208
|
// a DOM selection change and the "selectionchange" event for it
|
|
209
209
|
// can cause a spurious DOM selection update, disrupting mouse
|
|
210
210
|
// drag selection.
|
|
211
|
+
let mouseDown = this.input.mouseDown
|
|
211
212
|
if (forceSelUpdate ||
|
|
212
|
-
!(
|
|
213
|
-
anchorInRightPlace(this))) {
|
|
213
|
+
!(mouseDown && this.domObserver.currentSelection.eq(this.domSelectionRange()) &&
|
|
214
|
+
anchorInRightPlace(this) && mouseDown.delaySelUpdate())) {
|
|
214
215
|
selectionToDOM(this, forceSelUpdate)
|
|
215
216
|
} else {
|
|
216
217
|
syncNodeSelection(this, state.selection)
|