VCardSerializer.swift 33 lignes · 1594 octets
import Foundation

/// vCard 3.0 export.
enum VCardSerializer {
    static func toVCard3(_ card: ContactCard) -> String {
        var lines: [String] = ["BEGIN:VCARD", "VERSION:3.0"]
        if let v = card.fullName?.nilIfBlank { lines.append("FN:\(escape(v))") }
        if let n = buildNField(card) { lines.append("N:\(n)") }
        if let v = card.company?.nilIfBlank { lines.append("ORG:\(escape(v))") }
        if let v = card.jobTitle?.nilIfBlank { lines.append("TITLE:\(escape(v))") }
        for phone in card.phones { lines.append("TEL;TYPE=CELL:\(escape(phone))") }
        for email in card.emails { lines.append("EMAIL;TYPE=INTERNET:\(escape(email))") }
        if let v = card.website?.nilIfBlank { lines.append("URL:\(escape(v))") }
        if let v = card.address?.nilIfBlank { lines.append("ADR;TYPE=WORK:;;\(escape(v));;;;") }
        if let v = card.note?.nilIfBlank { lines.append("NOTE:\(escape(v))") }
        lines.append("END:VCARD")
        return lines.joined(separator: "\n")
    }

    private static func buildNField(_ card: ContactCard) -> String? {
        guard let last = card.lastName?.nilIfBlank else { return nil }
        let first = card.firstName ?? ""
        return "\(escape(last));\(escape(first));;;"
    }

    static func escape(_ value: String) -> String {
        value.replacingOccurrences(of: "\\", with: "\\\\")
            .replacingOccurrences(of: ";", with: "\\;")
            .replacingOccurrences(of: ",", with: "\\,")
            .replacingOccurrences(of: "\n", with: "\\n")
            .replacingOccurrences(of: "\r", with: "")
    }
}