Skip to content

Commit 70e07e8

Browse files
committed
Require Node.js 18
1 parent 2f7ecc9 commit 70e07e8

File tree

6 files changed

+98
-107
lines changed

6 files changed

+98
-107
lines changed

.github/security.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Security Policy
2+
3+
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.

.github/workflows/main.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
node-version:
13-
- 16
13+
- 20
14+
- 18
1415
steps:
15-
- uses: actions/checkout@v2
16-
- uses: actions/setup-node@v2
16+
- uses: actions/checkout@v4
17+
- uses: actions/setup-node@v4
1718
with:
1819
node-version: ${{ matrix.node-version }}
1920
- run: npm install

index.js

Lines changed: 50 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,27 @@
1-
import {createRequire} from 'node:module';
21
import path from 'node:path';
32
import process from 'node:process';
4-
import log from 'fancy-log';
5-
import PluginError from 'plugin-error';
6-
import through from 'through2-concurrent';
73
import prettyBytes from 'pretty-bytes';
84
import chalk from 'chalk';
95
import imagemin from 'imagemin';
106
import plur from 'plur';
11-
12-
const require = createRequire(import.meta.url);
7+
import {gulpPlugin} from 'gulp-plugin-extras';
138

149
const PLUGIN_NAME = 'gulp-imagemin';
1510
const defaultPlugins = ['gifsicle', 'mozjpeg', 'optipng', 'svgo'];
1611

