Handy script to generate all mobile assets and favicon related to Progressive Web Applications based on a logo image
NOTE: works best if the logo is square shaped.
// Shortcut: command option p// Menu: P.I.G// version: 1.0.0// Description: 🌆 Generate favicons, assets and splash screens for Progressive Web Apps// Author: Pramod Jingade// Twitter: @avj2352import "@johnlindquist/kit";const Jimp = await npm("jimp");// allowed file extensionsconst allowImageExtensions: string[] = [".png", ".jpg"];// Read source iconlet imagePath: string = await getSelectedFile();if (!imagePath || imagePath === "")imagePath = await selectFile(`Choose icon to generate PWA assets:`);// Check if extension is .PNG or .JPGlet extension: string = path.extname(imagePath);// guard check - extensionwhile (!allowImageExtensions.includes(extension)) {let fileName: string = path.basename(imagePath);imagePath = await selectFile(`${fileName} wasn't an image:`);if (!imagePath) {exit();}// get file extensionextension = path.extname(imagePath);}// Create image list - androidconst createAndroidImageList: Promise<string>[] = [createImage(imagePath, 16, "android"),createImage(imagePath, 32, "android"),createImage(imagePath, 72, "android"),createImage(imagePath, 96, "android"),createImage(imagePath, 128, "android"),createImage(imagePath, 144, "android"),createImage(imagePath, 152, "android"),createImage(imagePath, 192, "android"),createImage(imagePath, 384, "android"),createImage(imagePath, 512, "android"),];// Create image list - windowsconst creaeMicrosoftImageList: Promise<string>[] = [createImage(imagePath, 70, "ms-icon"),createImage(imagePath, 150, "ms-icon"),createImage(imagePath, 310, "ms-icon"),];// Create image list - iOSconst createiOSImageList: Promise<string>[] = [createImage(imagePath, 120, "ios"),createImage(imagePath, 152, "ios"),createImage(imagePath, 167, "ios"),createImage(imagePath, 180, "ios"),createImage(imagePath, 192, "ios"),createImage(imagePath, 512, "ios"),];// Create splash screensconst createSplashScreenList: Promise<string>[] = [createSplashScreenWithLogo(imagePath, 1536, 2048),createSplashScreenWithLogo(imagePath, 2436, 1125),createSplashScreenWithLogo(imagePath, 1620, 2160),createSplashScreenWithLogo(imagePath, 2532, 1170),createSplashScreenWithLogo(imagePath, 1668, 2224),createSplashScreenWithLogo(imagePath, 1668, 2388),createSplashScreenWithLogo(imagePath, 2688, 1242),createSplashScreenWithLogo(imagePath, 2732, 2048),createSplashScreenWithLogo(imagePath, 1125, 2436),createSplashScreenWithLogo(imagePath, 1792, 828),createSplashScreenWithLogo(imagePath, 2778, 1284),createSplashScreenWithLogo(imagePath, 1136, 640),createSplashScreenWithLogo(imagePath, 2046, 1536),createSplashScreenWithLogo(imagePath, 1170, 2532),createSplashScreenWithLogo(imagePath, 2048, 2732),createSplashScreenWithLogo(imagePath, 750, 1334),createSplashScreenWithLogo(imagePath, 1242, 2208),createSplashScreenWithLogo(imagePath, 2160, 1620),createSplashScreenWithLogo(imagePath, 828, 1792),createSplashScreenWithLogo(imagePath, 1242, 2688),createSplashScreenWithLogo(imagePath, 2208, 1242),createSplashScreenWithLogo(imagePath, 1284, 2778),createSplashScreenWithLogo(imagePath, 2224, 1668),createSplashScreenWithLogo(imagePath, 1334, 750),createSplashScreenWithLogo(imagePath, 2388, 1668),];// Create faviconcreateFavicon(imagePath);// Create assetsPromise.all(createAndroidImageList);Promise.all(creaeMicrosoftImageList);Promise.all(createiOSImageList);Promise.all(createSplashScreenList);/*** Reusable function to create image* @param {string} imagePath - complete file path* @param {number} width - width of image*/async function createImage(imagePath: string,width: number,folder: string = "android"): Promise<string> {let image = await Jimp.read(imagePath);const dirName: string = path.parse(imagePath).dir;const newHeight = Math.floor(image.bitmap.height * (width / image.bitmap.width));const resizedImageName = `${folder}-icon-${width}x${width}${extension}`;await image.resize(width, newHeight).write(`${dirName}/${folder}/${resizedImageName}`);return `Created image: ${imagePath}-${width}${extension}`;}/*** Create splash screen with logo in center* @param {string} imagePath - complete file path* @param {number} canvasWidth - width of splash screen* @param {number} canvasHeight - height of splash screen*/async function createSplashScreenWithLogo(imagePath: string,canvasWidth: number,canvasHeight: number,color = "#FFFFFF",folder = "ios"): Promise<string> {const dirName: string = path.parse(imagePath).dir;const resizedImageName = `${folder}-splash-${canvasWidth}x${canvasHeight}${extension}`;let image = await Jimp.read(imagePath);const imageCanvas = new Jimp(canvasWidth, canvasHeight, color);// compositeimageCanvas.composite(image,alignImageCenter(canvasWidth, image.bitmap.width),alignImageCenter(canvasHeight, image.bitmap.height)).write(`${dirName}/${folder}/${resizedImageName}`);return `Created splash screen!`;}/*** util function to offset image to the center of canvas* @param {number} canvasSize* @param {number} imageSize* @returns {number} offset size*/function alignImageCenter(canvasSize: number, imageSize: number): number {return (canvasSize - imageSize) / 2;}/*** Create favicon.ico file at the root of the folder* @param {string} imagePath*/async function createFavicon(imagePath: string) {const dirName: string = path.parse(imagePath).dir;let image = await Jimp.read(imagePath);const resizedImageName = `favicon.ico`;await image.resize(16, 16).write(`${dirName}/${resizedImageName}`);return `Created Favicon!`;}