Last active
February 15, 2023 22:56
-
-
Save o-az/d2b707b96b2729edeedc0abe194db4a0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ts-node | |
import fs from "node:fs/promises"; | |
import tinify from "tinify"; | |
/** | |
* This script will travel through the public folder and its subdirectories and | |
* compress all images with tinify. It will also convert all images to webp. | |
* then it will delete the original images. | |
* | |
* You can run this with ts-node: | |
* | |
* TINIFY_API_KEY="APT_KEY_HERE" node_modules/.bin/ts-node tinify.mts | |
*/ | |
const API_KEY = process.env.TINIFY_API_KEY; | |
if (!API_KEY) throw new Error("TINIFY_API_KEY is not set"); | |
// set tinify key | |
Object.assign(tinify, { key: API_KEY }); | |
// supported extensions | |
const extensions = ["jpg", "jpeg", "png"]; | |
// path to images | |
const imagesPath = "./public"; | |
processPath(imagesPath) | |
.then(() => { | |
console.log("done"); | |
process.exit(0); | |
}) | |
.catch((error) => { | |
console.error(error); | |
process.exit(1); | |
}); | |
async function processPath(path: string) { | |
const paths = await fs.readdir(path); | |
for (let item of paths) { | |
item = `${path}/${item}`; | |
const pathType = await getPathType(item); | |
if (pathType === "skip") continue; | |
if (pathType === "directory") await processPath(item); | |
if (pathType === "image") { | |
const { extension } = await fileInfo(item); | |
await processImage(item); | |
await fs.rename(`${item}.webp`, item.replace(extension, "webp")); | |
await fs.unlink(item); | |
} | |
} | |
} | |
async function fileInfo(path: string) { | |
const [, name, extension] = path.split("."); | |
return { name, extension }; | |
} | |
async function getPathType( | |
path: string | |
): Promise<"image" | "directory" | "skip"> { | |
return (await fs.stat(path)).isDirectory() | |
? "directory" | |
: extensions.includes((await fileInfo(path)).extension) | |
? "image" | |
: "skip"; | |
} | |
async function compress(image: string) { | |
return await tinify.fromFile(image).toFile(`${image}`); | |
} | |
async function convert(image: string, to: "webp" | "jpg" | "png") { | |
const source = tinify.fromFile(image); | |
const converted = source.convert({ type: `image/${to}` }); | |
const extension = await converted.result().extension(); | |
await converted.toFile(`${image}.${extension}`); | |
} | |
async function processImage(filename: string) { | |
console.log(`Compressing ${filename}...`); | |
await convert(filename, "webp"); | |
await compress(filename); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment