1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-15 09:34:13 +00:00

Copy and Paste don't work as expected inside the LongText field editor (rich and plain)

This commit is contained in:
Przemyslaw Kukulski 2025-02-25 18:46:27 +00:00
parent 966ecdb801
commit 14ea722cb4
3 changed files with 40 additions and 34 deletions
changelog/entries/unreleased/bug
web-frontend/modules
core/components/editor
database/mixins

View file

@ -0,0 +1,7 @@
{
"type": "bug",
"message": "Fix pasting markdown text into rich edit that resulted in unformatted markdown",
"issue_number": 2383,
"bullet_points": [],
"created_at": "2025-02-07"
}

View file

@ -110,6 +110,8 @@ const richTextEditorExtensions = ({
Markdown.configure({
html: false,
breaks: true,
transformPastedText: true,
transformCopiedText: true,
}),
History,
]
@ -287,6 +289,15 @@ export default {
return true
}
},
handlePaste: (view, event) => {
const plainText = event.clipboardData.getData('text/plain')
if (plainText.startsWith('"') && plainText.endsWith('"')) {
const cleanText = plainText.slice(1, -1)
this.editor.commands.insertContent(cleanText)
return true
}
return false
},
},
extensions,
onUpdate: () => {
@ -337,7 +348,6 @@ export default {
this.registerResizeObserver()
this.registerAutoCollapseFloatingMenuHandler()
this.registerAutoHideBubbleMenuHandler()
this.registerOnPasteHandler()
} else {
this.unregisterResizeObserver()
}
@ -368,12 +378,6 @@ export default {
elem.removeEventListener('scroll', handler)
})
},
registerOnPasteHandler() {
document.addEventListener('paste', this.onPaste)
this.$once('hook:unmounted', () => {
document.removeEventListener('paste', this.onPaste)
})
},
renderHTMLMention() {
const loggedUserId = this.loggedUserId
const isUserInWorkspace = (userId) =>
@ -476,22 +480,6 @@ export default {
this.dragTarget = null
}
},
onPaste(event) {
if (
!event.clipboardData.types.includes('text/plain') ||
event.clipboardData.getData('text/plain').startsWith('file:///')
) {
const { items } = event.clipboardData
for (const item of items) {
if (item.type.includes('image')) {
const file = item.getAsFile()
this.uploadFiles([file])
return true
}
}
}
return false
},
},
}
</script>

View file

@ -40,6 +40,13 @@ export default {
prepareHTMLData(textData, firstRowIsHeader) {
const table = document.createElement('table')
const tbody = document.createElement('tbody')
// For single cells we don't need html clipboard data as it's
// conflicting with tiptap
if (textData.length === 1 && textData[0].length === 1) {
return
}
textData.forEach((row, index) => {
const tr = document.createElement('tr')
row.forEach((cell) => {
@ -63,7 +70,6 @@ export default {
// The HTML table renders a structured table when pasted into an email or rich
// text document.
const htmlData = this.prepareHTMLData(textData, includeHeader)
try {
localStorage.setItem(
LOCAL_STORAGE_CLIPBOARD_KEY,
@ -78,19 +84,24 @@ export default {
// need to check if it is available. Safari instead, needs the
// ClipboardItem type to save async data to the clipboard.
if (typeof ClipboardItem !== 'undefined') {
navigator.clipboard.write([
new ClipboardItem({
'text/plain': new Blob([tsvData], { type: 'text/plain' }),
'text/html': new Blob([htmlData], { type: 'text/html' }),
}),
])
const clipboardConfig = {
'text/plain': new Blob([tsvData], { type: 'text/plain' }),
}
if (htmlData) {
clipboardConfig['text/html'] = new Blob([htmlData], {
type: 'text/html',
})
}
navigator.clipboard.write([new ClipboardItem(clipboardConfig)])
} else if (typeof navigator.clipboard?.writeText !== 'undefined') {
navigator.clipboard.writeText(tsvData)
} else {
setRichClipboard({
'text/plain': tsvData,
'text/html': htmlData,
})
const richClipboardConfig = { 'text/plain': tsvData }
if (htmlData) {
richClipboardConfig['text/html'] = htmlData
}
setRichClipboard(richClipboardConfig)
}
},
async extractClipboardData(event) {