ckeditor5-elements-actions 49.0.0-alpha.2 → 49.0.0-alpha.4

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/README.md CHANGED
@@ -1,8 +1,13 @@
1
1
  # ckeditor5-elements-actions
2
2
 
3
- Element actions for CKEditor 5 Elements: `ElementActions` registers `moveElementUp`, `moveElementDown`,
4
- `duplicateElement` and `deleteElement`, which move an element within its parent, insert an empty copy of it after it, or
5
- delete it.
3
+ Element actions for CKEditor 5 Elements, the commands that act on a whole element:
4
+
5
+ - `ElementActions` registers `moveElementUp`, `moveElementDown`, `duplicateElement` and `deleteElement`, which move an
6
+ element within its parent, insert an empty copy of it after it, or delete it.
7
+ - `ElementClipboard` registers `copyElement`, `cutElement`, `pasteElement`, `pasteElementBefore` and `pasteElementAfter`,
8
+ which copy, cut and paste an element, through the CKEditor clipboard pipeline.
9
+
10
+ The commands have titles and icons, so they are menu items and buttons as they are.
6
11
 
7
12
  ## Installation
8
13
 
@@ -15,21 +20,31 @@ npm install ckeditor5 ckeditor5-elements
15
20
  ## Usage
16
21
 
17
22
  ```ts
18
- import { ElementActions, ElementContextMenu } from 'ckeditor5-elements';
23
+ import { ElementActions, ElementClipboard, ElementContextMenu } from 'ckeditor5-elements';
19
24
  import 'ckeditor5-elements/index.css';
20
25
 
21
26
  // In the editor config:
22
- plugins: [..., ElementActions, ElementContextMenu],
27
+ plugins: [..., ElementActions, ElementClipboard, ElementContextMenu],
23
28
  elementContextMenu: (element, editor) => [
24
29
  editor.commands.get('moveElementUp'),
25
30
  editor.commands.get('moveElementDown'),
26
31
  '|',
27
32
  editor.commands.get('duplicateElement'),
28
- editor.commands.get('deleteElement')
33
+ editor.commands.get('deleteElement'),
34
+ '|',
35
+ editor.commands.get('copyElement'),
36
+ editor.commands.get('cutElement'),
37
+ editor.commands.get('pasteElementAfter')
29
38
  ]
30
39
  ```
31
40
 
