1 | const plur = require('plur');
|
2 | const strip = require('strip-ansi');
|
3 |
|
4 | module.exports = {
|
5 | assets(stats) {
|
6 | const result = [];
|
7 |
|
8 |
|
9 | for (const asset of stats.assets) {
|
10 | const assetFile = (asset.name || '').toString();
|
11 | let name = asset.chunkNames.join(', ');
|
12 |
|
13 |
|
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 |
|
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;
|
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 |
|
144 |
|
145 | if (rePerformance.test(problem)) {
|
146 |
|
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 |
|
155 |
|
156 |
|
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 |
|
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 |
|
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 | };
|