generator-rn-toolbox-gv
Version:
React-Native generators to kickstart your project
233 lines (207 loc) • 6.46 kB
JavaScript
const gm = require('gm').subClass({ imageMagick: true });
const fs = require('fs-extra');
const path = require('path');
const Promise = require('bluebird');
require('colors');
Promise.promisifyAll(gm.prototype);
/* eslint-disable no-multi-spaces */
const iosIconSizes = [
{ size: 20, multipliers: [1, 2, 3] },
{ size: 29, multipliers: [1, 2, 3] },
{ size: 40, multipliers: [1, 2, 3] },
{ size: 50, multipliers: [1, 2] },
{ size: 57, multipliers: [1, 2] },
{ size: 60, multipliers: [2, 3] },
{ size: 72, multipliers: [1, 2] },
{ size: 76, multipliers: [1, 2] },
{ size: 83.5, multipliers: [2] },
{ size: 1024, multipliers: [1] },
];
const androidIconSizes = [
{ value: 36, density: 'ldpi' },
{ value: 48, density: 'mdpi' },
{ value: 72, density: 'hdpi' },
{ value: 96, density: 'xhdpi' },
{ value: 144, density: 'xxhdpi' },
{ value: 192, density: 'xxxhdpi' },
];
const androidSplashSizes = [
{ width: 320, height: 240, density: 'land-ldpi' },
{ width: 480, height: 320, density: 'land-mdpi' },
{ width: 800, height: 480, density: 'land-hdpi' },
{ width: 1280, height: 720, density: 'land-xhdpi' },
{ width: 1600, height: 960, density: 'land-xxhdpi' },
{ width: 1920, height: 1280, density: 'land-xxxhdpi' },
{ width: 240, height: 320, density: 'port-ldpi' },
{ width: 320, height: 480, density: 'port-mdpi' },
{ width: 480, height: 800, density: 'port-hdpi' },
{ width: 720, height: 1280, density: 'port-xhdpi' },
{ width: 960, height: 1600, density: 'port-xxhdpi' },
{ width: 1280, height: 1920, density: 'port-xxxhdpi' },
];
// See http://iconhandbook.co.uk/reference/chart/android/
const androidNotificationIconSizes = [
{ value: 24, density: 'ldpi' },
{ value: 24, density: 'mdpi' },
{ value: 36, density: 'hdpi' },
{ value: 48, density: 'xhdpi' },
{ value: 72, density: 'xxhdpi' },
{ value: 96, density: 'xxxhdpi' },
];
const iosSplashSizes = [
{ name: 'Default-Portrait-812h@3x', width: 1125, height: 2436 },
{ name: 'Default-Landscape-812h@3x', width: 2436, height: 1125 },
{ name: 'Default-568h@2x', width: 640, height: 1136 },
{ name: 'Default-667h@2x', width: 750, height: 1334 },
{ name: 'Default-Portrait-736h@3x', width: 1242, height: 2208 },
{ name: 'Default-Landscape-736h@3x', width: 2208, height: 1242 },
{ name: 'Default-Landscape@2x', width: 2048, height: 1536 },
{ name: 'Default-Landscape', width: 1024, height: 768 },
{ name: 'Default-Portrait@2x', width: 1536, height: 2048 },
{ name: 'Default-Portrait', width: 768, height: 1024 },
{ name: 'Default@2x', width: 640, height: 960 },
];
const itunesIconSize = { name: 'itunes-icon.png', value: 1024 };
const playStoreIconSize = { name: 'play-store-icon.png', value: 512 };
const playStoreImageSize = {
name: 'play-store-image.png',
width: 1024,
height: 500,
};
/* eslint-enable no-multi-spaces */
const getResizedImageGraphic = (sourcePath, width, height) => {
const maxSize = Math.max(width, height);
return gm(path.normalize(sourcePath))
.resize(maxSize, maxSize)
.gravity('center')
.crop(
width,
height,
height > width ? (height - width) / 2 : 0,
width > height ? (width - height) / 2 : 0
);
};
const checkImageIsSquare = sourcePath =>
gm(path.normalize(sourcePath))
.sizeAsync()
.then(size => {
if (size.width !== size.height) {
console.log('Please use a square image'.red);
process.exit(1);
}
});
const generateResizedAssets = (
sourcePath,
destinationPath,
width,
givenHeight
) => {
const height = givenHeight || width;
const directory = path.dirname(destinationPath);
if (!fs.existsSync(directory)) {
fs.mkdirpSync(directory);
}
const psdSafeSourcePath = `${sourcePath}${
sourcePath.split('.').pop() === 'psd' ? '[0]' : ''
}`;
return checkImageIsSquare(psdSafeSourcePath).then(() =>
getResizedImageGraphic(psdSafeSourcePath, width, height)
.writeAsync(path.normalize(destinationPath))
.then(() => console.log(`Wrote ${destinationPath}`))
);
};
const generateIosIcons = (iconSource, iosIconFolder) =>
Promise.all(
iosIconSizes.map(size =>
Promise.all(
size.multipliers.map(multiplier =>
generateResizedAssets(
iconSource,
`${iosIconFolder}/icon-${size.size}@${multiplier}x.png`,
size.size * multiplier
)
)
)
)
);
const generateAndroidIcons = (
iconSource,
assetsOutputPath,
androidSrcDirectory
) =>
Promise.all(
androidIconSizes.map(size =>
generateResizedAssets(
iconSource,
`${assetsOutputPath}/android/app/src/${androidSrcDirectory}/res/mipmap-${
size.density
}/ic_launcher.png`,
size.value
)
)
);
const generateIosSplashScreen = (splashSource, iosSplashFolder) =>
Promise.all(
iosSplashSizes.map(size =>
generateResizedAssets(
splashSource,
`${iosSplashFolder}/${size.name}.png`,
size.width,
size.height
)
)
);
const generateAndroidSplashScreen = (
splashSource,
assetsOutputPath,
androidSrcDirectory
) =>
androidSplashSizes.map(size =>
generateResizedAssets(
splashSource,
`${assetsOutputPath}/android/app/src/${androidSrcDirectory}/res/drawable-${
size.density
}/launch_screen.png`,
size.width,
size.height
)
);
const generateAndroidNotificationIcons = (
iconSource,
assetsOutputPath,
androidSrcDirectory
) =>
androidNotificationIconSizes.map(size =>
generateResizedAssets(
iconSource,
`${assetsOutputPath}/android/app/src/${androidSrcDirectory}/res/mipmap-${
size.density
}/ic_notification.png`,
size.value
)
);
const generatePlayStoreIcon = iconSource =>
generateResizedAssets(
iconSource,
playStoreIconSize.name,
playStoreIconSize.value
);
const generateItunesIcon = iconSource =>
generateResizedAssets(iconSource, itunesIconSize.name, itunesIconSize.value);
const generatePlayStoreImage = iconSource =>
generateResizedAssets(
iconSource,
playStoreImageSize.name,
playStoreImageSize.width,
playStoreImageSize.height
);
module.exports = {
generateIosSplashScreen,
generateAndroidIcons,
generateIosIcons,
generateAndroidSplashScreen,
generateAndroidNotificationIcons,
generatePlayStoreIcon,
generateItunesIcon,
generatePlayStoreImage,
};