escover 6.2.4 → 6.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ChangeLog CHANGED
@@ -1,3 +1,8 @@
1
+ 2026.05.08, v6.2.5
2
+
3
+ feature:
4
+ - 4c12ec6 responsive: line numbers
5
+
1
6
  2026.05.08, v6.2.4
2
7
 
3
8
  feature:
@@ -5,6 +5,7 @@ import {
5
5
  } from 'table';
6
6
  import chalk from 'chalk';
7
7
 
8
+ const isNumber = (a) => !Number.isNaN(a) && typeof a === 'number';
8
9
  const CWD = process.cwd();
9
10
  const {entries, keys} = Object;
10
11
 
@@ -13,71 +14,64 @@ const makeRed = chalk.hex('#f44336');
13
14
 
14
15
  export default (coverageFile, {skipFull = false} = {}) => {
15
16
  const files = parseCoverageFile(coverageFile, skipFull);
16
-
17
+
17
18
  if (skipFull && !files.length)
18
19
  return '💪 coverage 100% Good Job!\n';
19
-
20
+
20
21
  const totalWidth = process.stdout.columns || 80;
21
-
22
- let showPercent = false;
23
-
24
- if (totalWidth >= 70)
25
- showPercent = true;
26
-
27
- const tableData = buildGroupedTable(files, showPercent);
28
-
22
+ const showPercent = totalWidth >= 70;
23
+
24
+ const percentColWidth = showPercent ? 6 : 0;
25
+ const linesColWidth = 20;
26
+ const borderPadding = 6;
27
+ const fileColWidth = Math.max(10, totalWidth - percentColWidth - linesColWidth - borderPadding);
28
+
29
+ const tableData = buildGroupedTable(files, showPercent, linesColWidth);
30
+
29
31
  const options = createTableOptions({
30
- totalWidth,
31
32
  showPercent,
32
33
  tableData,
34
+ fileColWidth,
35
+ percentColWidth,
36
+ linesColWidth,
33
37
  });
34
-
38
+
35
39
  return table(tableData, options);
36
40
  };
37
41
 
