import * as potrace from 'potrace'; import * as cheerio from 'cheerio'; import axios from 'axios'; import Vibrant = require('node-vibrant') type GenerateLogoOutput = { coloredLogoSVG: string, transparentLogoSVG: string, color: string, clearbitLogoURL: string, } const generateLogo = (url?: string, color?: string, invert:boolean = false, clearbitLogoId?: string): Promise => new Promise(async (resolve, reject) => { let params: object = { color: 'white', }; if (!url && !clearbitLogoId) return reject('[Logo Generator] Error: No URL or clearbitLogoId found'); let logoURL = url; let clearbitLogoURL : string = null; if (!url && clearbitLogoId) { clearbitLogoURL = `https://logo.clearbit.com/${clearbitLogoId}?s=800`; await axios.get(clearbitLogoURL) .then(() => { logoURL = clearbitLogoURL; }) .catch(() => { return reject(`[Logo Generator] Error with Clearbit URL (clearbitLogoId: ${clearbitLogoId})`); }); } if (!color) { await Vibrant.from(logoURL).getPalette((error, palette) => { if (error) return reject(`[Logo Generator] Error with Vibrant: ${error}`); if (palette.Vibrant) { color = palette.Vibrant.getHex(); } }); } if (invert) { params = { blackOnWhite: false, color: 'white' }; } potrace.trace(logoURL, params, function (err, svg) { if (err) return reject(`[Logo Generator] Error with potrace: ${err}`); resolve({ coloredLogoSVG: createSVG(svg, color, SVGVersion.Colored), transparentLogoSVG: createSVG(svg, color, SVGVersion.Transparent), color, clearbitLogoURL, }) }); }); export default generateLogo; const iconSize = 60; const template = (color: string, icon: string, size: number = iconSize) => ` ${icon} `; enum SVGVersion { Colored, // icon-provider Transparent // provider-svg } function createSVG(svg: string, color: string, version: SVGVersion = SVGVersion.Colored): string { const $ = cheerio.load(svg); const svgWidthStr = $('svg').attr('width'); const svgWidth = typeof svgWidthStr == 'number' ? svgWidthStr : parseInt(svgWidthStr, 10); const svgHeightStr = $('svg').attr('height'); const svgHeight = typeof svgHeightStr == 'number' ? svgHeightStr : parseInt(svgHeightStr, 10); const minSize = Math.min(svgWidth, svgHeight); $('path').attr('transform', `scale(${(50 / 2) / minSize}) translate(${(minSize - svgWidth) / 2} ${(minSize - svgHeight) / 2})`); let path = $('svg').html().trim(); if (version == SVGVersion.Colored) { return template(color, path, 50).trim(); } else { $('path').attr('transform', `scale(${(iconSize / 2) / minSize}) translate(${(minSize - svgWidth) / 2} ${(minSize - svgHeight) / 2})`); path = $('svg').html().trim(); return template('transparent', path,).trim(); } }