@ckeditor/ckeditor5-clipboard 0.0.0-nightly-20231011.0 → 0.0.0-nightly-20231013.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/package.json +6 -6
- package/src/dragdrop.js +2 -2
- package/src/dragdroptarget.d.ts +3 -3
- package/src/dragdroptarget.js +27 -17
- package/src/utils/viewtoplaintext.js +48 -31
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckeditor/ckeditor5-clipboard",
|
|
3
|
-
"version": "0.0.0-nightly-
|
|
3
|
+
"version": "0.0.0-nightly-20231013.0",
|
|
4
4
|
"description": "Clipboard integration feature for CKEditor 5.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ckeditor",
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
],
|
|
13
13
|
"main": "src/index.js",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@ckeditor/ckeditor5-core": "0.0.0-nightly-
|
|
16
|
-
"@ckeditor/ckeditor5-engine": "0.0.0-nightly-
|
|
17
|
-
"@ckeditor/ckeditor5-ui": "0.0.0-nightly-
|
|
18
|
-
"@ckeditor/ckeditor5-utils": "0.0.0-nightly-
|
|
19
|
-
"@ckeditor/ckeditor5-widget": "0.0.0-nightly-
|
|
15
|
+
"@ckeditor/ckeditor5-core": "0.0.0-nightly-20231013.0",
|
|
16
|
+
"@ckeditor/ckeditor5-engine": "0.0.0-nightly-20231013.0",
|
|
17
|
+
"@ckeditor/ckeditor5-ui": "0.0.0-nightly-20231013.0",
|
|
18
|
+
"@ckeditor/ckeditor5-utils": "0.0.0-nightly-20231013.0",
|
|
19
|
+
"@ckeditor/ckeditor5-widget": "0.0.0-nightly-20231013.0",
|
|
20
20
|
"lodash-es": "4.17.21"
|
|
21
21
|
},
|
|
22
22
|
"author": "CKSource (http://cksource.com/)",
|
package/src/dragdrop.js
CHANGED
|
@@ -242,7 +242,7 @@ export default class DragDrop extends Plugin {
|
|
|
242
242
|
return;
|
|
243
243
|
}
|
|
244
244
|
const { clientX, clientY } = data.domEvent;
|
|
245
|
-
dragDropTarget.updateDropMarker(data.target, data.targetRanges, clientX, clientY, this._blockMode);
|
|
245
|
+
dragDropTarget.updateDropMarker(data.target, data.targetRanges, clientX, clientY, this._blockMode, this._draggedRange);
|
|
246
246
|
// If this is content being dragged from another editor, moving out of current editor instance
|
|
247
247
|
// is not possible until 'dragend' event case will be fixed.
|
|
248
248
|
if (!this._draggedRange) {
|
|
@@ -274,7 +274,7 @@ export default class DragDrop extends Plugin {
|
|
|
274
274
|
return;
|
|
275
275
|
}
|
|
276
276
|
const { clientX, clientY } = data.domEvent;
|
|
277
|
-
const targetRange = dragDropTarget.getFinalDropRange(data.target, data.targetRanges, clientX, clientY, this._blockMode);
|
|
277
|
+
const targetRange = dragDropTarget.getFinalDropRange(data.target, data.targetRanges, clientX, clientY, this._blockMode, this._draggedRange);
|
|
278
278
|
if (!targetRange) {
|
|
279
279
|
this._finalizeDragging(false);
|
|
280
280
|
evt.stop();
|
package/src/dragdroptarget.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @module clipboard/dragdroptarget
|
|
7
7
|
*/
|
|
8
8
|
import { Plugin } from '@ckeditor/ckeditor5-core';
|
|
9
|
-
import { type Range, type ViewElement, type ViewRange } from '@ckeditor/ckeditor5-engine';
|
|
9
|
+
import { type Range, type LiveRange, type ViewElement, type ViewRange } from '@ckeditor/ckeditor5-engine';
|
|
10
10
|
/**
|
|
11
11
|
* Part of the Drag and Drop handling. Responsible for finding and displaying the drop target.
|
|
12
12
|
*
|
|
@@ -56,13 +56,13 @@ export default class DragDropTarget extends Plugin {
|
|
|
56
56
|
*
|
|
57
57
|
* @internal
|
|
58
58
|
*/
|
|
59
|
-
updateDropMarker(targetViewElement: ViewElement, targetViewRanges: Array<ViewRange> | null, clientX: number, clientY: number, blockMode: boolean): void;
|
|
59
|
+
updateDropMarker(targetViewElement: ViewElement, targetViewRanges: Array<ViewRange> | null, clientX: number, clientY: number, blockMode: boolean, draggedRange: LiveRange | null): void;
|
|
60
60
|
/**
|
|
61
61
|
* Finds the final drop target range.
|
|
62
62
|
*
|
|
63
63
|
* @internal
|
|
64
64
|
*/
|
|
65
|
-
getFinalDropRange(targetViewElement: ViewElement, targetViewRanges: Array<ViewRange> | null, clientX: number, clientY: number, blockMode: boolean): Range | null;
|
|
65
|
+
getFinalDropRange(targetViewElement: ViewElement, targetViewRanges: Array<ViewRange> | null, clientX: number, clientY: number, blockMode: boolean, draggedRange: LiveRange | null): Range | null;
|
|
66
66
|
/**
|
|
67
67
|
* Removes the drop target marker.
|
|
68
68
|
*
|
package/src/dragdroptarget.js
CHANGED
|
@@ -78,21 +78,26 @@ export default class DragDropTarget extends Plugin {
|
|
|
78
78
|
*
|
|
79
79
|
* @internal
|
|
80
80
|
*/
|
|
81
|
-
updateDropMarker(targetViewElement, targetViewRanges, clientX, clientY, blockMode) {
|
|
81
|
+
updateDropMarker(targetViewElement, targetViewRanges, clientX, clientY, blockMode, draggedRange) {
|
|
82
82
|
this.removeDropMarkerDelayed.cancel();
|
|
83
|
-
const targetRange = findDropTargetRange(this.editor, targetViewElement, targetViewRanges, clientX, clientY, blockMode);
|
|
84
|
-
/* istanbul ignore
|
|
85
|
-
if (targetRange) {
|
|
86
|
-
|
|
83
|
+
const targetRange = findDropTargetRange(this.editor, targetViewElement, targetViewRanges, clientX, clientY, blockMode, draggedRange);
|
|
84
|
+
/* istanbul ignore next -- @preserve */
|
|
85
|
+
if (!targetRange) {
|
|
86
|
+
return;
|
|
87
87
|
}
|
|
88
|
+
if (draggedRange && draggedRange.containsRange(targetRange)) {
|
|
89
|
+
// Target range is inside the dragged range.
|
|
90
|
+
return this.removeDropMarker();
|
|
91
|
+
}
|
|
92
|
+
this._updateDropMarkerThrottled(targetRange);
|
|
88
93
|
}
|
|
89
94
|
/**
|
|
90
95
|
* Finds the final drop target range.
|
|
91
96
|
*
|
|
92
97
|
* @internal
|
|
93
98
|
*/
|
|
94
|
-
getFinalDropRange(targetViewElement, targetViewRanges, clientX, clientY, blockMode) {
|
|
95
|
-
const targetRange = findDropTargetRange(this.editor, targetViewElement, targetViewRanges, clientX, clientY, blockMode);
|
|
99
|
+
getFinalDropRange(targetViewElement, targetViewRanges, clientX, clientY, blockMode, draggedRange) {
|
|
100
|
+
const targetRange = findDropTargetRange(this.editor, targetViewElement, targetViewRanges, clientX, clientY, blockMode, draggedRange);
|
|
96
101
|
// The dragging markers must be removed after searching for the target range because sometimes
|
|
97
102
|
// the target lands on the marker itself.
|
|
98
103
|
this.removeDropMarker();
|
|
@@ -246,7 +251,7 @@ export default class DragDropTarget extends Plugin {
|
|
|
246
251
|
/**
|
|
247
252
|
* Returns fixed selection range for given position and target element.
|
|
248
253
|
*/
|
|
249
|
-
function findDropTargetRange(editor, targetViewElement, targetViewRanges, clientX, clientY, blockMode) {
|
|
254
|
+
function findDropTargetRange(editor, targetViewElement, targetViewRanges, clientX, clientY, blockMode, draggedRange) {
|
|
250
255
|
const model = editor.model;
|
|
251
256
|
const mapper = editor.editing.mapper;
|
|
252
257
|
const targetModelElement = getClosestMappedModelElement(editor, targetViewElement);
|
|
@@ -254,15 +259,20 @@ function findDropTargetRange(editor, targetViewElement, targetViewRanges, client
|
|
|
254
259
|
while (modelElement) {
|
|
255
260
|
if (!blockMode) {
|
|
256
261
|
if (model.schema.checkChild(modelElement, '$text')) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
262
|
+
if (targetViewRanges) {
|
|
263
|
+
const targetViewPosition = targetViewRanges[0].start;
|
|
264
|
+
const targetModelPosition = mapper.toModelPosition(targetViewPosition);
|
|
265
|
+
const canDropOnPosition = !draggedRange || Array
|
|
266
|
+
.from(draggedRange.getItems())
|
|
267
|
+
.every(item => model.schema.checkChild(targetModelPosition, item));
|
|
268
|
+
if (canDropOnPosition) {
|
|
269
|
+
if (model.schema.checkChild(targetModelPosition, '$text')) {
|
|
270
|
+
return model.createRange(targetModelPosition);
|
|
271
|
+
}
|
|
272
|
+
else if (targetViewPosition) {
|
|
273
|
+
// This is the case of dropping inside a span wrapper of an inline image.
|
|
274
|
+
return findDropTargetRangeForElement(editor, getClosestMappedModelElement(editor, targetViewPosition.parent), clientX, clientY);
|
|
275
|
+
}
|
|
266
276
|
}
|
|
267
277
|
}
|
|
268
278
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// Most `view.ContainerElement` want to be separate by new-line, but some are creating one structure
|
|
7
7
|
// together (like `<li>`) so it is better to separate them by only one "\n".
|
|
8
8
|
const smallPaddingElements = ['figcaption', 'li'];
|
|
9
|
+
const listElements = ['ol', 'ul'];
|
|
9
10
|
/**
|
|
10
11
|
* Converts {@link module:engine/view/item~Item view item} and all of its children to plain text.
|
|
11
12
|
*
|
|
@@ -13,38 +14,54 @@ const smallPaddingElements = ['figcaption', 'li'];
|
|
|
13
14
|
* @returns Plain text representation of `viewItem`.
|
|
14
15
|
*/
|
|
15
16
|
export default function viewToPlainText(viewItem) {
|
|
16
|
-
let text = '';
|
|
17
17
|
if (viewItem.is('$text') || viewItem.is('$textProxy')) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// Separate container element children with one or more new-line characters.
|
|
36
|
-
if (prev && (prev.is('containerElement') || child.is('containerElement'))) {
|
|
37
|
-
if (smallPaddingElements.includes(prev.name) ||
|
|
38
|
-
smallPaddingElements.includes(child.name)) {
|
|
39
|
-
text += '\n';
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
text += '\n\n';
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
text += childText;
|
|
46
|
-
prev = child;
|
|
47
|
-
}
|
|
18
|
+
return viewItem.data;
|
|
19
|
+
}
|
|
20
|
+
if (viewItem.is('element', 'img') && viewItem.hasAttribute('alt')) {
|
|
21
|
+
return viewItem.getAttribute('alt');
|
|
22
|
+
}
|
|
23
|
+
if (viewItem.is('element', 'br')) {
|
|
24
|
+
return '\n'; // Convert soft breaks to single line break (#8045).
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Item is a document fragment, attribute element or container element. It doesn't
|
|
28
|
+
* have it's own text value, so we need to convert its children elements.
|
|
29
|
+
*/
|
|
30
|
+
let text = '';
|
|
31
|
+
let prev = null;
|
|
32
|
+
for (const child of viewItem.getChildren()) {
|
|
33
|
+
text += newLinePadding(child, prev) + viewToPlainText(child);
|
|
34
|
+
prev = child;
|
|
48
35
|
}
|
|
49
36
|
return text;
|
|
50
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns new line padding to prefix the given elements with.
|
|
40
|
+
*/
|
|
41
|
+
function newLinePadding(element, previous) {
|
|
42
|
+
if (!previous) {
|
|
43
|
+
// Don't add padding to first elements in a level.
|
|
44
|
+
return '';
|
|
45
|
+
}
|
|
46
|
+
if (element.is('element', 'li') && !element.isEmpty && element.getChild(0).is('containerElement')) {
|
|
47
|
+
// Separate document list items with empty lines.
|
|
48
|
+
return '\n\n';
|
|
49
|
+
}
|
|
50
|
+
if (listElements.includes(element.name) && listElements.includes(previous.name)) {
|
|
51
|
+
/**
|
|
52
|
+
* Because `<ul>` and `<ol>` are AttributeElements, two consecutive lists will not have any padding between
|
|
53
|
+
* them (see the `if` statement below). To fix this, we need to make an exception for this case.
|
|
54
|
+
*/
|
|
55
|
+
return '\n\n';
|
|
56
|
+
}
|
|
57
|
+
if (!element.is('containerElement') && !previous.is('containerElement')) {
|
|
58
|
+
// Don't add padding between non-container elements.
|
|
59
|
+
return '';
|
|
60
|
+
}
|
|
61
|
+
if (smallPaddingElements.includes(element.name) || smallPaddingElements.includes(previous.name)) {
|
|
62
|
+
// Add small padding between selected container elements.
|
|
63
|
+
return '\n';
|
|
64
|
+
}
|
|
65
|
+
// Add empty lines between container elements.
|
|
66
|
+
return '\n\n';
|
|
67
|
+
}
|