@canyonjs/report-component 0.0.10 → 1.0.16
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 +61 -10
- package/dist/index.js +274 -51
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -152,22 +152,73 @@
|
|
|
152
152
|
border-bottom: 1px solid #e0e0e0;
|
|
153
153
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
154
154
|
z-index: 1000;
|
|
155
|
-
transition: max-height 0.3s ease;
|
|
155
|
+
transition: max-height 0.3s ease, opacity 0.3s ease;
|
|
156
|
+
opacity: 0;
|
|
156
157
|
}
|
|
157
158
|
|
|
158
|
-
.canyonjs-report-html .canyon-changed-code-coverage-
|
|
159
|
-
|
|
159
|
+
.canyonjs-report-html .canyon-changed-code-coverage-content[style*="max-height: auto"] {
|
|
160
|
+
opacity: 1;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.canyonjs-report-html .canyon-changed-code-coverage-select-wrapper {
|
|
164
|
+
padding: 12px 16px;
|
|
160
165
|
background: #ffffff;
|
|
161
166
|
font-family:
|
|
162
167
|
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
163
|
-
|
|
164
|
-
|
|
168
|
+
display: flex;
|
|
169
|
+
justify-content: flex-start;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/* 下拉选项样式优化 */
|
|
173
|
+
.canyonjs-report-html .canyon-changed-code-coverage-select-wrapper .ant-select-item {
|
|
174
|
+
padding: 6px 12px !important;
|
|
175
|
+
line-height: 20px !important;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.canyonjs-report-html .canyon-changed-code-coverage-select-wrapper .ant-select-item-option-active {
|
|
179
|
+
background-color: #f5f5f5;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.canyonjs-report-html .canyon-changed-code-coverage-select-wrapper .ant-select-item-option-content {
|
|
183
|
+
display: flex;
|
|
184
|
+
align-items: center;
|
|
165
185
|
}
|
|
166
186
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
187
|
+
/* 跳转高亮样式 - 整行高亮 */
|
|
188
|
+
.canyonjs-report-html .canyon-jump-highlight-line {
|
|
189
|
+
background-color: rgba(255, 193, 7, 0.4) !important;
|
|
190
|
+
border-left: 4px solid #ff9800;
|
|
191
|
+
box-shadow: 0 0 8px rgba(255, 193, 7, 0.5);
|
|
192
|
+
animation: canyon-jump-pulse 0.6s ease-out;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* 跳转高亮样式 - 行号区域高亮 */
|
|
196
|
+
.canyonjs-report-html .canyon-jump-highlight-line-margin {
|
|
197
|
+
background-color: rgba(255, 193, 7, 0.3) !important;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* 跳转高亮样式 - 范围高亮 */
|
|
201
|
+
.canyonjs-report-html .canyon-jump-highlight-range {
|
|
202
|
+
background-color: rgba(255, 193, 7, 0.5) !important;
|
|
203
|
+
border: 2px solid #ff9800;
|
|
204
|
+
border-radius: 3px;
|
|
205
|
+
box-shadow: 0 0 6px rgba(255, 193, 7, 0.6);
|
|
206
|
+
animation: canyon-jump-pulse 0.6s ease-out;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* 脉冲动画效果 - 让高亮更醒目 */
|
|
210
|
+
@keyframes canyon-jump-pulse {
|
|
211
|
+
0% {
|
|
212
|
+
background-color: rgba(255, 193, 7, 0.7);
|
|
213
|
+
box-shadow: 0 0 12px rgba(255, 193, 7, 0.8);
|
|
214
|
+
}
|
|
215
|
+
50% {
|
|
216
|
+
background-color: rgba(255, 193, 7, 0.5);
|
|
217
|
+
box-shadow: 0 0 8px rgba(255, 193, 7, 0.6);
|
|
218
|
+
}
|
|
219
|
+
100% {
|
|
220
|
+
background-color: rgba(255, 193, 7, 0.4);
|
|
221
|
+
box-shadow: 0 0 8px rgba(255, 193, 7, 0.5);
|
|
222
|
+
}
|
|
172
223
|
}
|
|
173
224
|
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigProvider, Divider, Input, Progress, Segmented, Space, Spin, Switch, Table, Tag, Typography, theme } from "antd";
|
|
1
|
+
import { ConfigProvider, Divider, Input, Progress, Segmented, Select, 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
4
|
import { genSummaryTreeItem } from "canyon-data";
|
|
@@ -236,10 +236,36 @@ function coreFn(fileCoverage, fileDetail) {
|
|
|
236
236
|
|
|
237
237
|
//#endregion
|
|
238
238
|
//#region src/widgets/ChangedCodeCoverageTable.tsx
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
239
|
+
const formatLineRanges = (lines) => {
|
|
240
|
+
if (lines.length === 0) return "";
|
|
241
|
+
if (lines.length === 1) {
|
|
242
|
+
const first$1 = lines[0];
|
|
243
|
+
return first$1 !== void 0 ? first$1.toString() : "";
|
|
244
|
+
}
|
|
245
|
+
const sorted = [...lines].sort((a, b) => a - b);
|
|
246
|
+
const ranges = [];
|
|
247
|
+
const first = sorted[0];
|
|
248
|
+
if (first === void 0) return "";
|
|
249
|
+
let start = first;
|
|
250
|
+
let end = first;
|
|
251
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
252
|
+
const current = sorted[i];
|
|
253
|
+
if (current === void 0) continue;
|
|
254
|
+
if (current === end + 1) end = current;
|
|
255
|
+
else {
|
|
256
|
+
if (start === end) ranges.push(start.toString());
|
|
257
|
+
else ranges.push(`${start}-${end}`);
|
|
258
|
+
start = current;
|
|
259
|
+
end = current;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (start === end) ranges.push(start.toString());
|
|
263
|
+
else ranges.push(`${start}-${end}`);
|
|
264
|
+
return ranges.join(", ");
|
|
265
|
+
};
|
|
266
|
+
const ChangedCodeCoverageTable = ({ coverage, addLines, onJumpToRange }) => {
|
|
242
267
|
const [isOpen, setIsOpen] = useState(false);
|
|
268
|
+
const [selectedValue, setSelectedValue] = useState(null);
|
|
243
269
|
const relatedStatements = useMemo(() => {
|
|
244
270
|
if (addLines.length === 0 || !coverage.s || !coverage.statementMap) return [];
|
|
245
271
|
const addedLinesSet = new Set(addLines);
|
|
@@ -252,39 +278,102 @@ const ChangedCodeCoverageTable = ({ coverage, addLines }) => {
|
|
|
252
278
|
const relatedLines = [];
|
|
253
279
|
for (let line = startLine; line <= endLine; line++) if (addedLinesSet.has(line)) relatedLines.push(line);
|
|
254
280
|
if (relatedLines.length > 0) {
|
|
255
|
-
const count = coverage.s[stId] || 0;
|
|
281
|
+
const count = coverage.s?.[stId] || 0;
|
|
256
282
|
const covered = count > 0;
|
|
257
|
-
const locationDisplay = endLine > startLine ?
|
|
258
|
-
const relatedLinesDisplay = relatedLines
|
|
283
|
+
const locationDisplay = endLine > startLine ? `L${startLine} C${startCol + 1} - L${endLine} C${endCol + 1}` : `L${startLine} C${startCol + 1}`;
|
|
284
|
+
const relatedLinesDisplay = formatLineRanges(relatedLines);
|
|
259
285
|
statements.push({
|
|
260
286
|
key: stId,
|
|
261
287
|
Status: covered ? "✓ Covered" : "✗ Not Covered",
|
|
262
288
|
Location: locationDisplay,
|
|
263
289
|
"Changed Lines": relatedLinesDisplay,
|
|
264
|
-
"Hit Count": covered ? `${count}x` : "
|
|
290
|
+
"Hit Count": covered ? `${count}x` : "0x",
|
|
291
|
+
startLine,
|
|
292
|
+
startCol: startCol + 1,
|
|
293
|
+
endLine,
|
|
294
|
+
endCol: endCol + 1,
|
|
295
|
+
relatedLines
|
|
265
296
|
});
|
|
266
297
|
}
|
|
267
298
|
});
|
|
268
299
|
statements.sort((a, b) => {
|
|
269
|
-
|
|
300
|
+
const aMatch = a.Location.match(/L(\d+)/);
|
|
301
|
+
const bMatch = b.Location.match(/L(\d+)/);
|
|
302
|
+
return (aMatch ? parseInt(aMatch[1] || "0") : 0) - (bMatch ? parseInt(bMatch[1] || "0") : 0);
|
|
270
303
|
});
|
|
271
304
|
return statements;
|
|
272
305
|
}, [addLines, coverage]);
|
|
306
|
+
const filteredStatements = useMemo(() => {
|
|
307
|
+
return relatedStatements.filter((s) => s.Status.includes("✗"));
|
|
308
|
+
}, [relatedStatements]);
|
|
309
|
+
const allStatementsForSelect = useMemo(() => {
|
|
310
|
+
return relatedStatements;
|
|
311
|
+
}, [relatedStatements]);
|
|
312
|
+
const groupedOptions = useMemo(() => {
|
|
313
|
+
const covered = relatedStatements.filter((s) => s.Status.includes("✓"));
|
|
314
|
+
const notCovered = relatedStatements.filter((s) => s.Status.includes("✗"));
|
|
315
|
+
const groups = [];
|
|
316
|
+
if (notCovered.length > 0) groups.push({
|
|
317
|
+
label: /* @__PURE__ */ jsxs("span", {
|
|
318
|
+
style: {
|
|
319
|
+
fontWeight: 500,
|
|
320
|
+
color: "#f44336"
|
|
321
|
+
},
|
|
322
|
+
children: [
|
|
323
|
+
"✗ Not Covered (",
|
|
324
|
+
notCovered.length,
|
|
325
|
+
")"
|
|
326
|
+
]
|
|
327
|
+
}),
|
|
328
|
+
title: "Not Covered",
|
|
329
|
+
options: notCovered.map((stmt) => ({
|
|
330
|
+
value: stmt.key,
|
|
331
|
+
label: `${stmt.Location} Lines: ${stmt["Changed Lines"]} ${stmt["Hit Count"]}`
|
|
332
|
+
}))
|
|
333
|
+
});
|
|
334
|
+
if (covered.length > 0) groups.push({
|
|
335
|
+
label: /* @__PURE__ */ jsxs("span", {
|
|
336
|
+
style: {
|
|
337
|
+
fontWeight: 500,
|
|
338
|
+
color: "#4caf50"
|
|
339
|
+
},
|
|
340
|
+
children: [
|
|
341
|
+
"✓ Covered (",
|
|
342
|
+
covered.length,
|
|
343
|
+
")"
|
|
344
|
+
]
|
|
345
|
+
}),
|
|
346
|
+
title: "Covered",
|
|
347
|
+
options: covered.map((stmt) => ({
|
|
348
|
+
value: stmt.key,
|
|
349
|
+
label: `${stmt.Location} Lines: ${stmt["Changed Lines"]} ${stmt["Hit Count"]}`
|
|
350
|
+
}))
|
|
351
|
+
});
|
|
352
|
+
return groups;
|
|
353
|
+
}, [relatedStatements]);
|
|
273
354
|
const coverageStats = useMemo(() => {
|
|
274
355
|
if (relatedStatements.length === 0) return {
|
|
275
356
|
coveredCount: 0,
|
|
276
357
|
totalCount: 0,
|
|
277
|
-
coveragePercent: 0
|
|
358
|
+
coveragePercent: 0,
|
|
359
|
+
notCoveredCount: 0
|
|
278
360
|
};
|
|
279
361
|
const coveredCount = relatedStatements.filter((s) => s.Status.includes("✓")).length;
|
|
280
362
|
const totalCount = relatedStatements.length;
|
|
363
|
+
const notCoveredCount = filteredStatements.length;
|
|
281
364
|
return {
|
|
282
365
|
coveredCount,
|
|
283
366
|
totalCount,
|
|
284
|
-
coveragePercent: totalCount > 0 ? Math.round(coveredCount / totalCount * 100) : 0
|
|
367
|
+
coveragePercent: totalCount > 0 ? Math.round(coveredCount / totalCount * 100) : 0,
|
|
368
|
+
notCoveredCount
|
|
285
369
|
};
|
|
286
|
-
}, [relatedStatements]);
|
|
287
|
-
if (
|
|
370
|
+
}, [relatedStatements, filteredStatements]);
|
|
371
|
+
if (filteredStatements.length === 0) return null;
|
|
372
|
+
const handleSelectChange = (value) => {
|
|
373
|
+
setSelectedValue(value);
|
|
374
|
+
const statement = allStatementsForSelect.find((s) => s.key === value);
|
|
375
|
+
if (statement && onJumpToRange) onJumpToRange(statement.startLine, statement.startCol, statement.endLine, statement.endCol);
|
|
376
|
+
};
|
|
288
377
|
return /* @__PURE__ */ jsxs("div", {
|
|
289
378
|
className: "canyon-changed-code-coverage-table",
|
|
290
379
|
children: [/* @__PURE__ */ jsxs("button", {
|
|
@@ -303,7 +392,9 @@ const ChangedCodeCoverageTable = ({ coverage, addLines }) => {
|
|
|
303
392
|
coverageStats.coveredCount,
|
|
304
393
|
"/",
|
|
305
394
|
coverageStats.totalCount,
|
|
306
|
-
")"
|
|
395
|
+
") - ",
|
|
396
|
+
coverageStats.notCoveredCount,
|
|
397
|
+
" 未覆盖"
|
|
307
398
|
] }),
|
|
308
399
|
/* @__PURE__ */ jsx("span", {
|
|
309
400
|
className: "canyon-changed-code-coverage-arrow",
|
|
@@ -312,43 +403,136 @@ const ChangedCodeCoverageTable = ({ coverage, addLines }) => {
|
|
|
312
403
|
]
|
|
313
404
|
}), /* @__PURE__ */ jsx("div", {
|
|
314
405
|
className: "canyon-changed-code-coverage-content",
|
|
315
|
-
style: {
|
|
406
|
+
style: {
|
|
407
|
+
maxHeight: isOpen ? "100px" : "0",
|
|
408
|
+
overflow: isOpen ? "visible" : "hidden",
|
|
409
|
+
opacity: isOpen ? 1 : 0
|
|
410
|
+
},
|
|
316
411
|
children: /* @__PURE__ */ jsx("div", {
|
|
317
|
-
className: "canyon-changed-code-coverage-
|
|
318
|
-
children: /* @__PURE__ */ jsx(
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
412
|
+
className: "canyon-changed-code-coverage-select-wrapper",
|
|
413
|
+
children: /* @__PURE__ */ jsx(Select, {
|
|
414
|
+
value: selectedValue,
|
|
415
|
+
onChange: handleSelectChange,
|
|
416
|
+
placeholder: "Select code location (use arrow keys)",
|
|
417
|
+
style: {
|
|
418
|
+
width: "480px",
|
|
419
|
+
maxWidth: "100%"
|
|
420
|
+
},
|
|
421
|
+
size: "small",
|
|
422
|
+
showSearch: true,
|
|
423
|
+
optionFilterProp: "label",
|
|
424
|
+
tagRender: (props) => {
|
|
425
|
+
const { value } = props;
|
|
426
|
+
const stmt = allStatementsForSelect.find((s) => s.key === value);
|
|
427
|
+
if (!stmt) return /* @__PURE__ */ jsx("span", { children: value });
|
|
428
|
+
const isCovered = stmt.Status.includes("✓");
|
|
429
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
430
|
+
style: {
|
|
431
|
+
display: "inline-flex",
|
|
432
|
+
alignItems: "center",
|
|
433
|
+
gap: "6px",
|
|
434
|
+
fontSize: "13px",
|
|
435
|
+
lineHeight: "20px"
|
|
336
436
|
},
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
437
|
+
children: [
|
|
438
|
+
/* @__PURE__ */ jsx("span", {
|
|
439
|
+
style: {
|
|
440
|
+
color: isCovered ? "#4caf50" : "#f44336",
|
|
441
|
+
fontWeight: "bold",
|
|
442
|
+
fontSize: "14px"
|
|
443
|
+
},
|
|
444
|
+
children: isCovered ? "✓" : "✗"
|
|
445
|
+
}),
|
|
446
|
+
/* @__PURE__ */ jsx("span", {
|
|
447
|
+
style: { fontFamily: "monospace" },
|
|
448
|
+
children: stmt.Location
|
|
449
|
+
}),
|
|
450
|
+
/* @__PURE__ */ jsxs("span", {
|
|
451
|
+
style: {
|
|
452
|
+
color: "#666",
|
|
453
|
+
fontSize: "12px"
|
|
454
|
+
},
|
|
455
|
+
children: ["Lines: ", stmt["Changed Lines"]]
|
|
456
|
+
}),
|
|
457
|
+
/* @__PURE__ */ jsx("span", {
|
|
458
|
+
style: {
|
|
459
|
+
color: isCovered ? "#4caf50" : "#f44336",
|
|
460
|
+
fontSize: "12px"
|
|
461
|
+
},
|
|
462
|
+
children: stmt["Hit Count"]
|
|
463
|
+
})
|
|
464
|
+
]
|
|
465
|
+
});
|
|
466
|
+
},
|
|
467
|
+
filterOption: (input, option) => {
|
|
468
|
+
if (!option) return false;
|
|
469
|
+
if (option.options) return true;
|
|
470
|
+
return (option?.label?.toString() || "").toLowerCase().includes(input.toLowerCase());
|
|
471
|
+
},
|
|
472
|
+
optionRender: (option) => {
|
|
473
|
+
if (!option) return null;
|
|
474
|
+
if (option.options) return option.label;
|
|
475
|
+
const stmt = allStatementsForSelect.find((s) => s.key === option.value);
|
|
476
|
+
if (!stmt) return option.label;
|
|
477
|
+
const isCovered = stmt.Status.includes("✓");
|
|
478
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
479
|
+
style: {
|
|
480
|
+
display: "flex",
|
|
481
|
+
alignItems: "center",
|
|
482
|
+
gap: "6px",
|
|
483
|
+
padding: "2px 0",
|
|
484
|
+
fontSize: "13px",
|
|
485
|
+
lineHeight: "20px"
|
|
341
486
|
},
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
487
|
+
children: [
|
|
488
|
+
/* @__PURE__ */ jsx("span", {
|
|
489
|
+
style: {
|
|
490
|
+
color: isCovered ? "#4caf50" : "#f44336",
|
|
491
|
+
fontWeight: "bold",
|
|
492
|
+
width: "16px",
|
|
493
|
+
fontSize: "14px",
|
|
494
|
+
textAlign: "center",
|
|
495
|
+
flexShrink: 0
|
|
496
|
+
},
|
|
497
|
+
title: isCovered ? "Covered" : "Not Covered",
|
|
498
|
+
children: isCovered ? "✓" : "✗"
|
|
499
|
+
}),
|
|
500
|
+
/* @__PURE__ */ jsx("span", {
|
|
501
|
+
style: {
|
|
502
|
+
fontFamily: "monospace",
|
|
503
|
+
width: "180px",
|
|
504
|
+
flexShrink: 0,
|
|
505
|
+
overflow: "hidden",
|
|
506
|
+
textOverflow: "ellipsis",
|
|
507
|
+
whiteSpace: "nowrap"
|
|
508
|
+
},
|
|
509
|
+
children: stmt.Location
|
|
510
|
+
}),
|
|
511
|
+
/* @__PURE__ */ jsxs("span", {
|
|
512
|
+
style: {
|
|
513
|
+
color: "#666",
|
|
514
|
+
fontSize: "12px",
|
|
515
|
+
width: "100px",
|
|
516
|
+
flexShrink: 0,
|
|
517
|
+
textAlign: "left"
|
|
518
|
+
},
|
|
519
|
+
children: ["Lines: ", stmt["Changed Lines"]]
|
|
520
|
+
}),
|
|
521
|
+
/* @__PURE__ */ jsx("span", {
|
|
522
|
+
style: {
|
|
523
|
+
color: isCovered ? "#4caf50" : "#f44336",
|
|
524
|
+
fontSize: "12px",
|
|
525
|
+
width: "80px",
|
|
526
|
+
flexShrink: 0,
|
|
527
|
+
textAlign: "right",
|
|
528
|
+
fontWeight: isCovered ? "500" : "normal"
|
|
529
|
+
},
|
|
530
|
+
children: stmt["Hit Count"]
|
|
531
|
+
})
|
|
532
|
+
]
|
|
533
|
+
});
|
|
534
|
+
},
|
|
535
|
+
options: groupedOptions
|
|
352
536
|
})
|
|
353
537
|
})
|
|
354
538
|
})]
|
|
@@ -414,9 +598,12 @@ function lineNumbers(lineNumber, linesState, _addLines) {
|
|
|
414
598
|
//#region src/widgets/CoverageDetail.tsx
|
|
415
599
|
const CoverageDetail = ({ source, coverage, diff }) => {
|
|
416
600
|
const addLines = diff.additions || [];
|
|
417
|
-
coverage = changeModeFilterIrrelevantData(coverage, diff);
|
|
601
|
+
coverage = addLines.length > 0 ? changeModeFilterIrrelevantData(coverage, diff) : coverage;
|
|
418
602
|
const { lines } = coreFn(coverage, source);
|
|
419
603
|
const ref = useRef(null);
|
|
604
|
+
const editorRef = useRef(null);
|
|
605
|
+
const highlightDecorationsRef = useRef(null);
|
|
606
|
+
const highlightTimeoutRef = useRef(null);
|
|
420
607
|
const hasChangedLines = addLines.length > 0 && coverage["s"] && coverage["statementMap"];
|
|
421
608
|
const linesState = (() => {
|
|
422
609
|
return lines.map((line, index) => {
|
|
@@ -453,6 +640,7 @@ const CoverageDetail = ({ source, coverage, diff }) => {
|
|
|
453
640
|
};
|
|
454
641
|
if (window.monaco?.editor && dom) {
|
|
455
642
|
const editor = window.monaco.editor.create(dom, options);
|
|
643
|
+
editorRef.current = editor;
|
|
456
644
|
const decorations = (() => {
|
|
457
645
|
const all = [];
|
|
458
646
|
const annotateStatementsList = annotateStatements(coverage);
|
|
@@ -495,9 +683,20 @@ const CoverageDetail = ({ source, coverage, diff }) => {
|
|
|
495
683
|
}
|
|
496
684
|
return arr;
|
|
497
685
|
})();
|
|
498
|
-
if (editor)
|
|
686
|
+
if (editor) {
|
|
687
|
+
editor?.createDecorationsCollection?.(decorations);
|
|
688
|
+
highlightDecorationsRef.current = editor.createDecorationsCollection([]);
|
|
689
|
+
}
|
|
499
690
|
}
|
|
500
691
|
}
|
|
692
|
+
return () => {
|
|
693
|
+
if (highlightTimeoutRef.current) clearTimeout(highlightTimeoutRef.current);
|
|
694
|
+
if (editorRef.current) {
|
|
695
|
+
editorRef.current.dispose();
|
|
696
|
+
editorRef.current = null;
|
|
697
|
+
}
|
|
698
|
+
highlightDecorationsRef.current = null;
|
|
699
|
+
};
|
|
501
700
|
}, [source, coverage]);
|
|
502
701
|
return /* @__PURE__ */ jsxs("div", {
|
|
503
702
|
className: "canyon-coverage-detail-container",
|
|
@@ -507,7 +706,31 @@ const CoverageDetail = ({ source, coverage, diff }) => {
|
|
|
507
706
|
},
|
|
508
707
|
children: [hasChangedLines ? /* @__PURE__ */ jsx(ChangedCodeCoverageTable_default, {
|
|
509
708
|
coverage,
|
|
510
|
-
addLines
|
|
709
|
+
addLines,
|
|
710
|
+
onJumpToRange: (startLine, startCol, endLine, endCol) => {
|
|
711
|
+
if (editorRef.current && window.monaco) {
|
|
712
|
+
const editor = editorRef.current;
|
|
713
|
+
if (highlightTimeoutRef.current) clearTimeout(highlightTimeoutRef.current);
|
|
714
|
+
if (highlightDecorationsRef.current) highlightDecorationsRef.current.clear();
|
|
715
|
+
const range = new window.monaco.Range(startLine, startCol, endLine, endCol);
|
|
716
|
+
if (highlightDecorationsRef.current) highlightDecorationsRef.current.set([{
|
|
717
|
+
range,
|
|
718
|
+
options: {
|
|
719
|
+
isWholeLine: false,
|
|
720
|
+
inlineClassName: "canyon-jump-highlight-range",
|
|
721
|
+
stickiness: window.monaco.editor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
|
|
722
|
+
}
|
|
723
|
+
}]);
|
|
724
|
+
editor.setPosition({
|
|
725
|
+
lineNumber: startLine,
|
|
726
|
+
column: startCol
|
|
727
|
+
});
|
|
728
|
+
editor.revealRange(range, window.monaco.editor.ScrollType.Smooth);
|
|
729
|
+
highlightTimeoutRef.current = setTimeout(() => {
|
|
730
|
+
if (highlightDecorationsRef.current) highlightDecorationsRef.current.clear();
|
|
731
|
+
}, 3e3);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
511
734
|
}) : null, /* @__PURE__ */ jsx("div", {
|
|
512
735
|
ref,
|
|
513
736
|
className: "canyon-coverage-detail-editor",
|