mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-07-09 00:30:49 +00:00
134 lines
4.0 KiB
JavaScript
134 lines
4.0 KiB
JavaScript
import sharp from "sharp";
|
|
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
import { join, dirname } from "path";
|
|
import { fileURLToPath } from "url";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const root = join(__dirname, "..");
|
|
const publicDir = join(root, "public");
|
|
const iconsDir = join(publicDir, "icons");
|
|
|
|
mkdirSync(iconsDir, { recursive: true });
|
|
|
|
const svgBuffer = readFileSync(join(publicDir, "icon.svg"));
|
|
|
|
const pngSizes = [16, 24, 32, 48, 64, 128, 256, 512, 1024];
|
|
|
|
console.log("Generating PNG icons...");
|
|
await Promise.all(
|
|
pngSizes.map((size) =>
|
|
sharp(svgBuffer)
|
|
.resize(size, size)
|
|
.png()
|
|
.toFile(join(iconsDir, `${size}x${size}.png`))
|
|
.then(() => console.log(` ✓ icons/${size}x${size}.png`)),
|
|
),
|
|
);
|
|
|
|
// icon.png (1024x1024) for Linux electron-builder
|
|
await sharp(svgBuffer)
|
|
.resize(1024, 1024)
|
|
.png()
|
|
.toFile(join(publicDir, "icon.png"));
|
|
console.log(" ✓ icon.png");
|
|
|
|
// icon-mac.png (512x512) for macOS
|
|
await sharp(svgBuffer)
|
|
.resize(512, 512)
|
|
.png()
|
|
.toFile(join(publicDir, "icon-mac.png"));
|
|
console.log(" ✓ icon-mac.png");
|
|
|
|
// full-icon.png (1024x1024) used in app UI
|
|
await sharp(svgBuffer)
|
|
.resize(1024, 1024)
|
|
.png()
|
|
.toFile(join(publicDir, "full-icon.png"));
|
|
console.log(" ✓ full-icon.png");
|
|
|
|
// favicon.ico — embed 16, 32, 48 px layers
|
|
console.log("Generating favicon.ico...");
|
|
const icoSizes = [16, 32, 48];
|
|
const icoBuffers = await Promise.all(
|
|
icoSizes.map((size) => sharp(svgBuffer).resize(size, size).png().toBuffer()),
|
|
);
|
|
writeFileSync(join(publicDir, "favicon.ico"), buildIco(icoBuffers, icoSizes));
|
|
console.log(" ✓ favicon.ico");
|
|
|
|
// icon.ico — embed 16, 32, 48, 64, 128, 256 px layers
|
|
console.log("Generating icon.ico...");
|
|
const winSizes = [16, 32, 48, 64, 128, 256];
|
|
const winBuffers = await Promise.all(
|
|
winSizes.map((size) => sharp(svgBuffer).resize(size, size).png().toBuffer()),
|
|
);
|
|
writeFileSync(join(publicDir, "icon.ico"), buildIco(winBuffers, winSizes));
|
|
console.log(" ✓ icon.ico");
|
|
|
|
// icons/icon.ico and icons/icon.icns placeholders (stubs pointing to source)
|
|
// electron-builder generates .icns; copy the 1024 PNG as icons/icon.png for reference
|
|
await sharp(svgBuffer)
|
|
.resize(1024, 1024)
|
|
.png()
|
|
.toFile(join(iconsDir, "icon.ico").replace("icon.ico", "1024x1024.png"));
|
|
// Copy icon.ico and icon.icns into icons/ as well
|
|
import { copyFileSync } from "fs";
|
|
copyFileSync(join(publicDir, "icon.ico"), join(iconsDir, "icon.ico"));
|
|
console.log(" ✓ icons/icon.ico");
|
|
|
|
console.log(
|
|
"\nDone! Note: icon.icns requires macOS tools (iconutil). Use electron-builder on macOS to generate it.",
|
|
);
|
|
|
|
/**
|
|
* Builds a minimal ICO file from PNG buffers.
|
|
* @param {Buffer[]} pngBuffers
|
|
* @param {number[]} sizes
|
|
* @returns {Buffer}
|
|
*/
|
|
function buildIco(pngBuffers, sizes) {
|
|
const count = pngBuffers.length;
|
|
const headerSize = 6;
|
|
const dirEntrySize = 16;
|
|
const dirSize = headerSize + count * dirEntrySize;
|
|
|
|
let offset = dirSize;
|
|
const entries = pngBuffers.map((buf, i) => {
|
|
const size = sizes[i];
|
|
const entry = {
|
|
size,
|
|
width: size > 255 ? 0 : size,
|
|
height: size > 255 ? 0 : size,
|
|
buf,
|
|
offset,
|
|
};
|
|
offset += buf.length;
|
|
return entry;
|
|
});
|
|
|
|
const totalSize = offset;
|
|
const ico = Buffer.alloc(totalSize);
|
|
|
|
// ICO header
|
|
ico.writeUInt16LE(0, 0); // reserved
|
|
ico.writeUInt16LE(1, 2); // type: 1 = ICO
|
|
ico.writeUInt16LE(count, 4); // image count
|
|
|
|
// Directory entries
|
|
entries.forEach((e, i) => {
|
|
const base = headerSize + i * dirEntrySize;
|
|
ico.writeUInt8(e.width, base); // width (0 = 256)
|
|
ico.writeUInt8(e.height, base + 1); // height (0 = 256)
|
|
ico.writeUInt8(0, base + 2); // color count
|
|
ico.writeUInt8(0, base + 3); // reserved
|
|
ico.writeUInt16LE(1, base + 4); // planes
|
|
ico.writeUInt16LE(32, base + 6); // bit count
|
|
ico.writeUInt32LE(e.buf.length, base + 8); // size of image data
|
|
ico.writeUInt32LE(e.offset, base + 12); // offset of image data
|
|
});
|
|
|
|
// Image data
|
|
entries.forEach((e) => e.buf.copy(ico, e.offset));
|
|
|
|
return ico;
|
|
}
|