UNPKG

@appsemble/node-utils

Version:

NodeJS utilities used by Appsemble internally.

74 lines 2.83 kB
import sharp from 'sharp'; import { readAsset } from './readAsset.js'; /** * A transparent background color used by sharp. */ const transparent = { r: 0, g: 0, b: 0, alpha: 0 }; /** * The diameter of the safe area for maskable icons. * * https://css-tricks.com/maskable-icons-android-maskable-icons-for-your-pwa/ */ const safeAreaDiameter = 0.8; export async function serveIcon(ctx, { background, cache, fallback, height, icon, maskable, maskableIcon, raw, width, }) { const buffer = (maskable && maskableIcon) || icon || (await readAsset(fallback)); let img = sharp(buffer); if (raw) { const { format } = await img.metadata(); ctx.body = buffer; // @ts-expect-error 2322 null is not assignable to type (strictNullChecks) ctx.type = format; return; } if (!maskable) { // Serve the regular app icon, but scaled. img.resize({ width, height, fit: 'contain', background: background || transparent, }); if (background) { img.flatten({ background }); } } else if (maskableIcon) { img.resize({ width, height, fit: 'cover' }); if (background) { img.flatten({ background }); } } else { // Make the regular icon maskable const actual = img; const metadata = await actual.metadata(); // @ts-expect-error 18048 variable is possibly undefined (strictNullChecks) const angle = Math.atan(metadata.height / metadata.width); actual.resize({ // @ts-expect-error 18048 variable is possibly undefined (strictNullChecks) width: Math.ceil(Math.cos(angle) * safeAreaDiameter * width), // By leaving out height, libvips will determine this for us. This has better precision than // calculating this using JavasScript and passing it manually. // height: Math.ceil(Math.sin(angle) * safeAreaDiameter * size), fit: 'contain', background, }); // @ts-expect-error 18048 variable is possibly undefined (strictNullChecks) img = sharp(Buffer.alloc(width * height * 4, 0), { // @ts-expect-error 2322 null is not assignable to type (strictNullChecks) raw: { width, height, channels: 4 }, }); img.resize({ width, height }); img.composite([{ input: await actual.toFormat('png').toBuffer() }]); if (background) { img.flatten({ background }); } // Cache app icons for 1 week. if (cache) { ctx.set('cache-control', `public, max-age=${60 * 60 * 24 * 7},immutable`); } } ctx.body = await img.toFormat('png').toBuffer(); ctx.type = 'image/png'; } //# sourceMappingURL=icon.js.map