escover 6.2.4 → 6.2.6

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,13 @@
1
+ 2026.05.08, v6.2.6
2
+
3
+ feature:
4
+ - d3747a2 formatters: responsive: Lines
5
+
6
+ 2026.05.08, v6.2.5
7
+
8
+ feature:
9
+ - 4c12ec6 responsive: line numbers
10
+
1
11
  2026.05.08, v6.2.4
2
12
 
3
13
  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,58 @@ 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 linesColWidth = 20;
25
+ const percentColWidth = showPercent ? 7 : 0;
26
+
27
+ // резерв на бордеры и padding + дополнительный запас
28
+ const fileColWidth = Math.max(10, totalWidth - linesColWidth - percentColWidth - 6 - 4);
29
+
30
+ const tableData = buildGroupedTable(files, showPercent, linesColWidth);
31
+
29
32
  const options = createTableOptions({
30
- totalWidth,
31
33
  showPercent,
32
34
  tableData,
35
+ fileColWidth,
36
+ percentColWidth,
37
+ linesColWidth,
33
38
  });
34
-
39
+
35
40
  return table(tableData, options);
36
41
  };
37
42
 
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
-
43
+ export function createTableOptions({showPercent, tableData, fileColWidth, percentColWidth, linesColWidth}) {
47
44
  const columns = [{
48
45
  paddingLeft: 1,
49
46
  paddingRight: 1,
50
47
  width: fileColWidth,
51
48
  wrapWord: false,
52
49
  }];
53
-
50
+
54
51
  if (showPercent)
55
52
  columns.push({
56
53
  alignment: 'center',
57
54
  paddingLeft: 1,
58
- paddingRight: 0,
55
+ paddingRight: 1,
59
56
  width: percentColWidth,
60
57
  });
61
-
58
+
62
59
  columns.push({
63
60
  paddingLeft: 1,
64
- paddingRight: 0,
61
+ paddingRight: 1,
65
62
  width: linesColWidth,
63
+ wrapWord: false,
66
64
  });
67
-
65
+
68
66
  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
-
67
+ drawHorizontalLine: (i) => !i || i === 1 || i === tableData.length,
79
68
  columns,
80
-
81
69
  border: {
82
70
  ...getBorderCharacters('void'),
83
71
  topBody: '-',
@@ -89,58 +77,50 @@ export function createTableOptions({totalWidth, showPercent, tableData}) {
89
77
  bodyJoin: '|',
90
78
  },
91
79
  };
92
- };
80
+ }
93
81
 
94
82
  export function groupByFolder(files) {
95
83
  const groups = new Map();
96
-
84
+
97
85
  for (const f of files) {
98
86
  const parts = f.filename.split('/');
99
-
100
- let folder = '';
101
-
102
- if (parts.length > 1)
103
- folder = parts.slice(0, -1).join('/');
104
-
87
+ const folder = parts.length > 1 ? parts
88
+ .slice(0, -1)
89
+ .join('/') : '';
90
+
105
91
  const fileName = parts.at(-1);
106
-
92
+
107
93
  let group = groups.get(folder);
108
-
94
+
109
95
  if (!group) {
110
96
  group = {
111
97
  files: [],
112
98
  };
113
99
  groups.set(folder, group);
114
100
  }
115
-
101
+
116
102
  group.files.push({
117
103
  ...f,
118
104
  shortName: fileName,
119
105
  });
120
106
  }
121
-
107
+
122
108
  return groups;
123
109
  }
124
110
 
