@canyonjs/report-component 0.0.2 → 0.0.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/dist/index.css CHANGED
@@ -1,5 +1,24 @@
1
+ .canyonjs-report-html .canyon-coverage-detail-spin-wrapper {
2
+ height: 100%;
3
+ }
4
+ .canyonjs-report-html
5
+ .canyon-coverage-detail-spin-wrapper
6
+ > .ant-spin-container {
7
+ height: 100%;
8
+ }
1
9
  .canyonjs-report-html {
2
- /*background-color: #535bf2;*/
10
+ height: 100%;
11
+ display: flex;
12
+ flex-direction: column;
13
+ }
14
+ .canyonjs-report-html a {
15
+ color: #0071c2;
16
+ cursor: pointer;
17
+ }
18
+ .canyonjs-report-html a:hover {
19
+ color: #0071c2;
20
+ opacity: 0.8;
21
+ text-decoration: underline;
3
22
  }
4
23
  .canyonjs-report-html .line-number-wrapper {
5
24
  display: flex;
@@ -68,3 +87,84 @@
68
87
  margin-right: 5px;
69
88
  }
70
89
 
90
+ /* CoverageDetail 样式 */
91
+ .canyonjs-report-html .canyon-coverage-detail-container {
92
+ height: 100%;
93
+ position: relative;
94
+ }
95
+
96
+ .canyonjs-report-html .canyon-coverage-detail-editor {
97
+ width: 100%;
98
+ height: 100%;
99
+ }
100
+
101
+ /* ChangedCodeCoverageTable 折叠表格样式 */
102
+ .canyonjs-report-html .canyon-changed-code-coverage-table {
103
+ position: absolute;
104
+ top: 0;
105
+ left: 0;
106
+ right: 0;
107
+ z-index: 1000;
108
+ }
109
+
110
+ .canyonjs-report-html .canyon-changed-code-coverage-toggle {
111
+ position: absolute;
112
+ top: 0;
113
+ left: 0;
114
+ right: 0;
115
+ padding: 8px 16px;
116
+ background: #f5f5f5;
117
+ border: none;
118
+ border-bottom: 1px solid #e0e0e0;
119
+ color: #333333;
120
+ font-size: 13px;
121
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
122
+ cursor: pointer;
123
+ text-align: left;
124
+ display: flex;
125
+ align-items: center;
126
+ z-index: 1001;
127
+ transition: background 0.2s ease;
128
+ }
129
+
130
+ .canyonjs-report-html .canyon-changed-code-coverage-toggle:hover {
131
+ background: #e8e8e8;
132
+ }
133
+
134
+ .canyonjs-report-html .canyon-changed-code-coverage-icon {
135
+ margin-right: 8px;
136
+ }
137
+
138
+ .canyonjs-report-html .canyon-changed-code-coverage-arrow {
139
+ margin-left: 8px;
140
+ transition: transform 0.3s ease;
141
+ }
142
+
143
+ .canyonjs-report-html .canyon-changed-code-coverage-content {
144
+ position: absolute;
145
+ top: 33px;
146
+ left: 0;
147
+ right: 0;
148
+ max-height: 0;
149
+ overflow: hidden;
150
+ background: #ffffff;
151
+ border-bottom: 1px solid #e0e0e0;
152
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
153
+ z-index: 1000;
154
+ transition: max-height 0.3s ease;
155
+ }
156
+
157
+ .canyonjs-report-html .canyon-changed-code-coverage-table-wrapper {
158
+ padding: 16px;
159
+ background: #ffffff;
160
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
161
+ overflow: auto;
162
+ max-height: 300px;
163
+ }
164
+
165
+ .canyonjs-report-html .canyon-changed-code-coverage-table-title {
166
+ font-weight: bold;
167
+ font-size: 14px;
168
+ color: #007acc;
169
+ margin-bottom: 12px;
170
+ }
package/dist/index.js CHANGED
@@ -205,6 +205,142 @@ function coreFn(fileCoverage, fileDetail) {
205
205
  };
206
206
  }
207
207
 
