Files
ai-tool-pricing-transparenc…/scripts/generate-icons.mjs
T

97 lines
3.0 KiB
JavaScript

// Generate PNG icons for the Chrome extension
import { writeFileSync, mkdirSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import zlib from 'zlib';
const __dirname = dirname(fileURLToPath(import.meta.url));
const iconsDir = join(__dirname, '..', 'src', 'icons');
mkdirSync(iconsDir, { recursive: true });
function crc32(buf) {
var crc = 0xFFFFFFFF;
for (var i = 0; i < buf.length; i++) {
crc ^= buf[i];
for (var j = 0; j < 8; j++) {
crc = (crc >>> 1) ^ (crc & 1 ? 0xEDB88320 : 0);
}
}
return (crc ^ 0xFFFFFFFF) >>> 0;
}
function makeChunk(type, data) {
var len = Buffer.alloc(4);
len.writeUInt32BE(data.length, 0);
var typeBuffer = Buffer.from(type, 'ascii');
var crcData = Buffer.concat([typeBuffer, data]);
var crc = crc32(crcData);
var crcBuf = Buffer.alloc(4);
crcBuf.writeUInt32BE(crc, 0);
return Buffer.concat([len, typeBuffer, data, crcBuf]);
}
function createPNG(width, height) {
var signature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
var ihdrData = Buffer.alloc(13);
ihdrData.writeUInt32BE(width, 0);
ihdrData.writeUInt32BE(height, 4);
ihdrData[8] = 8; ihdrData[9] = 2; ihdrData[10] = 0; ihdrData[11] = 0; ihdrData[12] = 0;
var ihdr = makeChunk('IHDR', ihdrData);
var rawData = [];
var cx = width / 2, cy = height / 2;
var maxDist = Math.sqrt(cx * cx + cy * cy);
var innerR = Math.min(width, height) * 0.35;
var handleR = Math.min(width, height) * 0.08;
for (var y = 0; y < height; y++) {
rawData.push(0); // filter byte
for (var x = 0; x < width; x++) {
var dist = Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
var t = dist / maxDist;
// Background gradient: #667eea to #764ba2
var bgR = Math.round(102 * (1 - t) + 118 * t);
var bgG = Math.round(126 * (1 - t) + 75 * t);
var bgB = Math.round(234 * (1 - t) + 162 * t);
var pr = bgR, pg = bgG, pb = bgB;
// White circle (magnifying glass lens)
if (dist < innerR) {
pr = 255; pg = 255; pb = 255;
// Inner dark ring (lens border)
if (dist > innerR * 0.8) {
pr = 80; pg = 80; pb = 120;
}
}
// Handle (bottom-right diagonal)
var handleStart = innerR * 0.9;
var handleLen = maxDist * 0.5;
var hx = x - cx, hy = y - cy;
var proj = (hx + hy) / Math.sqrt(2);
var perp = Math.abs(hx - hy) / Math.sqrt(2);
if (proj > handleStart && proj < handleStart + handleLen && perp < handleR) {
pr = 200; pg = 200; pb = 220;
}
rawData.push(pr, pg, pb);
}
}
var deflated = zlib.deflateSync(Buffer.from(rawData));
var idat = makeChunk('IDAT', deflated);
var iend = makeChunk('IEND', Buffer.alloc(0));
return Buffer.concat([signature, ihdr, idat, iend]);
}
var sizes = [16, 48, 128];
sizes.forEach(function (size) {
var png = createPNG(size, size);
var filepath = join(iconsDir, 'icon-' + size + '.png');
writeFileSync(filepath, png);
console.log('Created ' + filepath + ' (' + png.length + ' bytes)');
});
console.log('Icons generated.');