Add basic functionality
This commit is contained in:
+117
-8
@@ -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, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user