32
- See the [Actions guide](https://ivankild.github.io/ckeditor5-elements/guide/actions) of the documentation.
41
+ ```ts
42
+ await editor.execute('copyElement', element);
43
+ await editor.execute('pasteElementAfter'); // The element at the selection.
44
+ ```
45
+
46
+ See the [Actions](https://ivankild.github.io/ckeditor5-elements/guide/actions) and
47
+ [Clipboard](https://ivankild.github.io/ckeditor5-elements/guide/clipboard) guides of the documentation.
33
48
 
34
49
  ## License
35
50
 
@@ -1,13 +1,19 @@
1
- import type { ElementActions, ElementDeleteCommand, ElementDuplicateCommand, ElementMoveCommand } from './index.js';
1
+ import type { ElementActions, ElementClipboard, ElementCopyCommand, ElementDeleteCommand, ElementDuplicateCommand, ElementMoveCommand, ElementPasteCommand } from './index.js';
2
2
  declare module 'ckeditor5' {
3
3
  interface PluginsMap {
4
4
  [ElementActions.pluginName]: ElementActions;
5
+ [ElementClipboard.pluginName]: ElementClipboard;
5
6
  }
6
7
  interface CommandsMap {
7
8
  moveElementUp: ElementMoveCommand;
8
9
  moveElementDown: ElementMoveCommand;
9
10
  duplicateElement: ElementDuplicateCommand;
10
11
  deleteElement: ElementDeleteCommand;
12
+ copyElement: ElementCopyCommand;
13
+ cutElement: ElementCopyCommand;
14
+ pasteElement: ElementPasteCommand;
15
+ pasteElementBefore: ElementPasteCommand;
16
+ pasteElementAfter: ElementPasteCommand;
11
17
  }
12
18
  }
13
19
  //# sourceMappingURL=augmentation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"augmentation.d.ts","sourceRoot":"","sources":["../src/augmentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEpH,OAAO,QAAQ,WAAW,CAAC;IAC1B,UAAU,UAAU;QACnB,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC;KAC5C;IAED,UAAU,WAAW;QACpB,aAAa,EAAE,kBAAkB,CAAC;QAClC,eAAe,EAAE,kBAAkB,CAAC;QACpC,gBAAgB,EAAE,uBAAuB,CAAC;QAC1C,aAAa,EAAE,oBAAoB,CAAC;KACpC;CACD"}
1
+ {"version":3,"file":"augmentation.d.ts","sourceRoot":"","sources":["../src/augmentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,QAAQ,WAAW,CAAC;IAC1B,UAAU,UAAU;QACnB,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC;QAC5C,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;KAChD;IAED,UAAU,WAAW;QACpB,aAAa,EAAE,kBAAkB,CAAC;QAClC,eAAe,EAAE,kBAAkB,CAAC;QACpC,gBAAgB,EAAE,uBAAuB,CAAC;QAC1C,aAAa,EAAE,oBAAoB,CAAC;QACpC,WAAW,EAAE,kBAAkB,CAAC;QAChC,UAAU,EAAE,kBAAkB,CAAC;QAC/B,YAAY,EAAE,mBAAmB,CAAC;QAClC,kBAAkB,EAAE,mBAAmB,CAAC;QACxC,iBAAiB,EAAE,mBAAmB,CAAC;KACvC;CACD"}
@@ -0,0 +1,18 @@
1
+ import { ClipboardPipeline, Notification, Plugin } from 'ckeditor5';
2
+ /**
3
+ * Registers clipboard commands that act on an element:
4
+ * `copyElement`, `cutElement`, `pasteElement`, `pasteElementBefore` and `pasteElementAfter`.
5
+ *
6
+ * ```ts
7
+ * await editor.execute('copyElement', element);
8
+ * ```
9
+ *
10
+ * The commands have titles and icons, so they can be menu items (e.g. in the `elementContextMenu` config of
11
+ * `ElementContextMenu`) and buttons. Copying and pasting go through the clipboard pipeline, as Ctrl+C and Ctrl+V do.
12
+ */
13
+ export default class ElementClipboard extends Plugin {
14
+ static get requires(): readonly [typeof ClipboardPipeline, typeof Notification];
15
+ static get pluginName(): 'ElementClipboard';
16
+ init(): void;
17
+ }
18
+ //# sourceMappingURL=elementClipboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementClipboard.d.ts","sourceRoot":"","sources":["../src/elementClipboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAIpE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,MAAM;IACnD,WAAkB,QAAQ,IAAI,SAAS,CAAC,OAAO,iBAAiB,EAAE,OAAO,YAAY,CAAC,CAGrF;IAED,WAAkB,UAAU,IAAI,kBAAkB,CAEjD;IAEM,IAAI,IAAI,IAAI;CASnB"}
@@ -0,0 +1,32 @@
1
+ import { ClipboardPipeline, Notification, Plugin } from 'ckeditor5';
2
+ import ElementCopyCommand from './elementCopyCommand.js';
3
+ import ElementPasteCommand from './elementPasteCommand.js';
4
+ /**
5
+ * Registers clipboard commands that act on an element:
6
+ * `copyElement`, `cutElement`, `pasteElement`, `pasteElementBefore` and `pasteElementAfter`.
7
+ *
8
+ * ```ts
9
+ * await editor.execute('copyElement', element);
10
+ * ```
11
+ *
12
+ * The commands have titles and icons, so they can be menu items (e.g. in the `elementContextMenu` config of
13
+ * `ElementContextMenu`) and buttons. Copying and pasting go through the clipboard pipeline, as Ctrl+C and Ctrl+V do.
14
+ */
15
+ export default class ElementClipboard extends Plugin {
16
+ static get requires() {
17
+ // The buttons of the commands report failures (e.g. no clipboard permission) with notifications.
18
+ return [ClipboardPipeline, Notification];
19
+ }
20
+ static get pluginName() {
21
+ return 'ElementClipboard';
22
+ }
23
+ init() {
24
+ const editor = this.editor;
25
+ editor.commands.add('copyElement', new ElementCopyCommand(editor));
26
+ editor.commands.add('cutElement', new ElementCopyCommand(editor, { cut: true }));
27
+ editor.commands.add('pasteElement', new ElementPasteCommand(editor, 'replace'));
28
+ editor.commands.add('pasteElementBefore', new ElementPasteCommand(editor, 'before'));
29
+ editor.commands.add('pasteElementAfter', new ElementPasteCommand(editor, 'after'));
30
+ }
31
+ }
32
+ //# sourceMappingURL=elementClipboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementClipboard.js","sourceRoot":"","sources":["../src/elementClipboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,kBAAkB,MAAM,yBAAyB,CAAC;AACzD,OAAO,mBAAmB,MAAM,0BAA0B,CAAC;AAE3D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,MAAM;IAC5C,MAAM,KAAK,QAAQ;QACzB,iGAAiG;QACjG,OAAO,CAAC,iBAAiB,EAAE,YAAY,CAAU,CAAC;IACnD,CAAC;IAEM,MAAM,KAAK,UAAU;QAC3B,OAAO,kBAA2B,CAAC;IACpC,CAAC;IAEM,IAAI;QACV,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE3B,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;QACnE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,kBAAkB,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACjF,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,mBAAmB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;QAChF,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;QACrF,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACpF,CAAC;CACD"}
@@ -0,0 +1,30 @@
1
+ import { type Editor } from 'ckeditor5';
2
+ import { ElementOrPositionCommand, type ElementOrPosition } from 'ckeditor5-elements-core';
3
+ /**
4
+ * Copies an element to the system clipboard, as HTML and plain text. With `cut: true`, it also removes the element.
5
+ *
6
+ * The element is the given one, the parent of the given position, or the selected element or the parent of the
7
+ * selection (see {@link ElementOrPositionCommand}). Parts of a structure, such as table cells, rows and captions, cannot
8
+ * be copied on their own, so the command is disabled for them.
9
+ *
10
+ * The content goes through the clipboard pipeline, as with Ctrl+C: other plugins can change it (they listen to the
11
+ * `outputTransformation` event of `ClipboardPipeline`, and to `clipboardOutput` of the editing view document).
12
+ *
13
+ * Requires a secure context (HTTPS or `localhost`), as it uses the asynchronous Clipboard API.
14
+ */
15
+ export default class ElementCopyCommand extends ElementOrPositionCommand {
16
+ /**
17
+ * Whether the element is removed after copying.
18
+ */
19
+ readonly cut: boolean;
20
+ constructor(editor: Editor, { cut }?: {
21
+ cut?: boolean;
22
+ });
23
+ protected _isEnabledFor(elementOrPosition?: ElementOrPosition): boolean;
24
+ /**
25
+ * Copies the element (and removes it, with `cut: true`). Resolves when the clipboard has been written; rejects when
26
+ * the browser does not allow it.
27
+ */
28
+ execute(elementOrPosition?: ElementOrPosition): Promise<void>;
29
+ }
30
+ //# sourceMappingURL=elementCopyCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementCopyCommand.d.ts","sourceRoot":"","sources":["../src/elementCopyCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgF,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AACtH,OAAO,EAAE,wBAAwB,EAA8B,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGvH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,OAAO,kBAAmB,SAAQ,wBAAwB;IACvE;;OAEG;IACH,SAAgB,GAAG,EAAE,OAAO,CAAC;gBAEjB,MAAM,EAAE,MAAM,EAAE,EAAE,GAAW,EAAE,GAAE;QAAE,GAAG,CAAC,EAAE,OAAO,CAAA;KAAO;cAWhD,aAAa,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAMhF;;;OAGG;IACmB,OAAO,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;CA+BnF"}
@@ -0,0 +1,64 @@
1
+ import { ClipboardPipeline, ViewDataTransfer } from 'ckeditor5';
2
+ import { ElementOrPositionCommand, isInDocument, isStandalone } from 'ckeditor5-elements-core';
3
+ import { copyIcon, cutIcon } from './icons.js';
4
+ /**
5
+ * Copies an element to the system clipboard, as HTML and plain text. With `cut: true`, it also removes the element.
6
+ *
7
+ * The element is the given one, the parent of the given position, or the selected element or the parent of the
8
+ * selection (see {@link ElementOrPositionCommand}). Parts of a structure, such as table cells, rows and captions, cannot
9
+ * be copied on their own, so the command is disabled for them.
10
+ *
11
+ * The content goes through the clipboard pipeline, as with Ctrl+C: other plugins can change it (they listen to the
12
+ * `outputTransformation` event of `ClipboardPipeline`, and to `clipboardOutput` of the editing view document).
13
+ *
14
+ * Requires a secure context (HTTPS or `localhost`), as it uses the asynchronous Clipboard API.
15
+ */
16
+ export default class ElementCopyCommand extends ElementOrPositionCommand {
17
+ /**
18
+ * Whether the element is removed after copying.
19
+ */
20
+ cut;
21
+ constructor(editor, { cut = false } = {}) {
22
+ super(editor);
23
+ this.cut = cut;
24
+ this.title = cut ? editor.t('Cut') : editor.t('Copy');
25
+ this.icon = cut ? cutIcon : copyIcon;
26
+ // Copying does not change the data, so it stays enabled in read-only mode.
27
+ this.affectsData = cut;
28
+ }
29
+ _isEnabledFor(elementOrPosition) {
30
+ const element = this._getElement(elementOrPosition);
31
+ return window.isSecureContext && !!element && isStandalone(this.editor.model.schema, element);
32
+ }
33
+ /**
34
+ * Copies the element (and removes it, with `cut: true`). Resolves when the clipboard has been written; rejects when
35
+ * the browser does not allow it.
36
+ */
37
+ async execute(elementOrPosition) {
38
+ const editor = this.editor;
39
+ const model = editor.model;
40
+ const element = this._getElement(elementOrPosition);
41
+ if (!element || !isStandalone(model.schema, element)) {
42
+ return;
43
+ }
44
+ const dataTransfer = new ViewDataTransfer(new DataTransfer());
45
+ // Always "copy": the pipeline would remove the content of the document selection when cutting.
46
+ editor.plugins.get(ClipboardPipeline).fire('outputTransformation', {
47
+ dataTransfer,
48
+ content: model.getSelectedContent(model.createSelection(element, 'on')),
49
+ method: 'copy'
50
+ });
51
+ await navigator.clipboard.write([
52
+ new ClipboardItem({
53
+ 'text/html': new Blob([dataTransfer.getData('text/html')], { type: 'text/html' }),
54
+ 'text/plain': new Blob([dataTransfer.getData('text/plain')], { type: 'text/plain' })
55
+ })
56
+ ]);
57
+ if (this.cut && isInDocument(element) && model.canEditAt(element)) {
58
+ model.change(writer => {
59
+ writer.remove(element);
60
+ });
61
+ }
62
+ }
63
+ }
64
+ //# sourceMappingURL=elementCopyCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementCopyCommand.js","sourceRoot":"","sources":["../src/elementCopyCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAwD,MAAM,WAAW,CAAC;AACtH,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,YAAY,EAA0B,MAAM,yBAAyB,CAAC;AACvH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,OAAO,kBAAmB,SAAQ,wBAAwB;IACvE;;OAEG;IACa,GAAG,CAAU;IAE7B,YAAY,MAAc,EAAE,EAAE,GAAG,GAAG,KAAK,KAAwB,EAAE;QAClE,KAAK,CAAC,MAAM,CAAC,CAAC;QAEd,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;QAErC,2EAA2E;QAC3E,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC;IACxB,CAAC;IAEkB,aAAa,CAAC,iBAAqC;QACrE,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;QAEpD,OAAO,MAAM,CAAC,eAAe,IAAI,CAAC,CAAC,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/F,CAAC;IAED;;;OAGG;IACa,KAAK,CAAC,OAAO,CAAC,iBAAqC;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;QAEpD,IAAI,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;YACtD,OAAO;QACR,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,gBAAgB,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;QAE9D,+FAA+F;QAC/F,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAqC,sBAAsB,EAAE;YACtG,YAAY;YACZ,OAAO,EAAE,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACvE,MAAM,EAAE,MAAM;SACd,CAAC,CAAC;QAEH,MAAM,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC;YAC/B,IAAI,aAAa,CAAC;gBACjB,WAAW,EAAE,IAAI,IAAI,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;gBACjF,YAAY,EAAE,IAAI,IAAI,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;aACpF,CAAC;SACF,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YACnE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;gBACrB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACxB,CAAC,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;CACD"}
@@ -0,0 +1,38 @@
1
+ import { type Editor } from 'ckeditor5';
2
+ import { ElementOrPositionCommand, type ElementOrPosition } from 'ckeditor5-elements-core';
3
+ /**
4
+ * Where the pasted content goes, relative to the element:
5
+ *
6
+ * * `'replace'` – replaces the element,
7
+ * * `'before'` – before the element,
8
+ * * `'after'` – after the element.
9
+ */
10
+ export type ElementPastePlacement = 'replace' | 'before' | 'after';
11
+ /**
12
+ * Pastes the system clipboard content relative to an element.
13
+ *
14
+ * The element is the given one, the parent of the given position, or the selected element or the parent of the
15
+ * selection (see {@link ElementOrPositionCommand}). Parts of a structure, such as table cells, rows and captions, cannot
16
+ * be replaced, nor have content pasted next to them, so the command is disabled for them.
17
+ *
18
+ * The content is pasted as with Ctrl+V: it goes through the clipboard pipeline (the `clipboardInput` event of the
19
+ * editing view document), so other plugins process it, e.g. paste from Office cleans up content from Word, and image
20
+ * upload uploads the images on the clipboard. The selection is moved to the pasted content.
21
+ *
22
+ * Requires a secure context (HTTPS or `localhost`), as it uses the asynchronous Clipboard API.
23
+ * The browser may ask the user for permission.
24
+ */
25
+ export default class ElementPasteCommand extends ElementOrPositionCommand {
26
+ /**
27
+ * Where the pasted content goes, relative to the element.
28
+ */
29
+ readonly placement: ElementPastePlacement;
30
+ constructor(editor: Editor, placement: ElementPastePlacement);
31
+ protected _isEnabledFor(elementOrPosition?: ElementOrPosition): boolean;
32
+ /**
33
+ * Pastes the clipboard content relative to the element. Resolves when the content has been pasted; rejects when the
34
+ * browser does not allow reading the clipboard.
35
+ */
36
+ execute(elementOrPosition?: ElementOrPosition): Promise<void>;
37
+ }
38
+ //# sourceMappingURL=elementPasteCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementPasteCommand.d.ts","sourceRoot":"","sources":["../src/elementPasteCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmE,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AACzG,OAAO,EAAE,wBAAwB,EAA8B,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGvH;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEnE;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,wBAAwB;IACxE;;OAEG;IACH,SAAgB,SAAS,EAAE,qBAAqB,CAAC;gBAErC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,qBAAqB;cAYzC,aAAa,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAMhF;;;OAGG;IACmB,OAAO,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;CAgDnF"}
@@ -0,0 +1,100 @@
1
+ import { ViewDataTransfer, plainTextToHtml } from 'ckeditor5';
2
+ import { ElementOrPositionCommand, isInDocument, isStandalone } from 'ckeditor5-elements-core';
3
+ import { pasteAfterIcon, pasteBeforeIcon, pasteIcon } from './icons.js';
4
+ /**
5
+ * Pastes the system clipboard content relative to an element.
6
+ *
7
+ * The element is the given one, the parent of the given position, or the selected element or the parent of the
8
+ * selection (see {@link ElementOrPositionCommand}). Parts of a structure, such as table cells, rows and captions, cannot
9
+ * be replaced, nor have content pasted next to them, so the command is disabled for them.
10
+ *
11
+ * The content is pasted as with Ctrl+V: it goes through the clipboard pipeline (the `clipboardInput` event of the
12
+ * editing view document), so other plugins process it, e.g. paste from Office cleans up content from Word, and image
13
+ * upload uploads the images on the clipboard. The selection is moved to the pasted content.
14
+ *
15
+ * Requires a secure context (HTTPS or `localhost`), as it uses the asynchronous Clipboard API.
16
+ * The browser may ask the user for permission.
17
+ */
18
+ export default class ElementPasteCommand extends ElementOrPositionCommand {
19
+ /**
20
+ * Where the pasted content goes, relative to the element.
21
+ */
22
+ placement;
23
+ constructor(editor, placement) {
24
+ super(editor);
25
+ this.placement = placement;
26
+ this.title = {
27
+ replace: editor.t('Paste'),
28
+ before: editor.t('Paste before'),
29
+ after: editor.t('Paste after')
30
+ }[placement];
31
+ this.icon = { replace: pasteIcon, before: pasteBeforeIcon, after: pasteAfterIcon }[placement];
32
+ }
33
+ _isEnabledFor(elementOrPosition) {
34
+ const element = this._getElement(elementOrPosition);
35
+ return window.isSecureContext && !!element && isStandalone(this.editor.model.schema, element);
36
+ }
37
+ /**
38
+ * Pastes the clipboard content relative to the element. Resolves when the content has been pasted; rejects when the
39
+ * browser does not allow reading the clipboard.
40
+ */
41
+ async execute(elementOrPosition) {
42
+ // Resolve the element before reading the clipboard, as the selection may change in the meantime.
43
+ const element = this._getElement(elementOrPosition);
44
+ if (!element || !isStandalone(this.editor.model.schema, element)) {
45
+ return;
46
+ }
47
+ const dataTransfer = await readClipboard();
48
+ if (!dataTransfer || !isInDocument(element)) {
49
+ return;
50
+ }
51
+ const editing = this.editor.editing;
52
+ const model = this.editor.model;
53
+ const viewElement = editing.mapper.toViewElement(element);
54
+ if (!viewElement) {
55
+ return;
56
+ }
57
+ model.change(writer => {
58
+ const target = this.placement === 'before'
59
+ ? writer.createRange(writer.createPositionBefore(element))
60
+ : this.placement === 'after'
61
+ ? writer.createRange(writer.createPositionAfter(element))
62
+ : writer.createRangeOn(element);
63
+ if (!model.canEditAt(target)) {
64
+ return;
65
+ }
66
+ // The same data as `ClipboardObserver` fires for Ctrl+V. The pipeline pastes at the selection.
67
+ const data = {
68
+ dataTransfer,
69
+ content: dataTransfer.getData('text/html') || plainTextToHtmlOrEmpty(dataTransfer.getData('text/plain')),
70
+ method: 'paste',
71
+ target: viewElement,
72
+ targetRanges: [editing.mapper.toViewRange(target)]
73
+ };
74
+ writer.setSelection(target);
75
+ editing.view.document.fire('clipboardInput', data);
76
+ });
77
+ }
78
+ }
79
+ /**
80
+ * Reads the system clipboard into a data transfer: HTML, plain text and images (as files).
81
+ */
82
+ async function readClipboard() {
83
+ const nativeDataTransfer = new DataTransfer();
84
+ for (const item of await navigator.clipboard.read()) {
85
+ for (const type of item.types) {
86
+ const blob = await item.getType(type);
87
+ if (type === 'text/html' || type === 'text/plain') {
88
+ nativeDataTransfer.setData(type, await blob.text());
89
+ }
90
+ else if (type.startsWith('image/')) {
91
+ nativeDataTransfer.items.add(new File([blob], `image.${type.slice('image/'.length)}`, { type }));
92
+ }
93
+ }
94
+ }
95
+ return nativeDataTransfer.types.length ? new ViewDataTransfer(nativeDataTransfer, { cacheFiles: true }) : null;
96
+ }
97
+ function plainTextToHtmlOrEmpty(text) {
98
+ return text ? plainTextToHtml(text) : '';
99
+ }
100
+ //# sourceMappingURL=elementPasteCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementPasteCommand.js","sourceRoot":"","sources":["../src/elementPasteCommand.ts"],"names":[],"mappings":"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"}
package/dist/icons.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The icons of the element actions, in the style of the CKEditor 5 icons (20×20).
2
+ * The icons of the element actions and of the clipboard commands, in the style of the CKEditor 5 icons (20×20).
3
3
  */
4
4
  /**
5
5
  * Move up: an arrow up, above a block.
@@ -17,4 +17,24 @@ export declare const duplicateIcon: string;
17
17
  * Delete: CKEditor's own remove icon.
18
18
  */
19
19
  export declare const deleteIcon: string;
20
+ /**
21
+ * Copy: CKEditor's own copy icon.
22
+ */
23
+ export declare const copyIcon: string;
24
+ /**
25
+ * Cut: scissors.
26
+ */
27
+ export declare const cutIcon: string;
28
+ /**
29
+ * Paste: a clipboard.
30
+ */
31
+ export declare const pasteIcon: string;
32
+ /**
33
+ * Paste before: a small clipboard above a block.
34
+ */
35
+ export declare const pasteBeforeIcon: string;
36
+ /**
37
+ * Paste after: a block above a small clipboard.
38
+ */
39
+ export declare const pasteAfterIcon: string;
20
40
  //# sourceMappingURL=icons.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH;;GAEG;AACH,eAAO,MAAM,UAAU,QAGkC,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,YAAY,QAGyC,CAAC;AAEnE;;GAEG;AACH,eAAO,MAAM,aAAa,QAIJ,CAAC;AAEvB;;GAEG;AACH,eAAO,MAAM,UAAU,QAAa,CAAC"}
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH;;GAEG;AACH,eAAO,MAAM,UAAU,QAGkC,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,YAAY,QAGyC,CAAC;AAEnE;;GAEG;AACH,eAAO,MAAM,aAAa,QAIJ,CAAC;AAEvB;;GAEG;AACH,eAAO,MAAM,UAAU,QAAa,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,QAAQ,QAAW,CAAC;AAEjC;;GAEG;AACH,eAAO,MAAM,OAAO,QAGiG,CAAC;AAEtH;;GAEG;AACH,eAAO,MAAM,SAAS,QAIa,CAAC;AAEpC;;GAEG;AACH,eAAO,MAAM,eAAe,QAGuE,CAAC;AAEpG;;GAEG;AACH,eAAO,MAAM,cAAc,QAG0E,CAAC"}
package/dist/icons.js CHANGED
@@ -1,6 +1,6 @@
1
- import { IconRemove } from 'ckeditor5';
1
+ import { IconCopy, IconRemove } from 'ckeditor5';
2
2
  /**
3
- * The icons of the element actions, in the style of the CKEditor 5 icons (20×20).
3
+ * The icons of the element actions and of the clipboard commands, in the style of the CKEditor 5 icons (20×20).
4
4
  */
5
5
  /**
6
6
  * Move up: an arrow up, above a block.
@@ -25,4 +25,33 @@ export const duplicateIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0
25
25
  * Delete: CKEditor's own remove icon.
26
26
  */
27
27
  export const deleteIcon = IconRemove;
28
+ /**
29
+ * Copy: CKEditor's own copy icon.
30
+ */
31
+ export const copyIcon = IconCopy;
32
+ /**
33
+ * Cut: scissors.
34
+ */
35
+ export const cutIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="' +
36
+ 'M5.3 2.9 6.6 2.1l6.2 10.3a3 3 0 1 1-1.3.8L10 10.7 8.5 13.2a3 3 0 1 1-1.3-.8l2-3.3zm7.4 11.1a1.5 1.5 0 1 0 2.1 2.1 ' +
37
+ '1.5 1.5 0 0 0-2.1-2.1zm-7.4 0a1.5 1.5 0 1 0 2.1 2.1 1.5 1.5 0 0 0-2.1-2.1zm5.4-5.3 3.9-6.6 1.3.8-4.4 7.3z"/></svg>';
38
+ /**
39
+ * Paste: a clipboard.
40
+ */
41
+ export const pasteIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="' +
42
+ 'M7.5 2h5a1 1 0 0 1 1 1v.5h1.7a1.3 1.3 0 0 1 1.3 1.3v11.9a1.3 1.3 0 0 1-1.3 1.3H4.8a1.3 1.3 0 0 1-1.3-1.3V4.8a1.3 ' +
43
+ '1.3 0 0 1 1.3-1.3h1.7V3a1 1 0 0 1 1-1zM8 3.5V5h4V3.5zM5 5v11.5h10V5h-1.5v.5a1 1 0 0 1-1 1h-5a1 1 0 0 1-1-1V5zm2 ' +
44
+ '4h6v1.5H7zm0 3h4v1.5H7z"/></svg>';
45
+ /**
46
+ * Paste before: a small clipboard above a block.
47
+ */
48
+ export const pasteBeforeIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="' +
49
+ 'M8.5 1.5h3v1h1.4a.6.6 0 0 1 .6.6v5.3a.6.6 0 0 1-.6.6H7.1a.6.6 0 0 1-.6-.6V3.1a.6.6 0 0 1 .6-.6h1.4zM8 4v3.5h4V4zM3.5 ' +
50
+ '11h13a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-13a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1zm.5 1.5v4h12v-4z"/></svg>';
51
+ /**
52
+ * Paste after: a block above a small clipboard.
53
+ */
54
+ export const pasteAfterIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="' +
55
+ 'M3.5 2h13a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-13a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1zm.5 1.5v4h12v-4zM8.5 10.5h3v1h1.4a.6.6 0 0 ' +
56
+ '1 .6.6v5.3a.6.6 0 0 1-.6.6H7.1a.6.6 0 0 1-.6-.6v-5.3a.6.6 0 0 1 .6-.6h1.4zM8 13v3.5h4V13z"/></svg>';
28
57
  //# sourceMappingURL=icons.js.map
package/dist/icons.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"icons.js","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC;;GAEG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GACtB,2FAA2F;IAC3F,uHAAuH;IACvH,wDAAwD,CAAC;AAE1D;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GACxB,2FAA2F;IAC3F,gHAAgH;IAChH,iEAAiE,CAAC;AAEnE;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GACzB,2FAA2F;IAC3F,mHAAmH;IACnH,qHAAqH;IACrH,qBAAqB,CAAC;AAEvB;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC"}
1
+ {"version":3,"file":"icons.js","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEjD;;GAEG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GACtB,2FAA2F;IAC3F,uHAAuH;IACvH,wDAAwD,CAAC;AAE1D;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GACxB,2FAA2F;IAC3F,gHAAgH;IAChH,iEAAiE,CAAC;AAEnE;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GACzB,2FAA2F;IAC3F,mHAAmH;IACnH,qHAAqH;IACrH,qBAAqB,CAAC;AAEvB;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAEjC;;GAEG;AACH,MAAM,CAAC,MAAM,OAAO,GACnB,2FAA2F;IAC3F,oHAAoH;IACpH,oHAAoH,CAAC;AAEtH;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GACrB,2FAA2F;IAC3F,mHAAmH;IACnH,kHAAkH;IAClH,kCAAkC,CAAC;AAEpC;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAC3B,2FAA2F;IAC3F,uHAAuH;IACvH,kGAAkG,CAAC;AAEpG;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAC1B,2FAA2F;IAC3F,uHAAuH;IACvH,oGAAoG,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,12 +1,16 @@
1
1
  /**
2
- * Element actions: move an element up or down, duplicate it, or delete it.
2
+ * Element actions: move an element up or down, duplicate it, or delete it; and the clipboard commands that act on an
3
+ * element: copy, cut, paste, paste before and paste after.
3
4
  *
4
5
  * @module ckeditor5-elements-actions
5
6
  */
6
7
  export { default as ElementActions } from './elementActions.js';
8
+ export { default as ElementClipboard } from './elementClipboard.js';
7
9
  export { default as ElementMoveCommand, type ElementMoveDirection } from './elementMoveCommand.js';
8
10
  export { default as ElementDuplicateCommand } from './elementDuplicateCommand.js';
9
11
  export { default as ElementDeleteCommand } from './elementDeleteCommand.js';
10
- export { deleteIcon, duplicateIcon, moveDownIcon, moveUpIcon } from './icons.js';
12
+ export { default as ElementCopyCommand } from './elementCopyCommand.js';
13
+ export { default as ElementPasteCommand, type ElementPastePlacement } from './elementPasteCommand.js';
14
+ export { copyIcon, cutIcon, deleteIcon, duplicateIcon, moveDownIcon, moveUpIcon, pasteAfterIcon, pasteBeforeIcon, pasteIcon } from './icons.js';
11
15
  import './augmentation.js';
12
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGhE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAG5E,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEjF,OAAO,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGpE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAGtG,OAAO,EACN,QAAQ,EACR,OAAO,EACP,UAAU,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,cAAc,EACd,eAAe,EACf,SAAS,EACT,MAAM,YAAY,CAAC;AAEpB,OAAO,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -1,15 +1,19 @@
1
1
  /**
2
- * Element actions: move an element up or down, duplicate it, or delete it.
2
+ * Element actions: move an element up or down, duplicate it, or delete it; and the clipboard commands that act on an
3
+ * element: copy, cut, paste, paste before and paste after.
3
4
  *
4
5
  * @module ckeditor5-elements-actions
5
6
  */
6
7
  // Plugins.
7
8
  export { default as ElementActions } from './elementActions.js';
9
+ export { default as ElementClipboard } from './elementClipboard.js';
8
10
  // Commands.
9
11
  export { default as ElementMoveCommand } from './elementMoveCommand.js';
10
12
  export { default as ElementDuplicateCommand } from './elementDuplicateCommand.js';
11
13
  export { default as ElementDeleteCommand } from './elementDeleteCommand.js';
14
+ export { default as ElementCopyCommand } from './elementCopyCommand.js';
15
+ export { default as ElementPasteCommand } from './elementPasteCommand.js';
12
16
  // Icons.
13
- export { deleteIcon, duplicateIcon, moveDownIcon, moveUpIcon } from './icons.js';
17
+ export { copyIcon, cutIcon, deleteIcon, duplicateIcon, moveDownIcon, moveUpIcon, pasteAfterIcon, pasteBeforeIcon, pasteIcon } from './icons.js';
14
18
  import './augmentation.js';
15
19
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,WAAW;AACX,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEhE,YAAY;AACZ,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAA6B,MAAM,yBAAyB,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAE5E,SAAS;AACT,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEjF,OAAO,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,WAAW;AACX,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEpE,YAAY;AACZ,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAA6B,MAAM,yBAAyB,CAAC;AACnG,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAA8B,MAAM,0BAA0B,CAAC;AAEtG,SAAS;AACT,OAAO,EACN,QAAQ,EACR,OAAO,EACP,UAAU,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,cAAc,EACd,eAAe,EACf,SAAS,EACT,MAAM,YAAY,CAAC;AAEpB,OAAO,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ckeditor5-elements-actions",
3
- "version": "49.0.0-alpha.2",
4
- "description": "Element actions for CKEditor 5: move an element up or down, duplicate it, or delete it.",
3
+ "version": "49.0.0-alpha.4",
4
+ "description": "Element actions for CKEditor 5: move, duplicate and delete an element, and copy, cut and paste it, as commands with titles and icons for menus and toolbars.",
5
5
  "keywords": [
6
6
  "ckeditor",
7
7
  "ckeditor5",
@@ -37,7 +37,7 @@
37
37
  ],
38
38
  "sideEffects": false,
39
39
  "dependencies": {
40
- "ckeditor5-elements-core": "49.0.0-alpha.2"
40
+ "ckeditor5-elements-core": "49.0.0-alpha.4"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "ckeditor5": "^49.0.0"
@@ -1,8 +1,17 @@
1
- import type { ElementActions, ElementDeleteCommand, ElementDuplicateCommand, ElementMoveCommand } from './index.js';
1
+ import type {
2
+ ElementActions,
3
+ ElementClipboard,
4
+ ElementCopyCommand,
5
+ ElementDeleteCommand,
6
+ ElementDuplicateCommand,
7
+ ElementMoveCommand,
8
+ ElementPasteCommand
9
+ } from './index.js';
2
10
 
3
11
  declare module 'ckeditor5' {
4
12
  interface PluginsMap {
5
13
  [ElementActions.pluginName]: ElementActions;
14
+ [ElementClipboard.pluginName]: ElementClipboard;
6
15
  }
7
16
 
8
17
  interface CommandsMap {
@@ -10,5 +19,10 @@ declare module 'ckeditor5' {
10
19
  moveElementDown: ElementMoveCommand;
11
20
  duplicateElement: ElementDuplicateCommand;
12
21
  deleteElement: ElementDeleteCommand;
22
+ copyElement: ElementCopyCommand;
23
+ cutElement: ElementCopyCommand;
24
+ pasteElement: ElementPasteCommand;
25
+ pasteElementBefore: ElementPasteCommand;
26
+ pasteElementAfter: ElementPasteCommand;
13
27
  }
14
28
  }
@@ -0,0 +1,35 @@
1
+ import { ClipboardPipeline, Notification, Plugin } from 'ckeditor5';
2
+ import ElementCopyCommand from './elementCopyCommand.js';
3
+ import ElementPasteCommand from './elementPasteCommand.js';
4
+
5
+ /**
6
+ * Registers clipboard commands that act on an element:
7
+ * `copyElement`, `cutElement`, `pasteElement`, `pasteElementBefore` and `pasteElementAfter`.
8
+ *
9
+ * ```ts
10
+ * await editor.execute('copyElement', element);
11
+ * ```
12
+ *
13
+ * The commands have titles and icons, so they can be menu items (e.g. in the `elementContextMenu` config of
14
+ * `ElementContextMenu`) and buttons. Copying and pasting go through the clipboard pipeline, as Ctrl+C and Ctrl+V do.
15
+ */
16
+ export default class ElementClipboard extends Plugin {
17
+ public static get requires(): readonly [typeof ClipboardPipeline, typeof Notification] {
18
+ // The buttons of the commands report failures (e.g. no clipboard permission) with notifications.
19
+ return [ClipboardPipeline, Notification] as const;
20
+ }
21
+
22
+ public static get pluginName(): 'ElementClipboard' {
23
+ return 'ElementClipboard' as const;
24
+ }
25
+
26
+ public init(): void {
27
+ const editor = this.editor;
28
+
29
+ editor.commands.add('copyElement', new ElementCopyCommand(editor));
30
+ editor.commands.add('cutElement', new ElementCopyCommand(editor, { cut: true }));
31
+ editor.commands.add('pasteElement', new ElementPasteCommand(editor, 'replace'));
32
+ editor.commands.add('pasteElementBefore', new ElementPasteCommand(editor, 'before'));
33
+ editor.commands.add('pasteElementAfter', new ElementPasteCommand(editor, 'after'));
34
+ }
35
+ }
@@ -0,0 +1,75 @@
1
+ import { ClipboardPipeline, ViewDataTransfer, type ClipboardOutputTransformationEvent, type Editor } from 'ckeditor5';
2
+ import { ElementOrPositionCommand, isInDocument, isStandalone, type ElementOrPosition } from 'ckeditor5-elements-core';
3
+ import { copyIcon, cutIcon } from './icons.js';
4
+
5
+ /**
6
+ * Copies an element to the system clipboard, as HTML and plain text. With `cut: true`, it also removes the element.
7
+ *
8
+ * The element is the given one, the parent of the given position, or the selected element or the parent of the
9
+ * selection (see {@link ElementOrPositionCommand}). Parts of a structure, such as table cells, rows and captions, cannot
10
+ * be copied on their own, so the command is disabled for them.
11
+ *
12
+ * The content goes through the clipboard pipeline, as with Ctrl+C: other plugins can change it (they listen to the
13
+ * `outputTransformation` event of `ClipboardPipeline`, and to `clipboardOutput` of the editing view document).
14
+ *
15
+ * Requires a secure context (HTTPS or `localhost`), as it uses the asynchronous Clipboard API.
16
+ */
17
+ export default class ElementCopyCommand extends ElementOrPositionCommand {
18
+ /**
19
+ * Whether the element is removed after copying.
20
+ */
21
+ public readonly cut: boolean;
22
+
23
+ constructor(editor: Editor, { cut = false }: { cut?: boolean } = {}) {
24
+ super(editor);
25
+
26
+ this.cut = cut;
27
+ this.title = cut ? editor.t('Cut') : editor.t('Copy');
28
+ this.icon = cut ? cutIcon : copyIcon;
29
+
30
+ // Copying does not change the data, so it stays enabled in read-only mode.
31
+ this.affectsData = cut;
32
+ }
33
+
34
+ protected override _isEnabledFor(elementOrPosition?: ElementOrPosition): boolean {
35
+ const element = this._getElement(elementOrPosition);
36
+
37
+ return window.isSecureContext && !!element && isStandalone(this.editor.model.schema, element);
38
+ }
39
+
40
+ /**
41
+ * Copies the element (and removes it, with `cut: true`). Resolves when the clipboard has been written; rejects when
42
+ * the browser does not allow it.
43
+ */
44
+ public override async execute(elementOrPosition?: ElementOrPosition): Promise<void> {
45
+ const editor = this.editor;
46
+ const model = editor.model;
47
+ const element = this._getElement(elementOrPosition);
48
+
49
+ if (!element || !isStandalone(model.schema, element)) {
50
+ return;
51
+ }
52
+
53
+ const dataTransfer = new ViewDataTransfer(new DataTransfer());
54
+
55
+ // Always "copy": the pipeline would remove the content of the document selection when cutting.
56
+ editor.plugins.get(ClipboardPipeline).fire<ClipboardOutputTransformationEvent>('outputTransformation', {
57
+ dataTransfer,
58
+ content: model.getSelectedContent(model.createSelection(element, 'on')),
59
+ method: 'copy'
60
+ });
61
+
62
+ await navigator.clipboard.write([
63
+ new ClipboardItem({
64
+ 'text/html': new Blob([dataTransfer.getData('text/html')], { type: 'text/html' }),
65
+ 'text/plain': new Blob([dataTransfer.getData('text/plain')], { type: 'text/plain' })
66
+ })
67
+ ]);
68
+
69
+ if (this.cut && isInDocument(element) && model.canEditAt(element)) {
70
+ model.change(writer => {
71
+ writer.remove(element);
72
+ });
73
+ }
74
+ }
75
+ }
@@ -0,0 +1,129 @@
1
+ import { ViewDataTransfer, plainTextToHtml, type ClipboardInputEventData, type Editor } from 'ckeditor5';
2
+ import { ElementOrPositionCommand, isInDocument, isStandalone, type ElementOrPosition } from 'ckeditor5-elements-core';
3
+ import { pasteAfterIcon, pasteBeforeIcon, pasteIcon } from './icons.js';
4
+
5
+ /**
6
+ * Where the pasted content goes, relative to the element:
7
+ *
8
+ * * `'replace'` – replaces the element,
9
+ * * `'before'` – before the element,
10
+ * * `'after'` – after the element.
11
+ */
12
+ export type ElementPastePlacement = 'replace' | 'before' | 'after';
13
+
14
+ /**
15
+ * Pastes the system clipboard content relative to an element.
16
+ *
17
+ * The element is the given one, the parent of the given position, or the selected element or the parent of the
18
+ * selection (see {@link ElementOrPositionCommand}). Parts of a structure, such as table cells, rows and captions, cannot
19
+ * be replaced, nor have content pasted next to them, so the command is disabled for them.
20
+ *
21
+ * The content is pasted as with Ctrl+V: it goes through the clipboard pipeline (the `clipboardInput` event of the
22
+ * editing view document), so other plugins process it, e.g. paste from Office cleans up content from Word, and image
23
+ * upload uploads the images on the clipboard. The selection is moved to the pasted content.
24
+ *
25
+ * Requires a secure context (HTTPS or `localhost`), as it uses the asynchronous Clipboard API.
26
+ * The browser may ask the user for permission.
27
+ */
28
+ export default class ElementPasteCommand extends ElementOrPositionCommand {
29
+ /**
30
+ * Where the pasted content goes, relative to the element.
31
+ */
32
+ public readonly placement: ElementPastePlacement;
33
+
34
+ constructor(editor: Editor, placement: ElementPastePlacement) {
35
+ super(editor);
36
+
37
+ this.placement = placement;
38
+ this.title = {
39
+ replace: editor.t('Paste'),
40
+ before: editor.t('Paste before'),
41
+ after: editor.t('Paste after')
42
+ }[placement];
43
+ this.icon = { replace: pasteIcon, before: pasteBeforeIcon, after: pasteAfterIcon }[placement];
44
+ }
45
+
46
+ protected override _isEnabledFor(elementOrPosition?: ElementOrPosition): boolean {
47
+ const element = this._getElement(elementOrPosition);
48
+
49
+ return window.isSecureContext && !!element && isStandalone(this.editor.model.schema, element);
50
+ }
51
+
52
+ /**
53
+ * Pastes the clipboard content relative to the element. Resolves when the content has been pasted; rejects when the
54
+ * browser does not allow reading the clipboard.
55
+ */
56
+ public override async execute(elementOrPosition?: ElementOrPosition): Promise<void> {
57
+ // Resolve the element before reading the clipboard, as the selection may change in the meantime.
58
+ const element = this._getElement(elementOrPosition);
59
+
60
+ if (!element || !isStandalone(this.editor.model.schema, element)) {
61
+ return;
62
+ }
63
+
64
+ const dataTransfer = await readClipboard();
65
+
66
+ if (!dataTransfer || !isInDocument(element)) {
67
+ return;
68
+ }
69
+
70
+ const editing = this.editor.editing;
71
+ const model = this.editor.model;
72
+ const viewElement = editing.mapper.toViewElement(element);
73
+
74
+ if (!viewElement) {
75
+ return;
76
+ }
77
+
78
+ model.change(writer => {
79
+ const target =
80
+ this.placement === 'before'
81
+ ? writer.createRange(writer.createPositionBefore(element))
82
+ : this.placement === 'after'
83
+ ? writer.createRange(writer.createPositionAfter(element))
84
+ : writer.createRangeOn(element);
85
+
86
+ if (!model.canEditAt(target)) {
87
+ return;
88
+ }
89
+
90
+ // The same data as `ClipboardObserver` fires for Ctrl+V. The pipeline pastes at the selection.
91
+ const data: ClipboardInputEventData = {
92
+ dataTransfer,
93
+ content:
94
+ dataTransfer.getData('text/html') || plainTextToHtmlOrEmpty(dataTransfer.getData('text/plain')),
95
+ method: 'paste',
96
+ target: viewElement,
97
+ targetRanges: [editing.mapper.toViewRange(target)]
98
+ };
99
+
100
+ writer.setSelection(target);
101
+ editing.view.document.fire('clipboardInput', data);
102
+ });
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Reads the system clipboard into a data transfer: HTML, plain text and images (as files).
108
+ */
109
+ async function readClipboard(): Promise<ViewDataTransfer | null> {
110
+ const nativeDataTransfer = new DataTransfer();
111
+
112
+ for (const item of await navigator.clipboard.read()) {
113
+ for (const type of item.types) {
114
+ const blob = await item.getType(type);
115
+
116
+ if (type === 'text/html' || type === 'text/plain') {
117
+ nativeDataTransfer.setData(type, await blob.text());
118
+ } else if (type.startsWith('image/')) {
119
+ nativeDataTransfer.items.add(new File([blob], `image.${type.slice('image/'.length)}`, { type }));
120
+ }
121
+ }
122
+ }
123
+
124
+ return nativeDataTransfer.types.length ? new ViewDataTransfer(nativeDataTransfer, { cacheFiles: true }) : null;
125
+ }
126
+
127
+ function plainTextToHtmlOrEmpty(text: string): string {
128
+ return text ? plainTextToHtml(text) : '';
129
+ }
package/src/icons.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { IconRemove } from 'ckeditor5';
1
+ import { IconCopy, IconRemove } from 'ckeditor5';
2
2
 
3
3
  /**
4
- * The icons of the element actions, in the style of the CKEditor 5 icons (20×20).
4
+ * The icons of the element actions and of the clipboard commands, in the style of the CKEditor 5 icons (20×20).
5
5
  */
6
6
 
7
7
  /**
@@ -33,3 +33,41 @@ export const duplicateIcon =
33
33
  * Delete: CKEditor's own remove icon.
34
34
  */
35
35
  export const deleteIcon = IconRemove;
36
+
37
+ /**
38
+ * Copy: CKEditor's own copy icon.
39
+ */
40
+ export const copyIcon = IconCopy;
41
+
42
+ /**
43
+ * Cut: scissors.
44
+ */
45
+ export const cutIcon =
46
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="' +
47
+ 'M5.3 2.9 6.6 2.1l6.2 10.3a3 3 0 1 1-1.3.8L10 10.7 8.5 13.2a3 3 0 1 1-1.3-.8l2-3.3zm7.4 11.1a1.5 1.5 0 1 0 2.1 2.1 ' +
48
+ '1.5 1.5 0 0 0-2.1-2.1zm-7.4 0a1.5 1.5 0 1 0 2.1 2.1 1.5 1.5 0 0 0-2.1-2.1zm5.4-5.3 3.9-6.6 1.3.8-4.4 7.3z"/></svg>';
49
+
50
+ /**
51
+ * Paste: a clipboard.
52
+ */
53
+ export const pasteIcon =
54
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="' +
55
+ 'M7.5 2h5a1 1 0 0 1 1 1v.5h1.7a1.3 1.3 0 0 1 1.3 1.3v11.9a1.3 1.3 0 0 1-1.3 1.3H4.8a1.3 1.3 0 0 1-1.3-1.3V4.8a1.3 ' +
56
+ '1.3 0 0 1 1.3-1.3h1.7V3a1 1 0 0 1 1-1zM8 3.5V5h4V3.5zM5 5v11.5h10V5h-1.5v.5a1 1 0 0 1-1 1h-5a1 1 0 0 1-1-1V5zm2 ' +
57
+ '4h6v1.5H7zm0 3h4v1.5H7z"/></svg>';
58
+
59
+ /**
60
+ * Paste before: a small clipboard above a block.
61
+ */
62
+ export const pasteBeforeIcon =
63
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="' +
64
+ 'M8.5 1.5h3v1h1.4a.6.6 0 0 1 .6.6v5.3a.6.6 0 0 1-.6.6H7.1a.6.6 0 0 1-.6-.6V3.1a.6.6 0 0 1 .6-.6h1.4zM8 4v3.5h4V4zM3.5 ' +
65
+ '11h13a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-13a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1zm.5 1.5v4h12v-4z"/></svg>';
66
+
67
+ /**
68
+ * Paste after: a block above a small clipboard.
69
+ */
70
+ export const pasteAfterIcon =
71
+ '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill-rule="evenodd" d="' +
72
+ 'M3.5 2h13a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-13a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1zm.5 1.5v4h12v-4zM8.5 10.5h3v1h1.4a.6.6 0 0 ' +
73
+ '1 .6.6v5.3a.6.6 0 0 1-.6.6H7.1a.6.6 0 0 1-.6-.6v-5.3a.6.6 0 0 1 .6-.6h1.4zM8 13v3.5h4V13z"/></svg>';
package/src/index.ts CHANGED
@@ -1,18 +1,32 @@
1
1
  /**
2
- * Element actions: move an element up or down, duplicate it, or delete it.
2
+ * Element actions: move an element up or down, duplicate it, or delete it; and the clipboard commands that act on an
3
+ * element: copy, cut, paste, paste before and paste after.
3
4
  *
4
5
  * @module ckeditor5-elements-actions
5
6
  */
6
7
 
7
8
  // Plugins.
8
9
  export { default as ElementActions } from './elementActions.js';
10
+ export { default as ElementClipboard } from './elementClipboard.js';
9
11
 
10
12
  // Commands.
11
13
  export { default as ElementMoveCommand, type ElementMoveDirection } from './elementMoveCommand.js';
12
14
  export { default as ElementDuplicateCommand } from './elementDuplicateCommand.js';
13
15
  export { default as ElementDeleteCommand } from './elementDeleteCommand.js';
16
+ export { default as ElementCopyCommand } from './elementCopyCommand.js';
17
+ export { default as ElementPasteCommand, type ElementPastePlacement } from './elementPasteCommand.js';
14
18
 
15
19
  // Icons.
16
- export { deleteIcon, duplicateIcon, moveDownIcon, moveUpIcon } from './icons.js';
20
+ export {
21
+ copyIcon,
22
+ cutIcon,
23
+ deleteIcon,
24
+ duplicateIcon,
25
+ moveDownIcon,
26
+ moveUpIcon,
27
+ pasteAfterIcon,
28
+ pasteBeforeIcon,
29
+ pasteIcon
30
+ } from './icons.js';
17
31
 
18
32
  import './augmentation.js';