escover 6.2.3 → 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,13 @@
1
+ 2026.05.08, v6.2.5
2
+
3
+ feature:
4
+ - 4c12ec6 responsive: line numbers
5
+
6
+ 2026.05.08, v6.2.4
7
+
8
+ feature:
9
+ - 39420cf formatters: responsive: simplify
10
+
1
11
  2026.05.08, v6.2.3
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
 
@@ -18,26 +19,38 @@ export default (coverageFile, {skipFull = false} = {}) => {
18
19
  return '💪 coverage 100% Good Job!\n';
19
20
 
20
21
  const totalWidth = process.stdout.columns || 80;
22
+ const showPercent = totalWidth >= 70;
21
23
 
22
- let showPercent = false;
24
+ const percentColWidth = showPercent ? 6 : 0;
25
+ const linesColWidth = 20;
26
+ const borderPadding = 6;
27
+ const fileColWidth = Math.max(10, totalWidth - percentColWidth - linesColWidth - borderPadding);
23
28
 
24
- if (totalWidth >= 70)
25
- showPercent = true;
29
+ const tableData = buildGroupedTable(files, showPercent, linesColWidth);
26
30
 
27
- let percentColWidth = 0;
28
-
29
- if (showPercent)
30
- percentColWidth = 8;
31
+ const options = createTableOptions({
32
+ showPercent,
33
+ tableData,
34
+ fileColWidth,
35
+ percentColWidth,
36
+ linesColWidth,
37
+ });
31
38
 
32
- const fileColWidth = Math.floor(totalWidth * 0.45);
33
- const linesColWidth = totalWidth - fileColWidth - percentColWidth - 6;
39
+ return table(tableData, options);
40
+ };
41
+
42
+ export function createTableOptions({showPercent, tableData, fileColWidth, percentColWidth, linesColWidth, totalWidth}) {
43
+ const width = totalWidth || process.stdout.columns || 80;
34
44
 
35
- const tableData = buildGroupedTable(files, showPercent);
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;
36
49
 
37
50
  const columns = [{
38
51
  paddingLeft: 1,
39
52
  paddingRight: 1,
40
- width: fileColWidth,
53
+ width: fileWidth,
41
54
  wrapWord: false,
42
55
  }];
43
56
 
@@ -46,28 +59,19 @@ export default (coverageFile, {skipFull = false} = {}) => {
46
59
  alignment: 'center',
47
60
  paddingLeft: 1,
48
61
  paddingRight: 0,
49
- width: percentColWidth,
62
+ width: percentWidth,
50
63
  });
51
64
 
52
65
  columns.push({
53
66
  paddingLeft: 1,
54
67
  paddingRight: 0,
55
- width: linesColWidth,
68
+ width: linesWidth,
69
+ wrapWord: false,
56
70
  });
57
71
 
58
- const options = {
59
- drawHorizontalLine: (raw) => {
60
- if (!raw)
61
- return true;
62
-
63
- if (raw === 1)
64
- return true;
65
-
66
- return raw === tableData.length;
67
- },
68
-
72
+ return {
73
+ drawHorizontalLine: (i) => !i || i === 1 || i === tableData.length,
69
74
  columns,
70
-
71
75
  border: {
72
76
  ...getBorderCharacters('void'),
73
77
  topBody: '-',
@@ -79,23 +83,16 @@ export default (coverageFile, {skipFull = false} = {}) => {
79
83
  bodyJoin: '|',
80
84
  },
81
85
  };
82
-
83
- return table(tableData, options);
84
- };
86
+ }
85
87
 
