Add basic functionality
This commit is contained in:
+117
-8
@@ -1,11 +1,120 @@
|
|||||||
<script setup lang="ts"></script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h1>You did it!</h1>
|
<div class="csv-clipboard">
|
||||||
<p>
|
<label class="upload-label" for="csvInput">
|
||||||
Visit <a href="https://vuejs.org/" target="_blank" rel="noopener">vuejs.org</a> to read the
|
CSV-Datei auswählen
|
||||||
documentation
|
<input
|
||||||
</p>
|
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>
|
</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