@@ -6,22 +6,45 @@ const chalk = require('chalk');
6
6
const prettyBytes = require ( 'pretty-bytes' ) ;
7
7
const StreamCounter = require ( 'stream-counter' ) ;
8
8
const gzipSize = require ( 'gzip-size' ) ;
9
+ const brotliSize = require ( 'brotli-size' ) ;
9
10
10
- module . exports = options => {
11
+ function hasSize ( sizes ) {
12
+ return [ ...sizes . values ( ) ] . some ( size => size > 0 ) ;
13
+ }
14
+
15
+ function promisify ( stream , property , event = 'end' ) {
16
+ return new Promise ( ( resolve , reject ) => {
17
+ stream . on ( event , ( ) => resolve ( stream [ property ] ) )
18
+ . on ( 'error' , error => reject ( error ) ) ;
19
+ } ) ;
20
+ }
21
+
22
+ module . exports = ( options = { } ) => {
11
23
options = {
12
24
pretty : true ,
13
25
showTotal : true ,
26
+ uncompressed : options . uncompressed || ! ( options . gzip || options . brotli ) ,
14
27
...options
15
28
} ;
16
29
17
- let totalSize = 0 ;
18
30
let fileCount = 0 ;
31
+ const totalSize = new Map ( ) ;
19
32
20
- function log ( what , size ) {
33
+ const description = new Map ( [
34
+ [ 'uncompressed' , '' ] ,
35
+ [ 'gzip' , ' (gzipped)' ] ,
36
+ [ 'brotli' , ' (brotli)' ]
37
+ ] ) ;
38
+
39
+ function log ( what , sizes ) {
21
40
let { title} = options ;
22
41
title = title ? chalk . cyan ( title ) + ' ' : '' ;
23
- size = options . pretty ? prettyBytes ( size ) : ( size + ' B' ) ;
24
- fancyLog ( title + what + ' ' + chalk . magenta ( size ) + ( options . gzip ? chalk . gray ( ' (gzipped)' ) : '' ) ) ;
42
+ const sizeStrings = [ ...sizes ] . map ( ( [ key , size ] ) => {
43
+ size = options . pretty ? prettyBytes ( size ) : ( size + ' B' ) ;
44
+ return chalk . magenta ( size ) + chalk . gray ( description . get ( key ) ) ;
45
+ } ) ;
46
+
47
+ fancyLog ( title + what + ' ' + sizeStrings . join ( chalk . magenta ( ', ' ) ) ) ;
25
48
}
26
49
27
50
return through . obj ( ( file , encoding , callback ) => {
@@ -30,56 +53,67 @@ module.exports = options => {
30
53
return ;
31
54
}
32
55
33
- const finish = ( error , size ) => {
56
+ const finish = ( error , sizes ) => {
34
57
if ( error ) {
35
58
callback ( new PluginError ( 'gulp-size' , error ) ) ;
36
59
return ;
37
60
}
38
61
39
- totalSize += size ;
62
+ for ( const [ key , size ] of sizes ) {
63
+ totalSize . set ( key , size + ( totalSize . get ( key ) || 0 ) ) ;
64
+ }
40
65
41
- if ( options . showFiles === true && size > 0 ) {
42
- log ( chalk . blue ( file . relative ) , size ) ;
66
+ if ( options . showFiles === true && hasSize ( sizes ) ) {
67
+ log ( chalk . blue ( file . relative ) , sizes ) ;
43
68
}
44
69
45
70
fileCount ++ ;
46
71
callback ( null , file ) ;
47
72
} ;
48
73
74
+ const selectedSizes = new Map ( ) ;
49
75
if ( file . isStream ( ) ) {
76
+ if ( options . uncompressed ) {
77
+ selectedSizes . set ( 'uncompressed' , promisify ( file . contents . pipe ( new StreamCounter ( ) ) , 'bytes' , 'finish' ) ) ;
78
+ }
79
+
50
80
if ( options . gzip ) {
51
- file . contents . pipe ( gzipSize . stream ( ) )
52
- . on ( 'error' , finish )
53
- . on ( 'end' , function ( ) {
54
- finish ( null , this . gzipSize ) ;
55
- } ) ;
56
- } else {
57
- file . contents . pipe ( new StreamCounter ( ) )
58
- . on ( 'error' , finish )
59
- . on ( 'finish' , function ( ) {
60
- finish ( null , this . bytes ) ;
61
- } ) ;
81
+ selectedSizes . set ( 'gzip' , promisify ( file . contents . pipe ( gzipSize . stream ( ) ) , 'gzipSize' ) ) ;
62
82
}
63
83
64
- return ;
84
+ if ( options . brotli ) {
85
+ selectedSizes . set ( 'brotli' , promisify ( file . contents . pipe ( brotliSize . stream ( ) ) , 'brotliSize' ) ) ;
86
+ }
65
87
}
66
88
67
- if ( options . gzip ) {
68
- ( async ( ) => {
69
- try {
70
- finish ( null , await gzipSize ( file . contents ) ) ;
71
- } catch ( error ) {
72
- finish ( error ) ;
73
- }
74
- } ) ( ) ;
75
- } else {
76
- finish ( null , file . contents . length ) ;
89
+ if ( file . isBuffer ( ) ) {
90
+ if ( options . uncompressed ) {
91
+ selectedSizes . set ( 'uncompressed' , file . contents . length ) ;
92
+ }
93
+
94
+ if ( options . gzip ) {
95
+ selectedSizes . set ( 'gzip' , gzipSize ( file . contents ) ) ;
96
+ }
97
+
98
+ if ( options . brotli ) {
99
+ selectedSizes . set ( 'brotli' , brotliSize . default ( file . contents ) ) ;
100
+ }
77
101
}
78
- } , function ( callback ) {
79
- this . size = totalSize ;
80
- this . prettySize = prettyBytes ( totalSize ) ;
81
102
82
- if ( ! ( fileCount === 1 && options . showFiles ) && totalSize > 0 && fileCount > 0 && options . showTotal ) {
103
+ ( async ( ) => {
104
+ try {
105
+ // We want to keep the names
106
+ const sizes = await Promise . all ( [ ...selectedSizes ] . map ( async ( [ key , size ] ) => [ key , await size ] ) ) ;
107
+
108
+ finish ( null , new Map ( sizes ) ) ;
109
+ } catch ( error ) {
110
+ finish ( error ) ;
111
+ }
112
+ } ) ( ) ;
113
+ } , function ( callback ) {
114
+ this . size = totalSize . values ( ) . next ( ) . value ;
115
+ this . prettySize = prettyBytes ( this . size ) ;
116
+ if ( ! ( fileCount === 1 && options . showFiles ) && hasSize ( totalSize ) && fileCount > 0 && options . showTotal ) {
83
117
log ( chalk . green ( 'all files' ) , totalSize ) ;
84
118
}
85
119
0 commit comments