Add basic functionality

This commit is contained in:
2026-08-31 20:41:47 +02:00
parent 58a05d7b98
commit 2010924025
2 changed files with 120 additions and 8 deletions
+117 -8
View File
@@ -1,11 +1,120 @@
<script setup lang="ts"></script>
<template>
<h1>You did it!</h1>
<p>
Visit <a href="https://vuejs.org/" target="_blank" rel="noopener">vuejs.org</a> to read the
documentation
</p>
<div class="csv-clipboard">
<label class="upload-label" for="csvInput">
CSV-Datei auswählen
<input
id="csvInput"
type="file"
accept=".csv"
@change="handleFileChange"
class="hidden-input"
/>
</label>
<button v-if="parsedRows" @click="copyToClipboard" class="copy-button">
In Zwischenablage kopieren
</button>
<p v-if="status === 'success'" class="status success">✅ Kopiert!</p>
<p v-else-if="status === 'error'" class="status error">❌ {{ errorMessage }}</p>
</div>
</template>
<style scoped></style>
<script setup>
import { ref } from 'vue'
const parsedRows = ref(null)
const status = ref(null)
const errorMessage = ref('')
async function handleFileChange(event) {
status.value = null
const file = event.target.files[0]
if (!file) return
const text = await file.text()
parsedRows.value = parseCSV(text)
event.target.value = ''
}
async function copyToClipboard() {
if (!parsedRows.value) return
const html = buildHtmlTable(parsedRows.value)
const plain = parsedRows.value.map((r) => r.join('\t')).join('\n')
try {
await navigator.clipboard.write([
new ClipboardItem({
'text/plain': new Blob([plain], { type: 'text/plain' }),
}),
])
status.value = 'success'
} catch (err) {
console.error('Kopieren fehlgeschlagen:', err)
status.value = 'error'
errorMessage.value = 'Kopieren fehlgeschlagen – bitte erneut versuchen.'
errorMessage.value = `${err.name}: ${err.message}`
}
}
function parseCSV(text) {
const rows = []
let row = []
let field = ''
let insideQuotes = false
for (let i = 0; i < text.length; i++) {
const char = text[i]
const next = text[i + 1]
if (insideQuotes) {
if (char === '"' && next === '"') {
field += '"'
i++
} else if (char === '"') {
insideQuotes = false
} else {
field += char
}
} else {
if (char === '"') {
insideQuotes = true
} else if (char === ',') {
row.push(field)
field = ''
} else if (char === '\n' || char === '\r') {
if (field.length > 0 || row.length > 0) {
row.push(field)
rows.push(row)
row = []
field = ''
}
if (char === '\r' && next === '\n') i++
} else {
field += char
}
}
}
if (field.length > 0 || row.length > 0) {
row.push(field)
rows.push(row)
}
return rows
}
function buildHtmlTable(rows) {
const trs = rows
.map((r, i) => {
const tag = i === 0 ? 'th' : 'td'
const cells = r.map((cell) => `<${tag}>${escapeHtml(cell)}</${tag}>`).join('')
return `<tr>${cells}</tr>`
})
.join('')
return `<table>${trs}</table>`
}
function escapeHtml(str) {
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
}
</script>
+3
View File
@@ -0,0 +1,3 @@
1,2
3,4
5,6
1 1 2
2 3 4
3 5 6