17-
const loadPlugin = (plugin, ...args) => {
12+
const loadPlugin = async (pluginName, ...arguments_) => {
1813
try {
19-
return require(`imagemin-${plugin}`)(...args);
20-
} catch {
21-
log(`${PLUGIN_NAME}: Could not load default plugin \`${plugin}\``);
14+
const {default: plugin} = await import(`imagemin-${pluginName}`);
15+
return plugin(...arguments_);
16+
} catch (error) {
17+
console.log('er', error);
18+
console.log(`${PLUGIN_NAME}: Could not load default plugin \`${pluginName}\``);
2219
}
2320
};
2421

25-
const exposePlugin = plugin => (...args) => loadPlugin(plugin, ...args);
22+
const exposePlugin = async plugin => (...arguments_) => loadPlugin(plugin, ...arguments_);
2623

27-
const getDefaultPlugins = () => defaultPlugins.flatMap(plugin => loadPlugin(plugin));
24+
const getDefaultPlugins = async () => Promise.all(defaultPlugins.flatMap(plugin => loadPlugin(plugin)));
2825

2926
export default function gulpImagemin(plugins, options) {
3027
if (typeof plugins === 'object' && !Array.isArray(plugins)) {
@@ -45,75 +42,58 @@ export default function gulpImagemin(plugins, options) {
4542
let totalSavedBytes = 0;
4643
let totalFiles = 0;
4744

48-
return through.obj({
49-
maxConcurrency: 8,
50-
}, (file, encoding, callback) => {
51-
if (file.isNull()) {
52-
callback(null, file);
53-
return;
45+
return gulpPlugin('gulp-imagemin', async file => {
46+
if (!validExtensions.has(path.extname(file.path).toLowerCase())) {
47+
if (options.verbose) {
48+
console.log(`${PLUGIN_NAME}: Skipping unsupported image ${chalk.blue(file.relative)}`);
49+
}
50+
51+
return file;
5452
}
5553

56-
if (file.isStream()) {
57-
callback(new PluginError(PLUGIN_NAME, 'Streaming not supported'));
58-
return;
54+
if (Array.isArray(plugins)) {
55+
plugins = await Promise.all(plugins);
5956
}
6057

61-
if (!validExtensions.has(path.extname(file.path).toLowerCase())) {
62-
if (options.verbose) {
63-
log(`${PLUGIN_NAME}: Skipping unsupported image ${chalk.blue(file.relative)}`);
64-
}
58+
const localPlugins = plugins ?? await getDefaultPlugins();
59+
const data = await imagemin.buffer(file.contents, {plugins: localPlugins});
60+
const originalSize = file.contents.length;
61+
const optimizedSize = data.length;
62+
const saved = originalSize - optimizedSize;
63+
const percent = originalSize > 0 ? (saved / originalSize) * 100 : 0;
64+
const savedMessage = `saved ${prettyBytes(saved)} - ${percent.toFixed(1).replace(/\.0$/, '')}%`;
65+
const message = saved > 0 ? savedMessage : 'already optimized';
66+
67+
if (saved > 0) {
68+
totalBytes += originalSize;
69+
totalSavedBytes += saved;
70+
totalFiles++;
71+
}
6572

66-
callback(null, file);
67-
return;
73+
if (options.verbose) {
74+
console.log(`${PLUGIN_NAME}:`, chalk.green('✔ ') + file.relative + chalk.gray(` (${message})`));
6875
}
6976

70-
const localPlugins = plugins || getDefaultPlugins();
71-
72-
(async () => {
73-
try {
74-
const data = await imagemin.buffer(file.contents, {
75-
plugins: localPlugins,
76-
});
77-
const originalSize = file.contents.length;
78-
const optimizedSize = data.length;
79-
const saved = originalSize - optimizedSize;
80-
const percent = originalSize > 0 ? (saved / originalSize) * 100 : 0;
81-
const savedMessage = `saved ${prettyBytes(saved)} - ${percent.toFixed(1).replace(/\.0$/, '')}%`;
82-
const message = saved > 0 ? savedMessage : 'already optimized';
83-
84-
if (saved > 0) {
85-
totalBytes += originalSize;
86-
totalSavedBytes += saved;
87-
totalFiles++;
88-
}
77+
file.contents = data;
8978

90-
if (options.verbose) {
91-
log(`${PLUGIN_NAME}:`, chalk.green('✔ ') + file.relative + chalk.gray(` (${message})`));
79+
return file;
80+
}, {
81+
async * onFinish() { // eslint-disable-line require-yield
82+
if (!options.silent) {
83+
const percent = totalBytes > 0 ? (totalSavedBytes / totalBytes) * 100 : 0;
84+
let message = `Minified ${totalFiles} ${plur('image', totalFiles)}`;
85+
86+
if (totalFiles > 0) {
87+
message += chalk.gray(` (saved ${prettyBytes(totalSavedBytes)} - ${percent.toFixed(1).replace(/\.0$/, '')}%)`);
9288
}
9389

94-
file.contents = data;
95-
callback(null, file);
96-
} catch (error) {
97-
callback(new PluginError(PLUGIN_NAME, error, {fileName: file.path}));
98-
}
99-
})();
100-
}, callback => {
101-
if (!options.silent) {
102-
const percent = totalBytes > 0 ? (totalSavedBytes / totalBytes) * 100 : 0;
103-
let message = `Minified ${totalFiles} ${plur('image', totalFiles)}`;
104-
105-
if (totalFiles > 0) {
106-
message += chalk.gray(` (saved ${prettyBytes(totalSavedBytes)} - ${percent.toFixed(1).replace(/\.0$/, '')}%)`);
90+
console.log(`${PLUGIN_NAME}:`, message);
10791
}
108-
109-
log(`${PLUGIN_NAME}:`, message);
110-
}
111-
112-
callback();
92+
},
11393
});
11494
}
11595

116-
export const gifsicle = exposePlugin('gifsicle');
117-
export const mozjpeg = exposePlugin('mozjpeg');
118-
export const optipng = exposePlugin('optipng');
119-
export const svgo = exposePlugin('svgo');
96+
export const gifsicle = await exposePlugin('gifsicle');
97+
export const mozjpeg = await exposePlugin('mozjpeg');
98+
export const optipng = await exposePlugin('optipng');
99+
export const svgo = await exposePlugin('svgo');

package.json

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"type": "module",
1414
"exports": "./index.js",
1515
"engines": {
16-
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
16+
"node": ">=18"
1717
},
1818
"scripts": {
1919
"test": "xo && ava"
@@ -38,26 +38,23 @@
3838
"svg"
3939
],
4040
"dependencies": {
41-
"chalk": "^4.1.2",
42-
"fancy-log": "^1.3.3",
41+
"chalk": "^5.3.0",
42+
"gulp-plugin-extras": "^0.2.2",
4343
"imagemin": "^8.0.1",
44-
"plugin-error": "^1.0.1",
45-
"plur": "^4.0.0",
46-
"pretty-bytes": "^5.6.0",
47-
"through2-concurrent": "^2.0.0"
44+
"plur": "^5.1.0",
45+
"pretty-bytes": "^6.1.1"
4846
},
4947
"devDependencies": {
50-
"ava": "^3.15.0",
51-
"get-stream": "^6.0.1",
48+
"ava": "^5.3.1",
5249
"imagemin-pngquant": "^9.0.2",
53-
"vinyl": "^2.2.1",
54-
"xo": "^0.44.0"
50+
"vinyl": "^3.0.0",
51+
"xo": "^0.56.0"
5552
},
5653
"optionalDependencies": {
5754
"imagemin-gifsicle": "^7.0.0",
58-
"imagemin-mozjpeg": "^9.0.0",
55+
"imagemin-mozjpeg": "^10.0.0",
5956
"imagemin-optipng": "^8.0.0",
60-
"imagemin-svgo": "^9.0.0"
57+
"imagemin-svgo": "^10.0.1"
6158
},
6259
"peerDependencies": {
6360
"gulp": ">=4"

readme.md

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
## Install
88

9-
```
10-
$ npm install --save-dev gulp-imagemin
9+
```sh
10+
npm install --save-dev gulp-imagemin
1111
```
1212

1313
## Usage
@@ -28,15 +28,23 @@ export default () => (
2828
### Custom plugin options
2929

3030
```js
31+
import imagemin, {gifsicle, mozjpeg, optipng, svgo} from 'gulp-imagemin';
32+
3133
//
3234
.pipe(imagemin([
33-
imagemin.gifsicle({interlaced: true}),
34-
imagemin.mozjpeg({quality: 75, progressive: true}),
35-
imagemin.optipng({optimizationLevel: 5}),
36-
imagemin.svgo({
35+
gifsicle({interlaced: true}),
36+
mozjpeg({quality: 75, progressive: true}),
37+
optipng({optimizationLevel: 5}),
38+
svgo({
3739
plugins: [
38-
{removeViewBox: true},
39-
{cleanupIDs: false}
40+
{
41+
name: 'removeViewBox',
42+
active: true
43+
},
44+
{
45+
name: 'cleanupIDs',
46+
active: false
47+
}
4048
]
4149
})
4250
]))
@@ -46,12 +54,15 @@ export default () => (
4654
### Custom plugin options and custom `gulp-imagemin` options
4755

4856
```js
57+
import imagemin, {svgo} from 'gulp-imagemin';
58+
4959
//
5060
.pipe(imagemin([
51-
imagemin.svgo({
61+
svgo({
5262
plugins: [
5363
{
54-
removeViewBox: true
64+
name: 'removeViewBox',
65+
active: true
5566
}
5667
]
5768
})
@@ -79,7 +90,7 @@ Unsupported files are ignored.
7990
#### plugins
8091

8192
Type: `Array`\
82-
Default: `[imagemin.gifsicle(), imagemin.mozjpeg(), imagemin.optipng(), imagemin.svgo()]`
93+
Default: `[gifsicle(), mozjpeg(), optipng(), svgo()]`
8394

8495
[Plugins](https://www.npmjs.com/browse/keyword/imageminplugin) to use. This will completely overwrite all the default plugins. So, if you want to use custom plugins and you need some of defaults too, then you should pass default plugins as well. Note that the default plugins come with good defaults and should be sufficient in most cases. See the individual plugins for supported options.
8596

test.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import path from 'node:path';
33
import {fileURLToPath} from 'node:url';
44
import imageminPngquant from 'imagemin-pngquant';
55
import Vinyl from 'vinyl';
6-
import getStream from 'get-stream';
76
import test from 'ava';
87
import gulpImagemin, {mozjpeg, svgo} from './index.js';
98

@@ -23,7 +22,7 @@ const createFixture = async (plugins, file = 'fixture.png') => {
2322

2423
test('minify images', async t => {
2524
const {buffer, stream} = await createFixture();
26-
const file = await getStream.array(stream);
25+
const file = await stream.toArray();
2726

2827
t.true(file[0].contents.length < buffer.length);
2928
});
@@ -35,16 +34,16 @@ test('minify JPEG with custom settings', async t => {
3534
smooth: 45,
3635
};
3736
const {buffer, stream} = await createFixture([mozjpeg(mozjpegOptions)], 'fixture.jpg');
38-
const file = await getStream.array(stream);
37+
const file = await stream.toArray();
3938

4039
t.true(file[0].contents.length < buffer.length);
4140
});
4241

4342
test('use custom plugins', async t => {
4443
const {stream} = await createFixture([imageminPngquant()]);
45-
const compareStream = (await createFixture()).stream;
46-
const file = await getStream.array(stream);
47-
const compareFile = await getStream.array(compareStream);
44+
const {stream: compareStream} = await createFixture();
45+
const file = await stream.toArray();
46+
const compareFile = await compareStream.toArray();
4847

4948
t.true(file[0].contents.length < compareFile[0].contents.length);
5049
});
@@ -57,17 +56,17 @@ test('use custom svgo settings', async t => {
5756
},
5857
};
5958
const {stream} = await createFixture([svgo(svgoOptions)], 'fixture-svg-logo.svg');
60-
const compareStream = (await createFixture(null, 'fixture-svg-logo.svg')).stream;
61-
const file = await getStream.array(stream);
62-
const compareFile = await getStream.array(compareStream);
59+
const {stream: compareStream} = await createFixture(null, 'fixture-svg-logo.svg');
60+
const file = await stream.toArray();
61+
const compareFile = await compareStream.toArray();
6362

6463
t.true(file[0].contents.length > compareFile[0].contents.length);
6564
});
6665

6766
test('skip unsupported images', async t => {
6867
const stream = gulpImagemin();
6968
stream.end(new Vinyl({path: path.join(__dirname, 'fixture.bmp')}));
70-
const file = await getStream.array(stream);
69+
const file = await stream.toArray();
7170

7271
t.is(file[0].contents, null);
7372
});

0 commit comments

Comments
 (0)