UNPKG

3.07 kBJavaScriptView Raw
1const capitalize = require('titleize');
2const chalk = require('chalk');
3const ora = require('ora');
4
5const parse = require('./parse');
6const Reporter = require('./Reporter');
7
8const style = require('./stylish/style');
9
10module.exports = class StylishReporter extends Reporter {
11 constructor(options) {
12 super(options);
13
14 this.rendered = {
15 footer: false,
16 header: false,
17 };
18
19 this.spinner = ora();
20
21 this.state = {
22 active: 0,
23 hashes: [],
24 instances: 0,
25 totals: {
26 errors: 0,
27 time: 0,
28 warnings: 0,
29 },
30 time: 0,
31 };
32 }
33
34 // TODO: create proper testing for this with a large build an stdout hooks.
35 /* istanbul ignore next */
36 progress(stage) {
37 if (!this.spinner.isSpinning && stage.step.percentage < 1) {
38 this.spinner.start(stage.step.name);
39 }
40
41 const name = capitalize(stage.step.name);
42 const percent = Math.floor(stage.step.percentage * 100);
43
44 this.spinner.text = chalk`${name} {dim (${percent}%)}`;
45
46 if (stage.step.percentage >= 1) {
47 this.spinner.stop();
48 }
49 }
50
51 render(error, resultStats) {
52 // handles both Stats and MultiStats
53 const allStats = resultStats.stats || [resultStats];
54 const compilers = this.compiler.compilers || [this.compiler];
55 const { log } = console;
56 const { compiler, state, rendered } = this;
57 const opts = {
58 context: compiler.context,
59 cached: false,
60 cachedAssets: false,
61 exclude: ['node_modules', 'bower_components', 'components'],
62 };
63 const out = [];
64 const first = allStats[0].toJson(opts, true);
65 const { version } = first;
66
67 out.push(chalk.cyan(`\nwebpack v${version}\n`));
68
69 state.instances = allStats.length;
70
71 for (const stats of allStats) {
72 const json = stats.toJson(opts, true);
73
74 // for --watch more than anything, don't print duplicate output for a hash
75 // if we've already seen that hash. compensates for a bug in webpack.
76 if (state.hashes.includes(json.hash)) {
77 return;
78 }
79
80 state.hashes.push(json.hash);
81 state.time += json.time;
82
83 // errors and warnings go first, to make sure the counts are correct for modules
84 const compilerIndex = allStats.indexOf(stats);
85 const compilerOptions = compilers[compilerIndex].options;
86 const problems = style.problems(parse.problems(json, state));
87 const files = style.files(parse.files(json), compilerOptions);
88 const hidden = style.hidden(parse.hidden(json));
89 const hash = style.hash(json, files, hidden);
90
91 out.push(hash);
92 out.push(problems);
93 }
94
95 const footer = style.footer(parse.footer(state));
96
97 if (footer.length) {
98 rendered.footer = true;
99 out.push(footer);
100 }
101
102 state.totals = { errors: 0, time: 0, warnings: 0 };
103
104 const result = out.join('\n');
105
106 log(result);
107
108 if (
109 rendered.footer &&
110 compilers.some((comp) => comp.options.watch === true)
111 ) {
112 log();
113 }
114
115 // eslint-disable-next-line consistent-return
116 return result;
117 }
118};