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 = 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 |
|
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;
|
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 |
|
125 |
|
126 | if (rePerformance.test(problem)) {
|
127 |
|
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 |
|
136 |
|
137 |
|
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 |
|
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 |
|
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 | };
|