prosemirror-view 1.40.1 → 1.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/index.cjs +13 -11
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +12 -12
- package/package.json +1 -1
- package/src/clipboard.ts +7 -3
- package/src/index.ts +3 -2
- package/src/input.ts +1 -1
- package/src/selection.ts +3 -6
- package/src/viewdesc.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## 1.41.0 (2025-09-06)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Make sure `transformPasted` is properly called when pasting into a code block.
|
|
6
|
+
|
|
7
|
+
Fix an issue where the editor didn't properly set the DOM selection in a shadow DOM on Safari in some situations.
|
|
8
|
+
|
|
9
|
+
Work around a Safari issue that broke composition right after changing the set of active marks.
|
|
10
|
+
|
|
11
|
+
### New features
|
|
12
|
+
|
|
13
|
+
Pass an argument to `transformPasted` that tells the handler whether the paste is plain text. Call transformPasted when pasting into a code block
|
|
14
|
+
|
|
1
15
|
## 1.40.1 (2025-07-18)
|
|
2
16
|
|
|
3
17
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -998,7 +998,7 @@ var ViewDesc = function () {
|
|
|
998
998
|
}
|
|
999
999
|
if (!(force || brKludge && safari) && isEquivalentPosition(anchorDOM.node, anchorDOM.offset, selRange.anchorNode, selRange.anchorOffset) && isEquivalentPosition(headDOM.node, headDOM.offset, selRange.focusNode, selRange.focusOffset)) return;
|
|
1000
1000
|
var domSelExtended = false;
|
|
1001
|
-
if ((domSel.extend || anchor == head) && !brKludge) {
|
|
1001
|
+
if ((domSel.extend || anchor == head) && !(brKludge && gecko)) {
|
|
1002
1002
|
domSel.collapse(anchorDOM.node, anchorDOM.offset);
|
|
1003
1003
|
try {
|
|
1004
1004
|
if (anchor != head) domSel.extend(headDOM.node, headDOM.offset);
|
|
@@ -2271,15 +2271,11 @@ function removeClassOnSelectionChange(view) {
|
|
|
2271
2271
|
});
|
|
2272
2272
|
}
|
|
2273
2273
|
function selectCursorWrapper(view) {
|
|
2274
|
-
var domSel = view.domSelection()
|
|
2275
|
-
range = document.createRange();
|
|
2274
|
+
var domSel = view.domSelection();
|
|
2276
2275
|
if (!domSel) return;
|
|
2277
2276
|
var node = view.cursorWrapper.dom,
|
|
2278
2277
|
img = node.nodeName == "IMG";
|
|
2279
|
-
if (img)
|
|
2280
|
-
range.collapse(true);
|
|
2281
|
-
domSel.removeAllRanges();
|
|
2282
|
-
domSel.addRange(range);
|
|
2278
|
+
if (img) domSel.collapse(node.parentNode, domIndex(node) + 1);else domSel.collapse(node, 0);
|
|
2283
2279
|
if (!img && !view.state.selection.visible && ie && ie_version <= 11) {
|
|
2284
2280
|
node.disabled = true;
|
|
2285
2281
|
node.disabled = false;
|
|
@@ -2677,12 +2673,18 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
2677
2673
|
var inCode = $context.parent.type.spec.code;
|
|
2678
2674
|
var dom, slice;
|
|
2679
2675
|
if (!html && !text) return null;
|
|
2680
|
-
var asText = text && (plainText || inCode || !html);
|
|
2676
|
+
var asText = !!text && (plainText || inCode || !html);
|
|
2681
2677
|
if (asText) {
|
|
2682
2678
|
view.someProp("transformPastedText", function (f) {
|
|
2683
2679
|
text = f(text, inCode || plainText, view);
|
|
2684
2680
|
});
|
|
2685
|
-
if (inCode)
|
|
2681
|
+
if (inCode) {
|
|
2682
|
+
slice = new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0);
|
|
2683
|
+
view.someProp("transformPasted", function (f) {
|
|
2684
|
+
slice = f(slice, view, true);
|
|
2685
|
+
});
|
|
2686
|
+
return slice;
|
|
2687
|
+
}
|
|
2686
2688
|
var parsed = view.someProp("clipboardTextParser", function (f) {
|
|
2687
2689
|
return f(text, $context, plainText, view);
|
|
2688
2690
|
});
|
|
@@ -2739,7 +2741,7 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
2739
2741
|
}
|
|
2740
2742
|
}
|
|
2741
2743
|
view.someProp("transformPasted", function (f) {
|
|
2742
|
-
slice = f(slice, view);
|
|
2744
|
+
slice = f(slice, view, asText);
|
|
2743
2745
|
});
|
|
2744
2746
|
return slice;
|
|
2745
2747
|
}
|
|
@@ -3492,7 +3494,7 @@ editHandlers.drop = function (view, _event) {
|
|
|
3492
3494
|
var slice = dragging && dragging.slice;
|
|
3493
3495
|
if (slice) {
|
|
3494
3496
|
view.someProp("transformPasted", function (f) {
|
|
3495
|
-
slice = f(slice, view);
|
|
3497
|
+
slice = f(slice, view, false);
|
|
3496
3498
|
});
|
|
3497
3499
|
} else {
|
|
3498
3500
|
slice = parseFromClipboard(view, getText(event.dataTransfer), brokenClipboardAPI ? null : event.dataTransfer.getData("text/html"), false, $mouse);
|
package/dist/index.d.cts
CHANGED
|
@@ -757,9 +757,10 @@ interface EditorProps<P = any> {
|
|
|
757
757
|
clipboardTextParser?: (this: P, text: string, $context: ResolvedPos, plain: boolean, view: EditorView) => Slice;
|
|
758
758
|
/**
|
|
759
759
|
Can be used to transform pasted or dragged-and-dropped content
|
|
760
|
-
before it is applied to the document.
|
|
760
|
+
before it is applied to the document. The `plain` flag will be
|
|
761
|
+
true when the text is pasted as plain text.
|
|
761
762
|
*/
|
|
762
|
-
transformPasted?: (this: P, slice: Slice, view: EditorView) => Slice;
|
|
763
|
+
transformPasted?: (this: P, slice: Slice, view: EditorView, plain: boolean) => Slice;
|
|
763
764
|
/**
|
|
764
765
|
Can be used to transform copied or cut content before it is
|
|
765
766
|
serialized to the clipboard.
|
package/dist/index.d.ts
CHANGED
|
@@ -757,9 +757,10 @@ interface EditorProps<P = any> {
|
|
|
757
757
|
clipboardTextParser?: (this: P, text: string, $context: ResolvedPos, plain: boolean, view: EditorView) => Slice;
|
|
758
758
|
/**
|
|
759
759
|
Can be used to transform pasted or dragged-and-dropped content
|
|
760
|
-
before it is applied to the document.
|
|
760
|
+
before it is applied to the document. The `plain` flag will be
|
|
761
|
+
true when the text is pasted as plain text.
|
|
761
762
|
*/
|
|
762
|
-
transformPasted?: (this: P, slice: Slice, view: EditorView) => Slice;
|
|
763
|
+
transformPasted?: (this: P, slice: Slice, view: EditorView, plain: boolean) => Slice;
|
|
763
764
|
/**
|
|
764
765
|
Can be used to transform copied or cut content before it is
|
|
765
766
|
serialized to the clipboard.
|
package/dist/index.js
CHANGED
|
@@ -1072,7 +1072,7 @@ class ViewDesc {
|
|
|
1072
1072
|
// (one where the focus is before the anchor), but not all
|
|
1073
1073
|
// browsers support it yet.
|
|
1074
1074
|
let domSelExtended = false;
|
|
1075
|
-
if ((domSel.extend || anchor == head) && !brKludge) {
|
|
1075
|
+
if ((domSel.extend || anchor == head) && !(brKludge && gecko)) {
|
|
1076
1076
|
domSel.collapse(anchorDOM.node, anchorDOM.offset);
|
|
1077
1077
|
try {
|
|
1078
1078
|
if (anchor != head)
|
|
@@ -2333,17 +2333,14 @@ function removeClassOnSelectionChange(view) {
|
|
|
2333
2333
|
});
|
|
2334
2334
|
}
|
|
2335
2335
|
function selectCursorWrapper(view) {
|
|
2336
|
-
let domSel = view.domSelection()
|
|
2336
|
+
let domSel = view.domSelection();
|
|
2337
2337
|
if (!domSel)
|
|
2338
2338
|
return;
|
|
2339
2339
|
let node = view.cursorWrapper.dom, img = node.nodeName == "IMG";
|
|
2340
2340
|
if (img)
|
|
2341
|
-
|
|
2341
|
+
domSel.collapse(node.parentNode, domIndex(node) + 1);
|
|
2342
2342
|
else
|
|
2343
|
-
|
|
2344
|
-
range.collapse(true);
|
|
2345
|
-
domSel.removeAllRanges();
|
|
2346
|
-
domSel.addRange(range);
|
|
2343
|
+
domSel.collapse(node, 0);
|
|
2347
2344
|
// Kludge to kill 'control selection' in IE11 when selecting an
|
|
2348
2345
|
// invisible cursor wrapper, since that would result in those weird
|
|
2349
2346
|
// resize handles and a selection that considers the absolutely
|
|
@@ -2821,11 +2818,14 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
2821
2818
|
let dom, slice;
|
|
2822
2819
|
if (!html && !text)
|
|
2823
2820
|
return null;
|
|
2824
|
-
let asText = text && (plainText || inCode || !html);
|
|
2821
|
+
let asText = !!text && (plainText || inCode || !html);
|
|
2825
2822
|
if (asText) {
|
|
2826
2823
|
view.someProp("transformPastedText", f => { text = f(text, inCode || plainText, view); });
|
|
2827
|
-
if (inCode)
|
|
2828
|
-
|
|
2824
|
+
if (inCode) {
|
|
2825
|
+
slice = new Slice(Fragment.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0);
|
|
2826
|
+
view.someProp("transformPasted", f => { slice = f(slice, view, true); });
|
|
2827
|
+
return slice;
|
|
2828
|
+
}
|
|
2829
2829
|
let parsed = view.someProp("clipboardTextParser", f => f(text, $context, plainText, view));
|
|
2830
2830
|
if (parsed) {
|
|
2831
2831
|
slice = parsed;
|
|
@@ -2883,7 +2883,7 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
2883
2883
|
slice = closeSlice(slice, openStart, openEnd);
|
|
2884
2884
|
}
|
|
2885
2885
|
}
|
|
2886
|
-
view.someProp("transformPasted", f => { slice = f(slice, view); });
|
|
2886
|
+
view.someProp("transformPasted", f => { slice = f(slice, view, asText); });
|
|
2887
2887
|
return slice;
|
|
2888
2888
|
}
|
|
2889
2889
|
const inlineParents = /^(a|abbr|acronym|b|cite|code|del|em|i|ins|kbd|label|output|q|ruby|s|samp|span|strong|sub|sup|time|u|tt|var)$/i;
|
|
@@ -3743,7 +3743,7 @@ editHandlers.drop = (view, _event) => {
|
|
|
3743
3743
|
let $mouse = view.state.doc.resolve(eventPos.pos);
|
|
3744
3744
|
let slice = dragging && dragging.slice;
|
|
3745
3745
|
if (slice) {
|
|
3746
|
-
view.someProp("transformPasted", f => { slice = f(slice, view); });
|
|
3746
|
+
view.someProp("transformPasted", f => { slice = f(slice, view, false); });
|
|
3747
3747
|
}
|
|
3748
3748
|
else {
|
|
3749
3749
|
slice = parseFromClipboard(view, getText(event.dataTransfer), brokenClipboardAPI ? null : event.dataTransfer.getData("text/html"), false, $mouse);
|
package/package.json
CHANGED
package/src/clipboard.ts
CHANGED
|
@@ -44,10 +44,14 @@ export function parseFromClipboard(view: EditorView, text: string, html: string
|
|
|
44
44
|
let inCode = $context.parent.type.spec.code
|
|
45
45
|
let dom: HTMLElement | undefined, slice: Slice | undefined
|
|
46
46
|
if (!html && !text) return null
|
|
47
|
-
let asText = text && (plainText || inCode || !html)
|
|
47
|
+
let asText = !!text && (plainText || inCode || !html)
|
|
48
48
|
if (asText) {
|
|
49
49
|
view.someProp("transformPastedText", f => { text = f(text, inCode || plainText, view) })
|
|
50
|
-
if (inCode)
|
|
50
|
+
if (inCode) {
|
|
51
|
+
slice = new Slice(Fragment.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0)
|
|
52
|
+
view.someProp("transformPasted", f => { slice = f(slice!, view, true) })
|
|
53
|
+
return slice
|
|
54
|
+
}
|
|
51
55
|
let parsed = view.someProp("clipboardTextParser", f => f(text, $context, plainText, view))
|
|
52
56
|
if (parsed) {
|
|
53
57
|
slice = parsed
|
|
@@ -101,7 +105,7 @@ export function parseFromClipboard(view: EditorView, text: string, html: string
|
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
107
|
|
|
104
|
-
view.someProp("transformPasted", f => { slice = f(slice!, view) })
|
|
108
|
+
view.someProp("transformPasted", f => { slice = f(slice!, view, asText) })
|
|
105
109
|
return slice
|
|
106
110
|
}
|
|
107
111
|
|
package/src/index.ts
CHANGED
|
@@ -714,8 +714,9 @@ export interface EditorProps<P = any> {
|
|
|
714
714
|
clipboardTextParser?: (this: P, text: string, $context: ResolvedPos, plain: boolean, view: EditorView) => Slice
|
|
715
715
|
|
|
716
716
|
/// Can be used to transform pasted or dragged-and-dropped content
|
|
717
|
-
/// before it is applied to the document.
|
|
718
|
-
|
|
717
|
+
/// before it is applied to the document. The `plain` flag will be
|
|
718
|
+
/// true when the text is pasted as plain text.
|
|
719
|
+
transformPasted?: (this: P, slice: Slice, view: EditorView, plain: boolean) => Slice
|
|
719
720
|
|
|
720
721
|
/// Can be used to transform copied or cut content before it is
|
|
721
722
|
/// serialized to the clipboard.
|
package/src/input.ts
CHANGED
|
@@ -718,7 +718,7 @@ editHandlers.drop = (view, _event) => {
|
|
|
718
718
|
let $mouse = view.state.doc.resolve(eventPos.pos)
|
|
719
719
|
let slice = dragging && dragging.slice
|
|
720
720
|
if (slice) {
|
|
721
|
-
view.someProp("transformPasted", f => { slice = f(slice!, view) })
|
|
721
|
+
view.someProp("transformPasted", f => { slice = f(slice!, view, false) })
|
|
722
722
|
} else {
|
|
723
723
|
slice = parseFromClipboard(view, getText(event.dataTransfer),
|
|
724
724
|
brokenClipboardAPI ? null : event.dataTransfer.getData("text/html"), false, $mouse)
|
package/src/selection.ts
CHANGED
|
@@ -147,14 +147,11 @@ function removeClassOnSelectionChange(view: EditorView) {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
function selectCursorWrapper(view: EditorView) {
|
|
150
|
-
let domSel = view.domSelection()
|
|
150
|
+
let domSel = view.domSelection()
|
|
151
151
|
if (!domSel) return
|
|
152
152
|
let node = view.cursorWrapper!.dom, img = node.nodeName == "IMG"
|
|
153
|
-
if (img)
|
|
154
|
-
else
|
|
155
|
-
range.collapse(true)
|
|
156
|
-
domSel.removeAllRanges()
|
|
157
|
-
domSel.addRange(range)
|
|
153
|
+
if (img) domSel.collapse(node.parentNode!, domIndex(node) + 1)
|
|
154
|
+
else domSel.collapse(node, 0)
|
|
158
155
|
// Kludge to kill 'control selection' in IE11 when selecting an
|
|
159
156
|
// invisible cursor wrapper, since that would result in those weird
|
|
160
157
|
// resize handles and a selection that considers the absolutely
|
package/src/viewdesc.ts
CHANGED
|
@@ -460,7 +460,7 @@ export class ViewDesc {
|
|
|
460
460
|
// (one where the focus is before the anchor), but not all
|
|
461
461
|
// browsers support it yet.
|
|
462
462
|
let domSelExtended = false
|
|
463
|
-
if ((domSel.extend || anchor == head) && !brKludge) {
|
|
463
|
+
if ((domSel.extend || anchor == head) && !(brKludge && browser.gecko)) {
|
|
464
464
|
domSel.collapse(anchorDOM.node, anchorDOM.offset)
|
|
465
465
|
try {
|
|
466
466
|
if (anchor != head)
|