diff --git a/src/converters/vcf.ts b/src/converters/vcf.ts index e5da423..2fff8ed 100644 --- a/src/converters/vcf.ts +++ b/src/converters/vcf.ts @@ -10,42 +10,48 @@ export const properties = { }; export function parseVCF(data: string): Record[] { - const cards = data.split(/BEGIN:VCARD/).slice(1).map(card => card.split(/END:VCARD/)[0]).filter(card => card); - return cards.map(card => { - if (!card) return {}; - const lines = card.split('\n').filter(line => line.trim()); - const contact: Record = {}; - for (const line of lines) { - const colonIndex = line.indexOf(':'); - if (colonIndex === -1) continue; - const key = line.slice(0, colonIndex).trim(); - const value = line.slice(colonIndex + 1).trim(); - if (key === 'FN') { - contact['Full Name'] = value; - } else if (key === 'N') { - const parts = value.split(';'); - contact['Last Name'] = parts[0] || ''; - contact['First Name'] = parts[1] || ''; - } else if (key.startsWith('TEL')) { - contact['Phone'] = value; - } else if (key.startsWith('EMAIL')) { - contact['Email'] = value; - } else if (key === 'ORG') { - contact['Organization'] = value.split(';')[0] || ''; + const cards = data + .split(/BEGIN:VCARD/) + .slice(1) + .map((card) => card.split(/END:VCARD/)[0]) + .filter((card) => card); + return cards + .map((card) => { + if (!card) return {}; + const lines = card.split("\n").filter((line) => line.trim()); + const contact: Record = {}; + for (const line of lines) { + const colonIndex = line.indexOf(":"); + if (colonIndex === -1) continue; + const key = line.slice(0, colonIndex).trim(); + const value = line.slice(colonIndex + 1).trim(); + if (key === "FN") { + contact["Full Name"] = value; + } else if (key === "N") { + const parts = value.split(";"); + contact["Last Name"] = parts[0] || ""; + contact["First Name"] = parts[1] || ""; + } else if (key.startsWith("TEL")) { + contact["Phone"] = value; + } else if (key.startsWith("EMAIL")) { + contact["Email"] = value; + } else if (key === "ORG") { + contact["Organization"] = value.split(";")[0] || ""; + } } - } - return contact; - }).filter(contact => Object.keys(contact).length > 0); + return contact; + }) + .filter((contact) => Object.keys(contact).length > 0); } export function toCSV(data: Record[]): string { - if (!data.length) return ''; + if (!data.length) return ""; const first = data[0]; - if (!first) return ''; + if (!first) return ""; const headers = Object.keys(first); const escape = (str: string) => `"${str.replace(/"/g, '""')}"`; - const rows = data.map(row => headers.map(h => escape(row[h] || '')).join(',')); - return [headers.join(','), ...rows].join('\n'); + const rows = data.map((row) => headers.map((h) => escape(row[h] || "")).join(",")); + return [headers.join(","), ...rows].join("\n"); } export async function convert( @@ -53,11 +59,11 @@ export async function convert( fileType: string, convertTo: string, targetPath: string, - options?: unknown, + options?: unknown, // eslint-disable-line @typescript-eslint/no-unused-vars ): Promise { - const vcfData = await readFile(filePath, 'utf-8'); + const vcfData = await readFile(filePath, "utf-8"); const contacts = parseVCF(vcfData); const csvData = toCSV(contacts); - await writeFile(targetPath, csvData, 'utf-8'); + await writeFile(targetPath, csvData, "utf-8"); return "Done"; } diff --git a/tests/converters/vcf.test.ts b/tests/converters/vcf.test.ts index 189beac..181dd71 100644 --- a/tests/converters/vcf.test.ts +++ b/tests/converters/vcf.test.ts @@ -16,13 +16,13 @@ END:VCARD`; expect(result).toEqual([ { - 'Full Name': 'John Doe', - 'Last Name': 'Doe', - 'First Name': 'John', - 'Phone': '+123456789', - 'Email': 'john@example.com', - 'Organization': 'Example Corp' - } + "Full Name": "John Doe", + "Last Name": "Doe", + "First Name": "John", + Phone: "+123456789", + Email: "john@example.com", + Organization: "Example Corp", + }, ]); }); @@ -36,10 +36,7 @@ END:VCARD`; const result = parseVCF(vcfData); - expect(result).toEqual([ - { 'Full Name': 'John Doe' }, - { 'Full Name': 'Jane Smith' } - ]); + expect(result).toEqual([{ "Full Name": "John Doe" }, { "Full Name": "Jane Smith" }]); }); test("should parse VCF with TYPE parameters", () => { @@ -55,12 +52,12 @@ END:VCARD`; expect(result).toEqual([ { - 'Full Name': 'John Doe', - 'Last Name': 'Doe', - 'First Name': 'John', - 'Phone': '(111) 555-1212', - 'Email': 'john.doe@example.com' - } + "Full Name": "John Doe", + "Last Name": "Doe", + "First Name": "John", + Phone: "(111) 555-1212", + Email: "john.doe@example.com", + }, ]); }); }); @@ -69,10 +66,10 @@ describe("toCSV", () => { test("should convert contacts to CSV", () => { const contacts = [ { - 'Full Name': 'John Doe', - 'Phone': '+123', - 'Email': 'john@example.com' - } + "Full Name": "John Doe", + Phone: "+123", + Email: "john@example.com", + }, ]; const result = toCSV(contacts); @@ -81,9 +78,7 @@ describe("toCSV", () => { }); test("should escape quotes", () => { - const contacts = [ - { 'Full Name': 'John "Johnny" Doe' } - ]; + const contacts = [{ "Full Name": 'John "Johnny" Doe' }]; const result = toCSV(contacts); @@ -92,7 +87,7 @@ describe("toCSV", () => { test("should handle empty data", () => { const result = toCSV([]); - expect(result).toBe(''); + expect(result).toBe(""); }); });