86
- function groupByFolder(files) {
88
+ export function groupByFolder(files) {
87
89
  const groups = new Map();
88
90
 
89
91
  for (const f of files) {
90
92
  const parts = f.filename.split('/');
91
-
92
- let folder = '';
93
-
94
- if (parts.length > 1)
95
- folder = parts
96
- .slice(0, -1)
97
- .join('/');
98
-
93
+ const folder = parts.length > 1 ? parts
94
+ .slice(0, -1)
95
+ .join('/') : '';
99
96
  const fileName = parts.at(-1);
100
97
 
101
98
  let group = groups.get(folder);
@@ -116,7 +113,33 @@ function groupByFolder(files) {
116
113
  return groups;
117
114
  }
118
115
 
119
- function buildGroupedTable(files, showPercent) {
116
+ export function parseCoverageFile(coverageFile, skipFull) {
117
+ const files = [];
118
+
119
+ for (const {name, lines} of coverageFile) {
120
+ const uncovered = parseUncoveredLines(lines);
121
+ const linesCount = keys(lines).length;
122
+ const uncoveredLinesCount = uncovered.length;
123
+ const percentLines = getLinesPercent(linesCount, uncoveredLinesCount);
124
+ const covered = uncoveredLinesCount === 0;
125
+
126
+ if (skipFull && covered)
127
+ continue;
128
+
129
+ files.push({
130
+ filename: name.replace(`${CWD}/`, ''),
131
+ covered,
132
+ lines: uncovered,
133
+ percentLines,
134
+ });
135
+ }
136
+
137
+ return files;
138
+ }
139
+
140
+ export const getColor = (value) => value === 100 ? makeGreen : makeRed;
141
+
142
+ export function buildGroupedTable(files, showPercent, linesColWidth) {
120
143
  const tableData = [];
121
144
 
122
145
  if (showPercent)
@@ -134,74 +157,37 @@ function buildGroupedTable(files, showPercent) {
134
157
  const groups = groupByFolder(files);
135
158
  const hideFolders = groups.size === 1;
136
159
 
160
+
137
161
  for (const [folder, group] of groups) {
138
162
  let sum = 0;
139
163
 
140
164
  for (const f of group.files)
141
165
  sum += f.percentLines;
142
166
 
143
- let coverage = 100;
144
-
145
- if (group.files.length > 0)
146
- coverage = Math.round(sum / group.files.length);
167
+ const coverage = Math.round(sum / group.files.length);
147
168
 
148
169
  if (!hideFolders) {
149
- let folderLabel = folder;
170
+ const row = [];
171
+ row.push(getColor(coverage)(folder));
150
172
 
151
- if (!folderLabel)
152
- folderLabel = '.';
173
+ if (showPercent)
174
+ row.push(getColor(coverage)(`${coverage}%`));
153
175
 
154
- // убрали завершающий slash
155
- const trimmedFolder = trim(folderLabel, 25);
156
-
157
- let folderColor = makeRed;
158
-
159
- if (coverage === 100)
160
- folderColor = makeGreen;
161
-
162
- const folderName = folderColor(trimmedFolder);
163
-
164
- const headerRow = [folderName];
165
-
166
- if (showPercent) {
167
- let color = makeRed;
168
-
169
- if (coverage === 100)
170
- color = makeGreen;
171
-
172
- headerRow.push(color(`${coverage}%`));
173
- }
174
-
175
- headerRow.push('');
176
- tableData.push(headerRow);
176
+ row.push('');
177
+ tableData.push(row);
177
178
  }
178
179
 
179
180
  for (const f of group.files) {
180
- const fileCell = ' ' + trim(f.shortName, 30);
181
-
182
- let fileColor = makeRed;
183
-
184
- if (f.covered)
185
- fileColor = makeGreen;
186
-
187
- const row = [fileColor(fileCell)];
188
-
189
- if (showPercent) {
190
- let percentColor = makeRed;
191
-
192
- if (f.percentLines === 100)
193
- percentColor = makeGreen;
194
-
195
- row.push(percentColor(`${f.percentLines}%`));
196
- }
181
+ const row = [];
182
+ row.push(f.covered ? makeGreen(' ' + f.shortName) : makeRed(' ' + f.shortName));
197
183
 
198
- let uncovered = '';
199
-
200
- if (!f.covered)
201
- uncovered = makeRed(formatLines(f.lines));
202
-
203
- row.push(uncovered);
184
+ if (showPercent)
185
+ row.push(f.percentLines === 100 ? makeGreen(`${f.percentLines}%`) : makeRed(`${f.percentLines}%`));
204
186
 
187
+ row.push(f.covered ? '' : makeRed(formatLines(
188
+ f.lines,
189
+ linesColWidth,
190
+ )));
205
191
  tableData.push(row);
206
192
  }
207
193
  }
@@ -209,69 +195,42 @@ function buildGroupedTable(files, showPercent) {
209
195
  return tableData;
210
196
  }
211
197
 
212
- function parseCoverageFile(coverageFile, skipFull) {
213
- const files = [];
214
-
215
- for (const {name, lines} of coverageFile) {
216
- const uncovered = parseUncoveredLines(lines);
217
-
218
- const linesCount = keys(lines).length;
219
- const uncoveredCount = uncovered.length;
220
-
221
- const percentLines = getLinesPercent(linesCount, uncoveredCount);
222
-
223
- let covered = true;
224
-
225
- if (uncoveredCount > 0)
226
- covered = false;
227
-
228
- if (skipFull && covered)
229
- continue;
230
-
231
- files.push({
232
- filename: name.replace(`${CWD}/`, ''),
233
- covered,
234
- lines: uncovered,
235
- percentLines,
236
- });
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
+ }
237
214
  }
238
215
 
239
- return files;
240
- }
241
-
242
- function trim(str, max) {
243
- if (str.length <= max)
244
- return str;
245
-
246
- return '...' + str.slice(-(max - 3));
247
- }
248
-
249
- export function formatLines(array) {
250
- if (array.length <= 10) {
251
- const joined = array.join(', ');
252
-
253
- if (joined.length <= 30)
254
- return joined;
255
- }
216
+ ranges.push(start === prev ? String(start) : `${start}..${prev}`);
256
217
 
257
- const [first] = array;
258
- const last = array.at(-1);
218
+ const joined = ranges.join(', ');
259
219
 
260
- const base = first + '..' + last;
220
+ if (joined.length <= maxLen)
221
+ return joined;
261
222
 
262
- if (base.length <= 30)
263
- return base;
223
+ const [first] = ranges;
264
224
 
265
- return last;
225
+ return first;
266
226
  }
267
227
 
268
- function parseUncoveredLines(lines) {
228
+ export function parseUncoveredLines(lines) {
269
229
  const out = [];
270
230
 
271
- for (const [line, covered] of entries(lines)) {
231
+ for (const [line, covered] of entries(lines))
272
232
  if (!covered)
273
233
  out.push(line);
274
- }
275
234
 
276
235
  return out;
277
236
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "escover",
3
- "version": "6.2.3",
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",