flechtware_generateTracking.../csv_to_html_converter.js

102 lines
2.8 KiB
JavaScript

const fs = require('fs');
const readline = require('readline');
class CsvToHtmlConverter {
/**
* Erstellt eine HTML-Tabelle aus einer CSV-Datei
* @param {string} csvFilePath Pfad zur CSV-Datei
* @returns {Promise<string>} HTML-Tabelle als String
*/
async convertToHtml(csvFilePath) {
if (!fs.existsSync(csvFilePath)) {
throw new Error(`CSV file not found: ${csvFilePath}`);
}
const fileStream = fs.createReadStream(csvFilePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity,
});
let html = this.getHtmlHeader();
let isFirstLine = true;
for await (const line of rl) {
const cells = this.parseCsvLine(line);
if (isFirstLine) {
html += '<thead><tr>';
cells.forEach(cell => {
html += `<th>${this.escapeHtml(cell)}</th>`;
});
html += '</tr></thead><tbody>';
isFirstLine = false;
} else {
html += '<tr>';
cells.forEach(cell => {
html += `<td>${this.escapeHtml(cell)}</td>`;
});
html += '</tr>';
}
}
html += '</tbody></table>';
return html;
}
/**
* Gibt das HTML- und CSS-Headergerüst für die Tabelle zurück
*/
getHtmlHeader() {
return `
<style>
table {
border-collapse: collapse;
width: 100%;
font-family: Arial, sans-serif;
}
th, td {
border: 1px solid #ccc;
padding: 6px 12px;
text-align: left;
}
thead {
background-color: #f2f2f2;
}
tbody tr:nth-child(odd) {
background-color: #ffffff;
}
tbody tr:nth-child(even) {
background-color: #f9f9f9;
}
</style>
<table>
`;
}
/**
* Wandelt eine CSV-Zeile in Felder um
* @param {string} line
* @returns {string[]}
*/
parseCsvLine(line) {
// Für einfache Fälle (Kommas, kein Quote-Parsing)
return line.split(',').map(field => field.trim());
}
/**
* Wandelt Sonderzeichen in HTML-Entities um
* @param {string} text
* @returns {string}
*/
escapeHtml(text) {
return String(text)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
}
module.exports = CsvToHtmlConverter;