UNPKG

ngx-vcard

Version:

Generate an RFC compliant vCard and download it.

566 lines (556 loc) 20.5 kB
import * as i0 from '@angular/core'; import { Directive, Input, HostListener, NgModule } from '@angular/core'; var VCardEncoding; (function (VCardEncoding) { VCardEncoding["none"] = ""; VCardEncoding["utf8"] = ";CHARSET=utf-8"; })(VCardEncoding || (VCardEncoding = {})); /** * Encodes string */ function e(value) { if (value) { if (typeof value !== 'string') { value = '' + value; } return (value // From https://datatracker.ietf.org/doc/html/rfc6350 // Some properties may contain one or more values delimited by a COMMA // character (U+002C). Therefore, a COMMA character in a value MUST be // escaped with a BACKSLASH character (U+005C), even for properties that // don't allow multiple instances (for consistency). .replace(/,/g, ',') // Some properties (e.g., N and ADR) comprise multiple fields delimited // by a SEMICOLON character (U+003B). Therefore, a SEMICOLON in a field // of such a "compound" property MUST be escaped with a BACKSLASH // character. SEMICOLON characters in non-compound properties MAY be // escaped. On input, an escaped SEMICOLON character is never a field // separator. An unescaped SEMICOLON character may be a field // separator, depending on the property in which it appears. .replace(/;/g, ';') // Finally, BACKSLASH characters in values MUST be escaped with a // BACKSLASH character. .replace(/\\/g, '\\\\') // NEWLINE (U+000A) characters in values MUST be // encoded by two characters: a BACKSLASH followed by either an 'n' // (U+006E) or an 'N' (U+004E). .replace(/\n/g, '\\n') // In all other cases, escaping MUST NOT be used. ); } return ''; } /** * Return new line characters */ function nl() { return '\n'; } function propertyToVCardString(property) { let str = ''; if (property.language) { str += ';LANGUAGE=' + e(property.language); } if (property.value) { str += ';VALUE=' + e(property.value); } if (property.altid) { str += ';ALTID=' + e(property.altid); } if (property.pid) { str += ';PID=' + property.pid.map((s) => e(s)).join(','); } if (property.type) { if (Array.isArray(property.type)) { if (property.type.length === 1) { str += ';TYPE=' + property.type[0]; } else { str += ';TYPE="' + property.type.map((s) => s.toLowerCase()).join(',') + '"'; } } else { str += ';TYPE=' + property.type; } } if (property.mediatype) { str += ';MEDIATYPE=' + e(property.mediatype); } if (property.pref) { str += ';PREF=' + property.pref; } if (property.calscale) { str += ';CALSCALE=' + e(property.calscale); } if (property.sortas) { str += ';SORT-AS="' + property.sortas.map((s) => e(s)).join(',') + '"'; } if (property.geo) { str += ';GEO=' + e(property.geo); } if (property.timezone) { str += ';TZ=' + e(property.timezone); } return str; } function isPropertyWithParameters(object) { const test = object; if (test == null || test.param == null || test.value == null) { return false; } return (test.param.language !== undefined || test.param.value !== undefined || test.param.pref !== undefined || test.param.altid !== undefined || test.param.pid !== undefined || test.param.type !== undefined || test.param.mediatype !== undefined || test.param.calscale !== undefined || test.param.sortas !== undefined || test.param.geo !== undefined || test.param.timezone !== undefined); } function isPropertyWithParametersAddressValue(object) { const test = object; if (test == null || test.param == null || test.value == null) { return false; } return (test.param.language !== undefined || test.param.value !== undefined || test.param.pref !== undefined || test.param.altid !== undefined || test.param.pid !== undefined || test.param.type !== undefined || test.param.mediatype !== undefined || test.param.calscale !== undefined || test.param.sortas !== undefined || test.param.geo !== undefined || test.param.timezone !== undefined); } class VCardFormatter { static getVCardAsBlob(vCard, encoding = VCardEncoding.none) { const data = VCardFormatter.getVCardAsString(vCard, encoding); return new Blob([data], { type: 'text/vcard' }); } /** * Get formatted vCard in VCF format */ static getVCardAsString(vCard, encodingPrefix = VCardEncoding.none) { if (!vCard.version) { vCard.version = '4.0'; } const majorVersion = getMajorVersion(vCard.version); let formattedVCardString = ''; formattedVCardString += 'BEGIN:VCARD' + nl(); formattedVCardString += 'VERSION:' + vCard.version + nl(); // const encodingPrefix = ''; let formattedName = ''; if (vCard.name == null) { vCard.name = {}; } let nameArray = []; if (vCard.formattedName != null) { nameArray = [ vCard.formattedName.firstNames, vCard.formattedName.addtionalNames, vCard.formattedName.lastNames, ]; } else { nameArray = [ vCard.name.firstNames, vCard.name.addtionalNames, vCard.name.lastNames, ]; } formattedName = nameArray.filter((string) => string != null).join(' '); formattedVCardString += 'FN' + encodingPrefix + ':' + e(formattedName) + nl(); formattedVCardString += 'N' + encodingPrefix + ':' + [ e(vCard.name.lastNames), e(vCard.name.firstNames), e(vCard.name.addtionalNames), e(vCard.name.namePrefix), e(vCard.name.nameSuffix), ].join(';') + nl(); if (vCard.nickname && majorVersion >= 3) { formattedVCardString += 'NICKNAME' + encodingPrefix + ':' + e(vCard.nickname) + nl(); } if (vCard.gender) { if (vCard.gender.sex) { formattedVCardString += 'GENDER:' + e(vCard.gender.sex); if (vCard.gender.text) { formattedVCardString += ';' + e(vCard.gender.text); } formattedVCardString += nl(); } else { formattedVCardString += 'GENDER:;' + e(vCard.gender.text) + 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.language) { vCard.language.forEach((language) => { if (isPropertyWithParameters(language)) { formattedVCardString += 'LANG' + propertyToVCardString(language.param) + ':' + e(language.value) + nl(); } else { formattedVCardString += 'LANG:' + e(language) + nl(); } }); } if (vCard.organization) { if (isPropertyWithParameters(vCard.organization)) { formattedVCardString += 'ORG' + propertyToVCardString(vCard.organization.param) + ':' + e(vCard.organization.value) + nl(); } else { formattedVCardString += 'ORG' + encodingPrefix + ':' + e(vCard.organization) + nl(); } } if (vCard.address) { vCard.address.forEach((address) => { if (isPropertyWithParametersAddressValue(address)) { formattedVCardString += 'ADR' + propertyToVCardString(address.param) + getFormattedAddress(address.value) + nl(); } else { formattedVCardString += 'ADR' + getFormattedAddress(address) + nl(); } }); } if (vCard.telephone) { vCard.telephone.forEach((element) => { if (!isPropertyWithParameters(element)) { element = { value: element, param: { type: 'voice', }, }; } formattedVCardString += 'TEL' + propertyToVCardString(element.param) + ':' + e(element.value) + nl(); }); } if (vCard.email) { vCard.email.forEach((email) => { if (isPropertyWithParameters(email)) { formattedVCardString += 'EMAIL' + propertyToVCardString(email.param) + ':' + e(email.value) + nl(); } else { formattedVCardString += 'EMAIL:' + e(email) + nl(); } }); } if (vCard.title) { formattedVCardString += 'TITLE' + encodingPrefix + ':' + e(vCard.title) + nl(); } if (vCard.logo) { if (isPropertyWithParameters(vCard.logo)) { formattedVCardString += 'LOGO' + propertyToVCardString(vCard.logo.param) + ':' + e(vCard.logo.value) + nl(); } else { formattedVCardString += 'LOGO:' + e(vCard.logo) + nl(); } } if (vCard.photo) { if (isPropertyWithParameters(vCard.photo)) { formattedVCardString += 'PHOTO' + propertyToVCardString(vCard.photo.param) + ':' + e(vCard.photo.value) + nl(); } else { formattedVCardString += 'PHOTO:' + e(vCard.photo) + nl(); } } if (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) { 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.role) { formattedVCardString += 'ROLE' + encodingPrefix + ':' + e(vCard.role) + nl(); } if (vCard.url) { let urlNotSet = true; if (hasProp(vCard.url, 'home')) { formattedVCardString += 'URL;type=HOME' + encodingPrefix + ':' + e(vCard.url.home) + nl(); urlNotSet = false; } if (hasProp(vCard.url, 'work')) { formattedVCardString += 'URL;type=WORK' + encodingPrefix + ':' + e(vCard.url.work) + nl(); urlNotSet = false; } if (urlNotSet) { formattedVCardString += 'URL' + encodingPrefix + ':' + e(vCard.url) + nl(); } } if (vCard.note) { formattedVCardString += 'NOTE' + encodingPrefix + ':' + e(vCard.note) + nl(); } if (vCard.socialUrls) { for (const 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) { if (isPropertyWithParameters(vCard.source)) { formattedVCardString += 'SOURCE' + encodingPrefix + propertyToVCardString(vCard.source.param) + ':' + e(vCard.source.value) + +nl(); } else { formattedVCardString += 'SOURCE' + encodingPrefix + ':' + e(vCard.source) + nl(); } } if (vCard.rev) { formattedVCardString += 'REV:' + vCard.rev + nl(); } formattedVCardString += 'END:VCARD' + nl(); return formattedVCardString; } } /** * Get formatted photo * @param photoType Photo type (PHOTO, LOGO) * @param url URL to attach photo from * @param mediaType Media-type of photo (JPEG, PNG, GIF) */ function getFormattedPhoto(photoType, url, mediaType, base64, majorVersion) { let 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;' : ';'; } const formattedPhoto = photoType + params + mediaType + ':' + e(url) + nl(); return formattedPhoto; } /** * Get formatted address */ function getFormattedAddress(address) { return ((address.label ? ';LABEL="' + e(address.label) + '"' : '') + ':' + e(address.postOfficeBox) + ';' + e(address.extendedAddress) + ';' + e(address.street) + ';' + e(address.locality) + ';' + e(address.region) + ';' + e(address.postalCode) + ';' + e(address.countryName)); } /** * Convert date to YYYYMMDD format */ function YYYYMMDD(date) { if (!date) { return ''; } return date.toLocaleDateString('se').replace(/\D/g, ''); // use Swedish date format } /** * Get major version from version string */ function getMajorVersion(version) { const majorVersionString = version ? version.slice(0, 1) : '4'; if (!isNaN(+majorVersionString)) { return Number.parseInt(majorVersionString); } return 4; } /** * Determines if the object has the Property * @param obj Object to test * @param property Property to check */ function hasProp(obj, property) { return Object.prototype.hasOwnProperty.call(obj, property); } const ERROR_MESSAGE = "ngx-vcard: No input specified. You must specify either 'vcdDownloadVCard' or 'generateVCardFunction'"; // TODO: Remove @Directive class DownloadVCardDirective { constructor(element) { this.element = element; this.encoding = VCardEncoding.none; } onclick() { if (this.vCard == '') { if (this.generateVCardFunction != undefined && this.generateVCardFunction != '') { this.vCard = this.generateVCardFunction(); } else { throw new Error(ERROR_MESSAGE); } } const blob = VCardFormatter.getVCardAsBlob(this.vCard, this.encoding); let filename = 'vCard'; if (this.vCard.name != null) { filename = this.vCard.name.firstNames + ' ' + this.vCard.name.lastNames + '.vcf'; } this.download(blob, filename); } download(data, filename) { const a = document.createElement('a'); const url = URL.createObjectURL(data); a.style.display = 'none'; a.href = url; a.download = filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); window.URL.revokeObjectURL(url); } ngOnInit() { if (this.vCard == '' && (this.generateVCardFunction == '' || this.generateVCardFunction == undefined)) { throw new Error(ERROR_MESSAGE); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: DownloadVCardDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.11", type: DownloadVCardDirective, selector: "[vcdDownloadVCard]", inputs: { vCard: ["vcdDownloadVCard", "vCard"], generateVCardFunction: "generateVCardFunction", encoding: "encoding" }, host: { listeners: { "click": "onclick()" } }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: DownloadVCardDirective, decorators: [{ type: Directive, args: [{ selector: '[vcdDownloadVCard]', }] }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { vCard: [{ type: Input, args: ['vcdDownloadVCard'] }], generateVCardFunction: [{ type: Input, args: ['generateVCardFunction'] }], encoding: [{ type: Input }], onclick: [{ type: HostListener, args: ['click'] }] } }); class NgxVcardModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: NgxVcardModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.11", ngImport: i0, type: NgxVcardModule, declarations: [DownloadVCardDirective], exports: [DownloadVCardDirective] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: NgxVcardModule }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.11", ngImport: i0, type: NgxVcardModule, decorators: [{ type: NgModule, args: [{ imports: [], declarations: [DownloadVCardDirective], exports: [DownloadVCardDirective], }] }] }); /* * Public API Surface of ngx-vcard */ /** * Generated bundle index. Do not edit. */ export { DownloadVCardDirective, NgxVcardModule, VCardEncoding, VCardFormatter, getMajorVersion, isPropertyWithParameters, isPropertyWithParametersAddressValue, propertyToVCardString }; //# sourceMappingURL=ngx-vcard.mjs.map