UNPKG

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