Skip to content

Commit

Permalink
feat: When adding an unspecified output path, overwrite the source fi…
Browse files Browse the repository at this point in the history
…le and retain the original folder tree relationship
  • Loading branch information
张连才 committed Jul 9, 2024
1 parent 3cd3c4c commit 890f545
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 127 deletions.
173 changes: 102 additions & 71 deletions cli.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
#!/usr/bin/env node
import process from 'node:process';
import arrify from 'arrify';
import meow from 'meow';
import getStdin from 'get-stdin';
import imagemin from 'imagemin';
import ora from 'ora';
import plur from 'plur';
import stripIndent from 'strip-indent';
import pairs from 'lodash.pairs';
import {isUint8Array} from 'uint8array-extras';

const cli = meow(`
import process from "node:process";

Check failure on line 2 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Strings must use singlequote.

Check failure on line 2 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Strings must use singlequote.
import arrify from "arrify";

Check failure on line 3 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Strings must use singlequote.

Check failure on line 3 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Strings must use singlequote.
import meow from "meow";

Check failure on line 4 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Strings must use singlequote.

Check failure on line 4 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Strings must use singlequote.
import getStdin from "get-stdin";

Check failure on line 5 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Strings must use singlequote.

Check failure on line 5 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Strings must use singlequote.
import imagemin from "imagemin";

Check failure on line 6 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Strings must use singlequote.

Check failure on line 6 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Strings must use singlequote.
import ora from "ora";

Check failure on line 7 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Strings must use singlequote.

Check failure on line 7 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Strings must use singlequote.
import plur from "plur";

Check failure on line 8 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Strings must use singlequote.

Check failure on line 8 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Strings must use singlequote.
import stripIndent from "strip-indent";

Check failure on line 9 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Strings must use singlequote.

Check failure on line 9 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Strings must use singlequote.
import pairs from "lodash.pairs";

Check failure on line 10 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 22

Strings must use singlequote.

Check failure on line 10 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Strings must use singlequote.
import { isUint8Array } from "uint8array-extras";

Check failure on line 11 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 22

There should be no space after '{'.

Check failure on line 11 in cli.js

View workflow job for this annotation

GitHub Actions / Node.js 18

There should be no space after '{'.

const cli = meow(
`
Usage
$ imagemin <path|glob> [options]
$ imagemin <path|glob> ... --out-dir=build [--plugin=<name> ...]
$ imagemin <file> > <output>
$ cat <file> | imagemin > <output>
Expand All @@ -21,6 +23,8 @@ const cli = meow(`
--out-dir, -o Output directory
Examples
$ imagemin images/*
$ imagemin images/* --plugin.pngquant.quality={0.1,0.2} --plugin.gifsicle.quality={0.1,0.2}
$ imagemin images/* --out-dir=build
$ imagemin foo.png > foo-optimized.png
$ cat foo.png | imagemin > foo-optimized.png
Expand All @@ -29,109 +33,136 @@ const cli = meow(`
# Non-Windows platforms may support the short CLI syntax for array arguments
$ imagemin foo.png --plugin.pngquant.quality={0.1,0.2} > foo-optimized.png
$ imagemin foo.png --plugin.webp.quality=95 --plugin.webp.preset=icon > foo-icon.webp
`, {
importMeta: import.meta,
flags: {
plugin: {
type: 'string',
shortFlag: 'p',
isMultiple: true,
default: [
'gifsicle',
'jpegtran',
'optipng',
'svgo',
],
},
outDir: {
type: 'string',
shortFlag: 'o',
`,
{
importMeta: import.meta,
flags: {
plugin: {
type: "string",
shortFlag: "p",
isMultiple: true,
default: ["gifsicle", "jpegtran", "optipng", "svgo"],
},
outDir: {
type: "string",
shortFlag: "o",
},
},
},
});
);