125
111
  export function parseCoverageFile(coverageFile, skipFull) {
126
112
  const files = [];
127
-
113
+
128
114
  for (const {name, lines} of coverageFile) {
129
115
  const uncovered = parseUncoveredLines(lines);
130
-
131
116
  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
-
117
+ const uncoveredLinesCount = uncovered.length;
118
+ const percentLines = getLinesPercent(linesCount, uncoveredLinesCount);
119
+ const covered = uncoveredLinesCount === 0;
120
+
141
121
  if (skipFull && covered)
142
122
  continue;
143
-
123
+
144
124
  files.push({
145
125
  filename: name.replace(`${CWD}/`, ''),
146
126
  covered,
@@ -148,13 +128,15 @@ export function parseCoverageFile(coverageFile, skipFull) {
148
128
  percentLines,
149
129
  });
150
130
  }
151
-
131
+
152
132
  return files;
153
133
  }
154
134
 
155
- export function buildGroupedTable(files, showPercent) {
156
- const tableData = [];
135
+ export const getColor = (value) => value === 100 ? makeGreen : makeRed;
157
136
 
137
+ export function buildGroupedTable(files, showPercent, linesColWidth) {
138
+ const tableData = [];
139
+
158
140
  if (showPercent)
159
141
  tableData.push([
160
142
  'File',
@@ -166,123 +148,102 @@ export function buildGroupedTable(files, showPercent) {
166
148
  'File',
167
149
  'Uncovered Lines #s',
168
150
  ]);
169
-
151
+
170
152
  const groups = groupByFolder(files);
171
153
  const hideFolders = groups.size === 1;
172
-
154
+
173
155
  for (const [folder, group] of groups) {
174
156
  let sum = 0;
175
-
157
+
176
158
  for (const f of group.files)
177
159
  sum += f.percentLines;
178
-
179
- let coverage = 100;
180
-
181
- if (group.files.length > 0)
182
- coverage = Math.round(sum / group.files.length);
183
-
160
+
161
+ const coverage = Math.round(sum / group.files.length);
162
+
184
163
  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);
164
+ const row = [];
165
+ row.push(getColor(coverage)(folder));
166
+
167
+ if (showPercent)
168
+ row.push(getColor(coverage)(`${coverage}%`));
169
+
170
+ row.push('');
171
+ tableData.push(row);
210
172
  }
211
-
173
+
212
174
  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);
175
+ const row = [];
176
+ row.push(f.covered ? makeGreen(' ' + f.shortName) : makeRed(' ' + f.shortName));
177
+
178
+ if (showPercent)
179
+ row.push(f.percentLines === 100 ? makeGreen(`${f.percentLines}%`) : makeRed(`${f.percentLines}%`));
180
+
181
+ row.push(f.covered ? '' : makeRed(formatLines(
182
+ f.lines,
183
+ linesColWidth,
184
+ )));
237
185
  tableData.push(row);
238
186
  }
239
187
  }
240
-
188
+
241
189
  return tableData;
242
190
  }
243
191
 
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)
192
+ export function formatLines(array, maxLen = 20) {
193
+ if (array.every(isNumber)) {
194
+ const nums = array
195
+ .slice()
196
+ .sort((a, b) => a - b);
197
+ const ranges = [];
198
+ let [start] = nums;
199
+ let [prev] = nums;
200
+
201
+ for (let i = 1; i < nums.length; i++) {
202
+ const n = nums[i];
203
+
204
+ if (n === prev + 1) {
205
+ prev = n;
206
+ } else {
207
+ ranges.push(start === prev ? String(start) : `${start}..${prev}`);
208
+ start = n;
209
+ prev = n;
210
+ }
211
+ }
212
+
213
+ ranges.push(start === prev ? String(start) : `${start}..${prev}`);
214
+
215
+ const joined = ranges.join(', ');
216
+
217
+ if (joined.length <= maxLen)
256
218
  return joined;
219
+
220
+ return ranges[0];
257
221
  }
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;
222
+
223
+ // если элементы строки — просто объединяем через ', ' и усечем
224
+ const joined = array.join(', ');
225
+
226
+ if (joined.length <= maxLen)
227
+ return joined;
228
+
229
+ return array[0];
268
230
  }
269
231
 
270
- function parseUncoveredLines(lines) {
232
+ export function parseUncoveredLines(lines) {
271
233
  const out = [];
272
-
273
- for (const [line, covered] of entries(lines)) {
234
+
235
+ for (const [line, covered] of entries(lines))
274
236
  if (!covered)
275
- out.push(line);
276
- }
277
-
237
+ out.push(Number(line));
238
+
278
239
  return out;
279
240
  }
280
241
 
281
242
  export function getLinesPercent(linesCount, uncoveredLinesCount) {
282
243
  if (!linesCount)
283
244
  return 100;
284
-
285
- const ratio = (100 / linesCount) * uncoveredLinesCount;
286
-
245
+
246
+ const ratio = 100 / linesCount * uncoveredLinesCount;
247
+
287
248
  return 100 - Math.round(ratio);
288
249
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "escover",
3
- "version": "6.2.4",
3
+ "version": "6.2.6",
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",