UNPKG

5.63 kBJavaScriptView Raw
1const plur = require('plur');
2const strip = require('strip-ansi');
3
4module.exports = {
5 assets(stats) {
6 const result = [];
7
8 // ['49.1 kB', 'main', './output.js', 'emitted'],
9 for (const asset of stats.assets) {
10 const assetFile = (asset.name || '').toString();
11 let name = asset.chunkNames.join(', ');
12
13 // some loaders populate chunkNames
14 if (!name) {
15 const matches = assetFile.match(/\.[\w]+$/);
16 name = matches && matches.length > 0 ? matches[0].substring(1) : '<unknown>';
17 }
18
19 result.push([asset.size, name, assetFile, [asset.emitted ? 'emitted' : '']]);
20 }
21
22 return result;
23 },
24
25 files(stats) {
26 const assets = module.exports.assets(stats);
27 const modules = module.exports.modules(stats);
28 let result = [].concat(module.exports.header(), modules);
29
30 if (assets.length) {
31 result = result.concat([['', '', '', '']], module.exports.header('asset'), assets);
32 }
33
34 return result;
35 },
36
37 footer(state) {
38 const { totals } = state;
39 if (state.instances > 1) {
40 totals.time = state.time;
41 }
42 return totals;
43 },
44
45 header(type) {
46 return [['size', 'name', type || 'module', 'status']];
47 },
48
49 hidden(stats) {
50 const result = [];
51 const assets = stats.filteredAssets;
52 const modules = stats.filteredModules;
53
54 if (assets > 0) {
55 result.push(`${assets} ${plur('asset', assets)}`);
56 }
57
58 if (modules > 0) {
59 result.push(`${modules} ${plur('module', modules)}`);
60 }
61
62 return result.length ? `(${result.join(', ')} hidden)` : '';
63 },
64
65 modules(stats) {
66 const result = [];
67 const { status } = module.exports;
68 const reLoader = /(.+node_modules\/)((.+-loader).+!)/i;
69 const reNodeModules = /(.*)node_modules/;
70
71 for (const module of stats.modules) {
72 let modulePath = (module.name || module.identifier).toString();
73
74 if (reLoader.test(modulePath)) {
75 modulePath = modulePath.replace(reLoader, '$3!');
76 } else if (reNodeModules.test(modulePath)) {
77 modulePath = modulePath.replace(reNodeModules, '(node_modules)');
78 }
79
80 const row = [module.size, module.id.toString(), modulePath, status(module)];
81
82 result.push(row);
83 }
84
85 return result;
86 },
87
88 problems(stats, state) {
89 const probs = {};
90
91 for (const level of ['errors', 'warnings']) {
92 for (const reported of stats[level]) {
93 const item = module.exports.problem(reported);
94 const { file } = item;
95 const problem = probs[file] || { errors: [], warnings: [] };
96
97 problem[level].push(item);
98
99 for (const module of stats.modules) {
100 // manually update the error count. something is broken in webpack
101 if (file === module.id || file === module.name || file === module.identifier) {
102 module[level] += 1;
103 }
104 }
105
106 probs[file] = problem;
107 state.totals[level] += 1; // eslint-disable-line no-param-reassign
108 }
109 }
110
111 return probs;
112 },
113
114 problem(original) {
115 const reFileList = /((assets|entrypoints):[\s\S]+)$/i;
116 const rePerformance = /^([\w ]+ limit|[\w ]+ recommendations): /i;
117 const rePosition = /\s?\(?((\d+):(\d+))(-\d+)?\)?/;
118
119 let problem = strip(` ${original}`.slice(1));
120 let file;
121 let fileList;
122 let line;
123 let column;
124 // let message;
125
126 if (rePerformance.test(problem)) {
127 // the prefix of the performance errors are overly verbose for stylish
128 file = 'performance';
129 problem = problem.replace(rePerformance, '');
130 }
131
132 if (reFileList.test(problem)) {
133 const matches = problem.match(reFileList);
134 fileList = matches.length ? matches[0] : '<stylish-error>';
135 // replace spaces with a unicode character we can replace later to
136 // preserve formatting, and allow for automation. replace 3 spaces with
137 // 2 to match stylish output.
138 fileList = fileList
139 .trim()
140 .replace(/ {3}/g, ' ')
141 .replace(/ /g, '░');
142 problem = problem.replace(reFileList, '');
143 }
144
145 const lines = problem.trim().split('\n');
146
147 if (!file) {
148 [file] = lines;
149 } else {
150 lines.unshift('');
151 }
152
153 let [, message] = lines;
154 message = message || 'webpack-stylish: <please report unknown message format>';
155
156 if (rePosition.test(message)) {
157 // warnings position format (beginning of the message)
158 [, , line, column] = message.match(rePosition) || [0, 0, 0, 0];
159
160 if (lines.length > 3) {
161 message = lines.slice(1, lines.length).join(' ');
162 }
163 } else {
164 // errors position format (end of the message)
165 const position = lines[lines.length - 1];
166 if (rePosition.test(position)) {
167 [, , line, column] = position.match(rePosition) || [0, 0, 0, 0];
168 message = lines.slice(1, lines.length - 1).join(' ');
169 } else {
170 [line, column] = [0, 0];
171 }
172 }
173
174 const item = {
175 file,
176 message: message.replace(rePosition, '').trim(),
177 line,
178 column
179 };
180
181 if (fileList) {
182 item.message += `\n ${fileList}`;
183 }
184
185 return item;
186 },
187
188 status(module) {
189 const result = [];
190
191 if (module.cacheable === false) {
192 result.push('no-cache');
193 }
194
195 if (module.optional) {
196 result.push('optional');
197 }
198
199 if (module.built) {
200 result.push('built');
201 }
202
203 if (module.prefetched) {
204 result.push('prefetch');
205 }
206
207 if (module.failed) {
208 result.push('failed');
209 }
210
211 if (module.warnings) {
212 result.push('warning');
213 }
214
215 if (module.errors) {
216 result.push('error');
217 }
218
219 return result;
220 }
221};