import React, { PureComponent } from 'react' import { StaticQuery, graphql } from 'gatsby' import saveAs from 'file-saver' import vCard from 'vcf' const query = graphql` query { contentYaml { title tagline description url email avatar { childImageSharp { original: resize { src } } } social { Email Blog Twitter GitHub Dribbble } gpg addressbook } } ` export default class Vcard extends PureComponent { render() { return ( { const meta = data.contentYaml const handleAddressbookClick = e => { e.preventDefault() constructVcard(meta) } return ( Add to addressbook ) }} /> ) } } // Construct the download from a blob of the just constructed vCard, // and save it to user's file system const downloadVcard = (vcard, meta) => { const name = meta.addressbook.split('/').join('') const blob = new Blob([vcard], { type: 'text/x-vcard' }) saveAs(blob, name) } const constructVcard = meta => { const contact = new vCard() const photoSrc = meta.avatar.childImageSharp.original.src // first, convert the avatar to base64, then construct all vCard elements toDataURL( photoSrc, dataUrl => { // stripping this data out of base64 string is required // for vcard to actually display the image for whatever reason const dataUrlCleaned = dataUrl.split('data:image/jpeg;base64,').join('') contact.set('photo', dataUrlCleaned, { encoding: 'b', type: 'JPEG' }) contact.set('fn', meta.title) contact.set('title', meta.tagline) contact.set('email', meta.email) contact.set('url', meta.url, { type: 'Portfolio' }) contact.add('url', meta.social.Blog, { type: 'Blog' }) contact.set('nickname', 'kremalicious') contact.add('x-socialprofile', meta.social.Twitter, { type: 'twitter' }) contact.add('x-socialprofile', meta.social.GitHub, { type: 'GitHub' }) const vcard = contact.toString('3.0') downloadVcard(vcard, meta) }, 'image/jpeg' ) } // Helper function to create base64 string from avatar image // without the need to read image file from file system const toDataURL = (src, callback, outputFormat) => { const img = new Image() img.crossOrigin = 'Anonymous' img.onload = function() { // yeah, we're gonna create a fake canvas to render the image // and then create a base64 string from the rendered result const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') let dataURL canvas.height = this.naturalHeight canvas.width = this.naturalWidth ctx.drawImage(this, 0, 0) dataURL = canvas.toDataURL(outputFormat) callback(dataURL) } img.src = src if (img.complete || img.complete === undefined) { img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==' img.src = src } }