208
+ //#endregion
209
+ //#region src/widgets/ChangedCodeCoverageTable.tsx
210
+ const ChangedCodeCoverageTable = ({ coverage, addLines }) => {
211
+ console.log("coverage", coverage);
212
+ console.log("addLines", addLines);
213
+ const [isOpen, setIsOpen] = useState(false);
214
+ const relatedStatements = useMemo(() => {
215
+ if (addLines.length === 0 || !coverage.s || !coverage.statementMap) return [];
216
+ const addedLinesSet = new Set(addLines);
217
+ const statements = [];
218
+ Object.entries(coverage.statementMap).forEach(([stId, meta]) => {
219
+ const startLine = meta.start.line;
220
+ const endLine = meta.end.line;
221
+ const startCol = meta.start.column;
222
+ const endCol = meta.end.column;
223
+ const relatedLines = [];
224
+ for (let line = startLine; line <= endLine; line++) if (addedLinesSet.has(line)) relatedLines.push(line);
225
+ if (relatedLines.length > 0) {
226
+ const count = coverage.s[stId] || 0;
227
+ const covered = count > 0;
228
+ const locationDisplay = endLine > startLine ? `${startLine}:${startCol + 1} - ${endLine}:${endCol + 1}` : `${startLine}:${startCol + 1}`;
229
+ const relatedLinesDisplay = relatedLines.join(", ");
230
+ statements.push({
231
+ key: stId,
232
+ Status: covered ? "✓ Covered" : "✗ Not Covered",
233
+ Location: locationDisplay,
234
+ "Changed Lines": relatedLinesDisplay,
235
+ "Hit Count": covered ? `${count}x` : "Not covered"
236
+ });
237
+ }
238
+ });
239
+ statements.sort((a, b) => {
240
+ return parseInt(a.Location.split(":")[0] || "0") - parseInt(b.Location.split(":")[0] || "0");
241
+ });
242
+ return statements;
243
+ }, [addLines, coverage]);
244
+ const coverageStats = useMemo(() => {
245
+ if (relatedStatements.length === 0) return {
246
+ coveredCount: 0,
247
+ totalCount: 0,
248
+ coveragePercent: 0
249
+ };
250
+ const coveredCount = relatedStatements.filter((s) => s.Status.includes("✓")).length;
251
+ const totalCount = relatedStatements.length;
252
+ return {
253
+ coveredCount,
254
+ totalCount,
255
+ coveragePercent: totalCount > 0 ? Math.round(coveredCount / totalCount * 100) : 0
256
+ };
257
+ }, [relatedStatements]);
258
+ if (relatedStatements.length === 0) return null;
259
+ return /* @__PURE__ */ jsxs("div", {
260
+ className: "canyon-changed-code-coverage-table",
261
+ children: [/* @__PURE__ */ jsxs("button", {
262
+ className: "canyon-changed-code-coverage-toggle",
263
+ onClick: () => setIsOpen(!isOpen),
264
+ type: "button",
265
+ children: [
266
+ /* @__PURE__ */ jsx("span", {
267
+ className: "canyon-changed-code-coverage-icon",
268
+ children: "📊"
269
+ }),
270
+ /* @__PURE__ */ jsxs("span", { children: [
271
+ "Changed Code Coverage: ",
272
+ coverageStats.coveragePercent,
273
+ "% (",
274
+ coverageStats.coveredCount,
275
+ "/",
276
+ coverageStats.totalCount,
277
+ ")"
278
+ ] }),
279
+ /* @__PURE__ */ jsx("span", {
280
+ className: "canyon-changed-code-coverage-arrow",
281
+ children: isOpen ? "▲" : "▼"
282
+ })
283
+ ]
284
+ }), /* @__PURE__ */ jsx("div", {
285
+ className: "canyon-changed-code-coverage-content",
286
+ style: { maxHeight: isOpen ? "350px" : "0" },
287
+ children: /* @__PURE__ */ jsxs("div", {
288
+ className: "canyon-changed-code-coverage-table-wrapper",
289
+ children: [/* @__PURE__ */ jsxs("div", {
290
+ className: "canyon-changed-code-coverage-table-title",
291
+ children: [
292
+ "Changed Code Statements (",
293
+ coverageStats.totalCount,
294
+ ") - Coverage:",
295
+ " ",
296
+ coverageStats.coveragePercent,
297
+ "% (",
298
+ coverageStats.coveredCount,
299
+ "/",
300
+ coverageStats.totalCount,
301
+ ")"
302
+ ]
303
+ }), /* @__PURE__ */ jsx(ConfigProvider, {
304
+ theme: { token: { borderRadius: 0 } },
305
+ children: /* @__PURE__ */ jsx(Table, {
306
+ dataSource: relatedStatements,
307
+ columns: [
308
+ {
309
+ title: "Status",
310
+ dataIndex: "Status",
311
+ key: "Status",
312
+ render: (text) => /* @__PURE__ */ jsx("span", {
313
+ style: { color: text.includes("✓") ? "#4caf50" : "#f44336" },
314
+ children: text
315
+ })
316
+ },
317
+ {
318
+ title: "Location",
319
+ dataIndex: "Location",
320
+ key: "Location"
321
+ },
322
+ {
323
+ title: "Changed Lines",
324
+ dataIndex: "Changed Lines",
325
+ key: "Changed Lines"
326
+ },
327
+ {
328
+ title: "Hit Count",
329
+ dataIndex: "Hit Count",
330
+ key: "Hit Count"
331
+ }
332
+ ],
333
+ pagination: false,
334
+ size: "small",
335
+ bordered: true
336
+ })
337
+ })]
338
+ })
339
+ })]
340
+ });
341
+ };
342
+ var ChangedCodeCoverageTable_default = ChangedCodeCoverageTable;
343
+
208
344
  //#endregion
