tech-debt-visualizer 0.2.4 → 0.2.6
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/reports/assets/report.css +227 -96
- package/dist/reports/assets/report.js +19 -2
- package/dist/reports/html.js +50 -39
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Technical Debt Report —
|
|
1
|
+
/* Technical Debt Report — Colorful dashboard, clean fit, scroll in sections */
|
|
2
2
|
:root {
|
|
3
3
|
--bg: #0b0c0e;
|
|
4
4
|
--bg-elevated: #111214;
|
|
@@ -9,8 +9,13 @@
|
|
|
9
9
|
--text: #e8e9ea;
|
|
10
10
|
--text-muted: #8b9199;
|
|
11
11
|
--link: #5794f2;
|
|
12
|
-
--radius:
|
|
13
|
-
--shadow: 0 1px
|
|
12
|
+
--radius: 6px;
|
|
13
|
+
--shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
|
|
14
|
+
--tier-1: #e53935;
|
|
15
|
+
--tier-2: #f57c00;
|
|
16
|
+
--tier-3: #f9a825;
|
|
17
|
+
--tier-4: #29b6f6;
|
|
18
|
+
--tier-5: #43a047;
|
|
14
19
|
}
|
|
15
20
|
|
|
16
21
|
[data-theme="light"] {
|
|
@@ -24,6 +29,11 @@
|
|
|
24
29
|
--text-muted: #6b7077;
|
|
25
30
|
--link: #3274d9;
|
|
26
31
|
--shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
|
|
32
|
+
--tier-1: #c62828;
|
|
33
|
+
--tier-2: #ef6c00;
|
|
34
|
+
--tier-3: #f9a825;
|
|
35
|
+
--tier-4: #0288d1;
|
|
36
|
+
--tier-5: #2e7d32;
|
|
27
37
|
}
|
|
28
38
|
|
|
29
39
|
* { box-sizing: border-box; }
|
|
@@ -40,7 +50,11 @@ body {
|
|
|
40
50
|
}
|
|
41
51
|
|
|
42
52
|
body.dashboard-page {
|
|
43
|
-
padding-bottom:
|
|
53
|
+
padding-bottom: 0;
|
|
54
|
+
height: 100vh;
|
|
55
|
+
overflow: hidden;
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-direction: column;
|
|
44
58
|
}
|
|
45
59
|
|
|
46
60
|
/* ——— Dashboard header (Grafana top bar: title left, score right) ——— */
|
|
@@ -104,70 +118,187 @@ body.dashboard-page {
|
|
|
104
118
|
.dashboard-score-of { font-size: 0.85rem; font-weight: 500; color: var(--text-muted); }
|
|
105
119
|
.dashboard-score-label { font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.04em; margin-left: 0.35rem; opacity: 0.95; }
|
|
106
120
|
|
|
107
|
-
.dashboard-score.tier-1 { background: rgba(
|
|
108
|
-
.dashboard-score.tier-2 { background: rgba(
|
|
109
|
-
.dashboard-score.tier-3 { background: rgba(
|
|
110
|
-
.dashboard-score.tier-4 { background: rgba(
|
|
111
|
-
.dashboard-score.tier-5 { background: rgba(
|
|
121
|
+
.dashboard-score.tier-1 { background: rgba(229, 57, 53, 0.25); color: #ff8a80; font-weight: 700; }
|
|
122
|
+
.dashboard-score.tier-2 { background: rgba(245, 124, 0, 0.25); color: #ffb74d; font-weight: 700; }
|
|
123
|
+
.dashboard-score.tier-3 { background: rgba(249, 168, 37, 0.25); color: #ffd54f; font-weight: 700; }
|
|
124
|
+
.dashboard-score.tier-4 { background: rgba(41, 182, 246, 0.25); color: #82b1ff; font-weight: 700; }
|
|
125
|
+
.dashboard-score.tier-5 { background: rgba(67, 160, 71, 0.25); color: #81c784; font-weight: 700; }
|
|
112
126
|
|
|
113
127
|
.dashboard-date {
|
|
114
128
|
font-size: 12px;
|
|
115
129
|
color: var(--text-muted);
|
|
116
130
|
}
|
|
117
131
|
|
|
118
|
-
/* ——— Main content: 2×2
|
|
132
|
+
/* ——— Main content: 2×2 grid, fills viewport, scroll inside cells ——— */
|
|
119
133
|
.dashboard-main {
|
|
120
|
-
|
|
134
|
+
flex: 1;
|
|
135
|
+
min-height: 0;
|
|
136
|
+
max-width: 1600px;
|
|
121
137
|
margin: 0 auto;
|
|
122
|
-
padding: 1rem
|
|
123
|
-
|
|
138
|
+
padding: 0.75rem 1rem;
|
|
139
|
+
width: 100%;
|
|
140
|
+
overflow: hidden;
|
|
141
|
+
display: flex;
|
|
142
|
+
flex-direction: column;
|
|
124
143
|
}
|
|
125
144
|
|
|
126
145
|
.dashboard-grid-2x2 {
|
|
146
|
+
flex: 1;
|
|
147
|
+
min-height: 0;
|
|
127
148
|
display: grid;
|
|
128
149
|
grid-template-columns: 1fr 1fr;
|
|
129
|
-
grid-template-rows: auto
|
|
130
|
-
gap:
|
|
131
|
-
align-items:
|
|
150
|
+
grid-template-rows: auto 1fr;
|
|
151
|
+
gap: 0.75rem;
|
|
152
|
+
align-items: stretch;
|
|
132
153
|
}
|
|
133
154
|
|
|
134
155
|
.dashboard-cell {
|
|
135
156
|
min-height: 0;
|
|
136
157
|
min-width: 0;
|
|
158
|
+
overflow: hidden;
|
|
137
159
|
}
|
|
138
160
|
|
|
139
161
|
.dashboard-cell .panel {
|
|
140
162
|
height: 100%;
|
|
141
163
|
display: flex;
|
|
142
164
|
flex-direction: column;
|
|
165
|
+
min-height: 0;
|
|
143
166
|
}
|
|
144
167
|
|
|
145
168
|
.dashboard-cell .panel-body {
|
|
146
169
|
flex: 1;
|
|
147
170
|
min-height: 0;
|
|
148
171
|
overflow: auto;
|
|
172
|
+
-webkit-overflow-scrolling: touch;
|
|
149
173
|
}
|
|
150
174
|
|
|
151
|
-
.dashboard-cell-score .panel-body-score { flex: 1 1 auto;
|
|
175
|
+
.dashboard-cell-score .panel-body-score { flex: 1 1 auto; min-height: 0; }
|
|
152
176
|
|
|
153
177
|
.dashboard-cell-heatmap .panel-body-heatmap,
|
|
154
178
|
.dashboard-cell-list .panel-body {
|
|
155
|
-
min-height:
|
|
179
|
+
min-height: 0;
|
|
156
180
|
}
|
|
157
181
|
|
|
158
182
|
@media (max-width: 900px) {
|
|
183
|
+
body.dashboard-page { height: auto; overflow: auto; }
|
|
159
184
|
.dashboard-grid-2x2 {
|
|
160
185
|
grid-template-columns: 1fr;
|
|
161
186
|
grid-template-rows: auto auto auto auto;
|
|
187
|
+
height: auto;
|
|
162
188
|
}
|
|
189
|
+
.dashboard-cell-heatmap .panel-body-heatmap { min-height: 240px; }
|
|
190
|
+
.dashboard-cell-list .panel-body { min-height: 240px; }
|
|
163
191
|
}
|
|
164
192
|
|
|
165
193
|
@media (max-width: 560px) {
|
|
166
|
-
.dashboard-header { padding: 0.
|
|
167
|
-
.dashboard-main { padding: 0.75rem
|
|
194
|
+
.dashboard-header { padding: 0.5rem 0.75rem; }
|
|
195
|
+
.dashboard-main { padding: 0.5rem 0.75rem; }
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/* ——— Footer: AI prompts button ——— */
|
|
199
|
+
.dashboard-footer {
|
|
200
|
+
flex-shrink: 0;
|
|
201
|
+
padding: 0.5rem 0;
|
|
202
|
+
border-top: 1px solid var(--border-subtle);
|
|
203
|
+
margin-top: 0.5rem;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.btn-ai-prompts {
|
|
207
|
+
font: inherit;
|
|
208
|
+
font-size: 13px;
|
|
209
|
+
font-weight: 600;
|
|
210
|
+
padding: 0.5rem 1rem;
|
|
211
|
+
background: var(--surface);
|
|
212
|
+
color: var(--text);
|
|
213
|
+
border: 1px solid var(--border);
|
|
214
|
+
border-radius: var(--radius);
|
|
215
|
+
cursor: pointer;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.btn-ai-prompts:hover {
|
|
219
|
+
background: var(--surface-hover);
|
|
220
|
+
border-color: var(--text-muted);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* ——— AI prompts overlay (blank screen) ——— */
|
|
224
|
+
.overlay {
|
|
225
|
+
position: fixed;
|
|
226
|
+
inset: 0;
|
|
227
|
+
z-index: 200;
|
|
228
|
+
display: none;
|
|
229
|
+
align-items: center;
|
|
230
|
+
justify-content: center;
|
|
231
|
+
padding: 1rem;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.overlay.show {
|
|
235
|
+
display: flex;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.overlay-backdrop {
|
|
239
|
+
position: absolute;
|
|
240
|
+
inset: 0;
|
|
241
|
+
background: rgba(0, 0, 0, 0.5);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.overlay-panel {
|
|
245
|
+
position: relative;
|
|
246
|
+
background: var(--surface);
|
|
247
|
+
border: 1px solid var(--border);
|
|
248
|
+
border-radius: var(--radius);
|
|
249
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
250
|
+
max-width: 560px;
|
|
251
|
+
width: 100%;
|
|
252
|
+
max-height: 85vh;
|
|
253
|
+
display: flex;
|
|
254
|
+
flex-direction: column;
|
|
255
|
+
overflow: hidden;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.overlay-header {
|
|
259
|
+
display: flex;
|
|
260
|
+
align-items: center;
|
|
261
|
+
justify-content: space-between;
|
|
262
|
+
padding: 0.75rem 1rem;
|
|
263
|
+
border-bottom: 1px solid var(--border-subtle);
|
|
264
|
+
flex-shrink: 0;
|
|
168
265
|
}
|
|
169
266
|
|
|
170
|
-
|
|
267
|
+
.overlay-title {
|
|
268
|
+
margin: 0;
|
|
269
|
+
font-size: 1rem;
|
|
270
|
+
font-weight: 600;
|
|
271
|
+
color: var(--text);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.overlay-close {
|
|
275
|
+
font-size: 1.5rem;
|
|
276
|
+
line-height: 1;
|
|
277
|
+
padding: 0.25rem;
|
|
278
|
+
background: none;
|
|
279
|
+
border: none;
|
|
280
|
+
color: var(--text-muted);
|
|
281
|
+
cursor: pointer;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.overlay-close:hover {
|
|
285
|
+
color: var(--text);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.overlay-body {
|
|
289
|
+
padding: 1rem;
|
|
290
|
+
overflow: auto;
|
|
291
|
+
flex: 1;
|
|
292
|
+
min-height: 0;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.overlay-placeholder {
|
|
296
|
+
margin: 0;
|
|
297
|
+
font-size: 13px;
|
|
298
|
+
color: var(--text-muted);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* ——— Panels: borders, colored accents ——— */
|
|
171
302
|
.panel {
|
|
172
303
|
background: var(--surface);
|
|
173
304
|
border: 1px solid var(--border);
|
|
@@ -177,9 +308,10 @@ body.dashboard-page {
|
|
|
177
308
|
}
|
|
178
309
|
|
|
179
310
|
.panel-header {
|
|
180
|
-
padding: 0.
|
|
311
|
+
padding: 0.6rem 0.85rem;
|
|
181
312
|
border-bottom: 1px solid var(--border-subtle);
|
|
182
|
-
background: rgba(0, 0, 0, 0.
|
|
313
|
+
background: rgba(0, 0, 0, 0.04);
|
|
314
|
+
flex-shrink: 0;
|
|
183
315
|
}
|
|
184
316
|
|
|
185
317
|
[data-theme="light"] .panel-header {
|
|
@@ -188,83 +320,80 @@ body.dashboard-page {
|
|
|
188
320
|
|
|
189
321
|
.panel-title {
|
|
190
322
|
margin: 0;
|
|
191
|
-
font-size:
|
|
192
|
-
font-weight:
|
|
323
|
+
font-size: 12px;
|
|
324
|
+
font-weight: 700;
|
|
193
325
|
color: var(--text);
|
|
194
|
-
letter-spacing:
|
|
326
|
+
letter-spacing: 0.02em;
|
|
327
|
+
text-transform: uppercase;
|
|
195
328
|
}
|
|
196
329
|
|
|
197
330
|
.panel-desc {
|
|
198
|
-
margin: 0.
|
|
199
|
-
font-size:
|
|
331
|
+
margin: 0.2rem 0 0;
|
|
332
|
+
font-size: 11px;
|
|
200
333
|
color: var(--text-muted);
|
|
201
|
-
line-height: 1.
|
|
334
|
+
line-height: 1.35;
|
|
202
335
|
}
|
|
203
336
|
|
|
204
337
|
.panel-body {
|
|
205
|
-
padding: 1rem;
|
|
338
|
+
padding: 0.85rem 1rem;
|
|
206
339
|
}
|
|
207
340
|
|
|
208
341
|
.panel-body-center {
|
|
209
342
|
text-align: center;
|
|
210
343
|
}
|
|
211
344
|
|
|
212
|
-
/* ——— Score panel (top-left:
|
|
345
|
+
/* ——— Score panel (top-left): numeric score only, scrollable ——— */
|
|
213
346
|
.panel-score .panel-body-score {
|
|
214
347
|
text-align: center;
|
|
215
|
-
padding:
|
|
348
|
+
padding: 1rem 0.85rem;
|
|
216
349
|
}
|
|
217
350
|
|
|
218
|
-
.
|
|
219
|
-
display:
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
.panel-score .score-badge-svg {
|
|
225
|
-
display: block;
|
|
226
|
-
width: 100px;
|
|
227
|
-
height: auto;
|
|
228
|
-
margin: 0 auto;
|
|
351
|
+
.score-numeric {
|
|
352
|
+
display: flex;
|
|
353
|
+
align-items: baseline;
|
|
354
|
+
justify-content: center;
|
|
355
|
+
gap: 0.25rem;
|
|
356
|
+
margin-bottom: 0.5rem;
|
|
229
357
|
}
|
|
230
358
|
|
|
231
|
-
.
|
|
232
|
-
font-size:
|
|
359
|
+
.score-num {
|
|
360
|
+
font-size: 2rem;
|
|
233
361
|
font-weight: 800;
|
|
234
|
-
|
|
362
|
+
line-height: 1;
|
|
363
|
+
letter-spacing: -0.04em;
|
|
364
|
+
color: var(--text);
|
|
235
365
|
}
|
|
236
366
|
|
|
237
|
-
.
|
|
238
|
-
font-size:
|
|
239
|
-
font-weight:
|
|
240
|
-
|
|
241
|
-
text-transform: uppercase;
|
|
242
|
-
opacity: 0.95;
|
|
367
|
+
.score-of {
|
|
368
|
+
font-size: 0.9rem;
|
|
369
|
+
font-weight: 600;
|
|
370
|
+
color: var(--text-muted);
|
|
243
371
|
}
|
|
244
372
|
|
|
245
373
|
.panel-score .score-label {
|
|
246
|
-
margin: 0 0 0.
|
|
247
|
-
font-size:
|
|
248
|
-
font-weight:
|
|
374
|
+
margin: 0 0 0.2rem;
|
|
375
|
+
font-size: 0.95rem;
|
|
376
|
+
font-weight: 700;
|
|
249
377
|
color: var(--text);
|
|
250
378
|
}
|
|
251
379
|
|
|
252
380
|
.panel-score .score-desc {
|
|
253
|
-
margin: 0 0 0.
|
|
254
|
-
font-size:
|
|
381
|
+
margin: 0 0 0.4rem;
|
|
382
|
+
font-size: 12px;
|
|
255
383
|
color: var(--text-muted);
|
|
256
|
-
line-height: 1.
|
|
257
|
-
max-width:
|
|
384
|
+
line-height: 1.4;
|
|
385
|
+
max-width: 260px;
|
|
258
386
|
margin-left: auto;
|
|
259
387
|
margin-right: auto;
|
|
260
388
|
}
|
|
261
389
|
|
|
262
390
|
.panel-score .score-stats {
|
|
263
391
|
margin: 0;
|
|
264
|
-
font-size:
|
|
392
|
+
font-size: 10px;
|
|
265
393
|
color: var(--text-muted);
|
|
266
394
|
text-transform: uppercase;
|
|
267
|
-
letter-spacing: 0.
|
|
395
|
+
letter-spacing: 0.04em;
|
|
396
|
+
font-weight: 600;
|
|
268
397
|
}
|
|
269
398
|
|
|
270
399
|
/* ——— Description of problems panel (top-right) ——— */
|
|
@@ -278,18 +407,18 @@ body.dashboard-page {
|
|
|
278
407
|
.priority-inline {
|
|
279
408
|
display: grid;
|
|
280
409
|
grid-template-columns: 1fr 1fr;
|
|
281
|
-
gap:
|
|
282
|
-
margin-top:
|
|
283
|
-
padding-top:
|
|
410
|
+
gap: 0.75rem;
|
|
411
|
+
margin-top: 0.75rem;
|
|
412
|
+
padding-top: 0.75rem;
|
|
284
413
|
border-top: 1px solid var(--border-subtle);
|
|
285
414
|
}
|
|
286
415
|
|
|
287
416
|
.priority-inline h4 {
|
|
288
|
-
margin: 0 0 0.
|
|
289
|
-
font-size:
|
|
290
|
-
font-weight:
|
|
417
|
+
margin: 0 0 0.35rem;
|
|
418
|
+
font-size: 10px;
|
|
419
|
+
font-weight: 700;
|
|
291
420
|
text-transform: uppercase;
|
|
292
|
-
letter-spacing: 0.
|
|
421
|
+
letter-spacing: 0.05em;
|
|
293
422
|
color: var(--text-muted);
|
|
294
423
|
}
|
|
295
424
|
|
|
@@ -324,10 +453,6 @@ body.dashboard-page {
|
|
|
324
453
|
border-radius: var(--radius);
|
|
325
454
|
}
|
|
326
455
|
|
|
327
|
-
/* LLM panel accent */
|
|
328
|
-
.panel-llm {
|
|
329
|
-
border-left: 3px solid var(--link);
|
|
330
|
-
}
|
|
331
456
|
|
|
332
457
|
/* ——— Banner ——— */
|
|
333
458
|
.no-llm-banner {
|
|
@@ -345,27 +470,33 @@ body.dashboard-page {
|
|
|
345
470
|
margin: 0;
|
|
346
471
|
}
|
|
347
472
|
|
|
348
|
-
/* ——— Treemap ——— */
|
|
473
|
+
/* ——— Treemap: square boxes per file ——— */
|
|
349
474
|
#treemap {
|
|
350
475
|
display: flex;
|
|
351
476
|
flex-wrap: wrap;
|
|
352
|
-
gap:
|
|
353
|
-
min-height:
|
|
477
|
+
gap: 6px;
|
|
478
|
+
min-height: 120px;
|
|
354
479
|
padding: 0.25rem 0;
|
|
355
480
|
}
|
|
356
481
|
|
|
357
482
|
.treemap-cell {
|
|
483
|
+
width: 44px;
|
|
484
|
+
height: 44px;
|
|
485
|
+
min-width: 44px;
|
|
486
|
+
min-height: 44px;
|
|
487
|
+
flex: none;
|
|
358
488
|
display: flex;
|
|
359
|
-
align-items:
|
|
360
|
-
|
|
361
|
-
padding:
|
|
362
|
-
font-size:
|
|
489
|
+
align-items: center;
|
|
490
|
+
justify-content: center;
|
|
491
|
+
padding: 4px;
|
|
492
|
+
font-size: 10px;
|
|
363
493
|
cursor: pointer;
|
|
364
494
|
overflow: hidden;
|
|
365
495
|
text-overflow: ellipsis;
|
|
366
496
|
white-space: nowrap;
|
|
367
497
|
border: 1px solid rgba(0, 0, 0, 0.15);
|
|
368
|
-
border-radius:
|
|
498
|
+
border-radius: 4px;
|
|
499
|
+
text-align: center;
|
|
369
500
|
}
|
|
370
501
|
|
|
371
502
|
.treemap-cell:hover {
|
|
@@ -373,11 +504,11 @@ body.dashboard-page {
|
|
|
373
504
|
outline-offset: 1px;
|
|
374
505
|
}
|
|
375
506
|
|
|
376
|
-
.treemap-cell[data-severity="critical"] { background:
|
|
377
|
-
.treemap-cell[data-severity="high"] { background:
|
|
378
|
-
.treemap-cell[data-severity="medium"] { background:
|
|
379
|
-
.treemap-cell[data-severity="low"] { background:
|
|
380
|
-
.treemap-cell[data-severity="none"] { background: var(--border); color: var(--text-muted); border-color: var(--border); }
|
|
507
|
+
.treemap-cell[data-severity="critical"] { background: var(--tier-1); color: #fff; border-color: rgba(0,0,0,0.2); }
|
|
508
|
+
.treemap-cell[data-severity="high"] { background: var(--tier-2); color: #fff; border-color: rgba(0,0,0,0.15); }
|
|
509
|
+
.treemap-cell[data-severity="medium"] { background: var(--tier-3); color: #1a1a1a; border-color: rgba(0,0,0,0.1); }
|
|
510
|
+
.treemap-cell[data-severity="low"] { background: var(--tier-5); color: #fff; border-color: rgba(0,0,0,0.1); }
|
|
511
|
+
.treemap-cell[data-severity="none"] { background: var(--border); color: var(--text-muted); border-color: var(--border-subtle); }
|
|
381
512
|
|
|
382
513
|
.legend {
|
|
383
514
|
display: flex;
|
|
@@ -389,12 +520,12 @@ body.dashboard-page {
|
|
|
389
520
|
color: var(--text-muted);
|
|
390
521
|
}
|
|
391
522
|
|
|
392
|
-
.legend span { display: inline-flex; align-items: center; gap: 0.
|
|
393
|
-
.legend .swatch { width:
|
|
394
|
-
.legend .swatch-crit { background:
|
|
395
|
-
.legend .swatch-high { background:
|
|
396
|
-
.legend .swatch-med { background:
|
|
397
|
-
.legend .swatch-low { background:
|
|
523
|
+
.legend span { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 11px; font-weight: 600; }
|
|
524
|
+
.legend .swatch { width: 12px; height: 12px; border-radius: 3px; }
|
|
525
|
+
.legend .swatch-crit { background: var(--tier-1); }
|
|
526
|
+
.legend .swatch-high { background: var(--tier-2); }
|
|
527
|
+
.legend .swatch-med { background: var(--tier-3); }
|
|
528
|
+
.legend .swatch-low { background: var(--tier-5); }
|
|
398
529
|
.legend .swatch-none { background: var(--border); }
|
|
399
530
|
|
|
400
531
|
/* ——— Priority lists ——— */
|
|
@@ -460,12 +591,12 @@ body.dashboard-page {
|
|
|
460
591
|
border-radius: 3px;
|
|
461
592
|
}
|
|
462
593
|
|
|
463
|
-
.badge-critical { background:
|
|
464
|
-
.badge-high { background:
|
|
465
|
-
.badge-medium { background:
|
|
466
|
-
.badge-low { background:
|
|
594
|
+
.badge-critical { background: var(--tier-1); color: #fff; font-weight: 700; }
|
|
595
|
+
.badge-high { background: var(--tier-2); color: #fff; font-weight: 700; }
|
|
596
|
+
.badge-medium { background: var(--tier-3); color: #1a1a1a; font-weight: 700; }
|
|
597
|
+
.badge-low { background: var(--tier-5); color: #fff; font-weight: 700; }
|
|
467
598
|
.badge-none { background: var(--border); color: var(--text-muted); }
|
|
468
|
-
.badge-llm { background: var(--link); color: #fff; }
|
|
599
|
+
.badge-llm { background: var(--link); color: #fff; font-weight: 700; }
|
|
469
600
|
|
|
470
601
|
/* ——— Detail modal ——— */
|
|
471
602
|
#detail {
|
|
@@ -145,8 +145,6 @@ fileScores.forEach(function (_ref) {
|
|
|
145
145
|
var cell = document.createElement("div");
|
|
146
146
|
cell.className = "treemap-cell";
|
|
147
147
|
cell.dataset.severity = severity;
|
|
148
|
-
cell.style.flex = String((score / maxScore) * 100) + " 1 80px";
|
|
149
|
-
cell.style.minWidth = "72px";
|
|
150
148
|
cell.title = file + llmScore;
|
|
151
149
|
cell.textContent = file.split("/").pop() || file;
|
|
152
150
|
cell.addEventListener("click", function () { showDetail(file, items); });
|
|
@@ -319,3 +317,22 @@ function showDetail(file, items) {
|
|
|
319
317
|
if (e.target === panel) panel.classList.remove("show");
|
|
320
318
|
};
|
|
321
319
|
}
|
|
320
|
+
|
|
321
|
+
(function () {
|
|
322
|
+
var btn = document.getElementById("btnAiPrompts");
|
|
323
|
+
var overlay = document.getElementById("aiPromptsOverlay");
|
|
324
|
+
var closeBtn = document.getElementById("closeAiPrompts");
|
|
325
|
+
var backdrop = overlay && overlay.querySelector(".overlay-backdrop");
|
|
326
|
+
if (!btn || !overlay) return;
|
|
327
|
+
function open() {
|
|
328
|
+
overlay.classList.add("show");
|
|
329
|
+
overlay.setAttribute("aria-hidden", "false");
|
|
330
|
+
}
|
|
331
|
+
function close() {
|
|
332
|
+
overlay.classList.remove("show");
|
|
333
|
+
overlay.setAttribute("aria-hidden", "true");
|
|
334
|
+
}
|
|
335
|
+
btn.addEventListener("click", open);
|
|
336
|
+
if (closeBtn) closeBtn.addEventListener("click", close);
|
|
337
|
+
if (backdrop) backdrop.addEventListener("click", close);
|
|
338
|
+
})();
|
package/dist/reports/html.js
CHANGED
|
@@ -14,25 +14,25 @@ export async function generateHtmlReport(run, options) {
|
|
|
14
14
|
const html = buildHtml(run, title, darkMode, css, script);
|
|
15
15
|
await writeFile(outputPath, html, "utf-8");
|
|
16
16
|
}
|
|
17
|
-
/** Inline SVG badge: shield shape with tier number and "of 5". */
|
|
17
|
+
/** Inline SVG badge: shield shape with tier number and "of 5" — clean, bold, tier-colored. */
|
|
18
18
|
function buildScoreBadgeSvg(tier, fillColor) {
|
|
19
|
-
const lighter = adjustHexBrightness(fillColor, 1.
|
|
19
|
+
const lighter = adjustHexBrightness(fillColor, 1.25);
|
|
20
20
|
const shadowId = "badge-shadow-" + tier;
|
|
21
21
|
const gradientId = "badge-shine-" + tier;
|
|
22
22
|
return `<svg class="score-badge-svg" viewBox="0 0 140 168" xmlns="http://www.w3.org/2000/svg" role="img">
|
|
23
23
|
<defs>
|
|
24
24
|
<linearGradient id="${gradientId}" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
25
|
-
<stop offset="0%" style="stop-color:${lighter};stop-opacity:0.
|
|
25
|
+
<stop offset="0%" style="stop-color:${lighter};stop-opacity:0.6" />
|
|
26
26
|
<stop offset="100%" style="stop-color:${fillColor};stop-opacity:1" />
|
|
27
27
|
</linearGradient>
|
|
28
|
-
<filter id="${shadowId}" x="-
|
|
29
|
-
<feDropShadow dx="0" dy="
|
|
28
|
+
<filter id="${shadowId}" x="-40%" y="-30%" width="180%" height="180%">
|
|
29
|
+
<feDropShadow dx="0" dy="4" stdDeviation="6" flood-color="${fillColor}" flood-opacity="0.4"/>
|
|
30
30
|
</filter>
|
|
31
31
|
</defs>
|
|
32
32
|
<path fill="url(#${gradientId})" filter="url(#${shadowId})" d="M70 12 C108 12 128 38 128 72 C128 106 70 156 70 156 C70 156 12 106 12 72 C12 38 32 12 70 12 Z"/>
|
|
33
|
-
<path fill="none" stroke="rgba(255,255,255,0.
|
|
34
|
-
<text x="70" y="
|
|
35
|
-
<text x="70" y="
|
|
33
|
+
<path fill="none" stroke="rgba(255,255,255,0.5)" stroke-width="2" stroke-linejoin="round" d="M70 12 C108 12 128 38 128 72 C128 106 70 156 70 156 C70 156 12 106 12 72 C12 38 32 12 70 12 Z"/>
|
|
34
|
+
<text x="70" y="80" text-anchor="middle" class="score-badge-num" fill="white">${tier}</text>
|
|
35
|
+
<text x="70" y="102" text-anchor="middle" class="score-badge-of" fill="rgba(255,255,255,0.95)">of 5</text>
|
|
36
36
|
</svg>`;
|
|
37
37
|
}
|
|
38
38
|
function adjustHexBrightness(hex, factor) {
|
|
@@ -69,15 +69,6 @@ function buildHtml(run, title, darkMode, css, script) {
|
|
|
69
69
|
});
|
|
70
70
|
const highCriticalCount = run.debtItems.filter((d) => d.severity === "high" || d.severity === "critical").length;
|
|
71
71
|
const hotspotCount = run.fileMetrics.filter((m) => (m.hotspotScore ?? 0) > 0.3).length;
|
|
72
|
-
const tierColors = {
|
|
73
|
-
1: "#c00",
|
|
74
|
-
2: "#e85d00",
|
|
75
|
-
3: "#b8860b",
|
|
76
|
-
4: "#069",
|
|
77
|
-
5: "#0a6b0a",
|
|
78
|
-
};
|
|
79
|
-
const tierColor = tierColors[cleanliness.tier] ?? "#666";
|
|
80
|
-
const scoreBadgeSvg = buildScoreBadgeSvg(cleanliness.tier, tierColor);
|
|
81
72
|
const statsLine = `${run.fileMetrics.length} files · ${run.debtItems.length} items · ${highCriticalCount} high/crit · ${hotspotCount} hotspots`;
|
|
82
73
|
return `<!DOCTYPE html>
|
|
83
74
|
<html lang="en" data-theme="${theme}">
|
|
@@ -113,12 +104,15 @@ function buildHtml(run, title, darkMode, css, script) {
|
|
|
113
104
|
<main class="dashboard-main">
|
|
114
105
|
<div class="dashboard-grid-2x2">
|
|
115
106
|
<div class="dashboard-cell dashboard-cell-score">
|
|
116
|
-
<div class="panel panel-score
|
|
107
|
+
<div class="panel panel-score">
|
|
117
108
|
<div class="panel-header">
|
|
118
109
|
<h2 class="panel-title">Technical Debt Cleanliness Score</h2>
|
|
119
110
|
</div>
|
|
120
111
|
<div class="panel-body panel-body-score">
|
|
121
|
-
<div class="score-
|
|
112
|
+
<div class="score-numeric">
|
|
113
|
+
<span class="score-num">${cleanliness.tier}</span>
|
|
114
|
+
<span class="score-of">of 5</span>
|
|
115
|
+
</div>
|
|
122
116
|
<p class="score-label">${escapeHtml(cleanliness.label)}</p>
|
|
123
117
|
<p class="score-desc">${escapeHtml(cleanliness.description)}</p>
|
|
124
118
|
<p class="score-stats">${statsLine}</p>
|
|
@@ -126,8 +120,27 @@ function buildHtml(run, title, darkMode, css, script) {
|
|
|
126
120
|
</div>
|
|
127
121
|
</div>
|
|
128
122
|
|
|
123
|
+
<div class="dashboard-cell dashboard-cell-heatmap">
|
|
124
|
+
<div class="panel panel-heatmap">
|
|
125
|
+
<div class="panel-header panel-header-heatmap">
|
|
126
|
+
<h2 class="panel-title">Files by debt</h2>
|
|
127
|
+
<p class="panel-desc">Size = complexity + churn. Color = severity. Click for details.</p>
|
|
128
|
+
<div class="legend legend-inline">
|
|
129
|
+
<span><span class="swatch swatch-crit"></span> Critical</span>
|
|
130
|
+
<span><span class="swatch swatch-high"></span> High</span>
|
|
131
|
+
<span><span class="swatch swatch-med"></span> Medium</span>
|
|
132
|
+
<span><span class="swatch swatch-low"></span> Low</span>
|
|
133
|
+
<span><span class="swatch swatch-none"></span> None</span>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
<div class="panel-body panel-body-heatmap">
|
|
137
|
+
<div id="treemap"></div>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
129
142
|
<div class="dashboard-cell dashboard-cell-problems">
|
|
130
|
-
<div class="panel
|
|
143
|
+
<div class="panel">
|
|
131
144
|
<div class="panel-header">
|
|
132
145
|
<h2 class="panel-title">Description of problems</h2>
|
|
133
146
|
</div>
|
|
@@ -153,25 +166,6 @@ function buildHtml(run, title, darkMode, css, script) {
|
|
|
153
166
|
</div>
|
|
154
167
|
</div>
|
|
155
168
|
|
|
156
|
-
<div class="dashboard-cell dashboard-cell-heatmap">
|
|
157
|
-
<div class="panel panel-heatmap">
|
|
158
|
-
<div class="panel-header panel-header-heatmap">
|
|
159
|
-
<h2 class="panel-title">Files by debt</h2>
|
|
160
|
-
<p class="panel-desc">Size = complexity + churn. Color = severity. Click for details.</p>
|
|
161
|
-
<div class="legend legend-inline">
|
|
162
|
-
<span><span class="swatch swatch-crit"></span> Critical</span>
|
|
163
|
-
<span><span class="swatch swatch-high"></span> High</span>
|
|
164
|
-
<span><span class="swatch swatch-med"></span> Medium</span>
|
|
165
|
-
<span><span class="swatch swatch-low"></span> Low</span>
|
|
166
|
-
<span><span class="swatch swatch-none"></span> None</span>
|
|
167
|
-
</div>
|
|
168
|
-
</div>
|
|
169
|
-
<div class="panel-body panel-body-heatmap">
|
|
170
|
-
<div id="treemap"></div>
|
|
171
|
-
</div>
|
|
172
|
-
</div>
|
|
173
|
-
</div>
|
|
174
|
-
|
|
175
169
|
<div class="dashboard-cell dashboard-cell-list">
|
|
176
170
|
<div class="panel">
|
|
177
171
|
<div class="panel-header">
|
|
@@ -184,8 +178,25 @@ function buildHtml(run, title, darkMode, css, script) {
|
|
|
184
178
|
</div>
|
|
185
179
|
</div>
|
|
186
180
|
</div>
|
|
181
|
+
|
|
182
|
+
<div class="dashboard-footer">
|
|
183
|
+
<button type="button" class="btn-ai-prompts" id="btnAiPrompts">AI cleanup prompts</button>
|
|
184
|
+
</div>
|
|
187
185
|
</main>
|
|
188
186
|
|
|
187
|
+
<div id="aiPromptsOverlay" class="overlay" aria-hidden="true">
|
|
188
|
+
<div class="overlay-backdrop"></div>
|
|
189
|
+
<div class="overlay-panel">
|
|
190
|
+
<div class="overlay-header">
|
|
191
|
+
<h2 class="overlay-title">AI cleanup prompts</h2>
|
|
192
|
+
<button type="button" class="overlay-close" id="closeAiPrompts" aria-label="Close">×</button>
|
|
193
|
+
</div>
|
|
194
|
+
<div class="overlay-body">
|
|
195
|
+
<p class="overlay-placeholder">Prompts to pass into AI for cleaning up the codebase will appear here.</p>
|
|
196
|
+
</div>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
|
|
189
200
|
<div id="detail">
|
|
190
201
|
<div class="panel">
|
|
191
202
|
<h3 id="detailTitle"></h3>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tech-debt-visualizer",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "Language-agnostic CLI that analyzes repos and generates interactive technical debt visualizations with AI-powered insights",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|