(data: string)
| 10 | }; |
| 11 | |
| 12 | export function parseVCF(data: string): Record<string, string>[] { |
| 13 | const cards = data |
| 14 | .split(/BEGIN:VCARD/) |
| 15 | .slice(1) |
| 16 | .map((card) => card.split(/END:VCARD/)[0]) |
| 17 | .filter((card) => card); |
| 18 | return cards |
| 19 | .map((card) => { |
| 20 | if (!card) return {}; |
| 21 | const lines = card.split("\n").filter((line) => line.trim()); |
| 22 | const contact: Record<string, string> = {}; |
| 23 | for (const line of lines) { |
| 24 | const colonIndex = line.indexOf(":"); |
| 25 | if (colonIndex === -1) continue; |
| 26 | const key = line.slice(0, colonIndex).trim(); |
| 27 | const value = line.slice(colonIndex + 1).trim(); |
| 28 | if (key === "FN") { |
| 29 | contact["Full Name"] = value; |
| 30 | } else if (key === "N") { |
| 31 | const parts = value.split(";"); |
| 32 | contact["Last Name"] = parts[0] || ""; |
| 33 | contact["First Name"] = parts[1] || ""; |
| 34 | } else if (key.startsWith("TEL")) { |
| 35 | contact["Phone"] = value; |
| 36 | } else if (key.startsWith("EMAIL")) { |
| 37 | contact["Email"] = value; |
| 38 | } else if (key === "ORG") { |
| 39 | contact["Organization"] = value.split(";")[0] || ""; |
| 40 | } |
| 41 | } |
| 42 | return contact; |
| 43 | }) |
| 44 | .filter((contact) => Object.keys(contact).length > 0); |
| 45 | } |
| 46 | |
| 47 | export function toCSV(data: Record<string, string>[]): string { |
| 48 | if (!data.length) return ""; |
no outgoing calls
no test coverage detected