@lexical/clipboard 0.7.8 → 0.8.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/LexicalClipboard.dev.js +36 -100
- package/package.json +6 -6
package/LexicalClipboard.dev.js
CHANGED
|
@@ -20,84 +20,75 @@ var lexical = require('lexical');
|
|
|
20
20
|
*/
|
|
21
21
|
function $getHtmlContent(editor) {
|
|
22
22
|
const selection = lexical.$getSelection();
|
|
23
|
-
|
|
24
23
|
if (selection == null) {
|
|
25
24
|
{
|
|
26
25
|
throw Error(`Expected valid LexicalSelection`);
|
|
27
26
|
}
|
|
28
|
-
}
|
|
29
|
-
|
|
27
|
+
}
|
|
30
28
|
|
|
29
|
+
// If we haven't selected anything
|
|
31
30
|
if (lexical.$isRangeSelection(selection) && selection.isCollapsed() || selection.getNodes().length === 0) {
|
|
32
31
|
return '';
|
|
33
32
|
}
|
|
34
|
-
|
|
35
33
|
return html.$generateHtmlFromNodes(editor, selection);
|
|
36
|
-
}
|
|
37
|
-
// TODO 0.6.0 Rename to $getJSON
|
|
34
|
+
}
|
|
38
35
|
|
|
36
|
+
// TODO 0.6.0 Return a blank string instead
|
|
37
|
+
// TODO 0.6.0 Rename to $getJSON
|
|
39
38
|
function $getLexicalContent(editor) {
|
|
40
39
|
const selection = lexical.$getSelection();
|
|
41
|
-
|
|
42
40
|
if (selection == null) {
|
|
43
41
|
{
|
|
44
42
|
throw Error(`Expected valid LexicalSelection`);
|
|
45
43
|
}
|
|
46
|
-
}
|
|
47
|
-
|
|
44
|
+
}
|
|
48
45
|
|
|
46
|
+
// If we haven't selected anything
|
|
49
47
|
if (lexical.$isRangeSelection(selection) && selection.isCollapsed() || selection.getNodes().length === 0) {
|
|
50
48
|
return null;
|
|
51
49
|
}
|
|
52
|
-
|
|
53
50
|
return JSON.stringify($generateJSONFromSelectedNodes(editor, selection));
|
|
54
51
|
}
|
|
55
52
|
function $insertDataTransferForPlainText(dataTransfer, selection) {
|
|
56
53
|
const text = dataTransfer.getData('text/plain');
|
|
57
|
-
|
|
58
54
|
if (text != null) {
|
|
59
55
|
selection.insertRawText(text);
|
|
60
56
|
}
|
|
61
57
|
}
|
|
62
58
|
function $insertDataTransferForRichText(dataTransfer, selection, editor) {
|
|
63
59
|
const lexicalString = dataTransfer.getData('application/x-lexical-editor');
|
|
64
|
-
|
|
65
60
|
if (lexicalString) {
|
|
66
61
|
try {
|
|
67
62
|
const payload = JSON.parse(lexicalString);
|
|
68
|
-
|
|
69
63
|
if (payload.namespace === editor._config.namespace && Array.isArray(payload.nodes)) {
|
|
70
64
|
const nodes = $generateNodesFromSerializedNodes(payload.nodes);
|
|
71
65
|
return $insertGeneratedNodes(editor, nodes, selection);
|
|
72
66
|
}
|
|
73
|
-
} catch {
|
|
67
|
+
} catch {
|
|
68
|
+
// Fail silently.
|
|
74
69
|
}
|
|
75
70
|
}
|
|
76
|
-
|
|
77
71
|
const htmlString = dataTransfer.getData('text/html');
|
|
78
|
-
|
|
79
72
|
if (htmlString) {
|
|
80
73
|
try {
|
|
81
74
|
const parser = new DOMParser();
|
|
82
75
|
const dom = parser.parseFromString(htmlString, 'text/html');
|
|
83
76
|
const nodes = html.$generateNodesFromDOM(editor, dom);
|
|
84
77
|
return $insertGeneratedNodes(editor, nodes, selection);
|
|
85
|
-
} catch {
|
|
78
|
+
} catch {
|
|
79
|
+
// Fail silently.
|
|
86
80
|
}
|
|
87
|
-
}
|
|
88
|
-
// instead of single paragraph with linebreaks.
|
|
89
|
-
|
|
81
|
+
}
|
|
90
82
|
|
|
83
|
+
// Multi-line plain text in rich text mode pasted as separate paragraphs
|
|
84
|
+
// instead of single paragraph with linebreaks.
|
|
91
85
|
const text = dataTransfer.getData('text/plain');
|
|
92
|
-
|
|
93
86
|
if (text != null) {
|
|
94
87
|
if (lexical.$isRangeSelection(selection)) {
|
|
95
88
|
const lines = text.split(/\r?\n/);
|
|
96
89
|
const linesLength = lines.length;
|
|
97
|
-
|
|
98
90
|
for (let i = 0; i < linesLength; i++) {
|
|
99
91
|
selection.insertText(lines[i]);
|
|
100
|
-
|
|
101
92
|
if (i < linesLength - 1) {
|
|
102
93
|
selection.insertParagraph();
|
|
103
94
|
}
|
|
@@ -109,36 +100,30 @@ function $insertDataTransferForRichText(dataTransfer, selection, editor) {
|
|
|
109
100
|
}
|
|
110
101
|
function $insertGeneratedNodes(editor, nodes, selection) {
|
|
111
102
|
const isSelectionInsideOfGrid = lexical.DEPRECATED_$isGridSelection(selection) || utils.$findMatchingParent(selection.anchor.getNode(), n => lexical.DEPRECATED_$isGridCellNode(n)) !== null && utils.$findMatchingParent(selection.focus.getNode(), n => lexical.DEPRECATED_$isGridCellNode(n)) !== null;
|
|
112
|
-
|
|
113
103
|
if (isSelectionInsideOfGrid && nodes.length === 1 && lexical.DEPRECATED_$isGridNode(nodes[0])) {
|
|
114
104
|
$mergeGridNodesStrategy(nodes, selection, false, editor);
|
|
115
105
|
return;
|
|
116
106
|
}
|
|
117
|
-
|
|
118
107
|
$basicInsertStrategy(nodes, selection);
|
|
119
108
|
return;
|
|
120
109
|
}
|
|
121
|
-
|
|
122
110
|
function $basicInsertStrategy(nodes, selection) {
|
|
123
111
|
// Wrap text and inline nodes in paragraph nodes so we have all blocks at the top-level
|
|
124
112
|
const topLevelBlocks = [];
|
|
125
113
|
let currentBlock = null;
|
|
126
|
-
|
|
127
114
|
for (let i = 0; i < nodes.length; i++) {
|
|
128
115
|
const node = nodes[i];
|
|
129
116
|
const isLineBreakNode = lexical.$isLineBreakNode(node);
|
|
130
|
-
|
|
131
117
|
if (isLineBreakNode || lexical.$isDecoratorNode(node) && node.isInline() || lexical.$isElementNode(node) && node.isInline() || lexical.$isTextNode(node) || node.isParentRequired()) {
|
|
132
118
|
if (currentBlock === null) {
|
|
133
119
|
currentBlock = node.createParentElementNode();
|
|
134
|
-
topLevelBlocks.push(currentBlock);
|
|
120
|
+
topLevelBlocks.push(currentBlock);
|
|
121
|
+
// In the case of LineBreakNode, we just need to
|
|
135
122
|
// add an empty ParagraphNode to the topLevelBlocks.
|
|
136
|
-
|
|
137
123
|
if (isLineBreakNode) {
|
|
138
124
|
continue;
|
|
139
125
|
}
|
|
140
126
|
}
|
|
141
|
-
|
|
142
127
|
if (currentBlock !== null) {
|
|
143
128
|
currentBlock.append(node);
|
|
144
129
|
}
|
|
@@ -147,30 +132,25 @@ function $basicInsertStrategy(nodes, selection) {
|
|
|
147
132
|
currentBlock = null;
|
|
148
133
|
}
|
|
149
134
|
}
|
|
150
|
-
|
|
151
135
|
if (lexical.$isRangeSelection(selection)) {
|
|
152
136
|
selection.insertNodes(topLevelBlocks);
|
|
153
137
|
} else if (lexical.DEPRECATED_$isGridSelection(selection)) {
|
|
154
138
|
// If there's an active grid selection and a non grid is pasted, add to the anchor.
|
|
155
139
|
const anchorCell = selection.anchor.getNode();
|
|
156
|
-
|
|
157
140
|
if (!lexical.DEPRECATED_$isGridCellNode(anchorCell)) {
|
|
158
141
|
{
|
|
159
142
|
throw Error(`Expected Grid Cell in Grid Selection`);
|
|
160
143
|
}
|
|
161
144
|
}
|
|
162
|
-
|
|
163
145
|
anchorCell.append(...topLevelBlocks);
|
|
164
146
|
}
|
|
165
147
|
}
|
|
166
|
-
|
|
167
148
|
function $mergeGridNodesStrategy(nodes, selection, isFromLexical, editor) {
|
|
168
149
|
if (nodes.length !== 1 || !lexical.DEPRECATED_$isGridNode(nodes[0])) {
|
|
169
150
|
{
|
|
170
151
|
throw Error(`$mergeGridNodesStrategy: Expected Grid insertion.`);
|
|
171
152
|
}
|
|
172
153
|
}
|
|
173
|
-
|
|
174
154
|
const newGrid = nodes[0];
|
|
175
155
|
const newGridRows = newGrid.getChildren();
|
|
176
156
|
const newColumnCount = newGrid.getFirstChildOrThrow().getChildrenSize();
|
|
@@ -178,13 +158,11 @@ function $mergeGridNodesStrategy(nodes, selection, isFromLexical, editor) {
|
|
|
178
158
|
const gridCellNode = utils.$findMatchingParent(selection.anchor.getNode(), n => lexical.DEPRECATED_$isGridCellNode(n));
|
|
179
159
|
const gridRowNode = gridCellNode && utils.$findMatchingParent(gridCellNode, n => lexical.DEPRECATED_$isGridRowNode(n));
|
|
180
160
|
const gridNode = gridRowNode && utils.$findMatchingParent(gridRowNode, n => lexical.DEPRECATED_$isGridNode(n));
|
|
181
|
-
|
|
182
161
|
if (!lexical.DEPRECATED_$isGridCellNode(gridCellNode) || !lexical.DEPRECATED_$isGridRowNode(gridRowNode) || !lexical.DEPRECATED_$isGridNode(gridNode)) {
|
|
183
162
|
{
|
|
184
163
|
throw Error(`$mergeGridNodesStrategy: Expected selection to be inside of a Grid.`);
|
|
185
164
|
}
|
|
186
165
|
}
|
|
187
|
-
|
|
188
166
|
const startY = gridRowNode.getIndexWithinParent();
|
|
189
167
|
const stopY = Math.min(gridNode.getChildrenSize() - 1, startY + newRowCount - 1);
|
|
190
168
|
const startX = gridCellNode.getIndexWithinParent();
|
|
@@ -197,51 +175,40 @@ function $mergeGridNodesStrategy(nodes, selection, isFromLexical, editor) {
|
|
|
197
175
|
let newRowIdx = 0;
|
|
198
176
|
let newAnchorCellKey;
|
|
199
177
|
let newFocusCellKey;
|
|
200
|
-
|
|
201
178
|
for (let r = fromY; r <= toY; r++) {
|
|
202
179
|
const currentGridRowNode = gridRowNodes[r];
|
|
203
|
-
|
|
204
180
|
if (!lexical.DEPRECATED_$isGridRowNode(currentGridRowNode)) {
|
|
205
181
|
{
|
|
206
182
|
throw Error(`getNodes: expected to find GridRowNode`);
|
|
207
183
|
}
|
|
208
184
|
}
|
|
209
|
-
|
|
210
185
|
const newGridRowNode = newGridRows[newRowIdx];
|
|
211
|
-
|
|
212
186
|
if (!lexical.DEPRECATED_$isGridRowNode(newGridRowNode)) {
|
|
213
187
|
{
|
|
214
188
|
throw Error(`getNodes: expected to find GridRowNode`);
|
|
215
189
|
}
|
|
216
190
|
}
|
|
217
|
-
|
|
218
191
|
const gridCellNodes = currentGridRowNode.getChildren();
|
|
219
192
|
const newGridCellNodes = newGridRowNode.getChildren();
|
|
220
193
|
let newColumnIdx = 0;
|
|
221
|
-
|
|
222
194
|
for (let c = fromX; c <= toX; c++) {
|
|
223
195
|
const currentGridCellNode = gridCellNodes[c];
|
|
224
|
-
|
|
225
196
|
if (!lexical.DEPRECATED_$isGridCellNode(currentGridCellNode)) {
|
|
226
197
|
{
|
|
227
198
|
throw Error(`getNodes: expected to find GridCellNode`);
|
|
228
199
|
}
|
|
229
200
|
}
|
|
230
|
-
|
|
231
201
|
const newGridCellNode = newGridCellNodes[newColumnIdx];
|
|
232
|
-
|
|
233
202
|
if (!lexical.DEPRECATED_$isGridCellNode(newGridCellNode)) {
|
|
234
203
|
{
|
|
235
204
|
throw Error(`getNodes: expected to find GridCellNode`);
|
|
236
205
|
}
|
|
237
206
|
}
|
|
238
|
-
|
|
239
207
|
if (r === fromY && c === fromX) {
|
|
240
208
|
newAnchorCellKey = currentGridCellNode.getKey();
|
|
241
209
|
} else if (r === toY && c === toX) {
|
|
242
210
|
newFocusCellKey = currentGridCellNode.getKey();
|
|
243
211
|
}
|
|
244
|
-
|
|
245
212
|
const originalChildren = currentGridCellNode.getChildren();
|
|
246
213
|
newGridCellNode.getChildren().forEach(child => {
|
|
247
214
|
if (lexical.$isTextNode(child)) {
|
|
@@ -255,10 +222,8 @@ function $mergeGridNodesStrategy(nodes, selection, isFromLexical, editor) {
|
|
|
255
222
|
originalChildren.forEach(n => n.remove());
|
|
256
223
|
newColumnIdx++;
|
|
257
224
|
}
|
|
258
|
-
|
|
259
225
|
newRowIdx++;
|
|
260
226
|
}
|
|
261
|
-
|
|
262
227
|
if (newAnchorCellKey && newFocusCellKey) {
|
|
263
228
|
const newGridSelection = lexical.DEPRECATED_$createGridSelection();
|
|
264
229
|
newGridSelection.set(gridNode.getKey(), newAnchorCellKey, newFocusCellKey);
|
|
@@ -266,20 +231,19 @@ function $mergeGridNodesStrategy(nodes, selection, isFromLexical, editor) {
|
|
|
266
231
|
editor.dispatchCommand(lexical.SELECTION_CHANGE_COMMAND, undefined);
|
|
267
232
|
}
|
|
268
233
|
}
|
|
269
|
-
|
|
270
234
|
function exportNodeToJSON(node) {
|
|
271
235
|
const serializedNode = node.exportJSON();
|
|
272
|
-
const nodeClass = node.constructor;
|
|
236
|
+
const nodeClass = node.constructor;
|
|
273
237
|
|
|
238
|
+
// @ts-expect-error TODO Replace Class utility type with InstanceType
|
|
274
239
|
if (serializedNode.type !== nodeClass.getType()) {
|
|
275
240
|
{
|
|
276
241
|
throw Error(`LexicalNode: Node ${nodeClass.name} does not implement .exportJSON().`);
|
|
277
242
|
}
|
|
278
|
-
}
|
|
279
|
-
|
|
243
|
+
}
|
|
280
244
|
|
|
245
|
+
// @ts-expect-error TODO Replace Class utility type with InstanceType
|
|
281
246
|
const serializedChildren = serializedNode.children;
|
|
282
|
-
|
|
283
247
|
if (lexical.$isElementNode(node)) {
|
|
284
248
|
if (!Array.isArray(serializedChildren)) {
|
|
285
249
|
{
|
|
@@ -287,50 +251,44 @@ function exportNodeToJSON(node) {
|
|
|
287
251
|
}
|
|
288
252
|
}
|
|
289
253
|
}
|
|
290
|
-
|
|
291
254
|
return serializedNode;
|
|
292
255
|
}
|
|
293
|
-
|
|
294
256
|
function $appendNodesToJSON(editor, selection$1, currentNode, targetArray = []) {
|
|
295
257
|
let shouldInclude = selection$1 != null ? currentNode.isSelected(selection$1) : true;
|
|
296
258
|
const shouldExclude = lexical.$isElementNode(currentNode) && currentNode.excludeFromCopy('html');
|
|
297
259
|
let target = currentNode;
|
|
298
|
-
|
|
299
260
|
if (selection$1 !== null) {
|
|
300
261
|
let clone = selection.$cloneWithProperties(currentNode);
|
|
301
262
|
clone = lexical.$isTextNode(clone) && selection$1 != null ? selection.$sliceSelectedTextNodeContent(selection$1, clone) : clone;
|
|
302
263
|
target = clone;
|
|
303
264
|
}
|
|
304
|
-
|
|
305
265
|
const children = lexical.$isElementNode(target) ? target.getChildren() : [];
|
|
306
|
-
const serializedNode = exportNodeToJSON(target);
|
|
266
|
+
const serializedNode = exportNodeToJSON(target);
|
|
267
|
+
|
|
268
|
+
// TODO: TextNode calls getTextContent() (NOT node.__text) within it's exportJSON method
|
|
307
269
|
// which uses getLatest() to get the text from the original node with the same key.
|
|
308
270
|
// This is a deeper issue with the word "clone" here, it's still a reference to the
|
|
309
271
|
// same node as far as the LexicalEditor is concerned since it shares a key.
|
|
310
272
|
// We need a way to create a clone of a Node in memory with it's own key, but
|
|
311
273
|
// until then this hack will work for the selected text extract use case.
|
|
312
|
-
|
|
313
274
|
if (lexical.$isTextNode(target)) {
|
|
314
|
-
const text = target.__text;
|
|
275
|
+
const text = target.__text;
|
|
276
|
+
// If an uncollapsed selection ends or starts at the end of a line of specialized,
|
|
315
277
|
// TextNodes, such as code tokens, we will get a 'blank' TextNode here, i.e., one
|
|
316
278
|
// with text of length 0. We don't want this, it makes a confusing mess. Reset!
|
|
317
|
-
|
|
318
279
|
if (text.length > 0) {
|
|
319
280
|
serializedNode.text = text;
|
|
320
281
|
} else {
|
|
321
282
|
shouldInclude = false;
|
|
322
283
|
}
|
|
323
284
|
}
|
|
324
|
-
|
|
325
285
|
for (let i = 0; i < children.length; i++) {
|
|
326
286
|
const childNode = children[i];
|
|
327
287
|
const shouldIncludeChild = $appendNodesToJSON(editor, selection$1, childNode, serializedNode.children);
|
|
328
|
-
|
|
329
288
|
if (!shouldInclude && lexical.$isElementNode(currentNode) && shouldIncludeChild && currentNode.extractWithChild(childNode, selection$1, 'clone')) {
|
|
330
289
|
shouldInclude = true;
|
|
331
290
|
}
|
|
332
291
|
}
|
|
333
|
-
|
|
334
292
|
if (shouldInclude && !shouldExclude) {
|
|
335
293
|
targetArray.push(serializedNode);
|
|
336
294
|
} else if (Array.isArray(serializedNode.children)) {
|
|
@@ -339,21 +297,18 @@ function $appendNodesToJSON(editor, selection$1, currentNode, targetArray = [])
|
|
|
339
297
|
targetArray.push(serializedChildNode);
|
|
340
298
|
}
|
|
341
299
|
}
|
|
342
|
-
|
|
343
300
|
return shouldInclude;
|
|
344
|
-
}
|
|
345
|
-
|
|
301
|
+
}
|
|
346
302
|
|
|
303
|
+
// TODO why $ function with Editor instance?
|
|
347
304
|
function $generateJSONFromSelectedNodes(editor, selection) {
|
|
348
305
|
const nodes = [];
|
|
349
306
|
const root = lexical.$getRoot();
|
|
350
307
|
const topLevelChildren = root.getChildren();
|
|
351
|
-
|
|
352
308
|
for (let i = 0; i < topLevelChildren.length; i++) {
|
|
353
309
|
const topLevelNode = topLevelChildren[i];
|
|
354
310
|
$appendNodesToJSON(editor, selection, topLevelNode, nodes);
|
|
355
311
|
}
|
|
356
|
-
|
|
357
312
|
return {
|
|
358
313
|
namespace: editor._config.namespace,
|
|
359
314
|
nodes
|
|
@@ -361,31 +316,27 @@ function $generateJSONFromSelectedNodes(editor, selection) {
|
|
|
361
316
|
}
|
|
362
317
|
function $generateNodesFromSerializedNodes(serializedNodes) {
|
|
363
318
|
const nodes = [];
|
|
364
|
-
|
|
365
319
|
for (let i = 0; i < serializedNodes.length; i++) {
|
|
366
320
|
const serializedNode = serializedNodes[i];
|
|
367
321
|
const node = lexical.$parseSerializedNode(serializedNode);
|
|
368
|
-
|
|
369
322
|
if (lexical.$isTextNode(node)) {
|
|
370
323
|
selection.$addNodeStyle(node);
|
|
371
324
|
}
|
|
372
|
-
|
|
373
325
|
nodes.push(node);
|
|
374
326
|
}
|
|
375
|
-
|
|
376
327
|
return nodes;
|
|
377
328
|
}
|
|
378
329
|
const EVENT_LATENCY = 50;
|
|
379
|
-
let clipboardEventTimeout = null;
|
|
380
|
-
// TODO potentially have a node customizable version for plain text
|
|
330
|
+
let clipboardEventTimeout = null;
|
|
381
331
|
|
|
332
|
+
// TODO custom selection
|
|
333
|
+
// TODO potentially have a node customizable version for plain text
|
|
382
334
|
async function copyToClipboard__EXPERIMENTAL(editor, event) {
|
|
383
335
|
if (clipboardEventTimeout !== null) {
|
|
384
336
|
// Prevent weird race conditions that can happen when this function is run multiple times
|
|
385
337
|
// synchronously. In the future, we can do better, we can cancel/override the previously running job.
|
|
386
338
|
return false;
|
|
387
339
|
}
|
|
388
|
-
|
|
389
340
|
if (event !== null) {
|
|
390
341
|
return new Promise((resolve, reject) => {
|
|
391
342
|
editor.update(() => {
|
|
@@ -393,14 +344,11 @@ async function copyToClipboard__EXPERIMENTAL(editor, event) {
|
|
|
393
344
|
});
|
|
394
345
|
});
|
|
395
346
|
}
|
|
396
|
-
|
|
397
347
|
const rootElement = editor.getRootElement();
|
|
398
348
|
const domSelection = document.getSelection();
|
|
399
|
-
|
|
400
349
|
if (rootElement === null || domSelection === null) {
|
|
401
350
|
return false;
|
|
402
351
|
}
|
|
403
|
-
|
|
404
352
|
const element = document.createElement('span');
|
|
405
353
|
element.style.cssText = 'position: fixed; top: -1000px;';
|
|
406
354
|
element.append(document.createTextNode('#'));
|
|
@@ -414,20 +362,17 @@ async function copyToClipboard__EXPERIMENTAL(editor, event) {
|
|
|
414
362
|
const removeListener = editor.registerCommand(lexical.COPY_COMMAND, secondEvent => {
|
|
415
363
|
if (secondEvent instanceof ClipboardEvent) {
|
|
416
364
|
removeListener();
|
|
417
|
-
|
|
418
365
|
if (clipboardEventTimeout !== null) {
|
|
419
366
|
window.clearTimeout(clipboardEventTimeout);
|
|
420
367
|
clipboardEventTimeout = null;
|
|
421
368
|
}
|
|
422
|
-
|
|
423
369
|
resolve($copyToClipboardEvent(editor, secondEvent));
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
|
|
370
|
+
}
|
|
371
|
+
// Block the entire copy flow while we wait for the next ClipboardEvent
|
|
427
372
|
return true;
|
|
428
|
-
}, lexical.COMMAND_PRIORITY_CRITICAL);
|
|
373
|
+
}, lexical.COMMAND_PRIORITY_CRITICAL);
|
|
374
|
+
// If the above hack execCommand hack works, this timeout code should never fire. Otherwise,
|
|
429
375
|
// the listener will be quickly freed so that the user can reuse it again
|
|
430
|
-
|
|
431
376
|
clipboardEventTimeout = window.setTimeout(() => {
|
|
432
377
|
removeListener();
|
|
433
378
|
clipboardEventTimeout = null;
|
|
@@ -436,46 +381,37 @@ async function copyToClipboard__EXPERIMENTAL(editor, event) {
|
|
|
436
381
|
document.execCommand('copy');
|
|
437
382
|
element.remove();
|
|
438
383
|
});
|
|
439
|
-
}
|
|
384
|
+
}
|
|
440
385
|
|
|
386
|
+
// TODO shouldn't pass editor (pass namespace directly)
|
|
441
387
|
function $copyToClipboardEvent(editor, event) {
|
|
442
388
|
const domSelection = window.getSelection();
|
|
443
|
-
|
|
444
389
|
if (!domSelection) {
|
|
445
390
|
return false;
|
|
446
391
|
}
|
|
447
|
-
|
|
448
392
|
const anchorDOM = domSelection.anchorNode;
|
|
449
393
|
const focusDOM = domSelection.focusNode;
|
|
450
|
-
|
|
451
394
|
if (anchorDOM !== null && focusDOM !== null && !lexical.isSelectionWithinEditor(editor, anchorDOM, focusDOM)) {
|
|
452
395
|
return false;
|
|
453
396
|
}
|
|
454
|
-
|
|
455
397
|
event.preventDefault();
|
|
456
398
|
const clipboardData = event.clipboardData;
|
|
457
399
|
const selection = lexical.$getSelection();
|
|
458
|
-
|
|
459
400
|
if (clipboardData === null || selection === null) {
|
|
460
401
|
return false;
|
|
461
402
|
}
|
|
462
|
-
|
|
463
403
|
const htmlString = $getHtmlContent(editor);
|
|
464
404
|
const lexicalString = $getLexicalContent(editor);
|
|
465
405
|
let plainString = '';
|
|
466
|
-
|
|
467
406
|
if (selection !== null) {
|
|
468
407
|
plainString = selection.getTextContent();
|
|
469
408
|
}
|
|
470
|
-
|
|
471
409
|
if (htmlString !== null) {
|
|
472
410
|
clipboardData.setData('text/html', htmlString);
|
|
473
411
|
}
|
|
474
|
-
|
|
475
412
|
if (lexicalString !== null) {
|
|
476
413
|
clipboardData.setData('application/x-lexical-editor', lexicalString);
|
|
477
414
|
}
|
|
478
|
-
|
|
479
415
|
clipboardData.setData('text/plain', plainString);
|
|
480
416
|
return true;
|
|
481
417
|
}
|
package/package.json
CHANGED
|
@@ -9,16 +9,16 @@
|
|
|
9
9
|
"paste"
|
|
10
10
|
],
|
|
11
11
|
"license": "MIT",
|
|
12
|
-
"version": "0.
|
|
12
|
+
"version": "0.8.0",
|
|
13
13
|
"main": "LexicalClipboard.js",
|
|
14
14
|
"peerDependencies": {
|
|
15
|
-
"lexical": "0.
|
|
15
|
+
"lexical": "0.8.0"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@lexical/utils": "0.
|
|
19
|
-
"@lexical/list": "0.
|
|
20
|
-
"@lexical/selection": "0.
|
|
21
|
-
"@lexical/html": "0.
|
|
18
|
+
"@lexical/utils": "0.8.0",
|
|
19
|
+
"@lexical/list": "0.8.0",
|
|
20
|
+
"@lexical/selection": "0.8.0",
|
|
21
|
+
"@lexical/html": "0.8.0"
|
|
22
22
|
},
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|