import { Plugin } from ".."; import sharp from "sharp"; export default class ImageOptimization extends Plugin { build: undefined; name = "image-optimization"; rewriteTriggers = ["png", "gif", "jpg", "jpeg", "webp", "avif"]; renameTo = "keep"; isBinary = true; longLasting = false; logging = true; constructor(logging = true) { super(); this.logging = logging; } async rewriteFile(file: Buffer, filePath: string) { const nonOptimized = file; const type = filePath.split(".").at(-1); let data: Buffer = file; if (type == "webp") { data = await sharp(file).webp({ lossless: true }).toBuffer(); } if (type == "avif") { data = await sharp(file).avif({ lossless: true }).toBuffer(); } if (type == "jpg" || type == "jpeg") { data = await sharp(file).jpeg({ quality: 100 }).toBuffer(); } if (type == "png") { data = await sharp(file).png({ quality: 100 }).toBuffer(); } if (type == "gif") { const gif = sharp(file, { animated: true }); const pageCount = (await gif.metadata()).pages; if (pageCount == 1) { data = await sharp(file, { animated: false }) .gif({ colors: 16 }) .toBuffer(); } else { data = await sharp(file, { animated: true }) .gif({ colors: 16 }) .toBuffer(); } } if (nonOptimized.byteLength < data.byteLength) { if (this.logging) { console.log( "❌ " + filePath + "(" + nonOptimized.byteLength + "B) optimized was " + data.byteLength + "B. It has been skipped." ); } data = nonOptimized; } return data; } }