@canyonjs/report-component 0.0.1-beta.9 → 0.0.2
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/dist/index.css +70 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +431 -705
- package/package.json +17 -22
package/dist/index.js
CHANGED
|
@@ -1,564 +1,360 @@
|
|
|
1
1
|
import { ConfigProvider, Divider, Input, Progress, Segmented, Space, Spin, Switch, Table, Tag, Typography, theme } from "antd";
|
|
2
2
|
import { Suspense, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
-
import Highlighter from "react-highlight-words";
|
|
5
4
|
import { genSummaryTreeItem } from "canyon-data";
|
|
5
|
+
import { renderToStaticMarkup } from "react-dom/server";
|
|
6
|
+
import Highlighter from "react-highlight-words";
|
|
6
7
|
import { FileOutlined, FolderFilled } from "@ant-design/icons";
|
|
7
8
|
|
|
8
|
-
//#region
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
var require_percent = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
14
|
-
module.exports = function percent$2(covered, total) {
|
|
15
|
-
let tmp;
|
|
16
|
-
if (total > 0) {
|
|
17
|
-
tmp = 1e3 * 100 * covered / total;
|
|
18
|
-
return Math.floor(tmp / 10) / 100;
|
|
19
|
-
} else return 100;
|
|
20
|
-
};
|
|
21
|
-
}));
|
|
9
|
+
//#region src/components/RIf.tsx
|
|
10
|
+
const RIf = ({ condition, children }) => {
|
|
11
|
+
return /* @__PURE__ */ jsx(Fragment, { children: condition ? children : null });
|
|
12
|
+
};
|
|
13
|
+
var RIf_default = RIf;
|
|
22
14
|
|
|
23
15
|
//#endregion
|
|
24
|
-
//#region
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
16
|
+
//#region src/helpers/generateCoreDataForEachComponent.ts
|
|
17
|
+
function checkSummaryOnlyChange(item, onlyChange) {
|
|
18
|
+
if (onlyChange === false) return true;
|
|
19
|
+
if (onlyChange && item.change) return true;
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
function checkSummaryKeywords(item, keywords) {
|
|
23
|
+
return item.path.toLowerCase().includes(keywords.toLowerCase());
|
|
24
|
+
}
|
|
25
|
+
function checkStartValue(item, startValue) {
|
|
26
|
+
return item.path.toLowerCase().includes(startValue.toLowerCase());
|
|
27
|
+
}
|
|
28
|
+
const generateCoreDataForEachComponent = ({ dataSource, filenameKeywords, value, onlyChange }) => {
|
|
29
|
+
const listDataSource = Object.values(dataSource).filter((item) => checkStartValue(item, value) && checkSummaryOnlyChange(item, onlyChange) && checkSummaryKeywords(item, filenameKeywords));
|
|
30
|
+
const aaaa = genSummaryTreeItem(value, listDataSource.reduce((acc, cur) => {
|
|
31
|
+
acc[cur.path] = cur;
|
|
32
|
+
return acc;
|
|
33
|
+
}, {}));
|
|
34
|
+
return {
|
|
35
|
+
treeDataSource: aaaa.children.map((item) => {
|
|
36
|
+
return {
|
|
37
|
+
path: item.path,
|
|
38
|
+
...item.summary
|
|
39
|
+
};
|
|
40
|
+
}),
|
|
41
|
+
rootDataSource: {
|
|
42
|
+
path: aaaa.path,
|
|
43
|
+
...aaaa.summary
|
|
44
|
+
},
|
|
45
|
+
listDataSource
|
|
35
46
|
};
|
|
36
|
-
}
|
|
47
|
+
};
|
|
37
48
|
|
|
38
49
|
//#endregion
|
|
39
|
-
//#region
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
//#region src/helpers/annotate.ts
|
|
51
|
+
function annotateStatements(fileCoverage) {
|
|
52
|
+
const annotateStatementsList = [];
|
|
53
|
+
const statementStats = fileCoverage.s;
|
|
54
|
+
const statementMeta = fileCoverage.statementMap;
|
|
55
|
+
Object.entries(statementStats).forEach(([stName, count]) => {
|
|
56
|
+
const meta = statementMeta[stName];
|
|
57
|
+
const type = count > 0 ? "yes" : "no";
|
|
58
|
+
const startCol = meta.start.column;
|
|
59
|
+
const endCol = meta.end.column + 1;
|
|
60
|
+
const startLine = meta.start.line;
|
|
61
|
+
const endLine = meta.end.line;
|
|
62
|
+
if (type === "no") annotateStatementsList.push({
|
|
63
|
+
startLine,
|
|
64
|
+
endLine,
|
|
65
|
+
startCol: startCol + 1,
|
|
66
|
+
endCol: endCol + 1,
|
|
67
|
+
type: "S"
|
|
49
68
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (!obj) this.data = blankSummary();
|
|
75
|
-
else if (obj instanceof CoverageSummary$3) this.data = obj.data;
|
|
76
|
-
else this.data = obj;
|
|
77
|
-
assertValidSummary(this.data);
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* merges a second summary coverage object into this one
|
|
81
|
-
* @param {CoverageSummary} obj - another coverage summary object
|
|
82
|
-
*/
|
|
83
|
-
merge(obj) {
|
|
84
|
-
[
|
|
85
|
-
"lines",
|
|
86
|
-
"statements",
|
|
87
|
-
"branches",
|
|
88
|
-
"functions",
|
|
89
|
-
"branchesTrue"
|
|
90
|
-
].forEach((key) => {
|
|
91
|
-
if (obj[key]) {
|
|
92
|
-
this[key].total += obj[key].total;
|
|
93
|
-
this[key].covered += obj[key].covered;
|
|
94
|
-
this[key].skipped += obj[key].skipped;
|
|
95
|
-
this[key].pct = percent$1(this[key].covered, this[key].total);
|
|
96
|
-
}
|
|
69
|
+
});
|
|
70
|
+
return annotateStatementsList;
|
|
71
|
+
}
|
|
72
|
+
function annotateFunctions(fileCoverage, structuredText) {
|
|
73
|
+
const fnStats = fileCoverage.f;
|
|
74
|
+
const fnMeta = fileCoverage.fnMap;
|
|
75
|
+
if (!fnStats) return [];
|
|
76
|
+
const list = [];
|
|
77
|
+
Object.entries(fnStats).forEach(([fName, count]) => {
|
|
78
|
+
const meta = fnMeta[fName];
|
|
79
|
+
const type = count > 0 ? "yes" : "no";
|
|
80
|
+
const decl = meta.decl || meta.loc;
|
|
81
|
+
const startCol = decl.start.column;
|
|
82
|
+
let endCol = decl.end.column + 1;
|
|
83
|
+
const startLine = decl.start.line;
|
|
84
|
+
const endLine = decl.end.line;
|
|
85
|
+
if (type === "no") {
|
|
86
|
+
if (endLine !== startLine) endCol = structuredText[startLine - 1].length;
|
|
87
|
+
list.push({
|
|
88
|
+
startLine,
|
|
89
|
+
endLine,
|
|
90
|
+
startCol: startCol + 1,
|
|
91
|
+
endCol: endCol + 1,
|
|
92
|
+
type: "F"
|
|
97
93
|
});
|
|
98
|
-
return this;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* returns a POJO that is JSON serializable. May be used to get the raw
|
|
102
|
-
* summary object.
|
|
103
|
-
*/
|
|
104
|
-
toJSON() {
|
|
105
|
-
return this.data;
|
|
106
94
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
95
|
+
});
|
|
96
|
+
return list;
|
|
97
|
+
}
|
|
98
|
+
function annotateBranches(fileCoverage, structuredText) {
|
|
99
|
+
const branchStats = fileCoverage.b;
|
|
100
|
+
const branchMeta = fileCoverage.branchMap;
|
|
101
|
+
if (!branchStats) return [];
|
|
102
|
+
const arr = [];
|
|
103
|
+
Object.entries(branchStats).forEach(([branchName, branchArray]) => {
|
|
104
|
+
const sumCount = branchArray.reduce((p, n) => p + n, 0);
|
|
105
|
+
const metaArray = branchMeta[branchName].locations;
|
|
106
|
+
let i;
|
|
107
|
+
let count;
|
|
108
|
+
let meta;
|
|
109
|
+
let startCol;
|
|
110
|
+
let endCol;
|
|
111
|
+
let startLine;
|
|
112
|
+
let endLine;
|
|
113
|
+
if (sumCount > 0 || sumCount === 0 && branchArray.length === 1) {
|
|
114
|
+
if (branchMeta[branchName].type === "if" && branchArray.length === 2 && metaArray.length === 1 && branchArray[1] === 0) metaArray[1] = {
|
|
115
|
+
start: {},
|
|
116
|
+
end: {}
|
|
117
|
+
};
|
|
118
|
+
for (i = 0; i < branchArray.length && i < metaArray.length; i += 1) {
|
|
119
|
+
count = branchArray[i];
|
|
120
|
+
meta = metaArray[i];
|
|
121
|
+
startCol = meta.start.column;
|
|
122
|
+
endCol = meta.end.column + 1;
|
|
123
|
+
startLine = meta.start.line;
|
|
124
|
+
endLine = meta.end.line;
|
|
125
|
+
if (count === 0 && startLine === void 0 && branchMeta[branchName].type === "if") {
|
|
126
|
+
const prevMeta = metaArray[i - 1];
|
|
127
|
+
startCol = prevMeta.start.column;
|
|
128
|
+
endCol = prevMeta.end.column + 1;
|
|
129
|
+
startLine = prevMeta.start.line;
|
|
130
|
+
endLine = prevMeta.end.line;
|
|
131
|
+
}
|
|
132
|
+
if (count === 0 && structuredText[startLine]) {
|
|
133
|
+
if (endLine !== startLine) {}
|
|
134
|
+
structuredText[startLine].text;
|
|
135
|
+
if (branchMeta[branchName].type === "if") arr.push({
|
|
136
|
+
startLine,
|
|
137
|
+
endLine,
|
|
138
|
+
startCol: startCol + 1,
|
|
139
|
+
endCol: endCol + 1,
|
|
140
|
+
type: i === 0 ? "I" : "E",
|
|
141
|
+
skip: meta.skip
|
|
142
|
+
});
|
|
143
|
+
else arr.push({
|
|
144
|
+
startLine,
|
|
145
|
+
endLine,
|
|
146
|
+
startCol: startCol + 1,
|
|
147
|
+
endCol: endCol + 1,
|
|
148
|
+
type: "B",
|
|
149
|
+
skip: meta.skip
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
112
153
|
}
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
"statements",
|
|
117
|
-
"functions",
|
|
118
|
-
"branches",
|
|
119
|
-
"branchesTrue"
|
|
120
|
-
]);
|
|
121
|
-
module.exports = { CoverageSummary: CoverageSummary$3 };
|
|
122
|
-
}));
|
|
154
|
+
});
|
|
155
|
+
return arr;
|
|
156
|
+
}
|
|
123
157
|
|
|
124
158
|
//#endregion
|
|
125
|
-
//#region
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
path: filePath,
|
|
133
|
-
statementMap: {},
|
|
134
|
-
fnMap: {},
|
|
135
|
-
branchMap: {},
|
|
136
|
-
s: {},
|
|
137
|
-
f: {},
|
|
138
|
-
b: {}
|
|
139
|
-
};
|
|
140
|
-
if (reportLogic) cov.bT = {};
|
|
141
|
-
return cov;
|
|
142
|
-
}
|
|
143
|
-
function assertValidObject(obj) {
|
|
144
|
-
if (!(obj && obj.path && obj.statementMap && obj.fnMap && obj.branchMap && obj.s && obj.f && obj.b)) throw new Error("Invalid file coverage object, missing keys, found:" + Object.keys(obj).join(","));
|
|
145
|
-
}
|
|
146
|
-
const keyFromLoc = ({ start, end }) => `${start.line}|${start.column}|${end.line}|${end.column}`;
|
|
147
|
-
const isObj = (o) => !!o && typeof o === "object";
|
|
148
|
-
const isLineCol = (o) => isObj(o) && typeof o.line === "number" && typeof o.column === "number";
|
|
149
|
-
const isLoc = (o) => isObj(o) && isLineCol(o.start) && isLineCol(o.end);
|
|
150
|
-
const getLoc = (o) => isLoc(o) ? o : isLoc(o.loc) ? o.loc : null;
|
|
151
|
-
const findNearestContainer = (item, map) => {
|
|
152
|
-
const itemLoc = getLoc(item);
|
|
153
|
-
if (!itemLoc) return null;
|
|
154
|
-
let nearestContainingItem = null;
|
|
155
|
-
let containerDistance = null;
|
|
156
|
-
let containerKey = null;
|
|
157
|
-
for (const [i, mapItem] of Object.entries(map)) {
|
|
158
|
-
const mapLoc = getLoc(mapItem);
|
|
159
|
-
if (!mapLoc) continue;
|
|
160
|
-
const distance = [
|
|
161
|
-
itemLoc.start.line - mapLoc.start.line,
|
|
162
|
-
itemLoc.start.column - mapLoc.start.column,
|
|
163
|
-
mapLoc.end.line - itemLoc.end.line,
|
|
164
|
-
mapLoc.end.column - itemLoc.end.column
|
|
165
|
-
];
|
|
166
|
-
if (distance[0] < 0 || distance[2] < 0 || distance[0] === 0 && distance[1] < 0 || distance[2] === 0 && distance[3] < 0) continue;
|
|
167
|
-
if (nearestContainingItem === null) {
|
|
168
|
-
containerDistance = distance;
|
|
169
|
-
nearestContainingItem = mapItem;
|
|
170
|
-
containerKey = i;
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
const closerBefore = distance[0] < containerDistance[0] || distance[0] === 0 && distance[1] < containerDistance[1];
|
|
174
|
-
const closerAfter = distance[2] < containerDistance[2] || distance[2] === 0 && distance[3] < containerDistance[3];
|
|
175
|
-
if (closerBefore || closerAfter) {
|
|
176
|
-
containerDistance = distance;
|
|
177
|
-
nearestContainingItem = mapItem;
|
|
178
|
-
containerKey = i;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return containerKey;
|
|
182
|
-
};
|
|
183
|
-
const addHits = (aHits, bHits) => {
|
|
184
|
-
if (typeof aHits === "number" && typeof bHits === "number") return aHits + bHits;
|
|
185
|
-
else if (Array.isArray(aHits) && Array.isArray(bHits)) return aHits.map((a, i) => (a || 0) + (bHits[i] || 0));
|
|
186
|
-
return null;
|
|
159
|
+
//#region src/helpers/coreFn.ts
|
|
160
|
+
function coreFn(fileCoverage, fileDetail) {
|
|
161
|
+
const nullData = {
|
|
162
|
+
times: [],
|
|
163
|
+
rows: [],
|
|
164
|
+
maxWidth: 0,
|
|
165
|
+
lines: []
|
|
187
166
|
};
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
let aItemHits = aValue[0];
|
|
207
|
-
const aItem = aValue[1];
|
|
208
|
-
const bValue = bItems[key];
|
|
209
|
-
if (!bValue) aItemHits = addNearestContainerHits(aItem, aItemHits, bMap, bHits);
|
|
210
|
-
else aItemHits = addHits(aItemHits, bValue[0]);
|
|
211
|
-
mergedItems[key] = [aItemHits, aItem];
|
|
212
|
-
}
|
|
213
|
-
for (const [key, bValue] of Object.entries(bItems)) {
|
|
214
|
-
let bItemHits = bValue[0];
|
|
215
|
-
const bItem = bValue[1];
|
|
216
|
-
if (mergedItems[key]) continue;
|
|
217
|
-
bItemHits = addNearestContainerHits(bItem, bItemHits, aMap, aHits);
|
|
218
|
-
mergedItems[key] = [bItemHits, bItem];
|
|
219
|
-
}
|
|
220
|
-
const hits = {};
|
|
221
|
-
const map = {};
|
|
222
|
-
Object.values(mergedItems).forEach(([itemHits, item], i) => {
|
|
223
|
-
hits[i] = itemHits;
|
|
224
|
-
map[i] = item;
|
|
167
|
+
if (!fileCoverage.s) return nullData;
|
|
168
|
+
const content = fileDetail;
|
|
169
|
+
const rows = [""];
|
|
170
|
+
let index = 0;
|
|
171
|
+
for (let i = 0; i < content.length; i++) if (content[i] === "\n") {
|
|
172
|
+
index += 1;
|
|
173
|
+
rows.push("");
|
|
174
|
+
} else rows[index] += content[i];
|
|
175
|
+
const maxWidth = JSON.parse(JSON.stringify(rows)).sort((a, b) => -(a.length - b.length))[0].length;
|
|
176
|
+
function getLineCoverage(data) {
|
|
177
|
+
const statementMap = data.statementMap;
|
|
178
|
+
const statements = data.s;
|
|
179
|
+
const lineMap = Object.create(null);
|
|
180
|
+
Object.entries(statements).forEach(([st, count]) => {
|
|
181
|
+
if (!statementMap[st]) return;
|
|
182
|
+
const { line } = statementMap[st].start;
|
|
183
|
+
const prevVal = lineMap[line];
|
|
184
|
+
if (prevVal === void 0 || prevVal < count) lineMap[line] = count;
|
|
225
185
|
});
|
|
226
|
-
return
|
|
227
|
-
};
|
|
228
|
-
/**
|
|
229
|
-
* provides a read-only view of coverage for a single file.
|
|
230
|
-
* The deep structure of this object is documented elsewhere. It has the following
|
|
231
|
-
* properties:
|
|
232
|
-
*
|
|
233
|
-
* * `path` - the file path for which coverage is being tracked
|
|
234
|
-
* * `statementMap` - map of statement locations keyed by statement index
|
|
235
|
-
* * `fnMap` - map of function metadata keyed by function index
|
|
236
|
-
* * `branchMap` - map of branch metadata keyed by branch index
|
|
237
|
-
* * `s` - hit counts for statements
|
|
238
|
-
* * `f` - hit count for functions
|
|
239
|
-
* * `b` - hit count for branches
|
|
240
|
-
*/
|
|
241
|
-
var FileCoverage$2 = class FileCoverage$2 {
|
|
242
|
-
/**
|
|
243
|
-
* @constructor
|
|
244
|
-
* @param {Object|FileCoverage|String} pathOrObj is a string that initializes
|
|
245
|
-
* and empty coverage object with the specified file path or a data object that
|
|
246
|
-
* has all the required properties for a file coverage object.
|
|
247
|
-
*/
|
|
248
|
-
constructor(pathOrObj, reportLogic = false) {
|
|
249
|
-
if (!pathOrObj) throw new Error("Coverage must be initialized with a path or an object");
|
|
250
|
-
if (typeof pathOrObj === "string") this.data = emptyCoverage(pathOrObj, reportLogic);
|
|
251
|
-
else if (pathOrObj instanceof FileCoverage$2) this.data = pathOrObj.data;
|
|
252
|
-
else if (typeof pathOrObj === "object") this.data = pathOrObj;
|
|
253
|
-
else throw new Error("Invalid argument to coverage constructor");
|
|
254
|
-
assertValidObject(this.data);
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* returns computed line coverage from statement coverage.
|
|
258
|
-
* This is a map of hits keyed by line number in the source.
|
|
259
|
-
*/
|
|
260
|
-
getLineCoverage() {
|
|
261
|
-
const statementMap = this.data.statementMap;
|
|
262
|
-
const statements = this.data.s;
|
|
263
|
-
const lineMap = Object.create(null);
|
|
264
|
-
Object.entries(statements).forEach(([st, count]) => {
|
|
265
|
-
/* istanbul ignore if: is this even possible? */
|
|
266
|
-
if (!statementMap[st]) return;
|
|
267
|
-
const { line } = statementMap[st].start;
|
|
268
|
-
const prevVal = lineMap[line];
|
|
269
|
-
if (prevVal === void 0 || prevVal < count) lineMap[line] = count;
|
|
270
|
-
});
|
|
271
|
-
return lineMap;
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* returns an array of uncovered line numbers.
|
|
275
|
-
* @returns {Array} an array of line numbers for which no hits have been
|
|
276
|
-
* collected.
|
|
277
|
-
*/
|
|
278
|
-
getUncoveredLines() {
|
|
279
|
-
const lc = this.getLineCoverage();
|
|
280
|
-
const ret = [];
|
|
281
|
-
Object.entries(lc).forEach(([l, hits]) => {
|
|
282
|
-
if (hits === 0) ret.push(l);
|
|
283
|
-
});
|
|
284
|
-
return ret;
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* returns a map of branch coverage by source line number.
|
|
288
|
-
* @returns {Object} an object keyed by line number. Each object
|
|
289
|
-
* has a `covered`, `total` and `coverage` (percentage) property.
|
|
290
|
-
*/
|
|
291
|
-
getBranchCoverageByLine() {
|
|
292
|
-
const branchMap = this.branchMap;
|
|
293
|
-
const branches = this.b;
|
|
294
|
-
const ret = {};
|
|
295
|
-
Object.entries(branchMap).forEach(([k, map]) => {
|
|
296
|
-
const line = map.line || map.loc.start.line;
|
|
297
|
-
const branchData = branches[k];
|
|
298
|
-
ret[line] = ret[line] || [];
|
|
299
|
-
ret[line].push(...branchData);
|
|
300
|
-
});
|
|
301
|
-
Object.entries(ret).forEach(([k, dataArray]) => {
|
|
302
|
-
const covered = dataArray.filter((item) => item > 0);
|
|
303
|
-
const coverage = covered.length / dataArray.length * 100;
|
|
304
|
-
ret[k] = {
|
|
305
|
-
covered: covered.length,
|
|
306
|
-
total: dataArray.length,
|
|
307
|
-
coverage
|
|
308
|
-
};
|
|
309
|
-
});
|
|
310
|
-
return ret;
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* return a JSON-serializable POJO for this file coverage object
|
|
314
|
-
*/
|
|
315
|
-
toJSON() {
|
|
316
|
-
return this.data;
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* merges a second coverage object into this one, updating hit counts
|
|
320
|
-
* @param {FileCoverage} other - the coverage object to be merged into this one.
|
|
321
|
-
* Note that the other object should have the same structure as this one (same file).
|
|
322
|
-
*/
|
|
323
|
-
merge(other) {
|
|
324
|
-
if (other.all === true) return;
|
|
325
|
-
if (this.all === true) {
|
|
326
|
-
this.data = other.data;
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
let [hits, map] = mergeProp(this.s, this.statementMap, other.s, other.statementMap);
|
|
330
|
-
this.data.s = hits;
|
|
331
|
-
this.data.statementMap = map;
|
|
332
|
-
const keyFromLocProp = (x) => keyFromLoc(x.loc);
|
|
333
|
-
const keyFromLocationsProp = (x) => keyFromLoc(x.locations[0]);
|
|
334
|
-
[hits, map] = mergeProp(this.f, this.fnMap, other.f, other.fnMap, keyFromLocProp);
|
|
335
|
-
this.data.f = hits;
|
|
336
|
-
this.data.fnMap = map;
|
|
337
|
-
[hits, map] = mergeProp(this.b, this.branchMap, other.b, other.branchMap, keyFromLocationsProp);
|
|
338
|
-
this.data.b = hits;
|
|
339
|
-
this.data.branchMap = map;
|
|
340
|
-
if (this.bT && other.bT) {
|
|
341
|
-
[hits, map] = mergeProp(this.bT, this.branchMap, other.bT, other.branchMap, keyFromLocationsProp);
|
|
342
|
-
this.data.bT = hits;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
computeSimpleTotals(property) {
|
|
346
|
-
let stats = this[property];
|
|
347
|
-
if (typeof stats === "function") stats = stats.call(this);
|
|
348
|
-
const ret = {
|
|
349
|
-
total: Object.keys(stats).length,
|
|
350
|
-
covered: Object.values(stats).filter((v) => !!v).length,
|
|
351
|
-
skipped: 0
|
|
352
|
-
};
|
|
353
|
-
ret.pct = percent(ret.covered, ret.total);
|
|
354
|
-
return ret;
|
|
355
|
-
}
|
|
356
|
-
computeBranchTotals(property) {
|
|
357
|
-
const stats = this[property];
|
|
358
|
-
const ret = {
|
|
359
|
-
total: 0,
|
|
360
|
-
covered: 0,
|
|
361
|
-
skipped: 0
|
|
362
|
-
};
|
|
363
|
-
Object.values(stats).forEach((branches) => {
|
|
364
|
-
ret.covered += branches.filter((hits) => hits > 0).length;
|
|
365
|
-
ret.total += branches.length;
|
|
366
|
-
});
|
|
367
|
-
ret.pct = percent(ret.covered, ret.total);
|
|
368
|
-
return ret;
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* resets hit counts for all statements, functions and branches
|
|
372
|
-
* in this coverage object resulting in zero coverage.
|
|
373
|
-
*/
|
|
374
|
-
resetHits() {
|
|
375
|
-
const statements = this.s;
|
|
376
|
-
const functions = this.f;
|
|
377
|
-
const branches = this.b;
|
|
378
|
-
const branchesTrue = this.bT;
|
|
379
|
-
Object.keys(statements).forEach((s) => {
|
|
380
|
-
statements[s] = 0;
|
|
381
|
-
});
|
|
382
|
-
Object.keys(functions).forEach((f) => {
|
|
383
|
-
functions[f] = 0;
|
|
384
|
-
});
|
|
385
|
-
Object.keys(branches).forEach((b) => {
|
|
386
|
-
branches[b].fill(0);
|
|
387
|
-
});
|
|
388
|
-
if (branchesTrue) Object.keys(branchesTrue).forEach((bT) => {
|
|
389
|
-
branchesTrue[bT].fill(0);
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
/**
|
|
393
|
-
* returns a CoverageSummary for this file coverage object
|
|
394
|
-
* @returns {CoverageSummary}
|
|
395
|
-
*/
|
|
396
|
-
toSummary() {
|
|
397
|
-
const ret = {};
|
|
398
|
-
ret.lines = this.computeSimpleTotals("getLineCoverage");
|
|
399
|
-
ret.functions = this.computeSimpleTotals("f", "fnMap");
|
|
400
|
-
ret.statements = this.computeSimpleTotals("s", "statementMap");
|
|
401
|
-
ret.branches = this.computeBranchTotals("b");
|
|
402
|
-
if (this.bT) ret.branchesTrue = this.computeBranchTotals("bT");
|
|
403
|
-
return new CoverageSummary$2(ret);
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
dataProperties(FileCoverage$2, [
|
|
407
|
-
"path",
|
|
408
|
-
"statementMap",
|
|
409
|
-
"fnMap",
|
|
410
|
-
"branchMap",
|
|
411
|
-
"s",
|
|
412
|
-
"f",
|
|
413
|
-
"b",
|
|
414
|
-
"bT",
|
|
415
|
-
"all"
|
|
416
|
-
]);
|
|
417
|
-
module.exports = {
|
|
418
|
-
FileCoverage: FileCoverage$2,
|
|
419
|
-
findNearestContainer,
|
|
420
|
-
addHits,
|
|
421
|
-
addNearestContainerHits
|
|
422
|
-
};
|
|
423
|
-
}));
|
|
424
|
-
|
|
425
|
-
//#endregion
|
|
426
|
-
//#region ../../node_modules/.pnpm/istanbul-lib-coverage@3.2.2/node_modules/istanbul-lib-coverage/lib/coverage-map.js
|
|
427
|
-
var require_coverage_map = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
428
|
-
const { FileCoverage: FileCoverage$1 } = require_file_coverage();
|
|
429
|
-
const { CoverageSummary: CoverageSummary$1 } = require_coverage_summary();
|
|
430
|
-
function maybeConstruct(obj, klass) {
|
|
431
|
-
if (obj instanceof klass) return obj;
|
|
432
|
-
return new klass(obj);
|
|
186
|
+
return lineMap;
|
|
433
187
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
188
|
+
const lineStats = getLineCoverage(fileCoverage);
|
|
189
|
+
if (!lineStats) return nullData;
|
|
190
|
+
const numberOfRows = [];
|
|
191
|
+
Object.entries(lineStats).forEach(([lineNumber, count]) => {
|
|
192
|
+
numberOfRows.push({
|
|
193
|
+
lineNumber,
|
|
194
|
+
count
|
|
439
195
|
});
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
constructor(obj) {
|
|
450
|
-
if (obj instanceof CoverageMap$1) this.data = obj.data;
|
|
451
|
-
else this.data = loadMap(obj);
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* merges a second coverage map into this one
|
|
455
|
-
* @param {CoverageMap} obj - a CoverageMap or its raw data. Coverage is merged
|
|
456
|
-
* correctly for the same files and additional file coverage keys are created
|
|
457
|
-
* as needed.
|
|
458
|
-
*/
|
|
459
|
-
merge(obj) {
|
|
460
|
-
const other = maybeConstruct(obj, CoverageMap$1);
|
|
461
|
-
Object.values(other.data).forEach((fc) => {
|
|
462
|
-
this.addFileCoverage(fc);
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
/**
|
|
466
|
-
* filter the coveragemap based on the callback provided
|
|
467
|
-
* @param {Function (filename)} callback - Returns true if the path
|
|
468
|
-
* should be included in the coveragemap. False if it should be
|
|
469
|
-
* removed.
|
|
470
|
-
*/
|
|
471
|
-
filter(callback) {
|
|
472
|
-
Object.keys(this.data).forEach((k) => {
|
|
473
|
-
if (!callback(k)) delete this.data[k];
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* returns a JSON-serializable POJO for this coverage map
|
|
478
|
-
* @returns {Object}
|
|
479
|
-
*/
|
|
480
|
-
toJSON() {
|
|
481
|
-
return this.data;
|
|
482
|
-
}
|
|
483
|
-
/**
|
|
484
|
-
* returns an array for file paths for which this map has coverage
|
|
485
|
-
* @returns {Array{string}} - array of files
|
|
486
|
-
*/
|
|
487
|
-
files() {
|
|
488
|
-
return Object.keys(this.data);
|
|
489
|
-
}
|
|
490
|
-
/**
|
|
491
|
-
* returns the file coverage for the specified file.
|
|
492
|
-
* @param {String} file
|
|
493
|
-
* @returns {FileCoverage}
|
|
494
|
-
*/
|
|
495
|
-
fileCoverageFor(file) {
|
|
496
|
-
const fc = this.data[file];
|
|
497
|
-
if (!fc) throw new Error(`No file coverage available for: ${file}`);
|
|
498
|
-
return fc;
|
|
499
|
-
}
|
|
500
|
-
/**
|
|
501
|
-
* adds a file coverage object to this map. If the path for the object,
|
|
502
|
-
* already exists in the map, it is merged with the existing coverage
|
|
503
|
-
* otherwise a new key is added to the map.
|
|
504
|
-
* @param {FileCoverage} fc the file coverage to add
|
|
505
|
-
*/
|
|
506
|
-
addFileCoverage(fc) {
|
|
507
|
-
const cov = new FileCoverage$1(fc);
|
|
508
|
-
const { path } = cov;
|
|
509
|
-
if (this.data[path]) this.data[path].merge(cov);
|
|
510
|
-
else this.data[path] = cov;
|
|
511
|
-
}
|
|
512
|
-
/**
|
|
513
|
-
* returns the coverage summary for all the file coverage objects in this map.
|
|
514
|
-
* @returns {CoverageSummary}
|
|
515
|
-
*/
|
|
516
|
-
getCoverageSummary() {
|
|
517
|
-
const ret = new CoverageSummary$1();
|
|
518
|
-
Object.values(this.data).forEach((fc) => {
|
|
519
|
-
ret.merge(fc.toSummary());
|
|
520
|
-
});
|
|
521
|
-
return ret;
|
|
522
|
-
}
|
|
196
|
+
});
|
|
197
|
+
const lines = [];
|
|
198
|
+
for (let i = 0; i < rows.length; i++) if (numberOfRows.find((n) => Number(n.lineNumber) === i + 1)) lines.push({ executionNumber: numberOfRows.find((n) => Number(n.lineNumber) === i + 1).count });
|
|
199
|
+
else lines.push({ executionNumber: -1 });
|
|
200
|
+
return {
|
|
201
|
+
times: numberOfRows,
|
|
202
|
+
rows,
|
|
203
|
+
lines,
|
|
204
|
+
maxWidth
|
|
523
205
|
};
|
|
524
|
-
|
|
525
|
-
}));
|
|
206
|
+
}
|
|
526
207
|
|
|
527
208
|
//#endregion
|
|
528
|
-
//#region
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
209
|
+
//#region src/widgets/lineNumbers.tsx
|
|
210
|
+
function genBgColor(hit) {
|
|
211
|
+
if (hit > 0) return "rgb(230, 245, 208)";
|
|
212
|
+
else if (hit === 0) return "#f3aeac";
|
|
213
|
+
else return "rgb(234, 234, 234)";
|
|
214
|
+
}
|
|
215
|
+
const LineNumber = ({ lineNumber }) => {
|
|
216
|
+
return /* @__PURE__ */ jsx("span", {
|
|
217
|
+
className: "line-number",
|
|
218
|
+
children: lineNumber
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
const LineChange = ({ hasChange }) => {
|
|
222
|
+
return /* @__PURE__ */ jsx("span", {
|
|
223
|
+
className: "line-change",
|
|
224
|
+
children: hasChange ? "+" : ""
|
|
225
|
+
});
|
|
226
|
+
};
|
|
227
|
+
const LineCoverage = ({ hit, width }) => {
|
|
228
|
+
return /* @__PURE__ */ jsx("span", {
|
|
229
|
+
className: "line-coverage",
|
|
230
|
+
style: {
|
|
231
|
+
background: genBgColor(hit),
|
|
232
|
+
width: `${width}px`
|
|
545
233
|
},
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
234
|
+
children: hit > 0 ? `${hit}x` : ""
|
|
235
|
+
});
|
|
236
|
+
};
|
|
237
|
+
const LineNumberWrapper = ({ lineNumber, line, maxHitWidth }) => {
|
|
238
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
239
|
+
className: "line-number-wrapper",
|
|
240
|
+
children: [
|
|
241
|
+
/* @__PURE__ */ jsx(LineNumber, { lineNumber }),
|
|
242
|
+
/* @__PURE__ */ jsx(LineChange, { hasChange: line.change }),
|
|
243
|
+
/* @__PURE__ */ jsx(LineCoverage, {
|
|
244
|
+
hit: line.hit,
|
|
245
|
+
width: maxHitWidth
|
|
246
|
+
})
|
|
247
|
+
]
|
|
248
|
+
});
|
|
249
|
+
};
|
|
250
|
+
function lineNumbers(lineNumber, linesState, _addLines) {
|
|
251
|
+
return renderToStaticMarkup(/* @__PURE__ */ jsx(LineNumberWrapper, {
|
|
252
|
+
lineNumber,
|
|
253
|
+
line: linesState.find((line) => line.lineNumber === lineNumber) || {
|
|
254
|
+
change: false,
|
|
255
|
+
hit: 0,
|
|
256
|
+
lineNumber
|
|
549
257
|
},
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
258
|
+
maxHitWidth: (Math.max(...linesState.map((line) => line.hit)).toString().length + 2) * 7.2
|
|
259
|
+
}));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
//#endregion
|
|
263
|
+
//#region src/widgets/CoverageDetail.tsx
|
|
264
|
+
const CoverageDetail = ({ source, coverage, diff }) => {
|
|
265
|
+
const { lines } = coreFn(coverage, source);
|
|
266
|
+
const addLines = diff.additions || [];
|
|
267
|
+
const linesState = (() => {
|
|
268
|
+
return lines.map((line, index) => {
|
|
269
|
+
return {
|
|
270
|
+
lineNumber: index + 1,
|
|
271
|
+
change: addLines.includes(index + 1),
|
|
272
|
+
hit: line.executionNumber
|
|
273
|
+
};
|
|
274
|
+
});
|
|
275
|
+
})();
|
|
276
|
+
const lineNumbersMinChars = (() => {
|
|
277
|
+
return Math.max(...linesState.map((line) => line.hit)).toString().length + 8;
|
|
278
|
+
})();
|
|
279
|
+
const ref = useRef(null);
|
|
280
|
+
useEffect(() => {
|
|
281
|
+
if (ref.current) {
|
|
282
|
+
const dom = ref.current;
|
|
283
|
+
const options = {
|
|
284
|
+
value: source,
|
|
285
|
+
language: "javascript",
|
|
286
|
+
fontFamily: "IBMPlexMono",
|
|
287
|
+
lineHeight: 18,
|
|
288
|
+
lineNumbers: (lineNumber) => {
|
|
289
|
+
return lineNumbers(lineNumber, linesState);
|
|
290
|
+
},
|
|
291
|
+
lineNumbersMinChars,
|
|
292
|
+
readOnly: true,
|
|
293
|
+
folding: false,
|
|
294
|
+
minimap: { enabled: false },
|
|
295
|
+
scrollBeyondLastLine: false,
|
|
296
|
+
showUnused: false,
|
|
297
|
+
fontSize: 12,
|
|
298
|
+
contextmenu: false,
|
|
299
|
+
automaticLayout: true
|
|
300
|
+
};
|
|
301
|
+
if (window.monaco?.editor && dom) {
|
|
302
|
+
const editor = window.monaco.editor.create(dom, options);
|
|
303
|
+
const decorations = (() => {
|
|
304
|
+
const all = [];
|
|
305
|
+
const annotateStatementsList = annotateStatements(coverage);
|
|
306
|
+
all.push(...annotateStatementsList);
|
|
307
|
+
const annotateFunctionsList = annotateFunctions(coverage, source);
|
|
308
|
+
all.push(...annotateFunctionsList);
|
|
309
|
+
const annotateBranchesList = annotateBranches(coverage, source);
|
|
310
|
+
all.push(...annotateBranchesList);
|
|
311
|
+
const arr = [];
|
|
312
|
+
for (let i = 0; i < all.length; i++) {
|
|
313
|
+
const { startLine, startCol, endLine, endCol } = all[i];
|
|
314
|
+
if (all[i].type === "S" || all[i].type === "F") arr.push({
|
|
315
|
+
range: new window.monaco.Range(startLine, startCol, endLine, endCol),
|
|
316
|
+
options: {
|
|
317
|
+
isWholeLine: false,
|
|
318
|
+
inlineClassName: "content-class-no-found"
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
else if (all[i].type === "B") arr.push({
|
|
322
|
+
range: new window.monaco.Range(startLine, startCol, endLine, endCol),
|
|
323
|
+
options: {
|
|
324
|
+
isWholeLine: false,
|
|
325
|
+
inlineClassName: "content-class-no-found-branch"
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
else if (all[i].type === "I") arr.push({
|
|
329
|
+
range: new window.monaco.Range(startLine, startCol, startLine, startCol),
|
|
330
|
+
options: {
|
|
331
|
+
beforeContentClassName: "insert-i-decoration",
|
|
332
|
+
stickiness: window.monaco.editor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
else if (all[i].type === "E") arr.push({
|
|
336
|
+
range: new window.monaco.Range(startLine, startCol, startLine, startCol),
|
|
337
|
+
options: {
|
|
338
|
+
beforeContentClassName: "insert-e-decoration",
|
|
339
|
+
stickiness: window.monaco.editor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
return arr;
|
|
344
|
+
})();
|
|
345
|
+
if (editor) editor?.createDecorationsCollection?.(decorations);
|
|
346
|
+
}
|
|
553
347
|
}
|
|
554
|
-
};
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
}
|
|
348
|
+
}, [source]);
|
|
349
|
+
return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("div", {
|
|
350
|
+
ref,
|
|
351
|
+
style: { height: "calc(100vh - 150px)" }
|
|
352
|
+
}) });
|
|
353
|
+
};
|
|
354
|
+
var CoverageDetail_default = CoverageDetail;
|
|
558
355
|
|
|
559
356
|
//#endregion
|
|
560
357
|
//#region src/helpers/color.ts
|
|
561
|
-
var import_istanbul_lib_coverage = require_istanbul_lib_coverage();
|
|
562
358
|
const getColor = (pct) => {
|
|
563
359
|
if (pct >= 80) return "rgb(33,181,119)";
|
|
564
360
|
if (pct >= 50) return "rgb(244,176,27)";
|
|
@@ -579,24 +375,20 @@ const SummaryNav = ({ value, onClick, reportName }) => {
|
|
|
579
375
|
fontSize: "16px",
|
|
580
376
|
fontWeight: "bold"
|
|
581
377
|
},
|
|
582
|
-
children: `${reportName}/${value}`.split("/").map((item, index) => {
|
|
378
|
+
children: `${reportName}/${value}`.split("/").map((item, index, array) => {
|
|
379
|
+
const pathKey = `${reportName}-${array.slice(0, index + 1).join("/")}`;
|
|
583
380
|
return /* @__PURE__ */ jsxs("div", {
|
|
584
381
|
style: {
|
|
585
382
|
display: "flex",
|
|
586
383
|
gap: "6px"
|
|
587
384
|
},
|
|
588
385
|
children: [/* @__PURE__ */ jsx("a", {
|
|
589
|
-
style: {
|
|
590
|
-
color: token.colorPrimary,
|
|
591
|
-
cursor: "pointer",
|
|
592
|
-
textDecoration: "none"
|
|
593
|
-
},
|
|
594
386
|
onClick: () => {
|
|
595
387
|
onClick(value.split("/").slice(0, index).join("/"));
|
|
596
388
|
},
|
|
597
389
|
children: item
|
|
598
|
-
}
|
|
599
|
-
},
|
|
390
|
+
}), index === value.split("/").length || !value ? null : /* @__PURE__ */ jsx("span", { children: "/" })]
|
|
391
|
+
}, pathKey);
|
|
600
392
|
})
|
|
601
393
|
});
|
|
602
394
|
};
|
|
@@ -704,11 +496,6 @@ const SummaryList = ({ dataSource, onSelect, filenameKeywords, style, onlyChange
|
|
|
704
496
|
dataIndex: "path",
|
|
705
497
|
render(text) {
|
|
706
498
|
return /* @__PURE__ */ jsx("a", {
|
|
707
|
-
style: {
|
|
708
|
-
width: "420px",
|
|
709
|
-
display: "block",
|
|
710
|
-
overflowWrap: "break-word"
|
|
711
|
-
},
|
|
712
499
|
onClick: () => {
|
|
713
500
|
onSelect(text);
|
|
714
501
|
},
|
|
@@ -801,126 +588,6 @@ const SummaryList = ({ dataSource, onSelect, filenameKeywords, style, onlyChange
|
|
|
801
588
|
};
|
|
802
589
|
var SummaryList_default = SummaryList;
|
|
803
590
|
|
|
804
|
-
//#endregion
|
|
805
|
-
//#region src/widgets/TopControl.tsx
|
|
806
|
-
const TopControl = ({ total, showMode, onChangeShowMode, onChangeKeywords, filenameKeywords, onChangeOnlyChange, onlyChange }) => {
|
|
807
|
-
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("div", {
|
|
808
|
-
style: {
|
|
809
|
-
display: "flex",
|
|
810
|
-
marginBottom: "6px",
|
|
811
|
-
justifyContent: "space-between",
|
|
812
|
-
alignItems: "center"
|
|
813
|
-
},
|
|
814
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
815
|
-
style: {
|
|
816
|
-
display: "flex",
|
|
817
|
-
gap: "6px",
|
|
818
|
-
flexDirection: "column"
|
|
819
|
-
},
|
|
820
|
-
children: /* @__PURE__ */ jsxs(Space, { children: [/* @__PURE__ */ jsx(Segmented, {
|
|
821
|
-
size: "small",
|
|
822
|
-
value: showMode,
|
|
823
|
-
defaultValue: showMode,
|
|
824
|
-
onChange: (v) => {
|
|
825
|
-
onChangeShowMode(v);
|
|
826
|
-
},
|
|
827
|
-
options: [{
|
|
828
|
-
label: "Code Tree",
|
|
829
|
-
value: "tree"
|
|
830
|
-
}, {
|
|
831
|
-
label: "File List",
|
|
832
|
-
value: "list"
|
|
833
|
-
}]
|
|
834
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
835
|
-
style: { fontSize: "14px" },
|
|
836
|
-
children: /* @__PURE__ */ jsxs("span", {
|
|
837
|
-
style: { marginBottom: "6px" },
|
|
838
|
-
children: [
|
|
839
|
-
total,
|
|
840
|
-
" ",
|
|
841
|
-
"Total Files"
|
|
842
|
-
]
|
|
843
|
-
})
|
|
844
|
-
})] })
|
|
845
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
846
|
-
style: {
|
|
847
|
-
display: "flex",
|
|
848
|
-
alignItems: "center"
|
|
849
|
-
},
|
|
850
|
-
children: [
|
|
851
|
-
/* @__PURE__ */ jsxs("div", {
|
|
852
|
-
style: {
|
|
853
|
-
display: "flex",
|
|
854
|
-
alignItems: "center",
|
|
855
|
-
gap: "6px"
|
|
856
|
-
},
|
|
857
|
-
children: [/* @__PURE__ */ jsxs(Typography.Text, {
|
|
858
|
-
type: "secondary",
|
|
859
|
-
style: { fontSize: "12px" },
|
|
860
|
-
children: [
|
|
861
|
-
"Only Changed",
|
|
862
|
-
":",
|
|
863
|
-
" "
|
|
864
|
-
]
|
|
865
|
-
}), /* @__PURE__ */ jsx(Switch, {
|
|
866
|
-
checked: onlyChange,
|
|
867
|
-
size: "small",
|
|
868
|
-
onChange: onChangeOnlyChange
|
|
869
|
-
})]
|
|
870
|
-
}),
|
|
871
|
-
/* @__PURE__ */ jsx(Divider, { type: "vertical" }),
|
|
872
|
-
/* @__PURE__ */ jsx(Input, {
|
|
873
|
-
placeholder: "Enter the file path to search",
|
|
874
|
-
value: filenameKeywords,
|
|
875
|
-
style: { width: "240px" },
|
|
876
|
-
size: "small",
|
|
877
|
-
onChange: (val) => {
|
|
878
|
-
onChangeKeywords(val.target.value);
|
|
879
|
-
}
|
|
880
|
-
})
|
|
881
|
-
]
|
|
882
|
-
})]
|
|
883
|
-
}), /* @__PURE__ */ jsx(Divider, { style: {
|
|
884
|
-
margin: "0",
|
|
885
|
-
marginBottom: "6px"
|
|
886
|
-
} })] });
|
|
887
|
-
};
|
|
888
|
-
var TopControl_default = TopControl;
|
|
889
|
-
|
|
890
|
-
//#endregion
|
|
891
|
-
//#region src/helpers/generateCoreDataForEachComponent.ts
|
|
892
|
-
function checkSummaryOnlyChange(item, onlyChange) {
|
|
893
|
-
if (onlyChange === false) return true;
|
|
894
|
-
if (onlyChange && item.change) return true;
|
|
895
|
-
return false;
|
|
896
|
-
}
|
|
897
|
-
function checkSummaryKeywords(item, keywords) {
|
|
898
|
-
return item.path.toLowerCase().includes(keywords.toLowerCase());
|
|
899
|
-
}
|
|
900
|
-
function checkStartValue(item, startValue) {
|
|
901
|
-
return item.path.toLowerCase().includes(startValue.toLowerCase());
|
|
902
|
-
}
|
|
903
|
-
const generateCoreDataForEachComponent = ({ dataSource, filenameKeywords, value, onlyChange }) => {
|
|
904
|
-
const listDataSource = Object.values(dataSource).filter((item) => checkStartValue(item, value) && checkSummaryOnlyChange(item, onlyChange) && checkSummaryKeywords(item, filenameKeywords));
|
|
905
|
-
const aaaa = genSummaryTreeItem(value, listDataSource.reduce((acc, cur) => {
|
|
906
|
-
acc[cur.path] = cur;
|
|
907
|
-
return acc;
|
|
908
|
-
}, {}));
|
|
909
|
-
return {
|
|
910
|
-
treeDataSource: aaaa.children.map((item) => {
|
|
911
|
-
return {
|
|
912
|
-
path: item.path,
|
|
913
|
-
...item.summary
|
|
914
|
-
};
|
|
915
|
-
}),
|
|
916
|
-
rootDataSource: {
|
|
917
|
-
path: aaaa.path,
|
|
918
|
-
...aaaa.summary
|
|
919
|
-
},
|
|
920
|
-
listDataSource
|
|
921
|
-
};
|
|
922
|
-
};
|
|
923
|
-
|
|
924
591
|
//#endregion
|
|
925
592
|
//#region src/widgets/SummaryTree.tsx
|
|
926
593
|
function checkSuffix(str) {
|
|
@@ -948,7 +615,8 @@ const SummaryTree = ({ dataSource, onSelect, style, onlyChange }) => {
|
|
|
948
615
|
return /* @__PURE__ */ jsxs("a", {
|
|
949
616
|
style: {
|
|
950
617
|
display: "flex",
|
|
951
|
-
gap: "
|
|
618
|
+
gap: "2px",
|
|
619
|
+
alignItems: "center"
|
|
952
620
|
},
|
|
953
621
|
onClick: () => {
|
|
954
622
|
onSelect(text);
|
|
@@ -1038,34 +706,90 @@ const SummaryTree = ({ dataSource, onSelect, style, onlyChange }) => {
|
|
|
1038
706
|
var SummaryTree_default = SummaryTree;
|
|
1039
707
|
|
|
1040
708
|
//#endregion
|
|
1041
|
-
//#region src/
|
|
1042
|
-
const
|
|
1043
|
-
return /* @__PURE__ */
|
|
709
|
+
//#region src/widgets/TopControl.tsx
|
|
710
|
+
const TopControl = ({ total, showMode, onChangeShowMode, onChangeKeywords, filenameKeywords, onChangeOnlyChange, onlyChange }) => {
|
|
711
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("div", {
|
|
712
|
+
style: {
|
|
713
|
+
display: "flex",
|
|
714
|
+
marginBottom: "6px",
|
|
715
|
+
justifyContent: "space-between",
|
|
716
|
+
alignItems: "center"
|
|
717
|
+
},
|
|
718
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
719
|
+
style: {
|
|
720
|
+
display: "flex",
|
|
721
|
+
gap: "6px",
|
|
722
|
+
flexDirection: "column"
|
|
723
|
+
},
|
|
724
|
+
children: /* @__PURE__ */ jsxs(Space, { children: [/* @__PURE__ */ jsx(Segmented, {
|
|
725
|
+
size: "small",
|
|
726
|
+
value: showMode,
|
|
727
|
+
defaultValue: showMode,
|
|
728
|
+
onChange: (v) => {
|
|
729
|
+
onChangeShowMode(v);
|
|
730
|
+
},
|
|
731
|
+
options: [{
|
|
732
|
+
label: "Code Tree",
|
|
733
|
+
value: "tree"
|
|
734
|
+
}, {
|
|
735
|
+
label: "File List",
|
|
736
|
+
value: "list"
|
|
737
|
+
}]
|
|
738
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
739
|
+
style: { fontSize: "14px" },
|
|
740
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
741
|
+
style: { marginBottom: "6px" },
|
|
742
|
+
children: [
|
|
743
|
+
total,
|
|
744
|
+
" ",
|
|
745
|
+
"Total Files"
|
|
746
|
+
]
|
|
747
|
+
})
|
|
748
|
+
})] })
|
|
749
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
750
|
+
style: {
|
|
751
|
+
display: "flex",
|
|
752
|
+
alignItems: "center"
|
|
753
|
+
},
|
|
754
|
+
children: [
|
|
755
|
+
/* @__PURE__ */ jsxs("div", {
|
|
756
|
+
style: {
|
|
757
|
+
display: "flex",
|
|
758
|
+
alignItems: "center",
|
|
759
|
+
gap: "6px"
|
|
760
|
+
},
|
|
761
|
+
children: [/* @__PURE__ */ jsxs(Typography.Text, {
|
|
762
|
+
type: "secondary",
|
|
763
|
+
style: { fontSize: "12px" },
|
|
764
|
+
children: [
|
|
765
|
+
"Only Changed",
|
|
766
|
+
":",
|
|
767
|
+
" "
|
|
768
|
+
]
|
|
769
|
+
}), /* @__PURE__ */ jsx(Switch, {
|
|
770
|
+
checked: onlyChange,
|
|
771
|
+
size: "small",
|
|
772
|
+
onChange: onChangeOnlyChange
|
|
773
|
+
})]
|
|
774
|
+
}),
|
|
775
|
+
/* @__PURE__ */ jsx(Divider, { type: "vertical" }),
|
|
776
|
+
/* @__PURE__ */ jsx(Input, {
|
|
777
|
+
placeholder: "Enter the file path to search",
|
|
778
|
+
value: filenameKeywords,
|
|
779
|
+
style: { width: "240px" },
|
|
780
|
+
size: "small",
|
|
781
|
+
onChange: (val) => {
|
|
782
|
+
onChangeKeywords(val.target.value);
|
|
783
|
+
}
|
|
784
|
+
})
|
|
785
|
+
]
|
|
786
|
+
})]
|
|
787
|
+
}), /* @__PURE__ */ jsx(Divider, { style: {
|
|
788
|
+
margin: "0",
|
|
789
|
+
marginBottom: "6px"
|
|
790
|
+
} })] });
|
|
1044
791
|
};
|
|
1045
|
-
var
|
|
1046
|
-
|
|
1047
|
-
//#endregion
|
|
1048
|
-
//#region src/widgets/CoverageDetail.tsx
|
|
1049
|
-
function CanyonReport$1({ fileContent, fileCoverage, fileCodeChange }) {
|
|
1050
|
-
console.log(fileCodeChange, "fileCodeChange");
|
|
1051
|
-
const ref = useRef(null);
|
|
1052
|
-
useEffect(() => {
|
|
1053
|
-
if (ref.current) {
|
|
1054
|
-
const dom = ref.current;
|
|
1055
|
-
const options = {
|
|
1056
|
-
value: fileContent,
|
|
1057
|
-
language: "javascript",
|
|
1058
|
-
fontFamily: "IBMPlexMono"
|
|
1059
|
-
};
|
|
1060
|
-
if (window.monaco?.editor && dom) window.monaco.editor.create(dom, options);
|
|
1061
|
-
}
|
|
1062
|
-
}, []);
|
|
1063
|
-
return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("div", {
|
|
1064
|
-
ref,
|
|
1065
|
-
style: { height: "calc(100vh - 150px)" }
|
|
1066
|
-
}) });
|
|
1067
|
-
}
|
|
1068
|
-
var CoverageDetail_default = CanyonReport$1;
|
|
792
|
+
var TopControl_default = TopControl;
|
|
1069
793
|
|
|
1070
794
|
//#endregion
|
|
1071
795
|
//#region src/CanyonReport.tsx
|
|
@@ -1085,27 +809,29 @@ const CanyonReport = ({ value, name, dataSource, onSelect }) => {
|
|
|
1085
809
|
const [fileContent, setFileContent] = useState("");
|
|
1086
810
|
const [fileCodeChange, setFileCodeChange] = useState([]);
|
|
1087
811
|
const [onlyChange, setOnlyChange] = useState(Boolean(false));
|
|
1088
|
-
const rootClassName = useMemo(() => `report-scope-${Math.random().toString(36).slice(2, 9)}`, []);
|
|
812
|
+
const rootClassName = useMemo(() => `report-scope-${Math.random().toString(36).slice(2, 9)} canyonjs-report-html`, []);
|
|
1089
813
|
function onChangeOnlyChange(v) {
|
|
1090
814
|
setOnlyChange(v);
|
|
1091
815
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
816
|
+
const newOnSelect = useMemo(() => {
|
|
817
|
+
return async (val) => {
|
|
818
|
+
const res = await onSelect(val);
|
|
819
|
+
setFileContent(res.fileContent || "");
|
|
820
|
+
setFileCoverage(res.fileCoverage || {});
|
|
821
|
+
setFileCodeChange(res.fileCodeChange || "");
|
|
822
|
+
return res;
|
|
823
|
+
};
|
|
824
|
+
}, [onSelect]);
|
|
1099
825
|
useEffect(() => {
|
|
1100
826
|
newOnSelect(value);
|
|
1101
|
-
}, []);
|
|
827
|
+
}, [newOnSelect, value]);
|
|
1102
828
|
const isFile = useMemo(() => {
|
|
1103
829
|
return /\.(js|jsx|ts|tsx|vue)$/.test(value);
|
|
1104
830
|
}, [value]);
|
|
1105
831
|
const mode = useMemo(() => {
|
|
1106
832
|
if (isFile) return "file";
|
|
1107
833
|
return showMode;
|
|
1108
|
-
}, [showMode,
|
|
834
|
+
}, [showMode, isFile]);
|
|
1109
835
|
const isFileDataReady = useMemo(() => {
|
|
1110
836
|
const hasCoverage = fileCoverage && Object.keys(fileCoverage).length > 0;
|
|
1111
837
|
const hasContent = fileContent.length > 0;
|
|
@@ -1171,9 +897,9 @@ const CanyonReport = ({ value, name, dataSource, onSelect }) => {
|
|
|
1171
897
|
children: /* @__PURE__ */ jsx(RIf_default, {
|
|
1172
898
|
condition: isFileDataReady,
|
|
1173
899
|
children: /* @__PURE__ */ jsx(CoverageDetail_default, {
|
|
1174
|
-
fileContent,
|
|
1175
|
-
fileCoverage,
|
|
1176
|
-
fileCodeChange
|
|
900
|
+
source: fileContent,
|
|
901
|
+
coverage: fileCoverage,
|
|
902
|
+
diff: fileCodeChange
|
|
1177
903
|
})
|
|
1178
904
|
})
|
|
1179
905
|
})
|