|
1 | 1 | import {Fragment, type Node, type ResolvedPos, type Schema, Slice} from 'prosemirror-model'; |
2 | | -import {type EditorState, Plugin, type Selection} from 'prosemirror-state'; |
| 2 | +import {Plugin} from 'prosemirror-state'; |
3 | 3 | import type {EditorView} from 'prosemirror-view'; |
4 | 4 |
|
5 | 5 | import {type Parser, type Serializer, trackTransactionMetrics} from '../../../core'; |
6 | 6 | import {type Logger2, globalLogger} from '../../../logger'; |
7 | 7 | import '../../../types/spec'; |
8 | 8 | import {tryCatch} from '../../../utils/helpers'; |
9 | | -import {isNodeSelection, isTextSelection, isWholeSelection} from '../../../utils/selection'; |
10 | 9 | import {serializeForClipboard} from '../../../utils/serialize-for-clipboard'; |
11 | | -import {BaseNode, pType} from '../../base/BaseSchema'; |
| 10 | +import {pType} from '../../base/BaseSchema'; |
12 | 11 |
|
13 | 12 | import {isInsideCode} from './code'; |
14 | 13 | import { |
@@ -266,101 +265,6 @@ function setClipboardData(data: DataTransfer, result: SerializeResult) { |
266 | 265 | data.setData(DataTransferType.Text, result.text); |
267 | 266 | } |
268 | 267 |
|
269 | | -function getCopyContent(state: EditorState): Slice { |
270 | | - const sel = state.selection; |
271 | | - |
272 | | - if (isWholeSelection(sel)) { |
273 | | - return new Slice(state.doc.content, 0, 0); |
274 | | - } |
275 | | - |
276 | | - if (isTextSelectionWithinSameTextBlock(sel)) { |
277 | | - return new Slice(createFragmentFromInlineSelection(state), 0, 0); |
278 | | - } |
279 | | - |
280 | | - if (isNodeSelection(sel)) { |
281 | | - const {node} = sel; |
282 | | - if (node.type.spec.complex) { |
283 | | - if (node.isTextblock) { |
284 | | - return new Slice( |
285 | | - Fragment.from(state.schema.node(BaseNode.Paragraph, {}, node.content)), |
286 | | - 1, |
287 | | - 1, |
288 | | - ); |
289 | | - } else { |
290 | | - const {complex} = node.type.spec; |
291 | | - if (complex === 'root') { |
292 | | - return new Slice(Fragment.from(node), 1, 1); |
293 | | - } else if (complex === 'leaf') { |
294 | | - return new Slice(Fragment.from(node.content), 1, 1); |
295 | | - } else { |
296 | | - // TODO: handle copy of intermediate complex block node |
297 | | - } |
298 | | - } |
299 | | - } else { |
300 | | - return new Slice(Fragment.from(node), 1, 1); |
301 | | - } |
302 | | - } |
303 | | - |
304 | | - let slice = getSelectionContent(sel); |
305 | | - |
306 | | - // replace first node with paragraph if needed |
307 | | - if ( |
308 | | - slice.content.firstChild?.isTextblock && |
309 | | - slice.content.firstChild.type.name !== BaseNode.Paragraph |
310 | | - ) { |
311 | | - let shouldTransformFirstChildToPara = true; |
312 | | - const {firstChild} = slice.content; |
313 | | - |
314 | | - // if all text selected inside first node, don't replace it with paragraph |
315 | | - if (firstChild.eq(sel.$from.parent)) { |
316 | | - shouldTransformFirstChildToPara = false; |
317 | | - } |
318 | | - |
319 | | - if (shouldTransformFirstChildToPara) { |
320 | | - slice = new Slice( |
321 | | - slice.content.replaceChild( |
322 | | - 0, |
323 | | - state.schema.node(BaseNode.Paragraph, {}, firstChild.content), |
324 | | - ), |
325 | | - slice.openStart, |
326 | | - slice.openStart, |
327 | | - ); |
328 | | - } |
329 | | - } |
330 | | - |
331 | | - return slice; |
332 | | -} |
333 | | - |
334 | | -function isTextSelectionWithinSameTextBlock(sel: Selection) { |
335 | | - return isTextSelection(sel) && sel.$from.sameParent(sel.$to) && sel.$from.parent.isTextblock; |
336 | | -} |
337 | | - |
338 | | -function createFragmentFromInlineSelection(state: EditorState) { |
339 | | - const sel = state.selection; |
340 | | - const inlineSlice = state.doc.slice(sel.from, sel.to); |
341 | | - const isComplexTextblock = Boolean(sel.$from.parent.type.spec.complex); |
342 | | - const isAllContentSelected = sel.$from.parent.content.eq(inlineSlice.content); |
343 | | - if (isComplexTextblock || !isAllContentSelected) { |
344 | | - // copy selected inline content to paragraph if current node is complex |
345 | | - // or if only part of it's content was selected |
346 | | - return Fragment.from(state.schema.node(BaseNode.Paragraph, {}, inlineSlice.content)); |
347 | | - } |
348 | | - return Fragment.from(sel.$from.parent.copy(inlineSlice.content)); |
349 | | -} |
350 | | - |
351 | | -/** |
352 | | - * Like `selection.content()`, but smarter. |
353 | | - * Copy a structure of complex nodes, |
354 | | - * e.g. if select part of cut title it creates slice with yfm-cut –> yfm-cut-title -> selected text |
355 | | - * it works well with simple nodes, but to handle cases as described above, custom logic needed |
356 | | - */ |
357 | | -function getSelectionContent(sel: Selection) { |
358 | | - const sharedNodeType = getSharedDepthNode(sel).type; |
359 | | - const sharedNodeComplex = sharedNodeType.spec.complex; |
360 | | - const includeParents = sharedNodeComplex && sharedNodeComplex !== 'leaf'; |
361 | | - return sel.$from.doc.slice(sel.$from.pos, sel.to, includeParents); |
362 | | -} |
363 | | - |
364 | 268 | function getSharedDepthNode({$from, $to}: {$from: ResolvedPos; $to: ResolvedPos}): Node { |
365 | 269 | return $from.node($from.sharedDepth($to.pos)); |
366 | 270 | } |
0 commit comments