38
- export function createTableOptions({totalWidth, showPercent, tableData}) {
39
- let percentColWidth = 0;
40
-
41
- if (showPercent)
42
- percentColWidth = 8;
43
-
44
- const fileColWidth = Math.floor(totalWidth * 0.45);
45
- const linesColWidth = totalWidth - fileColWidth - percentColWidth - 6;
46
-
42
+ export function createTableOptions({showPercent, tableData, fileColWidth, percentColWidth, linesColWidth, totalWidth}) {
43
+ const width = totalWidth || process.stdout.columns || 80;
44
+
45
+ // если fileColWidth/percentColWidth не переданы — считаем
46
+ const fileWidth = fileColWidth || Math.max(10, width - (showPercent ? 6 : 0) - 20 - 6);
47
+ const percentWidth = percentColWidth || (showPercent ? 8 : 0);
48
+ const linesWidth = linesColWidth || 20;
49
+
47
50
  const columns = [{
48
51
  paddingLeft: 1,
49
52
  paddingRight: 1,
50
- width: fileColWidth,
53
+ width: fileWidth,
51
54
  wrapWord: false,
52
55
  }];
53
-
56
+
54
57
  if (showPercent)
55
58
  columns.push({
56
59
  alignment: 'center',
57
60
  paddingLeft: 1,
58
61
  paddingRight: 0,
59
- width: percentColWidth,
62
+ width: percentWidth,
60
63
  });
61
-
64
+
62
65
  columns.push({
63
66
  paddingLeft: 1,
64
67
  paddingRight: 0,
65
- width: linesColWidth,
68
+ width: linesWidth,
69
+ wrapWord: false,
66
70
  });
67
-
71
+
68
72
  return {
69
- drawHorizontalLine: (raw) => {
70
- if (!raw)
71
- return true;
72
-
73
- if (raw === 1)
74
- return true;
75
-
76
- return raw === tableData.length;
77
- },
78
-
73
+ drawHorizontalLine: (i) => !i || i === 1 || i === tableData.length,
79
74
  columns,
80
-
81
75
  border: {
82
76
  ...getBorderCharacters('void'),
83
77
  topBody: '-',
@@ -89,58 +83,49 @@ export function createTableOptions({totalWidth, showPercent, tableData}) {
89
83
  bodyJoin: '|',
90
84
  },
91
85
  };
92
- };
86
+ }
93
87
 
94
88
  export function groupByFolder(files) {
95
89
  const groups = new Map();
96
-
90
+
97
91
  for (const f of files) {
98
92
  const parts = f.filename.split('/');
99
-
100
- let folder = '';
101
-
102
- if (parts.length > 1)
103
- folder = parts.slice(0, -1).join('/');
104
-
93
+ const folder = parts.length > 1 ? parts
94
+ .slice(0, -1)
95
+ .join('/') : '';
105
96
  const fileName = parts.at(-1);
106
-
97
+
107
98
  let group = groups.get(folder);
108
-
99
+
109
100
  if (!group) {
110
101
  group = {
111
102
  files: [],
112
103
  };
113
104
  groups.set(folder, group);
114
105
  }
115
-
106
+
116
107
  group.files.push({
117
108
  ...f,
118
109
  shortName: fileName,
119
110
  });
120
111
  }
121
-
112
+
122
113
  return groups;
123
114
  }
124
115
 
125
116
  export function parseCoverageFile(coverageFile, skipFull) {
126
117
  const files = [];
127
-
118
+
128
119
  for (const {name, lines} of coverageFile) {
129
120
  const uncovered = parseUncoveredLines(lines);
130
-
131
121
  const linesCount = keys(lines).length;
132
- const uncoveredCount = uncovered.length;
133
-
134
- const percentLines = getLinesPercent(linesCount, uncoveredCount);
135
-
136
- let covered = true;
137
-
138
- if (uncoveredCount > 0)
139
- covered = false;
140
-
122
+ const uncoveredLinesCount = uncovered.length;
123
+ const percentLines = getLinesPercent(linesCount, uncoveredLinesCount);
124
+ const covered = uncoveredLinesCount === 0;
125
+
141
126
  if (skipFull && covered)
142
127
  continue;
143
-
128
+
144
129
  files.push({
145
130
  filename: name.replace(`${CWD}/`, ''),
146
131
  covered,
@@ -148,13 +133,15 @@ export function parseCoverageFile(coverageFile, skipFull) {
148
133
  percentLines,
149
134
  });
150
135
  }
151
-
136
+
152
137
  return files;
153
138
  }
154
139
 
155
- export function buildGroupedTable(files, showPercent) {
156
- const tableData = [];
140
+ export const getColor = (value) => value === 100 ? makeGreen : makeRed;
157
141
 
142
+ export function buildGroupedTable(files, showPercent, linesColWidth) {
143
+ const tableData = [];
144
+
158
145
  if (showPercent)
159
146
  tableData.push([
160
147
  'File',
@@ -166,123 +153,93 @@ export function buildGroupedTable(files, showPercent) {
166
153
  'File',
167
154
  'Uncovered Lines #s',
168
155
  ]);
169
-
156
+
170
157
  const groups = groupByFolder(files);
171
158
  const hideFolders = groups.size === 1;
172
-
159
+
160
+
173
161
  for (const [folder, group] of groups) {
174
162
  let sum = 0;
175
-
163
+
176
164
  for (const f of group.files)
177
165
  sum += f.percentLines;
178
-
179
- let coverage = 100;
180
-
181
- if (group.files.length > 0)
182
- coverage = Math.round(sum / group.files.length);
183
-
166
+
167
+ const coverage = Math.round(sum / group.files.length);
168
+
184
169
  if (!hideFolders) {
185
- let folderLabel = folder;
186
-
187
- if (!folderLabel)
188
- folderLabel = '.';
189
-
190
- const trimmedFolder = trim(folderLabel, 25);
191
-
192
- let folderColor = makeRed;
193
-
194
- if (coverage === 100)
195
- folderColor = makeGreen;
196
-
197
- const headerRow = [folderColor(trimmedFolder)];
198
-
199
- if (showPercent) {
200
- let color = makeRed;
201
-
202
- if (coverage === 100)
203
- color = makeGreen;
204
-
205
- headerRow.push(color(`${coverage}%`));
206
- }
207
-
208
- headerRow.push('');
209
- tableData.push(headerRow);
170
+ const row = [];
171
+ row.push(getColor(coverage)(folder));
172
+
173
+ if (showPercent)
174
+ row.push(getColor(coverage)(`${coverage}%`));
175
+
176
+ row.push('');
177
+ tableData.push(row);
210
178
  }
211
-
179
+
212
180
  for (const f of group.files) {
213
- const fileCell = ' ' + trim(f.shortName, 30);
214
-
215
- let fileColor = makeRed;
216
-
217
- if (f.covered)
218
- fileColor = makeGreen;
219
-
220
- const row = [fileColor(fileCell)];
221
-
222
- if (showPercent) {
223
- let percentColor = makeRed;
224
-
225
- if (f.percentLines === 100)
226
- percentColor = makeGreen;
227
-
228
- row.push(percentColor(`${f.percentLines}%`));
229
- }
230
-
231
- let uncovered = '';
232
-
233
- if (!f.covered)
234
- uncovered = makeRed(formatLines(f.lines));
235
-
236
- row.push(uncovered);
181
+ const row = [];
182
+ row.push(f.covered ? makeGreen(' ' + f.shortName) : makeRed(' ' + f.shortName));
183
+
184
+ if (showPercent)
185
+ row.push(f.percentLines === 100 ? makeGreen(`${f.percentLines}%`) : makeRed(`${f.percentLines}%`));
186
+
187
+ row.push(f.covered ? '' : makeRed(formatLines(
188
+ f.lines,
189
+ linesColWidth,
190
+ )));
237
191
  tableData.push(row);
238
192
  }
239
193
  }
240
-
194
+
241
195
  return tableData;
242
196
  }
243
197
 
244
- function trim(str, max) {
245
- if (str.length <= max)
246
- return str;
247
-
248
- return '...' + str.slice(-(max - 3));
249
- }
250
-
251
- export function formatLines(array) {
252
- if (array.length <= 10) {
253
- const joined = array.join(', ');
254
-
255
- if (joined.length <= 30)
256
- return joined;
198
+ export function formatLines(array, maxLen = 20) {
199
+ const nums = array;
200
+ const ranges = [];
201
+ let [start] = nums;
202
+ let [prev] = nums;
203
+
204
+ for (let i = 1; i < nums.length; i++) {
205
+ const n = nums[i];
206
+
207
+ if (isNumber(prev) && typeof n === 'number' && n === prev + 1 || prev === n - 0) {
208
+ prev = n;
209
+ } else {
210
+ ranges.push(String(start));
211
+ start = n;
212
+ prev = n;
213
+ }
257
214
  }
258
-
259
- const [first] = array;
260
- const last = array.at(-1);
261
-
262
- const base = first + '..' + last;
263
-
264
- if (base.length <= 30)
265
- return base;
266
-
267
- return last;
215
+
216
+ ranges.push(start === prev ? String(start) : `${start}..${prev}`);
217
+
218
+ const joined = ranges.join(', ');
219
+
220
+ if (joined.length <= maxLen)
221
+ return joined;
222
+
223
+ const [first] = ranges;
224
+
225
+ return first;
268
226
  }
269
227
 
270
- function parseUncoveredLines(lines) {
228
+ export function parseUncoveredLines(lines) {
271
229
  const out = [];
272
-
273
- for (const [line, covered] of entries(lines)) {
230
+
231
+ for (const [line, covered] of entries(lines))
274
232
  if (!covered)
275
233
  out.push(line);
276
- }
277
-
234
+
278
235
  return out;
279
236
  }
280
237
 
281
238
  export function getLinesPercent(linesCount, uncoveredLinesCount) {
282
239
  if (!linesCount)
283
240
  return 100;
284
-
285
- const ratio = (100 / linesCount) * uncoveredLinesCount;
286
-
241
+
242
+ const ratio = 100 / linesCount * uncoveredLinesCount;
243
+
287
244
  return 100 - Math.round(ratio);
288
245
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "escover",
3
- "version": "6.2.4",
3
+ "version": "6.2.5",
4
4
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
5
5
  "description": "Coverage for EcmaScript Modules",
6
6
  "main": "lib/escover.js",