Skip to content

Commit a8b7e41

Browse files
elzodymax-nextcloud
andcommitted
fix: copy-paste markdown/raw text inconsistencies (#5487)
* fix: traverse through nodes in order to determine the correct copy-paste behavior --------- Signed-off-by: Elizabeth Danzberger <lizzy7128@tutanota.de> Signed-off-by: Max <max@nextcloud.com> Co-authored-by: Max <max@nextcloud.com>
1 parent d8f1121 commit a8b7e41

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

src/extensions/Markdown.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,17 @@ const Markdown = Extension.create({
108108
return parser.parseSlice(dom, { preserveWhitespace: true, context: $context })
109109
},
110110
clipboardTextSerializer: (slice) => {
111-
return createMarkdownSerializer(this.editor.schema).serialize(slice.content)
111+
const traverseNodes = (slice) => {
112+
if (slice.content.childCount > 1) {
113+
return createMarkdownSerializer(this.editor.schema).serialize(slice.content)
114+
} else if (slice.isLeaf) {
115+
return slice.textContent
116+
} else {
117+
return traverseNodes(slice.content.firstChild)
118+
}
119+
}
120+
121+
return traverseNodes(slice)
112122
},
113123
transformPastedHTML,
114124
},

src/tests/extensions/Markdown.spec.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import { Markdown } from './../../extensions/index.js'
22
import { createMarkdownSerializer } from './../../extensions/Markdown.js'
3+
import CodeBlock from '@tiptap/extension-code-block'
4+
import Blockquote from '@tiptap/extension-blockquote'
35
import Image from './../../nodes/Image.js'
46
import ImageInline from './../../nodes/ImageInline.js'
57
import TaskList from './../../nodes/TaskList.js'
68
import TaskItem from './../../nodes/TaskItem.js'
79
import Underline from './../../marks/Underline.js'
810
import TiptapImage from '@tiptap/extension-image'
911
import { getExtensionField } from '@tiptap/core'
12+
import { __serializeForClipboard as serializeForClipboard } from '@tiptap/pm/view'
1013
import { createCustomEditor } from '../helpers.js'
1114

1215
describe('Markdown extension unit', () => {
@@ -77,4 +80,37 @@ describe('Markdown extension integrated in the editor', () => {
7780
expect(serializer.serialize(editor.state.doc)).toBe('inline image ![Hello](test) inside text')
7881
})
7982

83+
it('copies task lists to plaintext like markdown', () => {
84+
const editor = createCustomEditor({
85+
content: '<p><ul class="contains-task-list"><li><input type="checkbox">Hello</li></ul></p>',
86+
extensions: [Markdown, TaskList, TaskItem],
87+
})
88+
editor.commands.selectAll()
89+
const slice = editor.state.selection.content()
90+
const { text } = serializeForClipboard(editor.view, slice)
91+
expect(text).toBe('\n- [ ] Hello')
92+
})
93+
94+
it('copies code block content to plaintext according to their spec', () => {
95+
const editor = createCustomEditor({
96+
content: '<pre><code>Hello</code></pre>',
97+
extensions: [Markdown, CodeBlock],
98+
})
99+
editor.commands.selectAll()
100+
const slice = editor.state.selection.content()
101+
const { text } = serializeForClipboard(editor.view, slice)
102+
expect(text).toBe('Hello')
103+
})
104+
105+
it('copies nested task list nodes to markdown like syntax', () => {
106+
const editor = createCustomEditor({
107+
content: '<blockquote><p><ul class="contains-task-list"><li><input type="checkbox">Hello</li></ul></blockquote>',
108+
extensions: [Markdown, Blockquote, TaskList, TaskItem],
109+
})
110+
editor.commands.selectAll()
111+
const slice = editor.state.selection.content()
112+
const { text } = serializeForClipboard(editor.view, slice)
113+
expect(text).toBe('\n- [ ] Hello')
114+
})
115+
80116
})

0 commit comments

Comments
 (0)