33'use strict' ;
44
55const fs = require ( 'fs' ) ;
6- const path = require ( 'path' ) ;
76const meow = require ( 'meow' ) ;
87const ora = require ( 'ora' ) ;
98const globby = require ( 'globby' ) ;
9+ const makeDir = require ( 'make-dir' ) ;
10+ const hasExt = require ( 'has-ext' ) ;
1011const upath = require ( 'upath' ) ;
12+ const pAll = require ( 'p-all' ) ;
1113const { minify} = require ( 'html-minifier' ) ;
1214const CleanCSS = require ( 'clean-css' ) ;
1315const Terser = require ( 'terser' ) ;
16+ const imagemin = require ( 'imagemin' ) ;
17+ const imageminMozjpeg = require ( 'imagemin-mozjpeg' ) ;
18+ const imageminPngquant = require ( 'imagemin-pngquant' ) ;
19+ const imageminSvgo = require ( 'imagemin-svgo' ) ;
1420
1521const cli = meow ( `
1622 Usage
1723 $ minifly <options>
1824
19- Options
25+ Options
26+ --output, -o Output directory [default: minifly]
2027 --ignore, -i Ignore specific files or directories
2128
2229 Examples
2330 $ minifly
24- $ minifly --ignore 'index.js,dist/*.css'
31+ $ minifly --ignore 'index.js,dist/*.css' -o dist
2532` , {
2633 flags : {
34+ output : {
35+ type : 'string' ,
36+ alias : 'o' ,
37+ default : 'minifly'
38+ } ,
2739 ignore : {
2840 type : 'string' ,
2941 alias : 'i'
@@ -36,9 +48,9 @@ const cli = meow(`
3648
3749 await globby ( [ '*' , '{,!(node_modules)/**/}' , '!*.min.*' , `!{${ cli . flags . ignore } }` ] ) . then ( async files => {
3850 const minifyHtml = async ( ) => {
39- const html = await files . filter ( name => path . extname ( name ) . substr ( 1 ) === 'html' ) ;
51+ const html = await files . filter ( name => hasExt ( name , 'html' ) ) ;
4052
41- html . map ( async file => {
53+ await html . map ( async file => {
4254 const contents = await fs . readFileSync ( file , 'utf8' ) ;
4355
4456 if ( contents === '' ) {
@@ -58,7 +70,10 @@ const cli = meow(`
5870 minifyURLs : true
5971 } ) ;
6072
61- fs . writeFile ( upath . changeExt ( file , '.min.html' ) , output , err => {
73+ const path = await `${ cli . flags . output } /` + file . substring ( 0 , file . lastIndexOf ( '/' ) ) ;
74+ await makeDir ( path ) ;
75+
76+ fs . writeFile ( `${ cli . flags . output } /${ upath . changeExt ( file , '.min.html' ) } ` , output , err => {
6277 if ( err ) {
6378 spinner . fail ( 'Error!\n' + err ) ;
6479 }
@@ -67,9 +82,9 @@ const cli = meow(`
6782 } ;
6883
6984 const minifyCss = async ( ) => {
70- const css = await files . filter ( name => path . extname ( name ) . substr ( 1 ) === 'css' ) ;
85+ const css = await files . filter ( name => hasExt ( name , 'css' ) ) ;
7186
72- css . map ( async file => {
87+ await css . map ( async file => {
7388 const contents = await fs . readFileSync ( file , 'utf8' ) ;
7489
7590 if ( contents === '' ) {
@@ -78,7 +93,10 @@ const cli = meow(`
7893
7994 const output = await new CleanCSS ( ) . minify ( contents ) ;
8095
81- fs . writeFile ( upath . changeExt ( file , '.min.css' ) , output . styles , err => {
96+ const path = await `${ cli . flags . output } /` + file . substring ( 0 , file . lastIndexOf ( '/' ) ) ;
97+ await makeDir ( path ) ;
98+
99+ fs . writeFile ( `${ cli . flags . output } /${ upath . changeExt ( file , '.min.css' ) } ` , output . styles , err => {
82100 if ( err ) {
83101 spinner . fail ( 'Error!\n' + err ) ;
84102 }
@@ -87,9 +105,9 @@ const cli = meow(`
87105 } ;
88106
89107 const minifyJs = async ( ) => {
90- const js = await files . filter ( name => path . extname ( name ) . substr ( 1 ) === 'js' ) ;
108+ const js = await files . filter ( name => hasExt ( name , 'js' ) ) ;
91109
92- js . map ( async file => {
110+ await js . map ( async file => {
93111 const contents = await fs . readFileSync ( file , 'utf8' ) ;
94112
95113 if ( contents === '' ) {
@@ -111,15 +129,37 @@ const cli = meow(`
111129 }
112130 } ) ;
113131
114- fs . writeFile ( upath . changeExt ( file , '.min.js' ) , output . code , err => {
132+ const path = await `${ cli . flags . output } /` + file . substring ( 0 , file . lastIndexOf ( '/' ) ) ;
133+ await makeDir ( path ) ;
134+
135+ fs . writeFile ( `${ cli . flags . output } /${ upath . changeExt ( file , '.min.js' ) } ` , output . code , err => {
115136 if ( err ) {
116137 spinner . fail ( 'Error!\n' + err ) ;
117138 }
118139 } ) ;
119140 } ) ;
120141 } ;
121142
122- Promise . all ( [ minifyHtml ( ) , minifyCss ( ) , minifyJs ( ) ] ) . then ( ( ) => {
143+ const minifyImages = async ( ) => {
144+ const images = await files . filter ( name => hasExt ( name , [ 'jpg' , 'png' , 'svg' ] ) ) ;
145+
146+ await imagemin ( images , `${ cli . flags . output } /images` , {
147+ plugins : [
148+ imageminMozjpeg ( ) ,
149+ imageminPngquant ( ) ,
150+ imageminSvgo ( )
151+ ]
152+ } ) ;
153+ } ;
154+
155+ const actions = [
156+ ( ) => minifyHtml ( ) ,
157+ ( ) => minifyCss ( ) ,
158+ ( ) => minifyJs ( ) ,
159+ ( ) => minifyImages ( )
160+ ] ;
161+
162+ await pAll ( actions , { concurrency : 4 } ) . then ( ( ) => {
123163 spinner . succeed ( 'Done!' ) ;
124164 } ) ;
125165 } ) . catch ( error => {
0 commit comments