image optimization

This commit is contained in:
Soph :3 2024-08-30 03:51:53 +03:00
parent 47ac0b329c
commit 7b04c35c94
Signed by: sophie
GPG key ID: EDA5D222A0C270F2
7 changed files with 85 additions and 18 deletions

BIN
bun.lockb

Binary file not shown.

View file

@ -4,17 +4,18 @@
"type": "module",
"main": "src/index.ts",
"devDependencies": {
"@types/bun": "latest"
"@types/bun": "^1.1.8"
},
"peerDependencies": {
"typescript": "^5.0.0"
},
"dependencies": {
"@types/mime-types": "^2.1.4",
"esbuild": "^0.23.0",
"marked": "^13.0.3",
"esbuild": "^0.23.1",
"marked": "^14.1.0",
"mime-types": "^2.1.35",
"postcss": "^8.4.41",
"preact": "^10.23.1"
"preact": "^10.23.2",
"sharp": "^0.33.5"
}
}

View file

@ -4,11 +4,12 @@ export abstract class Plugin {
renameTo?: string;
abstract longLasting: boolean;
abstract build?(): void;
isBinary = false;
abstract rewriteFile(
file: string,
file: string | Buffer,
filePath: string
): Promise<string | undefined | null | void>;
): Promise<Buffer | string | undefined | null | void>;
}
import * as fs from "fs";
@ -35,13 +36,14 @@ export default class SSSG {
}
async build() {
for(const plugin of this.plugins) {
if(plugin.build) {
console.time("Building..");
for (const plugin of this.plugins) {
if (plugin.build) {
plugin.build();
}
}
try {
fs.rmSync(this.outputFolder, {recursive: true});
fs.rmSync(this.outputFolder, { recursive: true });
} catch {}
const sourceFiles = fs.readdirSync(this.inputFolder, {
@ -66,7 +68,6 @@ export default class SSSG {
z.rewriteTriggers.includes(type)
);
if (availablePlugins.length == 0) {
const oldPath = path.join(file.parentPath, file.name);
fs.cpSync(
@ -82,12 +83,20 @@ export default class SSSG {
file.parentPath,
shortname +
"." +
(plugin.rewriteTriggers.includes("*") ? type : plugin.renameTo)
(plugin.rewriteTriggers.includes("*") || plugin.renameTo == "keep"
? type
: plugin.renameTo)
)
.replace(this.inputFolder, this.outputFolder);
let data = fs.readFileSync(oldPath).toString("utf8");
let data: string | Buffer = fs.readFileSync(oldPath);
if (!plugin.isBinary) {
data = data.toString("utf8");
}
for await (const globalPlugin of globalPlugins) {
if (!globalPlugin.isBinary && plugin.isBinary) continue;
const rewritten = await globalPlugin.rewriteFile(data, oldPath);
if (!rewritten) continue;
data = rewritten;
@ -98,8 +107,14 @@ export default class SSSG {
if (!rewrite) continue;
fs.mkdirSync(path.dirname(newPath), { recursive: true });
fs.writeFileSync(newPath, rewrite);
fs.writeFileSync(
newPath,
plugin.isBinary
? new Uint8Array(rewrite as Buffer)
: (rewrite as string)
);
}
}
console.timeEnd("Building..");
}
}

View file

@ -5,7 +5,7 @@ export default class CompileTimeJS extends Plugin {
rewriteTriggers = ["html", "*"]
longLasting = false;
build = undefined;
async rewriteFile(file: string, filePath: string): Promise<string> {
let input = file;
const regex = /{&(.+)&}/gms;

View file

@ -3,7 +3,7 @@ import SSSG, { Plugin } from "..";
import * as fs from "fs";
import mime from "mime-types";
const script = `let reconnectTimeout;function connect(){console.log("[--dev] connecting to dev server");let ws=new WebSocket("ws://localhost:8080");ws.addEventListener("message",message=>{if(message.data=="refresh"){location.reload()}});ws.addEventListener("open",()=>{console.log("[--dev] connected")});ws.addEventListener("close",()=>{console.log("[--dev] socket closed, restarting in 1s");clearTimeout(reconnectTimeout);reconnectTimeout=setTimeout(()=>{connect()},1e3)})}window.addEventListener("load",()=>connect());`;
const script = `let reconnectTimeout,waitingForReconnect=!1;function connect(){console.log("[dev] connecting to dev server");var e=new WebSocket("ws://localhost:8080");e.addEventListener("message",e=>{"refresh"==e.data&&location.reload()}),e.addEventListener("open",()=>{console.log("[dev] connected"),waitingForReconnect&&location.reload()}),e.addEventListener("close",()=>{console.log("[dev] socket closed, restarting in 1s"),clearTimeout(reconnectTimeout),reconnectTimeout=setTimeout(()=>{connect(),waitingForReconnect=!0},1e3)})}window.addEventListener("load",()=>connect());`;
export default class DevPlugin extends Plugin {
build: undefined;
@ -14,10 +14,9 @@ export default class DevPlugin extends Plugin {
longLasting = true;
server!: Server;
allConnections: ServerWebSocket<number>[] = [];
constructor(sssg: SSSG) {
super();
if (!process.argv.includes("--dev")) return;
fs.watch(
sssg.inputFolder,

View file

@ -0,0 +1,53 @@
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") {
// not heavy optimizations, not a fan tbf, but whatever :shrug:
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;
}
}

View file

@ -1,7 +1,6 @@
import { Plugin } from "..";
export default class Variables extends Plugin {
name = "variables";
rewriteTriggers = ["html", "*"];
renameTo = undefined;