InvoiceChaser v1.0.0 — Freelancer Payment Tracker & Auto Follow-Up Chrome Extension
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
// Generate simple 1-color PNG icons using raw buffer construction
|
||||
// PNG signature + IHDR + IDAT + IEND for a solid-color square
|
||||
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
function createSolidPng(size: number, r: number, g: number, b: number): Buffer {
|
||||
// Simple zlib compression for raw RGBA data
|
||||
// This is a minimal approach; for solid colors we can construct a valid PNG
|
||||
// Using a pre-built minimal solid color PNG template would be easier
|
||||
// Let's use a small helper that creates a valid PNG via canvas-like approach
|
||||
// Actually, let's just write a simple PNG with the minimal required chunks
|
||||
|
||||
const width = size;
|
||||
const height = size;
|
||||
const bitDepth = 8;
|
||||
const colorType = 2; // RGB
|
||||
|
||||
// PNG signature
|
||||
const signature = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
||||
|
||||
// IHDR chunk
|
||||
const ihdrData = Buffer.alloc(13);
|
||||
ihdrData.writeUInt32BE(width, 0);
|
||||
ihdrData.writeUInt32BE(height, 4);
|
||||
ihdrData.writeUInt8(bitDepth, 8);
|
||||
ihdrData.writeUInt8(colorType, 9);
|
||||
ihdrData.writeUInt8(0, 10); // compression
|
||||
ihdrData.writeUInt8(0, 11); // filter
|
||||
ihdrData.writeUInt8(0, 12); // interlace
|
||||
|
||||
const ihdrChunk = makeChunk("IHDR", ihdrData);
|
||||
|
||||
// IDAT chunk - raw image data with filter byte
|
||||
// Each row: 1 filter byte (0 = none) + width * 3 bytes (RGB)
|
||||
const rowSize = 1 + width * 3;
|
||||
const imageData = Buffer.alloc(rowSize * height);
|
||||
for (let y = 0; y < height; y++) {
|
||||
imageData[y * rowSize] = 0; // filter: none
|
||||
for (let x = 0; x < width; x++) {
|
||||
const offset = y * rowSize + 1 + x * 3;
|
||||
imageData[offset] = r;
|
||||
imageData[offset + 1] = g;
|
||||
imageData[offset + 2] = b;
|
||||
}
|
||||
}
|
||||
|
||||
const compressed = zlibDeflate(imageData);
|
||||
const idatChunk = makeChunk("IDAT", compressed);
|
||||
|
||||
// IEND chunk
|
||||
const iendChunk = makeChunk("IEND", Buffer.alloc(0));
|
||||
|
||||
return Buffer.concat([signature, ihdrChunk, idatChunk, iendChunk]);
|
||||
}
|
||||
|
||||
function makeChunk(type: string, data: Buffer): Buffer {
|
||||
const typeBuf = Buffer.from(type, "ascii");
|
||||
const lenBuf = Buffer.alloc(4);
|
||||
lenBuf.writeUInt32BE(data.length, 0);
|
||||
const crcBuf = Buffer.alloc(4);
|
||||
const crcData = Buffer.concat([typeBuf, data]);
|
||||
crcBuf.writeInt32BE(crc32(crcData), 0);
|
||||
return Buffer.concat([lenBuf, typeBuf, data, crcBuf]);
|
||||
}
|
||||
|
||||
function crc32(buf: Buffer): number {
|
||||
const table = new Int32Array(256);
|
||||
for (let i = 0; i < 256; i++) {
|
||||
let c = i;
|
||||
for (let k = 0; k < 8; k++) {
|
||||
c = (c & 1) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1);
|
||||
}
|
||||
table[i] = c;
|
||||
}
|
||||
let crc = -1;
|
||||
for (let i = 0; i < buf.length; i++) {
|
||||
crc = table[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
|
||||
}
|
||||
return (crc ^ -1) >>> 0;
|
||||
}
|
||||
|
||||
function zlibDeflate(data: Buffer): Buffer {
|
||||
// Minimal deflate: no compression blocks (type 0) for small data
|
||||
// For larger images, we need proper zlib. Let's use Node's built-in zlib.
|
||||
import("zlib").then((zlib) => {
|
||||
// Not needed - we'll do this synchronously via a different approach
|
||||
});
|
||||
// Actually, we can use the zlib module directly since we're in Node
|
||||
const zlib = require("zlib");
|
||||
return zlib.deflateRawSync(data);
|
||||
}
|
||||
|
||||
const iconsDir = path.join(__dirname, "..", "src", "icons");
|
||||
fs.mkdirSync(iconsDir, { recursive: true });
|
||||
|
||||
// Green color (#22c55e) for InvoiceChaser
|
||||
const sizes = [16, 48, 128];
|
||||
for (const size of sizes) {
|
||||
const png = createSolidPng(size, 34, 197, 94);
|
||||
fs.writeFileSync(path.join(iconsDir, `icon${size}.png`), png);
|
||||
}
|
||||
|
||||
console.log("Icons generated successfully");
|
||||
Reference in New Issue
Block a user