Initial build: SimpleScan Solo v0.1.0 - Freelancer receipt capture Chrome extension

This commit is contained in:
Bun Bun
2026-06-16 18:27:31 +00:00
commit df4d26c049
33 changed files with 3962 additions and 0 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

+65
View File
@@ -0,0 +1,65 @@
const fs = require('fs');
const path = require('path');
const zlib = require('zlib');
const iconsDir = path.join(__dirname, 'icons');
fs.mkdirSync(iconsDir, { recursive: true });
function crc32(buf) {
const table = [];
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 (const byte of buf) {
crc = table[(crc ^ byte) & 0xFF] ^ (crc >>> 8);
}
return (crc ^ -1) >>> 0;
}
function makeChunk(typeStr, data) {
const typeBuf = Buffer.from(typeStr, 'ascii');
const c = crc32(Buffer.concat([typeBuf, data]));
const crcBuf = Buffer.alloc(4);
crcBuf.writeUInt32BE(c, 0);
const lenBuf = Buffer.alloc(4);
lenBuf.writeUInt32BE(data.length, 0);
return Buffer.concat([lenBuf, typeBuf, data, crcBuf]);
}
function makePng(size, r, g, b) {
const sig = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);
const ihdrData = Buffer.alloc(13);
ihdrData.writeUInt32BE(size, 0);
ihdrData.writeUInt32BE(size, 4);
ihdrData.writeUInt8(8, 8);
ihdrData.writeUInt8(2, 9);
ihdrData.writeUInt8(0, 10);
ihdrData.writeUInt8(0, 11);
ihdrData.writeUInt8(0, 12);
const rawData = [];
for (let y = 0; y < size; y++) {
rawData.push(0);
for (let x = 0; x < size; x++) {
rawData.push(r, g, b);
}
}
const imageData = zlib.deflateSync(Buffer.from(rawData));
const ihdr = makeChunk('IHDR', ihdrData);
const idat = makeChunk('IDAT', imageData);
const iend = makeChunk('IEND', Buffer.alloc(0));
return Buffer.concat([sig, ihdr, idat, iend]);
}
const r = 15, g = 52, b = 96;
fs.writeFileSync(path.join(iconsDir, 'icon16.png'), makePng(16, r, g, b));
fs.writeFileSync(path.join(iconsDir, 'icon48.png'), makePng(48, r, g, b));
fs.writeFileSync(path.join(iconsDir, 'icon128.png'), makePng(128, r, g, b));
console.log('Icons created');
+65
View File
@@ -0,0 +1,65 @@
const fs = require('fs');
const path = require('path');
const zlib = require('zlib');
const iconsDir = path.join(__dirname, '..', 'public', 'icons');
fs.mkdirSync(iconsDir, { recursive: true });
function crc32(buf) {
const table = [];
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 (const byte of buf) {
crc = table[(crc ^ byte) & 0xFF] ^ (crc >>> 8);
}
return (crc ^ -1) >>> 0;
}
function makeChunk(typeStr, data) {
const typeBuf = Buffer.from(typeStr, 'ascii');
const c = crc32(Buffer.concat([typeBuf, data]));
const crcBuf = Buffer.alloc(4);
crcBuf.writeUInt32BE(c, 0);
const lenBuf = Buffer.alloc(4);
lenBuf.writeUInt32BE(data.length, 0);
return Buffer.concat([lenBuf, typeBuf, data, crcBuf]);
}
function makePng(size, r, g, b) {
const sig = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);
const ihdrData = Buffer.alloc(13);
ihdrData.writeUInt32BE(size, 0);
ihdrData.writeUInt32BE(size, 4);
ihdrData.writeUInt8(8, 8);
ihdrData.writeUInt8(2, 9);
ihdrData.writeUInt8(0, 10);
ihdrData.writeUInt8(0, 11);
ihdrData.writeUInt8(0, 12);
const rawData = [];
for (let y = 0; y < size; y++) {
rawData.push(0);
for (let x = 0; x < size; x++) {
rawData.push(r, g, b);
}
}
const imageData = zlib.deflateSync(Buffer.from(rawData));
const ihdr = makeChunk('IHDR', ihdrData);
const idat = makeChunk('IDAT', imageData);
const iend = makeChunk('IEND', Buffer.alloc(0));
return Buffer.concat([sig, ihdr, idat, iend]);
}
const r = 15, g = 52, b = 96;
fs.writeFileSync(path.join(iconsDir, 'icon16.png'), makePng(16, r, g, b));
fs.writeFileSync(path.join(iconsDir, 'icon48.png'), makePng(48, r, g, b));
fs.writeFileSync(path.join(iconsDir, 'icon128.png'), makePng(128, r, g, b));
console.log('Icons created in public/icons');
+40
View File
@@ -0,0 +1,40 @@
const fs = require('fs');
const path = require('path');
const secretPatterns = [
/sk-[a-zA-Z0-9]{20,}/g,
/eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*/g,
/api[_-]?key\s*[:=]\s*['"][a-zA-Z0-9]{16,}['"]/gi,
/token\s*[:=]\s*['"][a-zA-Z0-9]{16,}['"]/gi,
];
const filesToCheck = [
'src/types.ts', 'src/background.ts', 'src/options.ts',
'src/popup/popup.ts', 'src/popup/popup.html', 'src/popup/popup.css',
'src/content/email-scanner.ts',
'src/utils/storage.ts', 'src/utils/categories.ts', 'src/utils/export.ts',
'options.html', 'package.json', 'vite.config.ts',
'tsconfig.json', 'tsconfig.test.json', '.gitignore'
];
let found = false;
for (const file of filesToCheck) {
const fp = path.join(__dirname, '..', file);
if (!fs.existsSync(fp)) continue;
const content = fs.readFileSync(fp, 'utf8');
for (const pattern of secretPatterns) {
const matches = content.match(pattern);
if (matches) {
console.log(`SECRET FOUND in ${file}: ${matches[0].substring(0, 30)}...`);
found = true;
}
}
}
if (found) {
console.log('SECRETS DETECTED - aborting');
process.exit(1);
} else {
console.log('No secrets found');
process.exit(0);
}