vcards-js
Version:
Create vCards to import contacts into Outlook, iOS, Mac OS, Android devices, and more.
397 lines (342 loc) • 11.2 kB
JavaScript
/********************************************************************************
vCards-js, Eric J Nesser, November 2014,
********************************************************************************/
/*jslint node: true */
;
/**
* vCard formatter for formatting vCards in VCF format
*/
(function vCardFormatter() {
var majorVersion = '3';
/**
* Encode string
* @param {String} value to encode
* @return {String} encoded string
*/
function e(value) {
if (value) {
if (typeof(value) !== 'string') {
value = '' + value;
}
return value.replace(/\n/g, '\\n').replace(/,/g, '\\,').replace(/;/g, '\\;');
}
return '';
}
/**
* Return new line characters
* @return {String} new line characters
*/
function nl() {
return '\r\n';
}
/**
* Get formatted photo
* @param {String} photoType Photo type (PHOTO, LOGO)
* @param {String} url URL to attach photo from
* @param {String} mediaType Media-type of photo (JPEG, PNG, GIF)
* @return {String} Formatted photo
*/
function getFormattedPhoto(photoType, url, mediaType, base64) {
var params;
if (majorVersion >= 4) {
params = base64 ? ';ENCODING=b;MEDIATYPE=image/' : ';MEDIATYPE=image/';
} else if (majorVersion === 3) {
params = base64 ? ';ENCODING=b;TYPE=' : ';TYPE=';
} else {
params = base64 ? ';ENCODING=BASE64;' : ';';
}
var formattedPhoto = photoType + params + mediaType + ':' + e(url) + nl();
return formattedPhoto;
}
/**
* Get formatted address
* @param {object} address
* @param {object} encoding prefix
* @return {String} Formatted address
*/
function getFormattedAddress(encodingPrefix, address) {
var formattedAddress = '';
if (address.details.label ||
address.details.street ||
address.details.city ||
address.details.stateProvince ||
address.details.postalCode ||
address.details.countryRegion) {
if (majorVersion >= 4) {
formattedAddress = 'ADR' + encodingPrefix + ';TYPE=' + address.type +
(address.details.label ? ';LABEL="' + e(address.details.label) + '"' : '') + ':;;' +
e(address.details.street) + ';' +
e(address.details.city) + ';' +
e(address.details.stateProvince) + ';' +
e(address.details.postalCode) + ';' +
e(address.details.countryRegion) + nl();
} else {
if (address.details.label) {
formattedAddress = 'LABEL' + encodingPrefix + ';TYPE=' + address.type + ':' + e(address.details.label) + nl();
}
formattedAddress += 'ADR' + encodingPrefix + ';TYPE=' + address.type + ':;;' +
e(address.details.street) + ';' +
e(address.details.city) + ';' +
e(address.details.stateProvince) + ';' +
e(address.details.postalCode) + ';' +
e(address.details.countryRegion) + nl();
}
}
return formattedAddress;
}
/**
* Convert date to YYYYMMDD format
* @param {Date} date to encode
* @return {String} encoded date
*/
function YYYYMMDD(date) {
return date.getFullYear() + ('0' + (date.getMonth()+1)).slice(-2) + ('0' + date.getDate()).slice(-2);
}
module.exports = {
/**
* Get formatted vCard in VCF format
* @param {object} vCard object
* @return {String} Formatted vCard in VCF format
*/
getFormattedString: function(vCard) {
majorVersion = vCard.getMajorVersion();
var formattedVCardString = '';
formattedVCardString += 'BEGIN:VCARD' + nl();
formattedVCardString += 'VERSION:' + vCard.version + nl();
var encodingPrefix = majorVersion >= 4 ? '' : ';CHARSET=UTF-8';
var formattedName = vCard.formattedName;
if (!formattedName) {
formattedName = '';
[vCard.firstName, vCard.middleName, vCard.lastName]
.forEach(function(name) {
if (name) {
if (formattedName) {
formattedName += ' ';
}
}
formattedName += name;
});
}
formattedVCardString += 'FN' + encodingPrefix + ':' + e(formattedName) + nl();
formattedVCardString += 'N' + encodingPrefix + ':' +
e(vCard.lastName) + ';' +
e(vCard.firstName) + ';' +
e(vCard.middleName) + ';' +
e(vCard.namePrefix) + ';' +
e(vCard.nameSuffix) + nl();
if (vCard.nickname && majorVersion >= 3) {
formattedVCardString += 'NICKNAME' + encodingPrefix + ':' + e(vCard.nickname) + nl();
}
if (vCard.gender) {
formattedVCardString += 'GENDER:' + e(vCard.gender) + nl();
}
if (vCard.uid) {
formattedVCardString += 'UID' + encodingPrefix + ':' + e(vCard.uid) + nl();
}
if (vCard.birthday) {
formattedVCardString += 'BDAY:' + YYYYMMDD(vCard.birthday) + nl();
}
if (vCard.anniversary) {
formattedVCardString += 'ANNIVERSARY:' + YYYYMMDD(vCard.anniversary) + nl();
}
if (vCard.email) {
if(!Array.isArray(vCard.email)){
vCard.email = [vCard.email];
}
vCard.email.forEach(
function(address) {
if (majorVersion >= 4) {
formattedVCardString += 'EMAIL' + encodingPrefix + ';type=HOME:' + e(address) + nl();
} else if (majorVersion >= 3 && majorVersion < 4) {
formattedVCardString += 'EMAIL' + encodingPrefix + ';type=HOME,INTERNET:' + e(address) + nl();
} else {
formattedVCardString += 'EMAIL' + encodingPrefix + ';HOME;INTERNET:' + e(address) + nl();
}
}
);
}
if (vCard.workEmail) {
if(!Array.isArray(vCard.workEmail)){
vCard.workEmail = [vCard.workEmail];
}
vCard.workEmail.forEach(
function(address) {
if (majorVersion >= 4) {
formattedVCardString += 'EMAIL' + encodingPrefix + ';type=WORK:' + e(address) + nl();
} else if (majorVersion >= 3 && majorVersion < 4) {
formattedVCardString += 'EMAIL' + encodingPrefix + ';type=WORK,INTERNET:' + e(address) + nl();
} else {
formattedVCardString += 'EMAIL' + encodingPrefix + ';WORK;INTERNET:' + e(address) + nl();
}
}
);
}
if (vCard.otherEmail) {
if(!Array.isArray(vCard.otherEmail)){
vCard.otherEmail = [vCard.otherEmail];
}
vCard.otherEmail.forEach(
function(address) {
if (majorVersion >= 4) {
formattedVCardString += 'EMAIL' + encodingPrefix + ';type=OTHER:' + e(address) + nl();
} else if (majorVersion >= 3 && majorVersion < 4) {
formattedVCardString += 'EMAIL' + encodingPrefix + ';type=OTHER,INTERNET:' + e(address) + nl();
} else {
formattedVCardString += 'EMAIL' + encodingPrefix + ';OTHER;INTERNET:' + e(address) + nl();
}
}
);
}
if (vCard.logo.url) {
formattedVCardString += getFormattedPhoto('LOGO', vCard.logo.url, vCard.logo.mediaType, vCard.logo.base64);
}
if (vCard.photo.url) {
formattedVCardString += getFormattedPhoto('PHOTO', vCard.photo.url, vCard.photo.mediaType, vCard.photo.base64);
}
if (vCard.cellPhone) {
if(!Array.isArray(vCard.cellPhone)){
vCard.cellPhone = [vCard.cellPhone];
}
vCard.cellPhone.forEach(
function(number){
if (majorVersion >= 4) {
formattedVCardString += 'TEL;VALUE=uri;TYPE="voice,cell":tel:' + e(number) + nl();
} else {
formattedVCardString += 'TEL;TYPE=CELL:' + e(number) + nl();
}
}
);
}
if (vCard.pagerPhone) {
if(!Array.isArray(vCard.pagerPhone)){
vCard.pagerPhone = [vCard.pagerPhone];
}
vCard.pagerPhone.forEach(
function(number) {
if (majorVersion >= 4) {
formattedVCardString += 'TEL;VALUE=uri;TYPE="pager,cell":tel:' + e(number) + nl();
} else {
formattedVCardString += 'TEL;TYPE=PAGER:' + e(number) + nl();
}
}
);
}
if (vCard.homePhone) {
if(!Array.isArray(vCard.homePhone)){
vCard.homePhone = [vCard.homePhone];
}
vCard.homePhone.forEach(
function(number) {
if (majorVersion >= 4) {
formattedVCardString += 'TEL;VALUE=uri;TYPE="voice,home":tel:' + e(number) + nl();
} else {
formattedVCardString += 'TEL;TYPE=HOME,VOICE:' + e(number) + nl();
}
}
);
}
if (vCard.workPhone) {
if(!Array.isArray(vCard.workPhone)){
vCard.workPhone = [vCard.workPhone];
}
vCard.workPhone.forEach(
function(number) {
if (majorVersion >= 4) {
formattedVCardString += 'TEL;VALUE=uri;TYPE="voice,work":tel:' + e(number) + nl();
} else {
formattedVCardString += 'TEL;TYPE=WORK,VOICE:' + e(number) + nl();
}
}
);
}
if (vCard.homeFax) {
if(!Array.isArray(vCard.homeFax)){
vCard.homeFax = [vCard.homeFax];
}
vCard.homeFax.forEach(
function(number) {
if (majorVersion >= 4) {
formattedVCardString += 'TEL;VALUE=uri;TYPE="fax,home":tel:' + e(number) + nl();
} else {
formattedVCardString += 'TEL;TYPE=HOME,FAX:' + e(number) + nl();
}
}
);
}
if (vCard.workFax) {
if(!Array.isArray(vCard.workFax)){
vCard.workFax = [vCard.workFax];
}
vCard.workFax.forEach(
function(number) {
if (majorVersion >= 4) {
formattedVCardString += 'TEL;VALUE=uri;TYPE="fax,work":tel:' + e(number) + nl();
} else {
formattedVCardString += 'TEL;TYPE=WORK,FAX:' + e(number) + nl();
}
}
);
}
if (vCard.otherPhone) {
if(!Array.isArray(vCard.otherPhone)){
vCard.otherPhone = [vCard.otherPhone];
}
vCard.otherPhone.forEach(
function(number) {
if (majorVersion >= 4) {
formattedVCardString += 'TEL;VALUE=uri;TYPE="voice,other":tel:' + e(number) + nl();
} else {
formattedVCardString += 'TEL;TYPE=OTHER:' + e(number) + nl();
}
}
);
}
[{
details: vCard.homeAddress,
type: 'HOME'
}, {
details: vCard.workAddress,
type: 'WORK'
}].forEach(
function(address) {
formattedVCardString += getFormattedAddress(encodingPrefix, address);
}
);
if (vCard.title) {
formattedVCardString += 'TITLE' + encodingPrefix + ':' + e(vCard.title) + nl();
}
if (vCard.role) {
formattedVCardString += 'ROLE' + encodingPrefix + ':' + e(vCard.role) + nl();
}
if (vCard.organization) {
formattedVCardString += 'ORG' + encodingPrefix + ':' + e(vCard.organization) + nl();
}
if (vCard.url) {
formattedVCardString += 'URL' + encodingPrefix + ':' + e(vCard.url) + nl();
}
if (vCard.workUrl) {
formattedVCardString += 'URL;type=WORK' + encodingPrefix + ':' + e(vCard.workUrl) + nl();
}
if (vCard.note) {
formattedVCardString += 'NOTE' + encodingPrefix + ':' + e(vCard.note) + nl();
}
if (vCard.socialUrls) {
for (var key in vCard.socialUrls) {
if (vCard.socialUrls.hasOwnProperty(key) &&
vCard.socialUrls[key]) {
formattedVCardString += 'X-SOCIALPROFILE' + encodingPrefix + ';TYPE=' + key + ':' + e(vCard.socialUrls[key]) + nl();
}
}
}
if (vCard.source) {
formattedVCardString += 'SOURCE' + encodingPrefix + ':' + e(vCard.source) + nl();
}
formattedVCardString += 'REV:' + (new Date()).toISOString() + nl();
if (vCard.isOrganization) {
formattedVCardString += 'X-ABShowAs:COMPANY' + nl();
}
formattedVCardString += 'END:VCARD' + nl();
return formattedVCardString;
}
};
})();