Skip to content

Commit 46f57b2

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 46f57b2

1 file changed

Lines changed: 69 additions & 1 deletion

File tree

src/components/Results/Submission.vue

Lines changed: 69 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,74 @@ 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 (
270+
node.nodeType !== Node.ELEMENT_NODE
271+
&& node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE
272+
) {
273+
return ''
274+
}
275+
276+
const tag = node.tagName?.toLowerCase()
277+
278+
if (tag && ['svg', 'script', 'style'].includes(tag)) return ''
279+
if (tag === 'br') return '\n'
280+
281+
const children = Array.from(node.childNodes)
282+
.map((child) => this.serializeNode(child))
283+
.join('')
284+
285+
// Answer blocks get a blank line before them as visual separator
286+
if (tag === 'div' && node.classList?.contains('answer')) {
287+
const trimmed = children.replace(/\s+$/, '')
288+
return trimmed ? '\n' + trimmed + '\n' : ''
289+
}
290+
291+
const isBlock =
292+
tag
293+
&& [
294+
'div',
295+
'p',
296+
'h1',
297+
'h2',
298+
'h3',
299+
'h4',
300+
'h5',
301+
'h6',
302+
'li',
303+
'td',
304+
'tr',
305+
'th',
306+
'dt',
307+
'dd',
308+
].includes(tag)
309+
if (isBlock) {
310+
const trimmed = children.replace(/\s+$/, '')
311+
return trimmed ? trimmed + '\n' : ''
312+
}
313+
314+
return children
315+
},
248316
},
249317
}
250318
</script>

0 commit comments

Comments
 (0)