Skip to content

Commit af9ee8e

Browse files
committed
Fix copypasting from responses page resulting in wrong paragraph/newline placement, fix #975
AI-assisted: Claude Code (Sonnet 4.6) Signed-off-by: Jan C. Borchardt <925062+jancborchardt@users.noreply.github.com>
1 parent 30d57bc commit af9ee8e

1 file changed

Lines changed: 49 additions & 1 deletion

File tree

src/components/Results/Submission.vue

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
-->
55

66
<template>
7-
<div class="section submission">
7+
<div class="section submission" @copy="onCopy">
88
<div class="submission-head">
99
<h3 dir="auto">
1010
{{ submission.userDisplayName }}
@@ -245,6 +245,54 @@ export default {
245245
onDelete() {
246246
this.$emit('delete')
247247
},
248+
249+
onCopy(event) {
250+
if (!event.clipboardData) return
251+
252+
const selection = window.getSelection()
253+
if (!selection || selection.isCollapsed) return
254+
255+
const fragment = selection.getRangeAt(0).cloneContents()
256+
const text = this.serializeNode(fragment).trim()
257+
258+
if (!text) return
259+
260+
event.clipboardData.setData('text/plain', text)
261+
event.preventDefault()
262+
},
263+
264+
serializeNode(node) {
265+
if (node.nodeType === Node.TEXT_NODE) {
266+
return node.textContent
267+
}
268+
269+
if (node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
270+
return ''
271+
}
272+
273+
const tag = node.tagName?.toLowerCase()
274+
275+
if (tag && ['svg', 'script', 'style'].includes(tag)) return ''
276+
if (tag === 'br') return '\n'
277+
278+
const children = Array.from(node.childNodes)
279+
.map((child) => this.serializeNode(child))
280+
.join('')
281+
282+
// Answer blocks get a blank line before them as visual separator
283+
if (tag === 'div' && node.classList?.contains('answer')) {
284+
const trimmed = children.replace(/\s+$/, '')
285+
return trimmed ? '\n' + trimmed + '\n' : ''
286+
}
287+
288+
const isBlock = tag && ['div', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'li', 'td', 'tr', 'th', 'dt', 'dd'].includes(tag)
289+
if (isBlock) {
290+
const trimmed = children.replace(/\s+$/, '')
291+
return trimmed ? trimmed + '\n' : ''
292+
}
293+
294+
return children
295+
},
248296
},
249297
}
250298
</script>

0 commit comments

Comments
 (0)