diff --git a/src/helpers/helpers.js b/src/helpers/helpers.js index 730a1a2..e96f2d7 100644 --- a/src/helpers/helpers.js +++ b/src/helpers/helpers.js @@ -1,5 +1,7 @@ import os from 'os'; import axios from 'axios'; +import hasBinary from 'hasbin'; +import path from 'path'; function isOSX() { return os.platform() === 'darwin'; @@ -15,12 +17,87 @@ function downloadFile(fileUrl) { responseType: 'arraybuffer' }) .then(function(response) { - return response.data; + if (!response.data) { + return null; + } + return { + data: response.data, + ext: path.extname(fileUrl) + }; }); } +function allowedIconFormats(platform) { + const hasIdentify = hasBinary.sync('identify'); + const hasConvert = hasBinary.sync('convert'); + const hasIconUtil = hasBinary.sync('iconutil'); + + const pngToIcns = hasConvert && hasIconUtil; + const pngToIco = hasConvert; + const icoToIcns = pngToIcns && hasIdentify; + const icoToPng = hasConvert; + + // todo scripts for the following + const icnsToPng = false; + const icnsToIco = false; + + const formats = []; + + // todo shell scripting is not supported on windows, temporary override + if (isWindows()) { + switch (platform) { + case 'darwin': + formats.push('.icns'); + break; + case 'linux': + formats.push('.png'); + break; + case 'win32': + formats.push('ico'); + break; + default: + throw `function allowedIconFormats error: Unknown platform ${platform}`; + } + return formats; + } + + switch (platform) { + case 'darwin': + formats.push('.icns'); + if (pngToIcns) { + formats.push('.png'); + } + if (icoToIcns) { + formats.push('.ico'); + } + break; + case 'linux': + formats.push('.png'); + if (icoToPng) { + formats.push('.ico'); + } + if (icnsToPng) { + formats.push('icns'); + } + break; + case 'win32': + formats.push('.ico'); + if (pngToIco) { + formats.push('.png'); + } + if (icnsToIco) { + formats.push('icns'); + } + break; + default: + throw `function allowedIconFormats error: Unknown platform ${platform}`; + } + return formats; +} + export default { isOSX, isWindows, - downloadFile + downloadFile, + allowedIconFormats }; diff --git a/src/infer/inferIcon.js b/src/infer/inferIcon.js index 009566d..9e66f75 100644 --- a/src/infer/inferIcon.js +++ b/src/infer/inferIcon.js @@ -3,27 +3,38 @@ import path from 'path'; import fs from 'fs'; import tmp from 'tmp'; import gitCloud from 'gitcloud'; +import helpers from './../helpers/helpers'; + +const {downloadFile, allowedIconFormats} = helpers; tmp.setGracefulCleanup(); -import helpers from './../helpers/helpers'; -const {downloadFile} = helpers; - function inferIconFromStore(targetUrl, platform) { - if (platform === 'win32') { - return new Promise((resolve, reject) => reject('Skipping icon retrieval from store on windows')); - } + const allowedFormats = allowedIconFormats(platform); return gitCloud('http://jiahaog.com/nativefier-icons/') .then(fileIndex => { - const matchingUrls = fileIndex + const matchingIcons = fileIndex .filter(item => { + // todo might have problems with matching length, e.g. `book` vs `facebook` return targetUrl .toLowerCase() .includes(item.name); }) - .map(item => item.url); + .map(item => { + item.ext = path.extname(item.url); + return item; + }); + + let matchingUrl; + for (let format of allowedFormats) { + for (let icon of matchingIcons) { + if (icon.ext !== format) { + continue; + } + matchingUrl = icon.url; + } + } - const matchingUrl = matchingUrls[0]; if (!matchingUrl) { return null; } @@ -49,11 +60,14 @@ function inferFromPage(targetUrl, platform, outDir) { preferredExt = 'ico'; } + // todo might want to pass list of preferences instead return pageIcon(targetUrl, {ext: preferredExt}) .then(icon => { if (!icon) { - throw 'Icon not found'; + return null; } + + // note that ext from page icon does not contain a '.' const outfilePath = path.join(outDir, `/icon.${icon.ext}`); return writeFilePromise(outfilePath, icon.data); }); @@ -67,18 +81,13 @@ function inferFromPage(targetUrl, platform, outDir) { function inferIconFromUrlToPath(targetUrl, platform, outDir) { return inferIconFromStore(targetUrl, platform) - .then(iconData => { - - if (!iconData) { - throw 'Unable to find icon from store'; + .then(icon => { + if (!icon) { + return inferFromPage(targetUrl, platform, outDir); } - const outfilePath = path.join(outDir, `/icon.png`); - return writeFilePromise(outfilePath, iconData); - }).catch(error => { - console.warn('Unable to find icon on store', error); - console.warn('Falling back to inferring from url'); - return inferFromPage(targetUrl, platform, outDir); + const outfilePath = path.join(outDir, `/icon${icon.ext}`); + return writeFilePromise(outfilePath, icon.data); }); }