UNPKG

3.09 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 if (error) {
53 return error;
54 }
55
56 // handles both Stats and MultiStats
57 const allStats = resultStats.stats || [resultStats];
58 const compilers = this.compiler.compilers || [this.compiler];
59 const { compiler, state, rendered } = this;
60 const { log } = console;
61 const opts = {
62 context: compiler.context,
63 cached: false,
64 cachedAssets: false,
65 exclude: ['node_modules', 'bower_components', 'components']
66 };
67 const out = [];
68 const first = allStats[0].toJson(opts, true);
69 const { version } = first;
70
71 out.push(chalk.cyan(`\nwebpack v${version}\n`));
72
73 state.instances = allStats.length;
74
75 for (const stats of allStats) {
76 const json = stats.toJson(opts, true);
77
78 // for --watch more than anything, don't print duplicate output for a hash
79 // if we've already seen that hash. compensates for a bug in webpack.
80 if (state.hashes.includes(json.hash)) {
81 return null;
82 }
83
84 state.hashes.push(json.hash);
85 state.time += json.time;
86
87 // errors and warnings go first, to make sure the counts are correct for modules
88 const compilerIndex = allStats.indexOf(stats);
89 const compilerOptions = compilers[compilerIndex].options;
90 const problems = style.problems(parse.problems(json, state));
91 const files = style.files(parse.files(json), compilerOptions);
92 const hidden = style.hidden(parse.hidden(json));
93 const hash = style.hash(json, files, hidden);
94
95 out.push(hash);
96 out.push(problems);
97 }
98
99 const footer = style.footer(parse.footer(state));
100
101 if (footer.length) {
102 rendered.footer = true;
103 out.push(footer);
104 }
105
106 state.totals = { errors: 0, time: 0, warnings: 0 };
107
108 const result = out.join('\n');
109
110 log(result);
111
112 if (rendered.footer && compilers.some((comp) => comp.options.watch === true)) {
113 log();
114 }
115
116 // eslint-disable-next-line consistent-return
117 return result;
118 }
119};