66 lines
2.2 KiB
TypeScript
66 lines
2.2 KiB
TypeScript
/**
|
||
* public/uni-logo altındaki PNG'leri kayıpsıza yakın sıkıştırır (palet
|
||
* kuantalama). Logolar en fazla ~80px CSS boyutunda gösterildiği için
|
||
* 300×300 kaynak korunur; yalnızca kodlama küçülür. %10'dan az kazanç
|
||
* veren dosyaya dokunulmaz (gradyanlı logolarda bantlanma riskine değmez).
|
||
*
|
||
* sharp, next'in bağımlılığından çözülür — ayrı kurulum gerektirmez.
|
||
* pnpm'in izole node_modules'ü yüzünden .pnpm dizininden bulunur.
|
||
* Kullanım: npx tsx scripts/logo-optimize.ts
|
||
*/
|
||
import { readdirSync, readFileSync, writeFileSync, statSync } from "node:fs";
|
||
import { createRequire } from "node:module";
|
||
import path from "node:path";
|
||
|
||
function sharpYolu(): string {
|
||
const pnpmDir = path.join(process.cwd(), "node_modules", ".pnpm");
|
||
const aday = readdirSync(pnpmDir).find((d) => d.startsWith("sharp@"));
|
||
if (!aday) throw new Error("sharp bulunamadı (node_modules/.pnpm)");
|
||
return path.join(pnpmDir, aday, "node_modules", "sharp");
|
||
}
|
||
|
||
// sharp doğrudan bağımlılık olmadığı için tipleri elde yok; kullanılan
|
||
// yüzey kadarı tanımlanır.
|
||
type SharpPng = {
|
||
png(opts: {
|
||
palette: boolean;
|
||
quality: number;
|
||
effort: number;
|
||
compressionLevel: number;
|
||
}): { toBuffer(): Promise<Buffer> };
|
||
};
|
||
const req = createRequire(import.meta.url);
|
||
const sharp = req(sharpYolu()) as (girdi: Buffer) => SharpPng;
|
||
|
||
async function main() {
|
||
const dir = path.join(process.cwd(), "public", "uni-logo");
|
||
const dosyalar = readdirSync(dir).filter((f) => f.endsWith(".png"));
|
||
let onceToplam = 0;
|
||
let sonraToplam = 0;
|
||
|
||
for (const f of dosyalar) {
|
||
const yol = path.join(dir, f);
|
||
const once = statSync(yol).size;
|
||
onceToplam += once;
|
||
const buf = await sharp(readFileSync(yol))
|
||
.png({ palette: true, quality: 90, effort: 10, compressionLevel: 9 })
|
||
.toBuffer();
|
||
if (buf.length < once * 0.9) {
|
||
writeFileSync(yol, buf);
|
||
sonraToplam += buf.length;
|
||
} else {
|
||
sonraToplam += once;
|
||
}
|
||
}
|
||
|
||
const mb = (n: number) => (n / 1024 / 1024).toFixed(1);
|
||
console.log(
|
||
`${dosyalar.length} logo: ${mb(onceToplam)} MB → ${mb(sonraToplam)} MB`,
|
||
);
|
||
}
|
||
|
||
main().catch((e) => {
|
||
console.error(e);
|
||
process.exit(1);
|
||
});
|