const requirePlugins = plugins => Promise.all(plugins.map(async ([plugin, options]) => {
try {
const {default: _plugin} = await import(`imagemin-${plugin}`);
return _plugin(options);
} catch {
console.error(stripIndent(`
const requirePlugins = (plugins) =>
Promise.all(
plugins.map(async ([plugin, options]) => {
try {
const { default: _plugin } = await import(`imagemin-${plugin}`);
return _plugin(options);
} catch {
console.error(
stripIndent(`
Unknown plugin: ${plugin}
Did you forget to install the plugin?
You can install it with:
$ npm install -g imagemin-${plugin}
`).trim());

process.exit(1);
}
}));

const normalizePluginOptions = plugin => {
`).trim(),
);
process.exit(1);
}
}),
);

const normalizePluginOptions = (plugin) => {
const pluginOptionsMap = {};

for (const v of arrify(plugin)) {
Object.assign(
pluginOptionsMap,
typeof v === 'object'
? v
: {[v]: {}},
);
Object.assign(pluginOptionsMap, typeof v === "object" ? v : { [v]: {} });
}

return pairs(pluginOptionsMap);
};

const run = async (input, {outDir, plugin} = {}) => {
/**
* Delete all hierarchical files in the original directory while preserving the folder structure
* @param {*} dir
*/
const emptyDirSync = (dir) => {
if (fs.existsSync(dir)) {
const files = fs.readdirSync(dir);
files.forEach((file) => {
const currentPath = path.join(dir, file);
if (fs.statSync(currentPath).isDirectory()) {
emptyDirSync(currentPath);
} else {
fs.unlinkSync(currentPath);
}
});
}
};

const run = async (input, { outDir, plugin } = {}) => {
const pluginOptions = normalizePluginOptions(plugin);
const plugins = await requirePlugins(pluginOptions);
const spinner = ora('Minifying images');
const spinner = ora("Minifying images");

if (isUint8Array(input)) {
process.stdout.write(await imagemin.buffer(input, {plugins}));
process.stdout.write(await imagemin.buffer(input, { plugins }));
return;
}

if (outDir) {
spinner.start();
}

let files;
let files,
failedCount = 0;
try {
files = await imagemin(input, {destination: outDir, plugins});
files = await imagemin(input, { destination: outDir, plugins });
if (!outDir) {
if (fs.statSync(input[0]).isDirectory()) {
emptyDirSync(input[0]);
}
files.forEach((file) => {
fs.writeFile(file.sourcePath, file.data, (err) => {
if (err) {
failedCount++;
console.error(`${file.sourcePath} -- Write failed!`, err);
}
});
});
}
} catch (error) {
spinner.stop();
throw error;
}

if (!outDir && files.length === 0) {
return;
}
// if (!outDir && files.length === 0) {
// return;
// }

if (!outDir && files.length > 1) {
console.error('Cannot write multiple files to stdout, specify `--out-dir`');
process.exit(1);
}
// if (!outDir && files.length > 1) {
// console.error('Cannot write multiple files to stdout, specify `--out-dir`');
// process.exit(1);
// }

if (!outDir) {
process.stdout.write(files[0].data);
return;
}
// if (!outDir) {
// process.stdout.write(files[0].data);
// return;
// }

spinner.stop();

console.log(`${files.length} ${plur('image', files.length)} minified`);
console.log(
`${files.length - failedCount} ${plur("image", files.length)} minified`,
);
};

if (cli.input.length === 0 && process.stdin.isTTY) {
console.error('Specify at least one file path');
console.error("Specify at least one file path");
process.exit(1);
}

await run(
cli.input.length > 0
? cli.input
: await getStdin.buffer(),
cli.input.length > 0 ? cli.input : await getStdin.buffer(),
cli.flags,
);
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"node": ">=18"
},
"scripts": {
"test": "xo && ava"
"test": "xo && ava",
"testonly": "ava"
},
"files": [
"cli.js"
Expand Down Expand Up @@ -63,4 +64,4 @@
"n/no-unsupported-features": "off"
}
}
}
}
Loading

0 comments on commit 890f545

Please sign in to comment.