Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Splitting bin #13

Merged
merged 4 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,27 @@
"bugs": {
"url": "https://github.com/wp-blocks/squashify/issues"
},
"type": "module",
"bin": "./lib/esm/index.js",
"engines": {
"node": ">=16.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/wp-blocks/squashify.git"
},
"main": "lib/esm/index.js",
"module": "lib/esm/",
"reqire": "lib/cjs/index.js",
"types": "lib/@types/index.d.ts",
"type": "module",
"bin": "lib/esm/bin.js",
"types": "./lib/@types/index.d.ts",
"module": "./lib/esm/",
"exports": {
"squashify": "./lib/esm/bin.js",
"default": "./lib/esm/bin.js"
},
"scripts": {
"prebuild": "rimraf lib && tsc --emitDeclarationOnly --outDir lib/@types/",
"build": "npx esbuild ./src/* --outdir=lib/esm/ --format=esm --platform=node --minify",
"postbuild": "npx esbuild src/index.ts --outfile=lib/cjs/index.js --bundle --platform=node --minify",
"watch": "tsc --watch --sourceMap --outDir lib/esm/",
"squashify": "node . --in tests/images/ --out tests/output --verbose",
"squashifyDefaults": "node . -d",
"squashify": "node ./lib/esm/bin.js --in tests/images/ --out tests/output --verbose",
"squashifyDefaults": "node ./lib/esm/bin.js -d",
"test": "vitest --coverage"
},
"files": [
Expand Down
49 changes: 49 additions & 0 deletions src/bin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env node

// Run the script as an async function
import { humanFileSize, logMessage } from "./utils.js";
import { OutputData } from "./types.js";
import squashify from "./index.js";
import { getCliOptions } from "./parseArgs.js";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import process from "node:process";

// Get the cli settings
export default async function main() {
const cliOptions = getCliOptions(yargs(hideBin(process.argv)));

squashify(cliOptions)
.then((response) => {
const { timeElapsed, result, verbose } = response;

if (result.length) {
result.forEach((result) => {
if (result.status !== "fulfilled") {
logMessage("🔴 " + result.reason, true);
} else {
const { status, value } =
result as PromiseFulfilledResult<OutputData>;
logMessage(
"✅ " +
JSON.stringify(
"size" in value
? { ...value, size: humanFileSize(value.size) }
: value,
),
verbose,
);
}
return;
});
}

// Print the time elapsed in seconds to the console
logMessage(`The end 🎉 - Time elapsed: ${timeElapsed} seconds`, true);
})
.catch((err) => {
console.error(err);
});
}

await main();
24 changes: 4 additions & 20 deletions src/compression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ import { encodeFileAsync } from "./encodeFileAsync.js";
* have keys that correspond to image formats (e.g. "jpg", "png", "webp") and values
* that are objects containing compression settings for that format (e.g. "no", "mozjpeg", "jpeg").
*/
export async function convertImages(settings: ScriptOptions): Promise<void> {
export async function convertImages(
settings: ScriptOptions,
): Promise<PromiseSettledResult<OutputData>[]> {
// destructuring the settings
const { srcDir, distDir, compressionOptions } = settings as ScriptOptions;

Expand Down Expand Up @@ -164,23 +166,5 @@ export async function convertImages(settings: ScriptOptions): Promise<void> {
}

// Wait for all promises to resolve before returning
const res = await Promise.allSettled(promises);
if (res.length) {
res.forEach((result) => {
if (result.status !== "fulfilled") {
logMessage("🔴 " + result.reason, true);
} else {
logMessage(
"✅ " +
JSON.stringify(
(result as PromiseFulfilledResult<OutputData>).value,
),
settings.verbose,
);
}
return;
});
} else {
logMessage("🔴 No files found", true);
}
return await Promise.allSettled(promises);
}
46 changes: 24 additions & 22 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
#!/usr/bin/env node
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import process from "node:process";

import { getCliOptions } from "./parseArgs.js";
import { convertImages } from "./compression.js";
import { getIniOptions } from "./parseIni.js";
import { getPromptOptions } from "./prompts.js";
import { parseOptions } from "./parseOptions.js";
import { logMessage } from "./utils.js";
import { getImageFormatsInFolder, logMessage } from "./utils.js";
import { encodeFileAsync } from "./encodeFileAsync.js";
import { encodeSvg } from "./encodeSvg.js";
import { encodeAnimation } from "./encodeAnimation.js";
import { encodeImage } from "./encodeImage.js";
import { CliOptions } from "./types.js";
import main from "./bin.js";

/**
* Prompts the user for the source and destination directories
* then runs a function that converts the images.
*
* @returns Promise that resolves when the image conversion is complete
*/
export default async function main() {
// Get the cli settings
const cliOptions = getCliOptions(yargs(hideBin(process.argv)));

export default async function squashify(cliOptions: CliOptions) {
// Get the settings from the .ini file
const iniOptions = getIniOptions(cliOptions.configFile);

Expand All @@ -46,17 +43,22 @@ export default async function main() {
const startTime = Date.now();

// Then convert the images in the source directory
await convertImages(options);

// Print the time elapsed in seconds to the console
logMessage(
`The end 🎉 - Time elapsed: ${(Date.now() - startTime) / 1000} seconds`,
true,
);
const result = await convertImages(options);

return;
return {
result,
timeElapsed: (Date.now() - startTime) / 1000,
verbose: cliOptions.verbose,
};
}

main().catch((err) => {
console.error(err);
});
export {
main,
getIniOptions,
convertImages,
getImageFormatsInFolder,
encodeFileAsync,
encodeSvg,
encodeAnimation,
encodeImage,
};
34 changes: 34 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,37 @@ export function generateDefaultConfigFile(

return writeFileSync(filename, iniFileContent);
}

/**
* Format bytes as human-readable text.
*
* @param bytes Number of bytes.
* @param si True to use metric (SI) units, aka powers of 1000. False to use
* binary (IEC), aka powers of 1024.
* @param dp Number of decimal places to display.
*
* @return Formatted string.
*/
export function humanFileSize(bytes, si = false, dp = 1) {
const thresh = si ? 1000 : 1024;

if (Math.abs(bytes) < thresh) {
return bytes + " B";
}

const units = si
? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
: ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
let u = -1;
const r = 10 ** dp;

do {
bytes /= thresh;
++u;
} while (
Math.round(Math.abs(bytes) * r) / r >= thresh &&
u < units.length - 1
);

return bytes.toFixed(dp) + " " + units[u];
}
1 change: 0 additions & 1 deletion tests/unit/ini.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { describe, expect, it } from "vitest";
import { getIniOptions } from "../../src/parseIni.js";
import { ScriptOptions } from "node:vm";
import { CliOptions } from "../../src/types.js";

describe("getIniOptions", () => {
Expand Down