feat: AI Pricing Transparency Scanner Chrome Extension v1.0.0
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
// scripts/build.mjs — copies src to dist (no transpilation needed, plain JS)
|
||||
import { readFileSync, writeFileSync, mkdirSync, readdirSync, statSync, copyFileSync, existsSync } from 'fs';
|
||||
import { join, dirname, relative } from 'path';
|
||||
|
||||
const root = dirname(new URL(import.meta.url).pathname);
|
||||
const projectRoot = join(root, '..');
|
||||
const srcDir = join(projectRoot, 'src');
|
||||
const distDir = join(projectRoot, 'dist');
|
||||
|
||||
function copyDir(src, dest) {
|
||||
mkdirSync(dest, { recursive: true });
|
||||
const entries = readdirSync(src);
|
||||
for (const entry of entries) {
|
||||
const srcPath = join(src, entry);
|
||||
const destPath = join(dest, entry);
|
||||
const stat = statSync(srcPath);
|
||||
if (stat.isDirectory()) {
|
||||
copyDir(srcPath, destPath);
|
||||
} else {
|
||||
copyFileSync(srcPath, destPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean dist
|
||||
if (existsSync(distDir)) {
|
||||
// Just overwrite files
|
||||
}
|
||||
|
||||
copyDir(srcDir, distDir);
|
||||
console.log('Build complete: src → dist');
|
||||
@@ -0,0 +1,96 @@
|
||||
// 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.');
|
||||
Reference in New Issue
Block a user