209
345
  //#region src/widgets/lineNumbers.tsx
210
346
  function genBgColor(hit) {
@@ -264,6 +400,8 @@ function lineNumbers(lineNumber, linesState, _addLines) {
264
400
  const CoverageDetail = ({ source, coverage, diff }) => {
265
401
  const { lines } = coreFn(coverage, source);
266
402
  const addLines = diff.additions || [];
403
+ const ref = useRef(null);
404
+ const hasChangedLines = addLines.length > 0 && coverage["s"] && coverage["statementMap"];
267
405
  const linesState = (() => {
268
406
  return lines.map((line, index) => {
269
407
  return {
@@ -276,7 +414,6 @@ const CoverageDetail = ({ source, coverage, diff }) => {
276
414
  const lineNumbersMinChars = (() => {
277
415
  return Math.max(...linesState.map((line) => line.hit)).toString().length + 8;
278
416
  })();
279
- const ref = useRef(null);
280
417
  useEffect(() => {
281
418
  if (ref.current) {
282
419
  const dom = ref.current;
@@ -345,11 +482,28 @@ const CoverageDetail = ({ source, coverage, diff }) => {
345
482
  if (editor) editor?.createDecorationsCollection?.(decorations);
346
483
  }
347
484
  }
348
- }, [source]);
349
- return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("div", {
350
- ref,
351
- style: { height: "calc(100vh - 150px)" }
352
- }) });
485
+ }, [source, coverage]);
486
+ return /* @__PURE__ */ jsxs("div", {
487
+ className: "canyon-coverage-detail-container",
488
+ style: {
489
+ height: "100%",
490
+ position: "relative"
491
+ },
492
+ children: [hasChangedLines ? /* @__PURE__ */ jsx(ChangedCodeCoverageTable_default, {
493
+ coverage,
494
+ addLines
495
+ }) : null, /* @__PURE__ */ jsx("div", {
496
+ ref,
497
+ className: "canyon-coverage-detail-editor",
498
+ style: {
499
+ height: hasChangedLines ? "calc(100% - 33px)" : "100%",
500
+ top: hasChangedLines ? "33px" : "0",
501
+ position: "absolute",
502
+ left: 0,
503
+ right: 0
504
+ }
505
+ })]
506
+ });
353
507
  };
354
508
  var CoverageDetail_default = CoverageDetail;
355
509
 
@@ -850,13 +1004,13 @@ const CanyonReport = ({ value, name, dataSource, onSelect }) => {
850
1004
  filenameKeywords,
851
1005
  onlyChange
852
1006
  ]);
853
- return /* @__PURE__ */ jsx("div", {
854
- className: rootClassName,
855
- children: /* @__PURE__ */ jsxs(ConfigProvider, {
856
- theme: { token: {
857
- colorPrimary: "#0071c2",
858
- borderRadius: 2
859
- } },
1007
+ return /* @__PURE__ */ jsx(ConfigProvider, {
1008
+ theme: { token: {
1009
+ colorPrimary: "#0071c2",
1010
+ borderRadius: 2
1011
+ } },
1012
+ children: /* @__PURE__ */ jsxs("div", {
1013
+ className: rootClassName,
860
1014
  children: [
861
1015
  /* @__PURE__ */ jsx("style", { children: `
862
1016
  .${rootClassName} .canyon-coverage-detail-spin-wrapper { height: 100%; }
@@ -888,8 +1042,7 @@ const CanyonReport = ({ value, name, dataSource, onSelect }) => {
888
1042
  style: {
889
1043
  flex: 1,
890
1044
  minHeight: 0,
891
- overflow: "auto",
892
- height: "100%"
1045
+ overflow: "auto"
893
1046
  },
894
1047
  children: /* @__PURE__ */ jsx(Spin, {
895
1048
  spinning: !isFileDataReady,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@canyonjs/report-component",
3
3
  "type": "module",
4
- "version": "0.0.2",
4
+ "version": "0.0.5",
5
5
  "author": "Travis Zhang<https://github.com/travzhang>",
6
6
  "repository": {
7
7
  "type": "git",