@atlaskit/editor-plugin-clipboard 0.1.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 -0
- package/LICENSE.md +13 -0
- package/README.md +30 -0
- package/dist/cjs/index.js +13 -0
- package/dist/cjs/plugin-key.js +8 -0
- package/dist/cjs/plugin.js +21 -0
- package/dist/cjs/pm-plugins/main.js +124 -0
- package/dist/es2019/index.js +1 -0
- package/dist/es2019/plugin-key.js +2 -0
- package/dist/es2019/plugin.js +11 -0
- package/dist/es2019/pm-plugins/main.js +102 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/plugin-key.js +2 -0
- package/dist/esm/plugin.js +15 -0
- package/dist/esm/pm-plugins/main.js +111 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/plugin-key.d.ts +2 -0
- package/dist/types/plugin.d.ts +4 -0
- package/dist/types/pm-plugins/main.d.ts +18 -0
- package/dist/types-ts4.5/index.d.ts +2 -0
- package/dist/types-ts4.5/plugin-key.d.ts +2 -0
- package/dist/types-ts4.5/plugin.d.ts +4 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +18 -0
- package/package.json +88 -0
- package/report.api.md +41 -0
- package/tmp/api-report-tmp.d.ts +17 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @atlaskit/editor-plugin-clipboard
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright 2023 Atlassian Pty Ltd
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Editor plugin clipboard
|
|
2
|
+
|
|
3
|
+
Clipboard plugin for @atlaskit/editor-core
|
|
4
|
+
|
|
5
|
+
**Note:** This component is designed for internal Atlassian development.
|
|
6
|
+
External contributors will be able to use this component but will not be able to submit issues.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
---
|
|
10
|
+
- **Install** - *yarn add @atlaskit/editor-plugin-clipboard*
|
|
11
|
+
- **npm** - [@atlaskit/editor-plugin-clipboard](https://www.npmjs.com/package/@atlaskit/editor-plugin-clipboard)
|
|
12
|
+
- **Source** - [Bitbucket](https://bitbucket.org/atlassian/atlassian-frontend/src/master/packages/editor/editor-plugin-clipboard)
|
|
13
|
+
- **Bundle** - [unpkg.com](https://unpkg.com/@atlaskit/editor-plugin-clipboard/dist/)
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
---
|
|
17
|
+
**Internal use only**
|
|
18
|
+
|
|
19
|
+
@atlaskit/editor-plugin-clipboard is intended for internal use by the @atlaskit/editor-core and as a plugin dependency of the Editor within your product.
|
|
20
|
+
|
|
21
|
+
Direct use of this component is not supported.
|
|
22
|
+
|
|
23
|
+
Please see [Atlaskit - Editor plugin clipboard](https://atlaskit.atlassian.com/packages/editor/editor-plugin-clipboard) for documentation and examples for this package.
|
|
24
|
+
|
|
25
|
+
## Support
|
|
26
|
+
---
|
|
27
|
+
For internal Atlassian, visit the slack channel [#help-editor](https://atlassian.slack.com/archives/CFG3PSQ9E) for support or visit [go/editor-help](https://go/editor-help) to submit a bug.
|
|
28
|
+
## License
|
|
29
|
+
---
|
|
30
|
+
Please see [Atlassian Frontend - License](https://hello.atlassian.net/wiki/spaces/AF/pages/2589099144/Documentation#License) for more licensing information.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
Object.defineProperty(exports, "clipboardPlugin", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function get() {
|
|
10
|
+
return _plugin.default;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
var _plugin = _interopRequireDefault(require("./plugin"));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.clipboardPluginKey = void 0;
|
|
7
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
8
|
+
var clipboardPluginKey = exports.clipboardPluginKey = new _state.PluginKey('clipboardPlugin');
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _main = require("./pm-plugins/main");
|
|
8
|
+
var clipboard = function clipboard() {
|
|
9
|
+
return {
|
|
10
|
+
name: 'clipboard',
|
|
11
|
+
pmPlugins: function pmPlugins() {
|
|
12
|
+
return [{
|
|
13
|
+
name: 'clipboard',
|
|
14
|
+
plugin: function plugin(options) {
|
|
15
|
+
return (0, _main.createPlugin)(options);
|
|
16
|
+
}
|
|
17
|
+
}];
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
var _default = exports.default = clipboard;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.createPlugin = exports.createClipboardSerializer = void 0;
|
|
8
|
+
Object.defineProperty(exports, "getAnalyticsPayload", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function get() {
|
|
11
|
+
return _clipboard.getAnalyticsPayload;
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
exports.sendClipboardAnalytics = void 0;
|
|
15
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
16
|
+
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
17
|
+
var _clipboard = require("@atlaskit/editor-common/clipboard");
|
|
18
|
+
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
19
|
+
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
20
|
+
var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
21
|
+
var _pluginKey = require("../plugin-key");
|
|
22
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
23
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
24
|
+
var createPlugin = exports.createPlugin = function createPlugin(_ref) {
|
|
25
|
+
var dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent,
|
|
26
|
+
schema = _ref.schema;
|
|
27
|
+
var editorView;
|
|
28
|
+
var getEditorView = function getEditorView() {
|
|
29
|
+
return editorView;
|
|
30
|
+
};
|
|
31
|
+
return new _safePlugin.SafePlugin({
|
|
32
|
+
key: _pluginKey.clipboardPluginKey,
|
|
33
|
+
view: function view(_view) {
|
|
34
|
+
editorView = _view;
|
|
35
|
+
return {
|
|
36
|
+
update: function update(view) {
|
|
37
|
+
editorView = view;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
props: {
|
|
42
|
+
handleDOMEvents: {
|
|
43
|
+
cut: function cut(view) {
|
|
44
|
+
return sendClipboardAnalytics(view, dispatchAnalyticsEvent, _analytics.ACTION.CUT);
|
|
45
|
+
},
|
|
46
|
+
copy: function copy(view) {
|
|
47
|
+
return sendClipboardAnalytics(view, dispatchAnalyticsEvent, _analytics.ACTION.COPIED);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
clipboardSerializer: createClipboardSerializer(schema, getEditorView)
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Overrides Prosemirror's default clipboardSerializer, in order to fix table row copy/paste bug raised in ED-13003.
|
|
57
|
+
* This allows us to store the original table’s attributes on the new table that the row is wrapped with when it is being copied.
|
|
58
|
+
* e.g. keeping the layout on a row that is copied.
|
|
59
|
+
* We store the default serializer in order to call it after we handle the table row case.
|
|
60
|
+
*/
|
|
61
|
+
var createClipboardSerializer = exports.createClipboardSerializer = function createClipboardSerializer(schema, getEditorView) {
|
|
62
|
+
var oldSerializer = _model.DOMSerializer.fromSchema(schema);
|
|
63
|
+
var newSerializer = new _model.DOMSerializer(oldSerializer.nodes, oldSerializer.marks);
|
|
64
|
+
var originalSerializeFragment = newSerializer.serializeFragment.bind(newSerializer);
|
|
65
|
+
newSerializer.serializeFragment = function (content) {
|
|
66
|
+
var _content$firstChild;
|
|
67
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
68
|
+
var target = arguments.length > 2 ? arguments[2] : undefined;
|
|
69
|
+
var editorView = getEditorView();
|
|
70
|
+
var selection = editorView.state.selection;
|
|
71
|
+
|
|
72
|
+
// We do not need to handle when a user copies a tableRow + other content.
|
|
73
|
+
// In that scenario it already wraps the Row with correct Table and attributes.
|
|
74
|
+
if (!options.tableWrapperExists) {
|
|
75
|
+
var i = 0;
|
|
76
|
+
while (i < content.childCount) {
|
|
77
|
+
var _content$maybeChild;
|
|
78
|
+
if (((_content$maybeChild = content.maybeChild(i)) === null || _content$maybeChild === void 0 ? void 0 : _content$maybeChild.type.name) === 'table') {
|
|
79
|
+
options.tableWrapperExists = true;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
i++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// When the content being copied includes a tableRow that is not already wrapped with a table,
|
|
87
|
+
// We will wrap it with one ourselves, while preserving the parent table's attributes.
|
|
88
|
+
if (((_content$firstChild = content.firstChild) === null || _content$firstChild === void 0 ? void 0 : _content$firstChild.type.name) === 'tableRow' && !options.tableWrapperExists) {
|
|
89
|
+
// We only want 1 table wrapping the rows.
|
|
90
|
+
// tableWrapperExist is a custom prop added solely for the purposes of this recursive algorithm.
|
|
91
|
+
// The function is recursively called for each node in the tree captured in the fragment.
|
|
92
|
+
// For recursive logic see the bind call above and the prosemirror-model (https://github.com/ProseMirror/prosemirror-model/blob/master/src/to_dom.js#L44
|
|
93
|
+
// and https://github.com/ProseMirror/prosemirror-model/blob/master/src/to_dom.js#L87)
|
|
94
|
+
options.tableWrapperExists = true;
|
|
95
|
+
var parentTable = (0, _utils.findParentNodeOfType)(schema.nodes.table)(selection);
|
|
96
|
+
var attributes = parentTable === null || parentTable === void 0 ? void 0 : parentTable.node.attrs;
|
|
97
|
+
var newTable = schema.nodes.table;
|
|
98
|
+
// Explicitly remove local id since we are creating a new table and it should have a unique local id which will be generated.
|
|
99
|
+
var newTableNode = newTable.createChecked(_objectSpread(_objectSpread({}, attributes), {}, {
|
|
100
|
+
localId: undefined
|
|
101
|
+
}), content);
|
|
102
|
+
var newContent = _model.Fragment.from(newTableNode);
|
|
103
|
+
// Pass updated content into original ProseMirror serializeFragment function.
|
|
104
|
+
// Currently incorrectly typed in @Types. See this GitHub thread: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57668
|
|
105
|
+
//@ts-ignore
|
|
106
|
+
return originalSerializeFragment(newContent, options, target);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// If we're not copying any rows, just run default serializeFragment function.
|
|
110
|
+
// Currently incorrectly typed in @Types. See this GitHub thread: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57668
|
|
111
|
+
//@ts-ignore
|
|
112
|
+
return originalSerializeFragment(content, options, target);
|
|
113
|
+
};
|
|
114
|
+
return newSerializer;
|
|
115
|
+
};
|
|
116
|
+
var sendClipboardAnalytics = exports.sendClipboardAnalytics = function sendClipboardAnalytics(view, dispatchAnalyticsEvent, action) {
|
|
117
|
+
var clipboardAnalyticsPayload = (0, _clipboard.getAnalyticsPayload)(view.state, action);
|
|
118
|
+
if (clipboardAnalyticsPayload) {
|
|
119
|
+
dispatchAnalyticsEvent(clipboardAnalyticsPayload);
|
|
120
|
+
}
|
|
121
|
+
// return false so we don't block any other plugins' cut or copy handlers
|
|
122
|
+
// from running just because we are sending an analytics event
|
|
123
|
+
return false;
|
|
124
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as clipboardPlugin } from './plugin';
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { ACTION } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { getAnalyticsPayload } from '@atlaskit/editor-common/clipboard';
|
|
3
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
4
|
+
import { DOMSerializer, Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
+
import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
6
|
+
import { clipboardPluginKey } from '../plugin-key';
|
|
7
|
+
export const createPlugin = ({
|
|
8
|
+
dispatchAnalyticsEvent,
|
|
9
|
+
schema
|
|
10
|
+
}) => {
|
|
11
|
+
let editorView;
|
|
12
|
+
const getEditorView = () => editorView;
|
|
13
|
+
return new SafePlugin({
|
|
14
|
+
key: clipboardPluginKey,
|
|
15
|
+
view: view => {
|
|
16
|
+
editorView = view;
|
|
17
|
+
return {
|
|
18
|
+
update: view => {
|
|
19
|
+
editorView = view;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
props: {
|
|
24
|
+
handleDOMEvents: {
|
|
25
|
+
cut: view => sendClipboardAnalytics(view, dispatchAnalyticsEvent, ACTION.CUT),
|
|
26
|
+
copy: view => sendClipboardAnalytics(view, dispatchAnalyticsEvent, ACTION.COPIED)
|
|
27
|
+
},
|
|
28
|
+
clipboardSerializer: createClipboardSerializer(schema, getEditorView)
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Overrides Prosemirror's default clipboardSerializer, in order to fix table row copy/paste bug raised in ED-13003.
|
|
35
|
+
* This allows us to store the original table’s attributes on the new table that the row is wrapped with when it is being copied.
|
|
36
|
+
* e.g. keeping the layout on a row that is copied.
|
|
37
|
+
* We store the default serializer in order to call it after we handle the table row case.
|
|
38
|
+
*/
|
|
39
|
+
export const createClipboardSerializer = (schema, getEditorView) => {
|
|
40
|
+
const oldSerializer = DOMSerializer.fromSchema(schema);
|
|
41
|
+
const newSerializer = new DOMSerializer(oldSerializer.nodes, oldSerializer.marks);
|
|
42
|
+
const originalSerializeFragment = newSerializer.serializeFragment.bind(newSerializer);
|
|
43
|
+
newSerializer.serializeFragment = (content, options = {}, target) => {
|
|
44
|
+
var _content$firstChild;
|
|
45
|
+
const editorView = getEditorView();
|
|
46
|
+
const selection = editorView.state.selection;
|
|
47
|
+
|
|
48
|
+
// We do not need to handle when a user copies a tableRow + other content.
|
|
49
|
+
// In that scenario it already wraps the Row with correct Table and attributes.
|
|
50
|
+
if (!options.tableWrapperExists) {
|
|
51
|
+
let i = 0;
|
|
52
|
+
while (i < content.childCount) {
|
|
53
|
+
var _content$maybeChild;
|
|
54
|
+
if (((_content$maybeChild = content.maybeChild(i)) === null || _content$maybeChild === void 0 ? void 0 : _content$maybeChild.type.name) === 'table') {
|
|
55
|
+
options.tableWrapperExists = true;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
i++;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// When the content being copied includes a tableRow that is not already wrapped with a table,
|
|
63
|
+
// We will wrap it with one ourselves, while preserving the parent table's attributes.
|
|
64
|
+
if (((_content$firstChild = content.firstChild) === null || _content$firstChild === void 0 ? void 0 : _content$firstChild.type.name) === 'tableRow' && !options.tableWrapperExists) {
|
|
65
|
+
// We only want 1 table wrapping the rows.
|
|
66
|
+
// tableWrapperExist is a custom prop added solely for the purposes of this recursive algorithm.
|
|
67
|
+
// The function is recursively called for each node in the tree captured in the fragment.
|
|
68
|
+
// For recursive logic see the bind call above and the prosemirror-model (https://github.com/ProseMirror/prosemirror-model/blob/master/src/to_dom.js#L44
|
|
69
|
+
// and https://github.com/ProseMirror/prosemirror-model/blob/master/src/to_dom.js#L87)
|
|
70
|
+
options.tableWrapperExists = true;
|
|
71
|
+
const parentTable = findParentNodeOfType(schema.nodes.table)(selection);
|
|
72
|
+
const attributes = parentTable === null || parentTable === void 0 ? void 0 : parentTable.node.attrs;
|
|
73
|
+
const newTable = schema.nodes.table;
|
|
74
|
+
// Explicitly remove local id since we are creating a new table and it should have a unique local id which will be generated.
|
|
75
|
+
const newTableNode = newTable.createChecked({
|
|
76
|
+
...attributes,
|
|
77
|
+
localId: undefined
|
|
78
|
+
}, content);
|
|
79
|
+
const newContent = Fragment.from(newTableNode);
|
|
80
|
+
// Pass updated content into original ProseMirror serializeFragment function.
|
|
81
|
+
// Currently incorrectly typed in @Types. See this GitHub thread: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57668
|
|
82
|
+
//@ts-ignore
|
|
83
|
+
return originalSerializeFragment(newContent, options, target);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// If we're not copying any rows, just run default serializeFragment function.
|
|
87
|
+
// Currently incorrectly typed in @Types. See this GitHub thread: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57668
|
|
88
|
+
//@ts-ignore
|
|
89
|
+
return originalSerializeFragment(content, options, target);
|
|
90
|
+
};
|
|
91
|
+
return newSerializer;
|
|
92
|
+
};
|
|
93
|
+
export const sendClipboardAnalytics = (view, dispatchAnalyticsEvent, action) => {
|
|
94
|
+
const clipboardAnalyticsPayload = getAnalyticsPayload(view.state, action);
|
|
95
|
+
if (clipboardAnalyticsPayload) {
|
|
96
|
+
dispatchAnalyticsEvent(clipboardAnalyticsPayload);
|
|
97
|
+
}
|
|
98
|
+
// return false so we don't block any other plugins' cut or copy handlers
|
|
99
|
+
// from running just because we are sending an analytics event
|
|
100
|
+
return false;
|
|
101
|
+
};
|
|
102
|
+
export { getAnalyticsPayload };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as clipboardPlugin } from './plugin';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createPlugin } from './pm-plugins/main';
|
|
2
|
+
var clipboard = function clipboard() {
|
|
3
|
+
return {
|
|
4
|
+
name: 'clipboard',
|
|
5
|
+
pmPlugins: function pmPlugins() {
|
|
6
|
+
return [{
|
|
7
|
+
name: 'clipboard',
|
|
8
|
+
plugin: function plugin(options) {
|
|
9
|
+
return createPlugin(options);
|
|
10
|
+
}
|
|
11
|
+
}];
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export default clipboard;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
import { ACTION } from '@atlaskit/editor-common/analytics';
|
|
5
|
+
import { getAnalyticsPayload } from '@atlaskit/editor-common/clipboard';
|
|
6
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
7
|
+
import { DOMSerializer, Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
8
|
+
import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
9
|
+
import { clipboardPluginKey } from '../plugin-key';
|
|
10
|
+
export var createPlugin = function createPlugin(_ref) {
|
|
11
|
+
var dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent,
|
|
12
|
+
schema = _ref.schema;
|
|
13
|
+
var editorView;
|
|
14
|
+
var getEditorView = function getEditorView() {
|
|
15
|
+
return editorView;
|
|
16
|
+
};
|
|
17
|
+
return new SafePlugin({
|
|
18
|
+
key: clipboardPluginKey,
|
|
19
|
+
view: function view(_view) {
|
|
20
|
+
editorView = _view;
|
|
21
|
+
return {
|
|
22
|
+
update: function update(view) {
|
|
23
|
+
editorView = view;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
props: {
|
|
28
|
+
handleDOMEvents: {
|
|
29
|
+
cut: function cut(view) {
|
|
30
|
+
return sendClipboardAnalytics(view, dispatchAnalyticsEvent, ACTION.CUT);
|
|
31
|
+
},
|
|
32
|
+
copy: function copy(view) {
|
|
33
|
+
return sendClipboardAnalytics(view, dispatchAnalyticsEvent, ACTION.COPIED);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
clipboardSerializer: createClipboardSerializer(schema, getEditorView)
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Overrides Prosemirror's default clipboardSerializer, in order to fix table row copy/paste bug raised in ED-13003.
|
|
43
|
+
* This allows us to store the original table’s attributes on the new table that the row is wrapped with when it is being copied.
|
|
44
|
+
* e.g. keeping the layout on a row that is copied.
|
|
45
|
+
* We store the default serializer in order to call it after we handle the table row case.
|
|
46
|
+
*/
|
|
47
|
+
export var createClipboardSerializer = function createClipboardSerializer(schema, getEditorView) {
|
|
48
|
+
var oldSerializer = DOMSerializer.fromSchema(schema);
|
|
49
|
+
var newSerializer = new DOMSerializer(oldSerializer.nodes, oldSerializer.marks);
|
|
50
|
+
var originalSerializeFragment = newSerializer.serializeFragment.bind(newSerializer);
|
|
51
|
+
newSerializer.serializeFragment = function (content) {
|
|
52
|
+
var _content$firstChild;
|
|
53
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
54
|
+
var target = arguments.length > 2 ? arguments[2] : undefined;
|
|
55
|
+
var editorView = getEditorView();
|
|
56
|
+
var selection = editorView.state.selection;
|
|
57
|
+
|
|
58
|
+
// We do not need to handle when a user copies a tableRow + other content.
|
|
59
|
+
// In that scenario it already wraps the Row with correct Table and attributes.
|
|
60
|
+
if (!options.tableWrapperExists) {
|
|
61
|
+
var i = 0;
|
|
62
|
+
while (i < content.childCount) {
|
|
63
|
+
var _content$maybeChild;
|
|
64
|
+
if (((_content$maybeChild = content.maybeChild(i)) === null || _content$maybeChild === void 0 ? void 0 : _content$maybeChild.type.name) === 'table') {
|
|
65
|
+
options.tableWrapperExists = true;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
i++;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// When the content being copied includes a tableRow that is not already wrapped with a table,
|
|
73
|
+
// We will wrap it with one ourselves, while preserving the parent table's attributes.
|
|
74
|
+
if (((_content$firstChild = content.firstChild) === null || _content$firstChild === void 0 ? void 0 : _content$firstChild.type.name) === 'tableRow' && !options.tableWrapperExists) {
|
|
75
|
+
// We only want 1 table wrapping the rows.
|
|
76
|
+
// tableWrapperExist is a custom prop added solely for the purposes of this recursive algorithm.
|
|
77
|
+
// The function is recursively called for each node in the tree captured in the fragment.
|
|
78
|
+
// For recursive logic see the bind call above and the prosemirror-model (https://github.com/ProseMirror/prosemirror-model/blob/master/src/to_dom.js#L44
|
|
79
|
+
// and https://github.com/ProseMirror/prosemirror-model/blob/master/src/to_dom.js#L87)
|
|
80
|
+
options.tableWrapperExists = true;
|
|
81
|
+
var parentTable = findParentNodeOfType(schema.nodes.table)(selection);
|
|
82
|
+
var attributes = parentTable === null || parentTable === void 0 ? void 0 : parentTable.node.attrs;
|
|
83
|
+
var newTable = schema.nodes.table;
|
|
84
|
+
// Explicitly remove local id since we are creating a new table and it should have a unique local id which will be generated.
|
|
85
|
+
var newTableNode = newTable.createChecked(_objectSpread(_objectSpread({}, attributes), {}, {
|
|
86
|
+
localId: undefined
|
|
87
|
+
}), content);
|
|
88
|
+
var newContent = Fragment.from(newTableNode);
|
|
89
|
+
// Pass updated content into original ProseMirror serializeFragment function.
|
|
90
|
+
// Currently incorrectly typed in @Types. See this GitHub thread: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57668
|
|
91
|
+
//@ts-ignore
|
|
92
|
+
return originalSerializeFragment(newContent, options, target);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// If we're not copying any rows, just run default serializeFragment function.
|
|
96
|
+
// Currently incorrectly typed in @Types. See this GitHub thread: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57668
|
|
97
|
+
//@ts-ignore
|
|
98
|
+
return originalSerializeFragment(content, options, target);
|
|
99
|
+
};
|
|
100
|
+
return newSerializer;
|
|
101
|
+
};
|
|
102
|
+
export var sendClipboardAnalytics = function sendClipboardAnalytics(view, dispatchAnalyticsEvent, action) {
|
|
103
|
+
var clipboardAnalyticsPayload = getAnalyticsPayload(view.state, action);
|
|
104
|
+
if (clipboardAnalyticsPayload) {
|
|
105
|
+
dispatchAnalyticsEvent(clipboardAnalyticsPayload);
|
|
106
|
+
}
|
|
107
|
+
// return false so we don't block any other plugins' cut or copy handlers
|
|
108
|
+
// from running just because we are sending an analytics event
|
|
109
|
+
return false;
|
|
110
|
+
};
|
|
111
|
+
export { getAnalyticsPayload };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DispatchAnalyticsEvent } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { ACTION } from '@atlaskit/editor-common/analytics';
|
|
3
|
+
import { getAnalyticsPayload } from '@atlaskit/editor-common/clipboard';
|
|
4
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
5
|
+
import type { PMPluginFactoryParams } from '@atlaskit/editor-common/types';
|
|
6
|
+
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
7
|
+
import type { Schema } from '@atlaskit/editor-prosemirror/model';
|
|
8
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
9
|
+
export declare const createPlugin: ({ dispatchAnalyticsEvent, schema, }: PMPluginFactoryParams) => SafePlugin<any>;
|
|
10
|
+
/**
|
|
11
|
+
* Overrides Prosemirror's default clipboardSerializer, in order to fix table row copy/paste bug raised in ED-13003.
|
|
12
|
+
* This allows us to store the original table’s attributes on the new table that the row is wrapped with when it is being copied.
|
|
13
|
+
* e.g. keeping the layout on a row that is copied.
|
|
14
|
+
* We store the default serializer in order to call it after we handle the table row case.
|
|
15
|
+
*/
|
|
16
|
+
export declare const createClipboardSerializer: (schema: Schema, getEditorView: () => EditorView) => DOMSerializer;
|
|
17
|
+
export declare const sendClipboardAnalytics: (view: EditorView, dispatchAnalyticsEvent: DispatchAnalyticsEvent, action: ACTION.CUT | ACTION.COPIED) => boolean;
|
|
18
|
+
export { getAnalyticsPayload };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DispatchAnalyticsEvent } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { ACTION } from '@atlaskit/editor-common/analytics';
|
|
3
|
+
import { getAnalyticsPayload } from '@atlaskit/editor-common/clipboard';
|
|
4
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
5
|
+
import type { PMPluginFactoryParams } from '@atlaskit/editor-common/types';
|
|
6
|
+
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
7
|
+
import type { Schema } from '@atlaskit/editor-prosemirror/model';
|
|
8
|
+
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
9
|
+
export declare const createPlugin: ({ dispatchAnalyticsEvent, schema, }: PMPluginFactoryParams) => SafePlugin<any>;
|
|
10
|
+
/**
|
|
11
|
+
* Overrides Prosemirror's default clipboardSerializer, in order to fix table row copy/paste bug raised in ED-13003.
|
|
12
|
+
* This allows us to store the original table’s attributes on the new table that the row is wrapped with when it is being copied.
|
|
13
|
+
* e.g. keeping the layout on a row that is copied.
|
|
14
|
+
* We store the default serializer in order to call it after we handle the table row case.
|
|
15
|
+
*/
|
|
16
|
+
export declare const createClipboardSerializer: (schema: Schema, getEditorView: () => EditorView) => DOMSerializer;
|
|
17
|
+
export declare const sendClipboardAnalytics: (view: EditorView, dispatchAnalyticsEvent: DispatchAnalyticsEvent, action: ACTION.CUT | ACTION.COPIED) => boolean;
|
|
18
|
+
export { getAnalyticsPayload };
|
package/package.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/editor-plugin-clipboard",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Clipboard plugin for @atlaskit/editor-core",
|
|
5
|
+
"author": "Atlassian Pty Ltd",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"registry": "https://registry.npmjs.org/"
|
|
9
|
+
},
|
|
10
|
+
"atlassian": {
|
|
11
|
+
"team": "Editor: Lego",
|
|
12
|
+
"singleton": true,
|
|
13
|
+
"releaseModel": "continuous"
|
|
14
|
+
},
|
|
15
|
+
"repository": "https://bitbucket.org/atlassian/atlassian-frontend",
|
|
16
|
+
"main": "dist/cjs/index.js",
|
|
17
|
+
"module": "dist/esm/index.js",
|
|
18
|
+
"module:es2019": "dist/es2019/index.js",
|
|
19
|
+
"types": "dist/types/index.d.ts",
|
|
20
|
+
"typesVersions": {
|
|
21
|
+
">=4.5 <4.9": {
|
|
22
|
+
"*": [
|
|
23
|
+
"dist/types-ts4.5/*",
|
|
24
|
+
"dist/types-ts4.5/index.d.ts"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"atlaskit:src": "src/index.ts",
|
|
30
|
+
"af:exports": {
|
|
31
|
+
".": "./src/index.ts"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@atlaskit/editor-common": "^76.1.0",
|
|
35
|
+
"@atlaskit/editor-prosemirror": "1.1.0",
|
|
36
|
+
"@babel/runtime": "^7.0.0"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"react": "^16.8.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@af/visual-regression": "*",
|
|
43
|
+
"@atlaskit/ssr": "*",
|
|
44
|
+
"@atlaskit/visual-regression": "*",
|
|
45
|
+
"@atlaskit/webdriver-runner": "*",
|
|
46
|
+
"@atlassian/atlassian-frontend-prettier-config-1.0.0": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.0",
|
|
47
|
+
"@testing-library/react": "^12.1.5",
|
|
48
|
+
"react-dom": "^16.8.0",
|
|
49
|
+
"typescript": "~4.9.5",
|
|
50
|
+
"wait-for-expect": "^1.2.0"
|
|
51
|
+
},
|
|
52
|
+
"techstack": {
|
|
53
|
+
"@atlassian/frontend": {
|
|
54
|
+
"import-structure": [
|
|
55
|
+
"atlassian-conventions"
|
|
56
|
+
],
|
|
57
|
+
"circular-dependencies": [
|
|
58
|
+
"file-and-folder-level"
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
"@repo/internal": {
|
|
62
|
+
"dom-events": "use-bind-event-listener",
|
|
63
|
+
"analytics": [
|
|
64
|
+
"analytics-next"
|
|
65
|
+
],
|
|
66
|
+
"design-tokens": [
|
|
67
|
+
"color"
|
|
68
|
+
],
|
|
69
|
+
"theming": [
|
|
70
|
+
"react-context"
|
|
71
|
+
],
|
|
72
|
+
"ui-components": [
|
|
73
|
+
"lite-mode"
|
|
74
|
+
],
|
|
75
|
+
"deprecation": [
|
|
76
|
+
"no-deprecated-imports"
|
|
77
|
+
],
|
|
78
|
+
"styling": [
|
|
79
|
+
"static",
|
|
80
|
+
"emotion"
|
|
81
|
+
],
|
|
82
|
+
"imports": [
|
|
83
|
+
"import-no-extraneous-disable-for-examples-and-docs"
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"prettier": "@atlassian/atlassian-frontend-prettier-config-1.0.0"
|
|
88
|
+
}
|
package/report.api.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!-- API Report Version: 2.3 -->
|
|
2
|
+
|
|
3
|
+
## API Report File for "@atlaskit/editor-plugin-clipboard"
|
|
4
|
+
|
|
5
|
+
> Do not edit this file. This report is auto-generated using [API Extractor](https://api-extractor.com/).
|
|
6
|
+
> [Learn more about API reports](https://hello.atlassian.net/wiki/spaces/UR/pages/1825484529/Package+API+Reports)
|
|
7
|
+
|
|
8
|
+
### Table of contents
|
|
9
|
+
|
|
10
|
+
- [Main Entry Types](#main-entry-types)
|
|
11
|
+
- [Peer Dependencies](#peer-dependencies)
|
|
12
|
+
|
|
13
|
+
### Main Entry Types
|
|
14
|
+
|
|
15
|
+
<!--SECTION START: Main Entry Types-->
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import type { NextEditorPlugin } from '@atlaskit/editor-common/types';
|
|
19
|
+
|
|
20
|
+
// @public (undocumented)
|
|
21
|
+
export type ClipboardPlugin = NextEditorPlugin<'clipboard'>;
|
|
22
|
+
|
|
23
|
+
// @public (undocumented)
|
|
24
|
+
export const clipboardPlugin: ClipboardPlugin;
|
|
25
|
+
|
|
26
|
+
// (No @packageDocumentation comment for this package)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
<!--SECTION END: Main Entry Types-->
|
|
30
|
+
|
|
31
|
+
### Peer Dependencies
|
|
32
|
+
|
|
33
|
+
<!--SECTION START: Peer Dependencies-->
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"react": "^16.8.0"
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
<!--SECTION END: Peer Dependencies-->
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## API Report File for "@atlaskit/editor-plugin-clipboard"
|
|
2
|
+
|
|
3
|
+
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
|
|
7
|
+
import type { NextEditorPlugin } from '@atlaskit/editor-common/types';
|
|
8
|
+
|
|
9
|
+
// @public (undocumented)
|
|
10
|
+
export type ClipboardPlugin = NextEditorPlugin<'clipboard'>;
|
|
11
|
+
|
|
12
|
+
// @public (undocumented)
|
|
13
|
+
export const clipboardPlugin: ClipboardPlugin;
|
|
14
|
+
|
|
15
|
+
// (No @packageDocumentation comment for this package)
|
|
16
|
+
|
|
17
|
+
```
|