@ckeditor/ckeditor5-clipboard 0.0.0-nightly-20240716.0 → 0.0.0-nightly-20240718.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 +1 -177
- package/dist/index.js +36 -18
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/pasteplaintext.js +32 -18
- package/src/utils/viewtoplaintext.js +5 -0
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-20240718.0",
|
|
4
4
|
"description": "Clipboard integration feature for CKEditor 5.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ckeditor",
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
"type": "module",
|
|
14
14
|
"main": "src/index.js",
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@ckeditor/ckeditor5-core": "0.0.0-nightly-
|
|
17
|
-
"@ckeditor/ckeditor5-engine": "0.0.0-nightly-
|
|
18
|
-
"@ckeditor/ckeditor5-ui": "0.0.0-nightly-
|
|
19
|
-
"@ckeditor/ckeditor5-utils": "0.0.0-nightly-
|
|
20
|
-
"@ckeditor/ckeditor5-widget": "0.0.0-nightly-
|
|
16
|
+
"@ckeditor/ckeditor5-core": "0.0.0-nightly-20240718.0",
|
|
17
|
+
"@ckeditor/ckeditor5-engine": "0.0.0-nightly-20240718.0",
|
|
18
|
+
"@ckeditor/ckeditor5-ui": "0.0.0-nightly-20240718.0",
|
|
19
|
+
"@ckeditor/ckeditor5-utils": "0.0.0-nightly-20240718.0",
|
|
20
|
+
"@ckeditor/ckeditor5-widget": "0.0.0-nightly-20240718.0",
|
|
21
21
|
"lodash-es": "4.17.21"
|
|
22
22
|
},
|
|
23
23
|
"author": "CKSource (http://cksource.com/)",
|
package/src/pasteplaintext.js
CHANGED
|
@@ -33,17 +33,10 @@ export default class PastePlainText extends Plugin {
|
|
|
33
33
|
const editor = this.editor;
|
|
34
34
|
const model = editor.model;
|
|
35
35
|
const view = editor.editing.view;
|
|
36
|
-
const viewDocument = view.document;
|
|
37
36
|
const selection = model.document.selection;
|
|
38
|
-
let shiftPressed = false;
|
|
39
37
|
view.addObserver(ClipboardObserver);
|
|
40
|
-
this.listenTo(viewDocument, 'keydown', (evt, data) => {
|
|
41
|
-
shiftPressed = data.shiftKey;
|
|
42
|
-
});
|
|
43
38
|
editor.plugins.get(ClipboardPipeline).on('contentInsertion', (evt, data) => {
|
|
44
|
-
|
|
45
|
-
// preserve selection attributes on pasted items.
|
|
46
|
-
if (!shiftPressed && !isPlainTextFragment(data.content, model.schema)) {
|
|
39
|
+
if (!isUnformattedInlineContent(data.content, model)) {
|
|
47
40
|
return;
|
|
48
41
|
}
|
|
49
42
|
model.change(writer => {
|
|
@@ -59,8 +52,10 @@ export default class PastePlainText extends Plugin {
|
|
|
59
52
|
textAttributes.push(...selection.getAttributes());
|
|
60
53
|
const range = writer.createRangeIn(data.content);
|
|
61
54
|
for (const item of range.getItems()) {
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
for (const attribute of textAttributes) {
|
|
56
|
+
if (model.schema.checkAttribute(item, attribute[0])) {
|
|
57
|
+
writer.setAttribute(attribute[0], attribute[1], item);
|
|
58
|
+
}
|
|
64
59
|
}
|
|
65
60
|
}
|
|
66
61
|
});
|
|
@@ -68,15 +63,34 @@ export default class PastePlainText extends Plugin {
|
|
|
68
63
|
}
|
|
69
64
|
}
|
|
70
65
|
/**
|
|
71
|
-
* Returns true if specified `documentFragment` represents
|
|
66
|
+
* Returns true if specified `documentFragment` represents the unformatted inline content.
|
|
72
67
|
*/
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
function isUnformattedInlineContent(documentFragment, model) {
|
|
69
|
+
let range = model.createRangeIn(documentFragment);
|
|
70
|
+
// We consider three scenarios here. The document fragment may include:
|
|
71
|
+
//
|
|
72
|
+
// 1. Only text and inline objects. Then it could be unformatted inline content.
|
|
73
|
+
// 2. Exactly one block element on top-level, eg. <p>Foobar</p> or <h2>Title</h2>.
|
|
74
|
+
// In this case, check this element content, it could be treated as unformatted inline content.
|
|
75
|
+
// 3. More block elements or block objects, then it is not unformatted inline content.
|
|
76
|
+
//
|
|
77
|
+
// We will check for scenario 2. specifically, and if it happens, we will unwrap it and follow with the regular algorithm.
|
|
78
|
+
//
|
|
79
|
+
if (documentFragment.childCount == 1) {
|
|
80
|
+
const child = documentFragment.getChild(0);
|
|
81
|
+
if (child.is('element') && model.schema.isBlock(child) && !model.schema.isObject(child) && !model.schema.isLimit(child)) {
|
|
82
|
+
// Scenario 2. as described above.
|
|
83
|
+
range = model.createRangeIn(child);
|
|
84
|
+
}
|
|
76
85
|
}
|
|
77
|
-
const child
|
|
78
|
-
|
|
79
|
-
|
|
86
|
+
for (const child of range.getItems()) {
|
|
87
|
+
if (!model.schema.isInline(child)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
const attributeKeys = Array.from(child.getAttributeKeys());
|
|
91
|
+
if (attributeKeys.find(key => model.schema.getAttributeProperties(key).isFormatting)) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
80
94
|
}
|
|
81
|
-
return
|
|
95
|
+
return true;
|
|
82
96
|
}
|
|
@@ -62,6 +62,11 @@ function newLinePadding(element, previous) {
|
|
|
62
62
|
// Add small padding between selected container elements.
|
|
63
63
|
return '\n';
|
|
64
64
|
}
|
|
65
|
+
// Do not add padding around the elements that won't be rendered.
|
|
66
|
+
if (element.is('element') && element.getCustomProperty('dataPipeline:transparentRendering') ||
|
|
67
|
+
previous.is('element') && previous.getCustomProperty('dataPipeline:transparentRendering')) {
|
|
68
|
+
return '';
|
|
69
|
+
}
|
|
65
70
|
// Add empty lines between container elements.
|
|
66
71
|
return '\n\n';
|
|
67
72
|
}
|