Refine ISAC selection controls and icons
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import sharp from 'sharp';
|
||||
import { readdir, rename, unlink } from 'node:fs/promises';
|
||||
import { join, resolve } from 'node:path';
|
||||
|
||||
const iconDirectory = resolve('./static');
|
||||
const iconFiles = (await readdir(iconDirectory))
|
||||
.filter((file) => file.toLocaleLowerCase().endsWith('.png'))
|
||||
.sort((left, right) => left.localeCompare(right));
|
||||
|
||||
for (const file of iconFiles) {
|
||||
const source = join(iconDirectory, file);
|
||||
const temporary = join(iconDirectory, `.${file}.trimmed`);
|
||||
const before = await sharp(source).metadata();
|
||||
|
||||
try {
|
||||
const result = await sharp(source)
|
||||
.trim({ background: { r: 0, g: 0, b: 0, alpha: 0 } })
|
||||
.extend({
|
||||
top: 2,
|
||||
right: 2,
|
||||
bottom: 2,
|
||||
left: 2,
|
||||
background: { r: 0, g: 0, b: 0, alpha: 0 }
|
||||
})
|
||||
.png({ compressionLevel: 9, adaptiveFiltering: true })
|
||||
.toFile(temporary);
|
||||
|
||||
if (!result.width || !result.height || result.channels !== 4) {
|
||||
throw new Error(`${file} did not produce a valid transparent RGBA icon.`);
|
||||
}
|
||||
|
||||
await rename(temporary, source);
|
||||
console.log(`${file}: ${before.width}x${before.height} -> ${result.width}x${result.height}`);
|
||||
} catch (error) {
|
||||
await unlink(temporary).catch(() => {});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Trimmed ${iconFiles.length} static PNG icons with a 2px transparent safety margin.`);
|
||||
Reference in New Issue
Block a user