|
1 | | -import {Fragment, Schema, Slice} from 'prosemirror-model'; |
| 1 | +import {Fragment, Node, ResolvedPos, Schema, Slice} from 'prosemirror-model'; |
2 | 2 | import {EditorState, Plugin, Selection} from 'prosemirror-state'; |
3 | 3 | import type {EditorView} from 'prosemirror-view'; |
4 | 4 |
|
@@ -192,20 +192,28 @@ function getSliceFromMarkupFragment(fragment: Fragment) { |
192 | 192 |
|
193 | 193 | type SerializeResult = { |
194 | 194 | text: string; |
195 | | - html: string; |
196 | | - markup: string; |
| 195 | + html?: string; |
| 196 | + markup?: string; |
197 | 197 | }; |
198 | 198 | function serializeSelected(view: EditorView, serializer: Serializer): SerializeResult | null { |
199 | | - if (view.state.selection.empty) return null; |
| 199 | + const sel = view.state.selection; |
| 200 | + |
| 201 | + if (sel.empty) return null; |
| 202 | + |
| 203 | + if (getSharedDepthNode(sel).type.spec.code) { |
| 204 | + const fragment = sel.content().content; |
| 205 | + return {text: fragment.textBetween(0, fragment.size)}; |
| 206 | + } |
| 207 | + |
200 | 208 | const markup = serializer.serialize(getCopyContent(view.state).content); |
201 | | - const {dom, text} = serializeForClipboard(view, view.state.selection.content()); |
| 209 | + const {dom, text} = serializeForClipboard(view, sel.content()); |
202 | 210 | return {markup, text, html: dom.innerHTML}; |
203 | 211 | } |
204 | 212 |
|
205 | 213 | function setClipboardData(data: DataTransfer, result: SerializeResult) { |
206 | 214 | data.clearData(); |
207 | | - data.setData(DataTransferType.Yfm, result.markup); |
208 | | - data.setData(DataTransferType.Html, result.html); |
| 215 | + if (typeof result.markup === 'string') data.setData(DataTransferType.Yfm, result.markup); |
| 216 | + if (typeof result.html === 'string') data.setData(DataTransferType.Html, result.html); |
209 | 217 | data.setData(DataTransferType.Text, result.text); |
210 | 218 | } |
211 | 219 |
|
@@ -297,9 +305,13 @@ function createFragmentFromInlineSelection(state: EditorState) { |
297 | 305 | * e.g. if select part of cut title it creates slice with yfm-cut –> yfm-cut-title -> selected text |
298 | 306 | * it works well with simple nodes, but to handle cases as described above, custom logic needed |
299 | 307 | */ |
300 | | -function getSelectionContent({$from, to}: Selection) { |
301 | | - const sharedNodeType = $from.node($from.sharedDepth(to)).type; |
| 308 | +function getSelectionContent(sel: Selection) { |
| 309 | + const sharedNodeType = getSharedDepthNode(sel).type; |
302 | 310 | const sharedNodeComplex = sharedNodeType.spec.complex; |
303 | 311 | const includeParents = sharedNodeComplex && sharedNodeComplex !== 'leaf'; |
304 | | - return $from.doc.slice($from.pos, to, includeParents); |
| 312 | + return sel.$from.doc.slice(sel.$from.pos, sel.to, includeParents); |
| 313 | +} |
| 314 | + |
| 315 | +function getSharedDepthNode({$from, $to}: {$from: ResolvedPos; $to: ResolvedPos}): Node { |
| 316 | + return $from.node($from.sharedDepth($to.pos)); |
305 | 317 | } |
0 commit comments