monocart-coverage-reports 1.1.0 → 2.0.1

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.
@@ -194,7 +194,7 @@ const Util = {
194
194
  return 'high';
195
195
  },
196
196
 
197
- isJsonType(contentType) {
197
+ isJsonType: (contentType) => {
198
198
  if (contentType) {
199
199
  if (contentType === 'application/json' || contentType === 'json') {
200
200
  return true;
@@ -203,7 +203,7 @@ const Util = {
203
203
  return false;
204
204
  },
205
205
 
206
- isMarkdownType(contentType) {
206
+ isMarkdownType: (contentType) => {
207
207
  if (contentType) {
208
208
  if (contentType === 'text/markdown' || contentType === 'markdown') {
209
209
  return true;
@@ -212,7 +212,7 @@ const Util = {
212
212
  return false;
213
213
  },
214
214
 
215
- isTextType(contentType) {
215
+ isTextType: (contentType) => {
216
216
  if (contentType) {
217
217
  if (contentType.startsWith('text')) {
218
218
  return true;
@@ -227,6 +227,107 @@ const Util = {
227
227
  return false;
228
228
  },
229
229
 
230
+ isBlank: (codeStr) => {
231
+ const blankBlock = /\S/;
232
+ return !blankBlock.test(codeStr);
233
+ },
234
+
235
+ getRangeLines: (sLoc, eLoc) => {
236
+
237
+ const lines = [];
238
+
239
+ // invalid location order
240
+ if (sLoc.line > eLoc.line) {
241
+ return lines;
242
+ }
243
+
244
+ // nothing middle
245
+ if (sLoc.line === eLoc.line && sLoc.column >= eLoc.column) {
246
+ return lines;
247
+ }
248
+
249
+ const addStart = () => {
250
+
251
+ // nothing start
252
+ if (sLoc.column >= sLoc.length) {
253
+ return;
254
+ }
255
+
256
+ const entire = sLoc.column <= sLoc.indent;
257
+ lines.push({
258
+ line: sLoc.line,
259
+ entire,
260
+ range: {
261
+ start: sLoc.column,
262
+ end: sLoc.length
263
+ }
264
+ });
265
+ };
266
+
267
+ const addMiddle = () => {
268
+
269
+ const start = sLoc.column <= sLoc.indent;
270
+ const end = Util.isBlank(eLoc.text.slice(eLoc.column));
271
+ const entire = start && end;
272
+ // same line
273
+ lines.push({
274
+ line: sLoc.line,
275
+ entire,
276
+ range: {
277
+ start: sLoc.column,
278
+ end: eLoc.column
279
+ }
280
+ });
281
+ };
282
+
283
+ const addEnd = () => {
284
+
285
+ // nothing end
286
+ if (eLoc.column === 0) {
287
+ return;
288
+ }
289
+
290
+ const entire = Util.isBlank(eLoc.text.slice(eLoc.column));
291
+ lines.push({
292
+ line: eLoc.line,
293
+ entire,
294
+ range: {
295
+ start: eLoc.indent,
296
+ end: eLoc.column
297
+ }
298
+ });
299
+ };
300
+
301
+ // same line, single line
302
+ if (sLoc.line === eLoc.line) {
303
+
304
+ addMiddle();
305
+
306
+ } else {
307
+ // multiple lines
308
+
309
+ addStart();
310
+
311
+ // always entire for middle lines
312
+ const lineStart = sLoc.line + 1;
313
+ const lineEnd = eLoc.line;
314
+ if (lineEnd > lineStart) {
315
+ for (let i = lineStart; i < lineEnd; i++) {
316
+ lines.push({
317
+ line: i,
318
+ entire: true
319
+ // no range for entire line
320
+ });
321
+ }
322
+ }
323
+
324
+ // check end
325
+ addEnd();
326
+ }
327
+
328
+ return lines;
329
+ },
330
+
230
331
  // =============================================================================
231
332
  // svg
232
333
 
@@ -1,5 +1,5 @@
1
1
  const path = require('path');
2
- const Util = require('../utils/util.js');
2
+ const Util = require('./util.js');
3
3
 
4
4
  const resolveUrl = (input) => {
5
5
  let url;
@@ -59,7 +59,7 @@ const getSourcePath = (url, index = '', type = '') => {
59
59
 
60
60
  const getSourceType = (sourcePath) => {
61
61
  let ext = path.extname(sourcePath);
62
- let type = '';
62
+ let type = 'js';
63
63
  if (ext) {
64
64
  ext = ext.slice(1);
65
65
  const reg = /^[a-z0-9]+$/;
package/lib/utils/util.js CHANGED
@@ -8,6 +8,8 @@ const CG = require('console-grid');
8
8
  const Share = require('../platform/share.js');
9
9
  const { deflateSync } = require('lz-utils');
10
10
 
11
+ const { acornWalk } = require('../packages/monocart-coverage-vendor.js');
12
+
11
13
  const Util = {
12
14
 
13
15
  root: process.cwd(),
@@ -216,6 +218,31 @@ const Util = {
216
218
  return '\n';
217
219
  },
218
220
 
221
+ visitAst: (rootNode, visitors) => {
222
+ const baseVisitor = acornWalk.base;
223
+ const parents = [rootNode];
224
+ const visitor = (node, st, override) => {
225
+ const type = override || node.type;
226
+ // console.log('visit', node.type, override, parents.length);
227
+ const handler = visitors[type];
228
+ if (handler) {
229
+ const res = handler(node, parents);
230
+ if (res === 'break') {
231
+ return;
232
+ }
233
+ }
234
+ const isNew = node !== parents[parents.length - 1];
235
+ if (isNew) {
236
+ parents.push(node);
237
+ }
238
+ baseVisitor[type](node, st, visitor);
239
+ if (isNew) {
240
+ parents.pop();
241
+ }
242
+ };
243
+ visitor(rootNode);
244
+ },
245
+
219
246
  forEachFile: function(dir, extList, callback) {
220
247
  if (!fs.existsSync(dir)) {
221
248
  return;
@@ -1,44 +1,41 @@
1
1
  // https://playwright.dev/docs/api/class-coverage
2
2
 
3
3
  // url, text, ranges: [ {start, end} ]
4
- const getCssSummary = (item) => {
4
+ const getCssSummaryBytes = (item) => {
5
5
 
6
6
  const source = item.source;
7
7
  const total = source.length;
8
8
 
9
9
  let covered = 0;
10
- const ranges = item.ranges;
11
- if (ranges) {
12
- ranges.forEach((range) => {
13
- covered += range.end - range.start;
10
+ const bytes = item.data.bytes;
11
+ if (bytes) {
12
+ bytes.forEach((range) => {
13
+ if (range.count > 0) {
14
+ covered += range.end - range.start;
15
+ }
14
16
  });
15
17
  }
16
18
 
17
- const uncovered = total - covered;
18
-
19
+ // no functions for css
19
20
  return {
20
- name: item.sourcePath,
21
- type: item.type,
22
- url: item.url,
23
21
  total,
24
- covered,
25
- uncovered
22
+ covered
26
23
  };
27
24
 
28
25
  };
29
26
 
30
27
  // url, source, ranges:[{start,end, count}]
31
- const getJsSummary = (item) => {
28
+ const getJsSummaryBytes = (item) => {
32
29
 
33
30
  const source = item.source;
34
31
  const total = source.length;
35
32
 
36
- const uncoveredRanges = item.ranges.filter((range) => range.count === 0);
33
+ const uncoveredBytes = item.data.bytes.filter((range) => range.count === 0);
37
34
 
38
35
  let uncovered = 0;
39
36
 
40
37
  let endPos = 0;
41
- uncoveredRanges.forEach((range) => {
38
+ uncoveredBytes.forEach((range) => {
42
39
  const { start, end } = range;
43
40
 
44
41
  if (start > endPos) {
@@ -58,23 +55,21 @@ const getJsSummary = (item) => {
58
55
 
59
56
  const covered = total - uncovered;
60
57
 
58
+ // console.log(item)
59
+
61
60
  return {
62
- name: item.sourcePath,
63
- type: item.type,
64
- url: item.url,
65
61
  total,
66
- covered,
67
- uncovered
62
+ covered
68
63
  };
69
64
  };
70
65
 
71
- const getV8Summary = (item) => {
66
+ const getV8SummaryBytes = (item) => {
72
67
  if (item.type === 'css') {
73
- return getCssSummary(item);
68
+ return getCssSummaryBytes(item);
74
69
  }
75
- return getJsSummary(item);
70
+ return getJsSummaryBytes(item);
76
71
  };
77
72
 
78
73
  module.exports = {
79
- getV8Summary
74
+ getV8SummaryBytes
80
75
  };
package/lib/v8/v8.js CHANGED
@@ -1,10 +1,11 @@
1
1
  const path = require('path');
2
2
  const Util = require('../utils/util.js');
3
- const { getV8Summary } = require('./v8-summary.js');
4
- const { dedupeRanges } = require('../converter/dedupe.js');
5
- const { getSourcePath } = require('../converter/source-path.js');
3
+ const { getV8SummaryBytes } = require('./v8-summary.js');
4
+ const { dedupeRanges } = require('../utils/dedupe.js');
5
+ const { getSourcePath } = require('../utils/source-path.js');
6
6
  const { mergeScriptCovs } = require('../packages/monocart-coverage-vendor.js');
7
7
  const collectSourceMaps = require('../converter/collect-source-maps.js');
8
+ const version = require('../../package.json').version;
8
9
 
9
10
  const initV8ListAndSourcemap = async (v8list, options, inlineSourceMap) => {
10
11
 
@@ -73,6 +74,7 @@ const initV8ListAndSourcemap = async (v8list, options, inlineSourceMap) => {
73
74
  const time_start = Date.now();
74
75
  const count = await collectSourceMaps(v8list, options, inlineSourceMap);
75
76
  if (count) {
77
+ // debug level time
76
78
  Util.logTime(`loaded ${count} sourcemaps`, time_start);
77
79
  }
78
80
 
@@ -227,48 +229,84 @@ const saveV8HtmlReport = async (reportData, options, v8HtmlOptions) => {
227
229
  return htmlPath;
228
230
  };
229
231
 
232
+ // calculate uncovered, pct, status
233
+ const calculatePctAndStatus = (item, watermarks) => {
234
+ Object.keys(item).forEach((k) => {
235
+ const indicateData = item[k];
236
+ indicateData.uncovered = indicateData.total - indicateData.covered;
237
+
238
+ let pct = '';
239
+ let status = 'unknown';
240
+
241
+ if (indicateData.total) {
242
+ pct = Util.PNF(indicateData.covered, indicateData.total, 2);
243
+ status = Util.getStatus(pct, watermarks[k]);
244
+ }
245
+
246
+ indicateData.pct = pct;
247
+ indicateData.status = status;
248
+
249
+ });
250
+ };
251
+
230
252
  const saveV8Report = async (v8list, options) => {
231
253
  const defaultWatermarks = {
232
- bytes: [50, 80]
254
+ bytes: [50, 80],
255
+ functions: [50, 80],
256
+ branches: [50, 80],
257
+ lines: [50, 80]
233
258
  };
234
259
  const watermarks = Util.resolveWatermarks(defaultWatermarks, options.watermarks);
235
260
 
236
- const bytesWatermarks = watermarks.bytes;
237
-
238
261
  // init summary
239
262
  v8list.forEach((entry) => {
240
- entry.summary = getV8Summary(entry);
263
+ entry.summary.bytes = getV8SummaryBytes(entry);
241
264
  });
242
265
 
243
- // calculate pct, status and summary
266
+ // overall summary
244
267
  const summaryList = v8list.map((entry) => entry.summary);
245
- let total = 0;
246
- let covered = 0;
268
+ const summary = {
269
+ bytes: {
270
+ total: 0,
271
+ covered: 0
272
+ },
273
+ functions: {
274
+ total: 0,
275
+ covered: 0
276
+ },
277
+ branches: {
278
+ total: 0,
279
+ covered: 0
280
+ },
281
+ lines: {
282
+ total: 0,
283
+ covered: 0,
284
+ blank: 0,
285
+ comment: 0
286
+ }
287
+ };
247
288
  summaryList.forEach((item) => {
289
+ calculatePctAndStatus(item, watermarks);
290
+ Object.keys(item).forEach((k) => {
291
+ const indicateData = item[k];
292
+ if (!indicateData) {
293
+ return;
294
+ }
295
+ summary[k].total += indicateData.total;
296
+ summary[k].covered += indicateData.covered;
248
297
 
249
- total += item.total;
250
- covered += item.covered;
251
-
252
- item.pct = Util.PNF(item.covered, item.total, 2);
253
- item.status = Util.getStatus(item.pct, bytesWatermarks);
254
-
298
+ if (k === 'lines') {
299
+ summary[k].blank += indicateData.blank;
300
+ summary[k].comment += indicateData.comment;
301
+ }
302
+ });
255
303
  });
256
304
 
257
- const uncovered = total - covered;
258
-
259
- const pct = Util.PNF(covered, total, 2);
260
- const status = Util.getStatus(pct, bytesWatermarks);
261
-
262
- const summary = {
263
- total,
264
- covered,
265
- uncovered,
266
- pct,
267
- status
268
- };
305
+ calculatePctAndStatus(summary, watermarks);
269
306
 
270
307
  const reportData = {
271
308
  name: options.name,
309
+ version,
272
310
  watermarks,
273
311
  summary,
274
312
  files: v8list
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monocart-coverage-reports",
3
- "version": "1.1.0",
3
+ "version": "2.0.1",
4
4
  "description": "Monocart coverage reports",
5
5
  "main": "lib/index.js",
6
6
  "exports": {
@@ -14,17 +14,20 @@
14
14
  },
15
15
  "types": "./lib/index.d.ts",
16
16
  "scripts": {
17
- "build-test": "npm run build-istanbul && npm run build-v8",
18
- "build-istanbul": "npx webpack --config mock/webpack.config-istanbul.js",
19
- "build-v8": "npx webpack --config mock/webpack.config-v8.js",
20
- "test": "node ./tests/test.js && npm run build-docs",
21
- "build": "sf lint && sf b -p && npm run build-docs",
22
- "dev": "sf d v8",
23
17
  "build-docs": "node ./scripts/build-docs.js",
18
+ "build-test": "node ./scripts/build-test.js",
19
+ "build": "sf lint && sf b -p && npm run build-test",
20
+ "test-node": "npm run test-node-env && npm run test-node-ins",
21
+ "test-node-env": "cross-env NODE_V8_COVERAGE=.temp/v8-coverage node ./test/test-node-env.js && node ./test/generate-node-report.js",
22
+ "test-node-ins": "node ./test/test-node-ins.js",
23
+ "test-browser": "node ./test/test.js",
24
+ "test": "npm run test-browser && npm run test-node && npm run build-docs",
25
+ "dev": "sf d v8",
24
26
  "patch": "npm run build && sf publish patch -r"
25
27
  },
26
28
  "workspaces": [
27
- "packages/*"
29
+ "packages/*",
30
+ "test"
28
31
  ],
29
32
  "files": [
30
33
  "lib"
@@ -35,31 +38,23 @@
35
38
  "url": "git+https://github.com/cenfun/monocart-coverage-reports.git"
36
39
  },
37
40
  "dependencies": {
38
- "console-grid": "^2.0.1",
39
- "eight-colors": "^1.0.3",
40
- "istanbul-lib-coverage": "^3.2.2",
41
- "istanbul-lib-report": "^3.0.1",
42
- "istanbul-reports": "^3.1.6",
43
- "lz-utils": "^2.0.1",
44
- "monocart-code-viewer": "^1.0.8",
45
- "monocart-formatter": "^1.0.7",
46
- "turbogrid": "^3.0.10"
41
+ "console-grid": "~2.0.1",
42
+ "eight-colors": "~1.0.3",
43
+ "istanbul-lib-coverage": "~3.2.2",
44
+ "istanbul-lib-report": "~3.0.1",
45
+ "istanbul-reports": "~3.1.6",
46
+ "lz-utils": "~2.0.1",
47
+ "monocart-code-viewer": "^1.0.12",
48
+ "monocart-formatter": "~2.2.0",
49
+ "turbogrid": "~3.0.12"
47
50
  },
48
51
  "devDependencies": {
49
- "babel-loader": "^9.1.3",
50
- "babel-plugin-istanbul": "^6.1.1",
51
- "eslint": "^8.55.0",
52
+ "cross-env": "^7.0.3",
53
+ "eslint": "^8.56.0",
52
54
  "eslint-config-plus": "^1.0.6",
53
55
  "eslint-plugin-html": "^7.1.0",
54
56
  "eslint-plugin-vue": "^9.19.2",
55
- "github-markdown-css": "^5.5.0",
56
- "koa": "^2.14.2",
57
- "koa-static-resolver": "^1.0.4",
58
- "marked": "^11.1.0",
59
- "playwright": "^1.40.1",
60
- "stylelint": "^16.0.2",
61
- "stylelint-config-plus": "^1.0.4",
62
- "webpack": "^5.89.0",
63
- "webpack-cli": "^5.1.4"
57
+ "stylelint": "^15.11.0",
58
+ "stylelint-config-plus": "^1.0.4"
64
59
  }
65
60
  }
@@ -1,183 +0,0 @@
1
-
2
- const findLine = function(list, position) {
3
- let start = 0;
4
- let end = list.length - 1;
5
- while (end - start > 1) {
6
- const i = Math.floor((start + end) * 0.5);
7
- const item = list[i];
8
- if (position < item.start) {
9
- end = i;
10
- continue;
11
- }
12
- if (position > item.end) {
13
- start = i;
14
- continue;
15
- }
16
- return list[i];
17
- }
18
- // last two items, less is start
19
- const endItem = list[end];
20
- if (position < endItem.start) {
21
- return list[start];
22
- }
23
- return list[end];
24
- };
25
-
26
- // =======================================================================================
27
-
28
- const isLineSingleCommented = (codeStr) => {
29
- const singleBlock = /^\s*\/\//g;
30
- return singleBlock.test(codeStr);
31
- };
32
-
33
- const isLineStartCommented = (codeStr) => {
34
- const multiStartBlock = /^\s*\/\*/g;
35
- return multiStartBlock.test(codeStr);
36
- };
37
-
38
- // multi-comment end but not at end
39
- const isLineEndCommented = (codeStr) => {
40
- const multiEndBlock = /.*\*\//g;
41
- return multiEndBlock.test(codeStr);
42
- };
43
-
44
- const isLineEndCommentedToEnd = (codeStr) => {
45
- const multiEndBlock = /.*\*\/\s*$/g;
46
- return multiEndBlock.test(codeStr);
47
- };
48
-
49
- const isLineBlank = (codeStr) => {
50
- const blankBlock = /\S/;
51
- return !blankBlock.test(codeStr);
52
- };
53
-
54
- class PositionMapping {
55
- constructor(source) {
56
- this.source = source;
57
- this.lines = this.buildLines(source);
58
- this.commentedLines = [];
59
- this.blankLines = [];
60
- this.parseLines(this.lines);
61
- }
62
-
63
- // =============================================================================
64
-
65
- getSlice(s, e) {
66
- return this.source.slice(s, e);
67
- }
68
-
69
- // 1-base
70
- locationToOffset(location) {
71
- const { line, column } = location;
72
- // 1-based
73
- const lineInfo = this.lines[line - 1];
74
- if (lineInfo) {
75
- if (column === Infinity) {
76
- return lineInfo.start + lineInfo.length;
77
- }
78
- return lineInfo.start + column;
79
- }
80
- return 0;
81
- }
82
-
83
- // 1-base
84
- offsetToLocation(offset) {
85
- const lineInfo = findLine(this.lines, offset);
86
-
87
- let indent = lineInfo.text.search(/\S/);
88
- if (indent === -1) {
89
- indent = lineInfo.length;
90
- }
91
-
92
- // 1-base
93
- const line = lineInfo.line + 1;
94
- const column = Math.min(Math.max(offset - lineInfo.start, 0), lineInfo.length);
95
-
96
- return {
97
- ... lineInfo,
98
- line,
99
- column,
100
- indent
101
- };
102
- }
103
-
104
- // 1-base
105
- getLine(line) {
106
- return this.lines[line - 1];
107
- }
108
-
109
- // =============================================================================
110
-
111
- buildLines(content) {
112
- let pos = 0;
113
- const lines = content.split(/\n/).map((text, line) => {
114
-
115
- let n = 1;
116
- // may ends with \r (don't consider double \r\r for now)
117
- const reg = /\r$/;
118
- if (reg.test(text)) {
119
- text = text.slice(0, -1);
120
- n += 1;
121
- }
122
-
123
- const length = text.length;
124
- const start = pos;
125
- const end = start + length;
126
-
127
- pos += length + n;
128
-
129
- return {
130
- line,
131
- start,
132
- end,
133
- length,
134
- text
135
- };
136
- });
137
-
138
- return lines;
139
- }
140
-
141
- parseLines(lines) {
142
- const commentedLines = [];
143
- const blankLines = [];
144
-
145
- let startCommented = false;
146
-
147
- const multiEndHandler = (text, i) => {
148
- if (isLineEndCommented(text)) {
149
- startCommented = false;
150
- if (isLineEndCommentedToEnd(text)) {
151
- commentedLines.push(i);
152
- }
153
- return;
154
- }
155
- commentedLines.push(i);
156
- };
157
-
158
- lines.forEach((line, i) => {
159
- const text = line.text;
160
- if (startCommented) {
161
- return multiEndHandler(text, i);
162
- }
163
- if (isLineStartCommented(text)) {
164
- startCommented = true;
165
- return multiEndHandler(text, i);
166
- }
167
- if (isLineSingleCommented(text)) {
168
- commentedLines.push(i);
169
- return;
170
- }
171
- if (isLineBlank(text)) {
172
- blankLines.push(i);
173
- }
174
- });
175
-
176
- this.commentedLines = commentedLines;
177
- this.blankLines = blankLines;
178
- }
179
-
180
- }
181
-
182
- module.exports = PositionMapping;
183
-
File without changes