diff --git a/.prettierignore b/.prettierignore index 99cfd3f..2667b90 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,4 @@ node_modules/ .cache/ -src/lib/vcf static/ public/ diff --git a/src/components/atoms/Vcard.jsx b/src/components/atoms/Vcard.jsx index 85bddc8..5d2085c 100644 --- a/src/components/atoms/Vcard.jsx +++ b/src/components/atoms/Vcard.jsx @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import FileSaver from 'file-saver' -import vCard from '../../lib/vcf/vcard' +import vCard from 'vcf' class Vcard extends PureComponent { constructor(props) { diff --git a/src/lib/vcf/parse-lines.js b/src/lib/vcf/parse-lines.js deleted file mode 100644 index 9d674e5..0000000 --- a/src/lib/vcf/parse-lines.js +++ /dev/null @@ -1,71 +0,0 @@ -var camelCase = require('camel-case') // that's the only change -var Property = require('./property') - -function set(object, key, value) { - if (Array.isArray(object[key])) { - object[key].push(value) - } else if (object[key] != null) { - object[key] = [object[key], value] - } else { - object[key] = value - } -} - -function createParams(params, param) { - var parts = param.split('=') - var k = camelCase(parts[0]) - var value = parts[1] - - if (value == null || value === '') { - value = parts[0] - k = 'type' - } - - if (k === 'type') { - value - .toLowerCase() - .split(',') - .forEach(function(value) { - set(params, k, value) - }) - - return params - } - - set(params, k, value) - - return params -} - -function parseLines(lines) { - var data = {} - - // NOTE: Line format: - // PROPERTY[;PARAMETER[=VALUE]]:Attribute[;Attribute] - var line = null - var pattern = /^([^;:]+)((?:;(?:[^;:]+))*)(?:\:(.+))?$/i // eslint-disable-line no-useless-escape - var len = lines.length - 1 - - for (var i = 1; i < len; i++) { - line = lines[i] - - var match = pattern.exec(line) - if (!match) continue - - var name = match[1].split('.') - var property = name.pop() - var group = name.pop() - var value = match[3] - var params = match[2] ? match[2].replace(/^;|;$/g, '').split(';') : [] - - var propParams = params.reduce(createParams, group ? { group: group } : {}) - var propName = camelCase(property) - var propVal = new Property(propName, value, propParams) - - set(data, propName, propVal) - } - - return data -} - -module.exports = parseLines diff --git a/src/lib/vcf/property.js b/src/lib/vcf/property.js deleted file mode 100644 index 81f38df..0000000 --- a/src/lib/vcf/property.js +++ /dev/null @@ -1,146 +0,0 @@ -/* eslint-disable no-unused-vars */ - -/** - * vCard Property - * @constructor - * @memberOf vCard - * @param {String} field - * @param {String} value - * @param {Object} params - * @return {Property} - */ -function Property(field, value, params) { - if (!(this instanceof Property)) return new Property(value) - - if (params != null) Object.assign(this, params) - - this._field = field - this._data = value - - Object.defineProperty(this, '_field', { enumerable: false }) - Object.defineProperty(this, '_data', { enumerable: false }) -} - -/** - * Constructs a vCard.Property from jCard data - * @param {Array} data - * @return {Property} - */ -Property.fromJSON = function(data) { - var field = data[0] - var params = data[1] - - if (!/text/i.test(data[2])) params.value = data[2] - - var value = Array.isArray(data[3]) ? data[3].join(';') : data[3] - - return new Property(field, value, params) -} - -/** - * Turn a string into capitalized dash-case - * @internal used by `Property#toString()` - * @param {String} value - * @return {String} - * @ignore - */ -function capitalDashCase(value) { - return value.replace(/([A-Z])/g, '-$1').toUpperCase() -} - -/** - * Property prototype - * @type {Object} - */ -Property.prototype = { - constructor: Property, - - /** - * Check whether the property is of a given type - * @param {String} type - * @return {Boolean} - */ - is: function(type) { - type = (type + '').toLowerCase() - return Array.isArray(this.type) - ? this.type.indexOf(type) - : this.type === type - }, - - /** - * Check whether the property is empty - * @return {Boolean} - */ - isEmpty: function() { - return this._data == null && Object.keys(this).length === 0 - }, - - /** - * Clone the property - * @return {Property} - */ - clone: function() { - return new Property(this._field, this._data, this) - }, - - /** - * Format the property as vcf with given version - * @param {String} version - * @return {String} - */ - toString: function(version) { - var propName = - (this.group ? this.group + '.' : '') + capitalDashCase(this._field) - var keys = Object.keys(this) - var params = [] - - for (var i = 0; i < keys.length; i++) { - if (keys[i] === 'group') continue - params.push(capitalDashCase(keys[i]) + '=' + this[keys[i]]) - } - - return ( - propName + - (params.length ? ';' + params.join(';') : params) + - ':' + - (Array.isArray(this._data) ? this._data.join(';') : this._data) - ) - }, - - /** - * Get the property's value - * @return {String} - */ - valueOf: function() { - return this._data - }, - - /** - * Format the property as jCard data - * @return {Array} - */ - toJSON: function() { - var params = Object.assign({}, this) - - if (params.value === 'text') { - params.value = void 0 - delete params.value - } - - var data = [this._field, params, this.value || 'text'] - - switch (this._field) { - default: - data.push(this._data) - break - case 'adr': - case 'n': - data.push(this._data.split(';')) - } - - return data - } -} - -// Exports -module.exports = Property diff --git a/src/lib/vcf/vcard.js b/src/lib/vcf/vcard.js deleted file mode 100644 index 8eadb08..0000000 --- a/src/lib/vcf/vcard.js +++ /dev/null @@ -1,322 +0,0 @@ -/* eslint-disable no-unused-vars */ - -/** - * vCard - * @constructor - * @return {vCard} - */ -function vCard() { - if (!(this instanceof vCard)) return new vCard() - - /** @type {String} Version number */ - this.version = vCard.versions[vCard.versions.length - 1] - /** @type {Object} Card data */ - this.data = {} -} - -/** - * vCard MIME type - * @type {String} - */ -vCard.mimeType = 'text/vcard' - -/** - * vCard file extension - * @type {String} - */ -vCard.extension = '.vcf' - -/** - * vCard versions - * @type {Array} - */ -vCard.versions = ['2.1', '3.0', '4.0'] - -/** - * Folds a long line according to the RFC 5322. - * @see http://tools.ietf.org/html/rfc5322#section-2.1.1 - * @param {String} input - * @param {Number} maxLength - * @param {Boolean} hardWrap - * @return {String} - */ -vCard.foldLine = require('foldline') - -/** - * Normalizes input (cast to string, line folding, whitespace) - * @param {String} input - * @return {String} - */ -vCard.normalize = function(input) { - return ( - (input + '') - // Trim whitespace - .replace(/^[\s\r\n]+|[\s\r\n]+$/g, '') - // Trim blank lines - .replace(/(\r?\n)\s*(\r?\n)|$/g, '$1') - // Unfold folded lines - .replace(/\r?\n[\x20\x09]+/g, '') // eslint-disable-line no-control-regex - ) -} - -/** - * Check whether a given version is supported - * @param {String} version - * @return {Boolean} - */ -vCard.isSupported = function(version) { - return /^\d\.\d$/.test(version) && vCard.versions.indexOf(version) !== -1 -} - -/** - * Parses a string or buffer into a vCard object - * @param {String|Buffer} value - * @return {Array} - */ -vCard.parse = function(value) { - var objects = (value + '').split(/(?=BEGIN\:VCARD)/gi) // eslint-disable-line no-useless-escape - var cards = [] - - for (var i = 0; i < objects.length; i++) { - cards.push(new vCard().parse(objects[i])) - } - - return cards -} - -/** - * Parse an array of vcf formatted lines - * @internal used by `vCard#parse()` - * @type {Function} - */ -vCard.parseLines = require('./parse-lines') - -/** - * Constructs a vCard from jCard data - * @param {Array} jcard - * @return {vCard} - */ -vCard.fromJSON = function(jcard) { - jcard = typeof jcard === 'string' ? JSON.parse(jcard) : jcard - - if (jcard == null || !Array.isArray(jcard)) return new vCard() - - if (!/vcard/i.test(jcard[0])) throw new Error('Object not in jCard format') - - var card = new vCard() - - jcard[1].forEach(function(prop) { - card.addProperty(vCard.Property.fromJSON(prop)) - }) - - return card -} - -/** - * Format a card object according to the given version - * @param {vCard} card - * @param {String} version - * @return {String} - */ -vCard.format = function(card, version) { - version = version || card.version || vCard.versions[vCard.versions.length - 1] - - if (!vCard.isSupported(version)) - throw new Error('Unsupported vCard version "' + version + '"') - - var vcf = [] - - vcf.push('BEGIN:VCARD') - vcf.push('VERSION:' + version) - - var props = Object.keys(card.data) - var prop = '' - - for (var i = 0; i < props.length; i++) { - if (props[i] === 'version') continue - prop = card.data[props[i]] - if (Array.isArray(prop)) { - for (var k = 0; k < prop.length; k++) { - if (prop[k].isEmpty()) continue - vcf.push(vCard.foldLine(prop[k].toString(version), 75)) - } - } else if (!prop.isEmpty()) { - vcf.push(vCard.foldLine(prop.toString(version), 75)) - } - } - - vcf.push('END:VCARD') - - return vcf.join('\n') -} - -// vCard Property constructor -vCard.Property = require('./property') - -/** - * vCard prototype - * @type {Object} - */ -vCard.prototype = { - constructor: vCard, - - /** - * Get a vCard property - * @param {String} key - * @return {Object|Array} - */ - get: function(key) { - if (this.data[key] == null) { - return this.data[key] - } - - if (Array.isArray(this.data[key])) { - return this.data[key].map(function(prop) { - return prop.clone() - }) - } else { - return this.data[key].clone() - } - }, - - /** - * Set a vCard property - * @param {String} key - * @param {String} value - * @param {Object} params - */ - set: function(key, value, params) { - return this.setProperty(new vCard.Property(key, value, params)) - }, - - /** - * Add a vCard property - * @param {String} key - * @param {String} value - * @param {Object} params - */ - add: function(key, value, params) { - var prop = new vCard.Property(key, value, params) - this.addProperty(prop) - return this - }, - - /** - * Set a vCard property from an already - * constructed vCard.Property - * @param {vCard.Property} prop - */ - setProperty: function(prop) { - this.data[prop._field] = prop - return this - }, - - /** - * Add a vCard property from an already - * constructed vCard.Property - * @param {vCard.Property} prop - */ - addProperty: function(prop) { - var key = prop._field - - if (Array.isArray(this.data[key])) { - this.data[key].push(prop) - } else if (this.data[key] != null) { - this.data[key] = [this.data[key], prop] - } else { - this.data[key] = prop - } - - return this - }, - - /** - * Parse a vcf formatted vCard - * @param {String} value - * @return {vCard} - */ - parse: function(value) { - // Normalize & split - var lines = vCard.normalize(value).split(/\r?\n/g) - - // Keep begin and end markers - // for eventual error messages - var begin = lines[0] - var version = lines[1] - var end = lines[lines.length - 1] - - if (!/BEGIN:VCARD/i.test(begin)) - throw new SyntaxError( - 'Invalid vCard: Expected "BEGIN:VCARD" but found "' + begin + '"' - ) - - if (!/END:VCARD/i.test(end)) - throw new SyntaxError( - 'Invalid vCard: Expected "END:VCARD" but found "' + end + '"' - ) - - // TODO: For version 2.1, the VERSION can be anywhere between BEGIN & END - if (!/VERSION:\d\.\d/i.test(version)) - throw new SyntaxError( - 'Invalid vCard: Expected "VERSION:\\d.\\d" but found "' + version + '"' - ) - - this.version = version.substring(8, 11) - - if (!vCard.isSupported(this.version)) - throw new Error('Unsupported version "' + this.version + '"') - - this.data = vCard.parseLines(lines) - - return this - }, - - /** - * Format the vCard as vcf with given version - * @param {String} version - * @param {String} charset - * @return {String} - */ - toString: function(version, charset) { - version = version || this.version - return vCard.format(this, version) - }, - - /** - * Format the card as jCard - * @param {String} version='4.0' - * @return {Array} jCard - */ - toJCard: function(version) { - version = version || '4.0' - - var keys = Object.keys(this.data) - var data = [['version', {}, 'text', version]] - var prop = null - - for (var i = 0; i < keys.length; i++) { - if (keys[i] === 'version') continue - prop = this.data[keys[i]] - if (Array.isArray(prop)) { - for (var k = 0; k < prop.length; k++) { - data.push(prop[k].toJSON()) - } - } else { - data.push(prop.toJSON()) - } - } - - return ['vcard', data] - }, - - /** - * Format the card as jCard - * @return {Array} jCard - */ - toJSON: function() { - return this.toJCard(this.version) - } -} - -// Exports -module.exports = vCard