Skip to content

Commit da81cb0

Browse files
authored
Prettier reporter (#321)
* add matched path info to files * get colors from ava * rewrite reporter * add compression to output * update snapsohts * rename tiny things * clean up main function * update snapshots * tiny change, big cleanup
1 parent 5ce8b93 commit da81cb0

File tree

10 files changed

+216
-40
lines changed

10 files changed

+216
-40
lines changed

index.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,34 @@
11
#!/usr/bin/env node
22

33
const { inspect } = require('util')
4-
const files = require('./src/files')
4+
const config = require('./src/files')
5+
const analyse = require('./src/analyse')
6+
const cli = require('./src/reporters/cli')
57
const reporter = require('./src/reporter')
68
const build = require('./src/build')
79

8-
reporter(files)
10+
const report = analyse(config)
11+
cli.report(report)
12+
// broke this
13+
// reporter(report.files)
914

1015
process.on('unhandledRejection', function(reason) {
1116
console.log('Unhandled Promise')
1217
console.log(inspect(reason))
1318
build.error()
1419
})
20+
21+
/*
22+
This is the ideal structure to get to:
23+
24+
- utilities function
25+
- pipe results down
26+
27+
start()
28+
.then(getConfig)
29+
.then(attachFiles)
30+
.then(attachSize)
31+
.then(attachComparison)
32+
.then(reportOnCli)
33+
.then(reportOnBuild)
34+
*/

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,13 @@
4242
"ci-env": "^1.4.0",
4343
"commander": "^2.20.0",
4444
"cosmiconfig": "^5.2.1",
45+
"figures": "^3.0.0",
4546
"github-build": "^1.2.0",
4647
"glob": "^7.1.4",
4748
"gzip-size": "^4.0.0",
48-
"prettycli": "^1.4.3"
49+
"plur": "^3.1.1",
50+
"prettycli": "^1.4.3",
51+
"right-pad": "^1.0.1"
4952
},
5053
"lint-staged": {
5154
"*.js": [

src/analyse.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
loop through files and add
3+
pass: true|false
4+
*/
5+
6+
const bytes = require('bytes')
7+
8+
function analyse(config) {
9+
return config.files.map(function(row) {
10+
row.filesMatched.map(function(file) {
11+
if (bytes.parse(file.size) > bytes.parse(row.maxSize)) file.pass = false
12+
else file.pass = true
13+
})
14+
return row
15+
})
16+
}
17+
18+
module.exports = analyse

src/config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ if (!configFromFile && !configFromCli) {
7676
)
7777
}
7878

79-
const config = configFromCli || configFromFile
79+
const files = configFromCli || configFromFile
8080

8181
debug('cli config', configFromCli)
8282
debug('file config', configFromFile)
83-
debug('selected config', config)
83+
debug('selected config', files)
8484

85-
module.exports = config
85+
module.exports = { files }

src/files.js

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,25 @@ const { error } = require('prettycli')
55
const config = require('./config')
66
const debug = require('./debug')
77
const compressedSize = require('./compressed-size')
8-
const files = []
98

10-
config.map(file => {
11-
const paths = glob.sync(file.path)
12-
if (!paths.length) {
13-
error(`There is no matching file for ${file.path} in ${process.cwd()}`, {
9+
config.files.map(row => {
10+
row.filesMatched = []
11+
12+
const files = glob.sync(row.path)
13+
14+
files.map(path => {
15+
const compression = row.compression || 'gzip'
16+
const size = compressedSize(fs.readFileSync(path, 'utf8'), compression)
17+
row.filesMatched.push({ path, size })
18+
})
19+
20+
if (!row.filesMatched.length) {
21+
error(`There is no matching file for ${row.path} in ${process.cwd()}`, {
1422
silent: true
1523
})
16-
} else {
17-
paths.map(path => {
18-
const maxSize = bytes(file.maxSize) || Infinity
19-
const compression = file.compression || 'gzip'
20-
const size = compressedSize(fs.readFileSync(path, 'utf8'), compression)
21-
files.push({ maxSize, path, size, compression })
22-
})
2324
}
2425
})
2526

26-
debug('files', files)
27+
debug('files', config)
2728

28-
module.exports = files
29+
module.exports = config

src/reporter.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,13 @@ const getGlobalMessage = ({
5353
const prettyChange =
5454
change === 0
5555
? 'no change'
56-
: change > 0 ? `+${bytes(change)}` : `-${bytes(Math.abs(change))}`
56+
: change > 0
57+
? `+${bytes(change)}`
58+
: `-${bytes(Math.abs(change))}`
5759

58-
globalMessage = `${failures} out of ${results.length} bundles are too big! (${prettyChange})`
60+
globalMessage = `${failures} out of ${
61+
results.length
62+
} bundles are too big! (${prettyChange})`
5963
} else {
6064
// multiple files, no failures
6165
const prettySize = bytes(totalSize)
@@ -64,7 +68,9 @@ const getGlobalMessage = ({
6468
const prettyChange =
6569
change === 0
6670
? 'no change'
67-
: change > 0 ? `+${bytes(change)}` : `-${bytes(Math.abs(change))}`
71+
: change > 0
72+
? `+${bytes(change)}`
73+
: `-${bytes(Math.abs(change))}`
6874

6975
globalMessage = `Total bundle size is ${prettySize}/${prettyMaxSize} (${prettyChange})`
7076
}
@@ -127,7 +133,7 @@ const analyse = ({ files, masterValues }) => {
127133
})
128134
}
129135

130-
const report = ({ files, globalMessage, fail }) => {
136+
const globalReport = ({ files, globalMessage, fail }) => {
131137
/* prepare the build page */
132138
const params = encodeURIComponent(
133139
JSON.stringify({ files, repo, branch, commit_message, sha })
@@ -160,7 +166,7 @@ const compare = (files, masterValues = {}) => {
160166
})
161167

162168
let fail = results.filter(result => result.fail).length > 0
163-
report({ files, globalMessage, fail })
169+
globalReport({ files, globalMessage, fail })
164170
}
165171

166172
const reporter = files => {

src/reporters/cli.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
const rightpad = require('right-pad')
2+
const figures = require('figures')
3+
const bytes = require('bytes')
4+
const plur = require('plur')
5+
6+
const colors = require('../utils/colors')
7+
8+
function report(results) {
9+
const maxFileLength = getMaxFileLenght(results)
10+
11+
const counter = { pass: 0, fail: 0 }
12+
13+
results.forEach(function(row) {
14+
printBlockHeader(row)
15+
16+
row.filesMatched.forEach(function(file) {
17+
printRow(file, row, maxFileLength)
18+
19+
if (file.pass) counter.pass++
20+
else counter.fail++
21+
})
22+
})
23+
24+
printSummary(counter)
25+
26+
// exit with error code 1 if there are any failed checks
27+
if (counter.fail) process.exit(1)
28+
}
29+
30+
module.exports = { report }
31+
32+
function getMaxFileLenght(results) {
33+
let maxFileLength = 0
34+
35+
results.forEach(function(row) {
36+
row.filesMatched.forEach(function(file) {
37+
if (file.path.length > maxFileLength) maxFileLength = file.path.length
38+
})
39+
})
40+
41+
return maxFileLength
42+
}
43+
44+
function printBlockHeader(row) {
45+
console.log()
46+
console.log(colors.subtle(`${figures.line} ${row.path}`))
47+
}
48+
49+
function printRow(file, row, maxFileLength) {
50+
const symbol = getSymbol(file)
51+
const operator = getOperator(file, row)
52+
53+
console.log(
54+
' ',
55+
symbol,
56+
rightpad(file.path, maxFileLength),
57+
' ',
58+
bytes(file.size),
59+
operator,
60+
row.maxSize,
61+
colors.subtle(row.compression || 'gzip')
62+
)
63+
}
64+
65+
function printSummary({ pass, fail }) {
66+
console.log()
67+
68+
if (pass) console.log(colors.pass(' ', pass, plur('check', pass), 'passed'))
69+
if (fail) console.log(colors.fail(' ', fail, plur('check', fail), 'failed'))
70+
71+
console.log()
72+
}
73+
74+
function getSymbol(file) {
75+
return file.pass ? colors.pass(figures.tick) : colors.fail(figures.cross)
76+
}
77+
78+
function getOperator(file, row) {
79+
const fileSize = bytes.parse(file.size)
80+
const maxSize = bytes.parse(row.maxSize)
81+
82+
if (fileSize > maxSize) return colors.fail('>')
83+
if (fileSize === maxSize) return colors.pass('=')
84+
return colors.pass('<')
85+
}

src/utils/colors.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const chalk = require('chalk')
2+
3+
module.exports = {
4+
subtle: chalk.gray,
5+
pass: chalk.green,
6+
fail: chalk.red,
7+
title: chalk.bold,
8+
info: chalk.magenta
9+
}

tests/snapshots/index.js.md

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,68 +8,102 @@ Generated by [AVA](https://ava.li).
88

99
> Snapshot 1
1010
11-
'PASS file-1.js: 270B < maxSize 300B (gzip)'
11+
`─ file-1.js␊
12+
✔ file-1.js 270B < 300B gzip␊
13+
14+
1 check passed`
1215

1316
## 10. pass: match by fuzzy name
1417

1518
> Snapshot 1
1619
17-
`PASS build/vendor-ha5h.js: 270B < maxSize 350B (gzip) ␊
20+
`─ build/vendor-*.js␊
21+
✔ build/vendor-ha5h.js 270B < 350B gzip␊
22+
23+
─ build/**/chunk-*.js␊
24+
✔ build/chunks/chunk-ch0nk.js 270B < 300B gzip␊
1825
19-
PASS build/chunks/chunk-ch0nk.js: 270B < maxSize 300B (gzip)`
26+
2 checks passed`
2027

2128
## 2. fail: single file larger than limit
2229

2330
> Snapshot 1
2431
25-
'FAIL file-2.js: 270B > maxSize 250B (gzip)'
32+
`─ file-2.js␊
33+
✖ file-2.js 270B > 250B gzip␊
34+
35+
1 check failed`
2636

2737
## 3. pass: use brotli
2838

2939
> Snapshot 1
3040
31-
'PASS file-3.js: 245B < maxSize 250B (brotli)'
41+
`─ file-3.js␊
42+
✔ file-3.js 245B < 250B brotli␊
43+
44+
1 check passed`
3245

3346
## 4. fail: dont use compression
3447

3548
> Snapshot 1
3649
37-
'FAIL file-4.js: 437B > maxSize 300B (no compression)'
50+
`─ file-4.js␊
51+
✖ file-4.js 437B > 300B none␊
52+
53+
1 check failed`
3854

3955
## 5. pass: custom config file
4056

4157
> Snapshot 1
4258
43-
'PASS file-5.js: 270B < maxSize 300B (gzip)'
59+
`─ file-5.js␊
60+
✔ file-5.js 270B < 300B gzip␊
61+
62+
1 check passed`
4463

4564
## 6. pass: multiple files, both smaller than limit
4665

4766
> Snapshot 1
4867
49-
`PASS file-61.js: 270B < maxSize 300B (gzip) ␊
68+
`─ file-61.js␊
69+
✔ file-61.js 270B < 300B gzip␊
70+
71+
─ file-62.js␊
72+
✔ file-62.js 270B < 300B gzip␊
5073
51-
PASS file-62.js: 270B < maxSize 300B (gzip)`
74+
2 checks passed`
5275

5376
## 7. fail: multiple files, both bigger than limit
5477

5578
> Snapshot 1
5679
57-
`FAIL file-61.js: 270B > maxSize 200B (gzip) ␊
80+
`─ file-61.js␊
81+
✖ file-61.js 270B > 200B gzip␊
5882
59-
FAIL file-62.js: 270B > maxSize 200B (gzip)`
83+
─ file-62.js␊
84+
✖ file-62.js 270B > 200B gzip␊
85+
86+
2 checks failed`
6087

6188
## 8. fail: multiple files, 1 smaller + 1 bigger than limit
6289

6390
> Snapshot 1
6491
65-
`PASS file-61.js: 270B < maxSize 300B (gzip) ␊
92+
`─ file-61.js␊
93+
✔ file-61.js 270B < 300B gzip␊
94+
95+
─ file-62.js␊
96+
✖ file-62.js 270B > 200B gzip␊
6697
67-
FAIL file-62.js: 270B > maxSize 200B (gzip)`
98+
1 check passed␊
99+
1 check failed`
68100

69101
## 9. pass: catch all js files
70102

71103
> Snapshot 1
72104
73-
`PASS build/chunks/chunk-ch0nk.js: 270B < maxSize 300B (gzip) ␊
105+
`─ build/**/*.js␊
106+
✔ build/chunks/chunk-ch0nk.js 270B < 300B gzip␊
107+
✔ build/vendor-ha5h.js 270B < 300B gzip␊
74108
75-
PASS build/vendor-ha5h.js: 270B < maxSize 300B (gzip)`
109+
2 checks passed`

tests/snapshots/index.js.snap

69 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)