mirror of
https://github.com/xx254/linkedin_skills.git
synced 2026-06-10 07:24:56 +03:00
86 lines
1.7 KiB
JavaScript
86 lines
1.7 KiB
JavaScript
function parseCsv(content) {
|
|
const rows = [];
|
|
let row = [];
|
|
let field = "";
|
|
let inQuotes = false;
|
|
|
|
// Character-level parser to correctly handle commas/newlines inside quotes.
|
|
for (let i = 0; i < content.length; i += 1) {
|
|
const char = content[i];
|
|
const next = content[i + 1];
|
|
|
|
if (char === "\"") {
|
|
if (inQuotes && next === "\"") {
|
|
field += "\"";
|
|
i += 1;
|
|
} else {
|
|
inQuotes = !inQuotes;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (char === "," && !inQuotes) {
|
|
row.push(field);
|
|
field = "";
|
|
continue;
|
|
}
|
|
|
|
if ((char === "\n" || char === "\r") && !inQuotes) {
|
|
if (char === "\r" && next === "\n") {
|
|
i += 1;
|
|
}
|
|
row.push(field);
|
|
field = "";
|
|
if (row.length > 1 || (row.length === 1 && row[0] !== "")) {
|
|
rows.push(row);
|
|
}
|
|
row = [];
|
|
continue;
|
|
}
|
|
|
|
field += char;
|
|
}
|
|
|
|
if (field.length || row.length) {
|
|
row.push(field);
|
|
rows.push(row);
|
|
}
|
|
|
|
if (!rows.length) {
|
|
return { headers: [], records: [] };
|
|
}
|
|
|
|
const headers = rows[0].map((h) => h.trim());
|
|
const records = rows.slice(1).map((r) => {
|
|
const obj = {};
|
|
headers.forEach((h, idx) => {
|
|
obj[h] = (r[idx] || "").trim();
|
|
});
|
|
return obj;
|
|
});
|
|
|
|
return { headers, records };
|
|
}
|
|
|
|
function escapeCsvValue(value) {
|
|
const s = String(value ?? "");
|
|
if (/[",\n\r]/.test(s)) {
|
|
return `"${s.replace(/"/g, "\"\"")}"`;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
function toCsv(headers, records) {
|
|
const lines = [headers.map(escapeCsvValue).join(",")];
|
|
records.forEach((record) => {
|
|
const row = headers.map((h) => escapeCsvValue(record[h] ?? ""));
|
|
lines.push(row.join(","));
|
|
});
|
|
return `${lines.join("\n")}\n`;
|
|
}
|
|
|
|
module.exports = {
|
|
parseCsv,
|
|
toCsv
|
|
};
|