dependency-radar 0.2.0 → 0.3.0

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.
@@ -0,0 +1,324 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateSpdxExpression = validateSpdxExpression;
4
+ exports.inferLicenseFromText = inferLicenseFromText;
5
+ exports.pickLicenseRisk = pickLicenseRisk;
6
+ const spdx_1 = require("./generated/spdx");
7
+ const LICENSE_ID_LOOKUP = new Map();
8
+ const EXCEPTION_ID_LOOKUP = new Map();
9
+ for (const id of spdx_1.SPDX_LICENSE_IDS) {
10
+ LICENSE_ID_LOOKUP.set(id.toLowerCase(), id);
11
+ }
12
+ for (const id of spdx_1.SPDX_DEPRECATED_LICENSE_IDS) {
13
+ if (!LICENSE_ID_LOOKUP.has(id.toLowerCase())) {
14
+ LICENSE_ID_LOOKUP.set(id.toLowerCase(), id);
15
+ }
16
+ }
17
+ for (const id of spdx_1.SPDX_EXCEPTION_IDS) {
18
+ EXCEPTION_ID_LOOKUP.set(id.toLowerCase(), id);
19
+ }
20
+ for (const id of spdx_1.SPDX_DEPRECATED_EXCEPTION_IDS) {
21
+ if (!EXCEPTION_ID_LOOKUP.has(id.toLowerCase())) {
22
+ EXCEPTION_ID_LOOKUP.set(id.toLowerCase(), id);
23
+ }
24
+ }
25
+ function normalizeSpdxId(raw) {
26
+ const trimmed = raw.trim();
27
+ if (!trimmed)
28
+ return undefined;
29
+ if (spdx_1.SPDX_LICENSE_IDS.has(trimmed) || spdx_1.SPDX_DEPRECATED_LICENSE_IDS.has(trimmed))
30
+ return trimmed;
31
+ return LICENSE_ID_LOOKUP.get(trimmed.toLowerCase());
32
+ }
33
+ function normalizeExceptionId(raw) {
34
+ const trimmed = raw.trim();
35
+ if (!trimmed)
36
+ return undefined;
37
+ if (spdx_1.SPDX_EXCEPTION_IDS.has(trimmed) || spdx_1.SPDX_DEPRECATED_EXCEPTION_IDS.has(trimmed))
38
+ return trimmed;
39
+ return EXCEPTION_ID_LOOKUP.get(trimmed.toLowerCase());
40
+ }
41
+ function tokenizeSpdxExpression(value) {
42
+ const tokens = [];
43
+ let current = '';
44
+ const pushCurrent = () => {
45
+ const trimmed = current.trim();
46
+ if (trimmed)
47
+ tokens.push(trimmed);
48
+ current = '';
49
+ };
50
+ for (let i = 0; i < value.length; i += 1) {
51
+ const ch = value[i];
52
+ if (ch === '(' || ch === ')') {
53
+ pushCurrent();
54
+ tokens.push(ch);
55
+ continue;
56
+ }
57
+ if (/\s/.test(ch)) {
58
+ pushCurrent();
59
+ continue;
60
+ }
61
+ current += ch;
62
+ }
63
+ pushCurrent();
64
+ return tokens;
65
+ }
66
+ function validateSpdxExpression(input) {
67
+ if (!input || typeof input !== 'string') {
68
+ return {
69
+ valid: false,
70
+ expression: false,
71
+ deprecated: false,
72
+ normalized: '',
73
+ licenseIds: [],
74
+ exceptions: []
75
+ };
76
+ }
77
+ const raw = input.trim();
78
+ const invalid = {
79
+ valid: false,
80
+ expression: false,
81
+ deprecated: false,
82
+ normalized: raw,
83
+ licenseIds: [],
84
+ exceptions: []
85
+ };
86
+ if (!raw)
87
+ return invalid;
88
+ const tokens = tokenizeSpdxExpression(raw);
89
+ if (tokens.length === 0)
90
+ return invalid;
91
+ const licenseIds = [];
92
+ const exceptions = [];
93
+ const normalizedTokens = [];
94
+ let deprecated = false;
95
+ let expectTerm = true;
96
+ let depth = 0;
97
+ let i = 0;
98
+ while (i < tokens.length) {
99
+ const token = tokens[i];
100
+ if (expectTerm) {
101
+ if (token === '(') {
102
+ depth += 1;
103
+ normalizedTokens.push('(');
104
+ i += 1;
105
+ continue;
106
+ }
107
+ const licenseId = normalizeSpdxId(token);
108
+ if (!licenseId)
109
+ return invalid;
110
+ const isDeprecated = spdx_1.SPDX_DEPRECATED_LICENSE_IDS.has(licenseId);
111
+ if (isDeprecated)
112
+ deprecated = true;
113
+ licenseIds.push(licenseId);
114
+ normalizedTokens.push(licenseId);
115
+ i += 1;
116
+ if (tokens[i] && tokens[i].toUpperCase() === 'WITH') {
117
+ const exceptionToken = tokens[i + 1];
118
+ if (!exceptionToken || exceptionToken === '(' || exceptionToken === ')')
119
+ return invalid;
120
+ const exceptionId = normalizeExceptionId(exceptionToken);
121
+ if (!exceptionId) {
122
+ exceptions.push({ id: exceptionToken, deprecated: false, valid: false });
123
+ return invalid;
124
+ }
125
+ const exceptionDeprecated = spdx_1.SPDX_DEPRECATED_EXCEPTION_IDS.has(exceptionId);
126
+ if (exceptionDeprecated)
127
+ deprecated = true;
128
+ exceptions.push({ id: exceptionId, deprecated: exceptionDeprecated, valid: true });
129
+ normalizedTokens.push('WITH', exceptionId);
130
+ i += 2;
131
+ }
132
+ expectTerm = false;
133
+ continue;
134
+ }
135
+ if (token === ')') {
136
+ depth -= 1;
137
+ if (depth < 0)
138
+ return invalid;
139
+ normalizedTokens.push(')');
140
+ i += 1;
141
+ continue;
142
+ }
143
+ const op = token.toUpperCase();
144
+ if (op !== 'AND' && op !== 'OR')
145
+ return invalid;
146
+ normalizedTokens.push(op);
147
+ i += 1;
148
+ expectTerm = true;
149
+ }
150
+ if (expectTerm || depth !== 0)
151
+ return invalid;
152
+ return {
153
+ valid: true,
154
+ expression: normalizedTokens.includes('AND') || normalizedTokens.includes('OR'),
155
+ deprecated,
156
+ normalized: normalizedTokens.join(' '),
157
+ licenseIds,
158
+ exceptions
159
+ };
160
+ }
161
+ function normalizeTextForMatch(text) {
162
+ return text
163
+ .replace(/\r\n/g, '\n')
164
+ .replace(/\r/g, '\n')
165
+ .split('\n')
166
+ .filter((line) => !/^copyright\b/i.test(line.trim()))
167
+ .join('\n')
168
+ .toLowerCase()
169
+ .replace(/[ \t]+/g, ' ')
170
+ .replace(/\n+/g, '\n')
171
+ .trim();
172
+ }
173
+ function scoreMatch(text, phrases) {
174
+ let score = 0;
175
+ for (const phrase of phrases) {
176
+ if (text.includes(phrase))
177
+ score += 1;
178
+ }
179
+ return score;
180
+ }
181
+ function confidenceFromScore(score, total) {
182
+ if (score === 0)
183
+ return undefined;
184
+ if (score === total)
185
+ return 'high';
186
+ if (score >= Math.max(2, Math.ceil(total * 0.6)))
187
+ return 'medium';
188
+ return 'low';
189
+ }
190
+ const MIT_PHRASES = [
191
+ 'permission is hereby granted, free of charge, to any person obtaining a copy',
192
+ 'the software is provided "as is"',
193
+ 'in no event shall the authors or copyright holders'
194
+ ];
195
+ const ISC_PHRASES = [
196
+ 'permission to use, copy, modify, and/or distribute this software for any purpose',
197
+ 'the software is provided "as is"'
198
+ ];
199
+ const APACHE_PHRASES = [
200
+ 'apache license',
201
+ 'version 2.0',
202
+ 'http://www.apache.org/licenses/',
203
+ 'unless required by applicable law or agreed to in writing'
204
+ ];
205
+ const BSD_COMMON = [
206
+ 'redistribution and use in source and binary forms',
207
+ 'this list of conditions and the following disclaimer'
208
+ ];
209
+ const BSD_3_CLAUSE = [
210
+ ...BSD_COMMON,
211
+ 'neither the name of'
212
+ ];
213
+ const BSD_2_CLAUSE = BSD_COMMON;
214
+ const MPL_PHRASES = ['mozilla public license', 'version 2.0'];
215
+ const GPL_PHRASES = ['gnu general public license'];
216
+ const LGPL_PHRASES = ['gnu lesser general public license'];
217
+ const AGPL_PHRASES = ['gnu affero general public license'];
218
+ const GPL_LATER_PHRASE = 'either version';
219
+ const GPL_LATER_PHRASE_SUFFIX = 'any later version';
220
+ const UNLICENSE_PHRASES = [
221
+ 'this is free and unencumbered software released into the public domain',
222
+ 'the software is provided "as is"'
223
+ ];
224
+ const CC0_PHRASES = ['creative commons zero', 'cc0 1.0'];
225
+ function inferLicenseFromText(rawText) {
226
+ if (!rawText)
227
+ return undefined;
228
+ const text = normalizeTextForMatch(rawText);
229
+ if (!text)
230
+ return undefined;
231
+ const candidates = [];
232
+ const mitScore = scoreMatch(text, MIT_PHRASES);
233
+ const mitConfidence = confidenceFromScore(mitScore, MIT_PHRASES.length);
234
+ if (mitConfidence)
235
+ candidates.push({ spdxId: 'MIT', confidence: mitConfidence });
236
+ const iscScore = scoreMatch(text, ISC_PHRASES);
237
+ const iscConfidence = confidenceFromScore(iscScore, ISC_PHRASES.length);
238
+ if (iscConfidence)
239
+ candidates.push({ spdxId: 'ISC', confidence: iscConfidence });
240
+ const apacheScore = scoreMatch(text, APACHE_PHRASES);
241
+ const apacheConfidence = confidenceFromScore(apacheScore, APACHE_PHRASES.length);
242
+ if (apacheConfidence)
243
+ candidates.push({ spdxId: 'Apache-2.0', confidence: apacheConfidence });
244
+ const bsd3Score = scoreMatch(text, BSD_3_CLAUSE);
245
+ const bsd3Confidence = confidenceFromScore(bsd3Score, BSD_3_CLAUSE.length);
246
+ if (bsd3Confidence) {
247
+ candidates.push({ spdxId: 'BSD-3-Clause', confidence: bsd3Confidence });
248
+ }
249
+ else {
250
+ const bsd2Score = scoreMatch(text, BSD_2_CLAUSE);
251
+ const bsd2Confidence = confidenceFromScore(bsd2Score, BSD_2_CLAUSE.length);
252
+ if (bsd2Confidence)
253
+ candidates.push({ spdxId: 'BSD-2-Clause', confidence: bsd2Confidence });
254
+ }
255
+ const mplScore = scoreMatch(text, MPL_PHRASES);
256
+ const mplConfidence = confidenceFromScore(mplScore, MPL_PHRASES.length);
257
+ if (mplConfidence)
258
+ candidates.push({ spdxId: 'MPL-2.0', confidence: mplConfidence });
259
+ const unlicenseScore = scoreMatch(text, UNLICENSE_PHRASES);
260
+ const unlicenseConfidence = confidenceFromScore(unlicenseScore, UNLICENSE_PHRASES.length);
261
+ if (unlicenseConfidence)
262
+ candidates.push({ spdxId: 'Unlicense', confidence: unlicenseConfidence });
263
+ const cc0Score = scoreMatch(text, CC0_PHRASES);
264
+ const cc0Confidence = confidenceFromScore(cc0Score, CC0_PHRASES.length);
265
+ if (cc0Confidence)
266
+ candidates.push({ spdxId: 'CC0-1.0', confidence: cc0Confidence });
267
+ if (text.includes('gnu')) {
268
+ if (text.includes(AGPL_PHRASES[0])) {
269
+ candidates.push({
270
+ spdxId: text.includes(GPL_LATER_PHRASE) && text.includes(GPL_LATER_PHRASE_SUFFIX)
271
+ ? 'AGPL-3.0-or-later'
272
+ : 'AGPL-3.0-only',
273
+ confidence: 'medium'
274
+ });
275
+ }
276
+ else if (text.includes(LGPL_PHRASES[0])) {
277
+ candidates.push({
278
+ spdxId: text.includes('version 2.1')
279
+ ? (text.includes(GPL_LATER_PHRASE) && text.includes(GPL_LATER_PHRASE_SUFFIX)
280
+ ? 'LGPL-2.1-or-later'
281
+ : 'LGPL-2.1-only')
282
+ : (text.includes(GPL_LATER_PHRASE) && text.includes(GPL_LATER_PHRASE_SUFFIX)
283
+ ? 'LGPL-3.0-or-later'
284
+ : 'LGPL-3.0-only'),
285
+ confidence: 'medium'
286
+ });
287
+ }
288
+ else if (text.includes(GPL_PHRASES[0])) {
289
+ const isVersion2 = text.includes('version 2');
290
+ const isVersion3 = text.includes('version 3');
291
+ const isLater = text.includes(GPL_LATER_PHRASE) && text.includes(GPL_LATER_PHRASE_SUFFIX);
292
+ if (isVersion2) {
293
+ candidates.push({ spdxId: isLater ? 'GPL-2.0-or-later' : 'GPL-2.0-only', confidence: 'medium' });
294
+ }
295
+ else if (isVersion3) {
296
+ candidates.push({ spdxId: isLater ? 'GPL-3.0-or-later' : 'GPL-3.0-only', confidence: 'medium' });
297
+ }
298
+ }
299
+ }
300
+ if (candidates.length === 0)
301
+ return undefined;
302
+ const confidenceRank = { high: 3, medium: 2, low: 1 };
303
+ candidates.sort((a, b) => confidenceRank[b.confidence] - confidenceRank[a.confidence]);
304
+ return candidates[0];
305
+ }
306
+ function pickLicenseRisk(licenseIds) {
307
+ if (!licenseIds || licenseIds.length === 0)
308
+ return 'red';
309
+ const normalized = licenseIds.map((id) => id.toUpperCase());
310
+ const green = ['MIT', 'BSD-2-CLAUSE', 'BSD-3-CLAUSE', 'APACHE-2.0', 'ISC', 'CC0-1.0', 'UNLICENSE'];
311
+ const amber = ['LGPL', 'LGPL-2.1', 'LGPL-3.0', 'MPL', 'MPL-2.0'];
312
+ let risk = 'green';
313
+ for (const id of normalized) {
314
+ if (green.includes(id))
315
+ continue;
316
+ if (amber.some((prefix) => id.startsWith(prefix))) {
317
+ if (risk === 'green')
318
+ risk = 'amber';
319
+ continue;
320
+ }
321
+ risk = 'red';
322
+ }
323
+ return risk;
324
+ }
@@ -8,11 +8,11 @@ exports.JS_CONTENT = exports.CSS_CONTENT = void 0;
8
8
  * CSS content for the dependency radar HTML report
9
9
  * Built from report-ui/style.css
10
10
  */
11
- exports.CSS_CONTENT = `*,*:before,*:after{box-sizing:border-box}:root{--bg-primary: #0c1222;--bg-secondary: #151d2e;--bg-card: rgba(21, 29, 46, .95);--bg-card-hover: rgba(30, 41, 59, .95);--text-primary: #e8edf5;--text-secondary: #8b99b0;--text-muted: #5c6b82;--border-color: rgba(99, 120, 150, .2);--border-color-strong: rgba(99, 120, 150, .35);--accent: #06b6d4;--accent-hover: #22d3ee;--accent-subtle: rgba(6, 182, 212, .15);--title-gradient: linear-gradient(135deg, #06b6d4 0%, #10b981 100%);--green: #10b981;--green-bg: rgba(16, 185, 129, .15);--amber: #f59e0b;--amber-bg: rgba(245, 158, 11, .15);--red: #ef4444;--red-bg: rgba(239, 68, 68, .15);--gray: #64748b;--gray-bg: rgba(100, 116, 139, .15);--license-permissive: #10b981;--license-weak-copyleft: #f59e0b;--license-strong-copyleft: #ef4444;--license-unknown: #64748b;--font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;--transition: .2s ease;--radius: 8px;--radius-lg: 12px}:root.light{--bg-primary: #f5f7fa;--bg-secondary: #e8ecf2;--bg-card: rgba(255, 255, 255, .98);--bg-card-hover: rgba(248, 250, 252, 1);--text-primary: #0f172a;--text-secondary: #475569;--text-muted: #64748b;--border-color: rgba(100, 116, 139, .18);--border-color-strong: rgba(100, 116, 139, .3);--accent: #0891b2;--accent-hover: #06b6d4;--accent-subtle: rgba(8, 145, 178, .1);--title-gradient: linear-gradient(135deg, #0891b2 0%, #059669 100%)}html{scroll-behavior:smooth}body{font-family:var(--font-stack);background:var(--bg-primary);color:var(--text-primary);margin:0;padding:0;line-height:1.5;transition:background var(--transition),color var(--transition)}.top-header{padding:28px 24px 20px;max-width:1400px;margin:0 auto}.header-row{display:flex;align-items:flex-start;justify-content:space-between;gap:24px}.header-content{display:flex;align-items:flex-start;gap:18px}.logo,.logo-wrapper{display:block;width:64px;height:64px;flex-shrink:0}.logo svg{width:100%;height:100%}.header-text h1{margin:0;font-size:26px;font-weight:700;background:var(--title-gradient);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;letter-spacing:-.02em}.header-meta{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px;font-size:12px}.meta-item{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:6px;color:var(--text-secondary)}.meta-item strong{color:var(--text-primary);font-family:var(--font-mono);font-size:11px;font-weight:500}.meta-label{color:var(--text-muted);font-size:10px;text-transform:uppercase;letter-spacing:.3px}.header-disclaimer{display:block;width:100%;font-size:10px;color:var(--text-muted);margin-top:6px;padding-left:2px}.cta-section{flex-shrink:0;text-align:right;max-width:280px}.cta-link{display:inline-flex;align-items:center;gap:8px;padding:10px 18px;background:var(--accent);color:#fff;text-decoration:none;border-radius:var(--radius);font-size:13px;font-weight:600;transition:all var(--transition);box-shadow:0 2px 8px #06b6d440}.cta-link:hover{background:var(--accent-hover);transform:translateY(-1px);box-shadow:0 4px 12px #06b6d459}.cta-benefits{margin-top:8px;font-size:11px;color:var(--text-muted);line-height:1.5;text-align:left;padding-left:2px}.cta-benefits span{display:block;padding-left:12px;position:relative}.cta-benefits span:before{content:"→";position:absolute;left:0;color:var(--accent);font-size:10px}.cta-text{display:block;font-size:11px;color:var(--text-muted);margin-top:6px}.cta-arrow{font-size:14px;transition:transform var(--transition)}.cta-link:hover .cta-arrow{transform:translate(2px)}.filter-bar{position:sticky;top:0;z-index:100;background:var(--bg-secondary);border-bottom:1px solid var(--border-color);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);padding:12px 24px;transition:background var(--transition),border-color var(--transition)}.filter-bar-inner{max-width:1400px;margin:0 auto;display:flex;flex-wrap:wrap;align-items:center;gap:12px}.filter-group{display:flex;align-items:center;gap:6px}.filter-label{font-size:12px;font-weight:500;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.search-wrapper{position:relative;flex:1;min-width:180px;max-width:280px}.search-icon{position:absolute;left:10px;top:50%;transform:translateY(-50%);color:var(--text-muted);pointer-events:none}input[type=search]{width:100%;padding:8px 12px 8px 32px;border:1px solid var(--border-color);border-radius:var(--radius);background:var(--bg-primary);color:var(--text-primary);font-size:14px;transition:border-color var(--transition),background var(--transition)}input[type=search]:focus{outline:none;border-color:var(--accent)}input[type=search]::placeholder{color:var(--text-muted)}select{padding:8px 28px 8px 10px;border:1px solid var(--border-color);border-radius:var(--radius);background:var(--bg-primary);color:var(--text-primary);font-size:13px;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center;transition:border-color var(--transition),background var(--transition)}select:focus{outline:none;border-color:var(--accent)}.sort-wrapper{display:flex;align-items:center;gap:4px}.sort-direction-btn{padding:8px;border:1px solid var(--border-color);border-radius:var(--radius);background:var(--bg-primary);color:var(--text-secondary);cursor:pointer;font-size:14px;line-height:1;transition:all var(--transition)}.sort-direction-btn:hover{border-color:var(--accent);color:var(--accent)}.checkbox-filter{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--text-secondary);cursor:pointer}.checkbox-filter input[type=checkbox]{width:16px;height:16px;accent-color:var(--accent);cursor:pointer}.theme-toggle{margin-left:auto;display:flex;align-items:center;gap:8px}.theme-toggle-label{font-size:12px;color:var(--text-muted)}.theme-switch{position:relative;width:44px;height:24px;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:12px;cursor:pointer;transition:background var(--transition),border-color var(--transition)}.theme-switch:after{content:"";position:absolute;top:2px;left:2px;width:18px;height:18px;background:var(--text-secondary);border-radius:50%;transition:transform var(--transition),background var(--transition)}.theme-switch.light:after{transform:translate(20px);background:var(--accent)}.license-filter-toggle{padding:6px 12px;border:1px solid var(--border-color);border-radius:var(--radius);background:transparent;color:var(--text-secondary);font-size:12px;cursor:pointer;display:flex;align-items:center;gap:6px;transition:all var(--transition)}.license-filter-toggle:hover{border-color:var(--accent);color:var(--accent)}.license-filter-toggle .chevron{transition:transform var(--transition)}.license-filter-toggle.open .chevron{transform:rotate(180deg)}.license-filter-panel{max-height:0;overflow:hidden;transition:max-height .3s ease-out;background:var(--bg-secondary);border-bottom:1px solid transparent}.license-filter-panel.open{max-height:200px;border-bottom-color:var(--border-color)}.license-filter-inner{max-width:1400px;margin:0 auto;padding:12px 24px}.license-filter-header{display:flex;align-items:center;gap:12px;margin-bottom:8px}.license-filter-title{font-size:12px;font-weight:500;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.license-quick-actions{display:flex;gap:8px}.quick-action-btn{padding:4px 10px;font-size:11px;border:1px solid var(--border-color);border-radius:4px;background:transparent;color:var(--text-secondary);cursor:pointer;transition:all var(--transition)}.quick-action-btn:hover{border-color:var(--accent);color:var(--accent)}.license-groups{display:flex;flex-wrap:wrap;gap:16px}.license-group-checkbox{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--text-secondary);cursor:pointer}.license-group-checkbox input[type=checkbox]{width:16px;height:16px;accent-color:var(--accent);cursor:pointer}.license-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}.license-dot.permissive{background:var(--license-permissive)}.license-dot.weak-copyleft{background:var(--license-weak-copyleft)}.license-dot.strong-copyleft{background:var(--license-strong-copyleft)}.license-dot.unknown{background:var(--license-unknown)}.tool-errors{max-width:1400px;margin:16px auto;padding:12px 16px;background:var(--red-bg);border:1px solid var(--red);border-radius:var(--radius);color:var(--red)}.tool-errors:empty{display:none}.tool-errors strong{display:block;margin-bottom:8px}.main-content{max-width:1400px;margin:0 auto;padding:16px 24px 48px}.results-summary{margin-bottom:16px;font-size:14px;color:var(--text-secondary)}.results-summary strong{color:var(--text-primary)}.dependency-grid{display:flex;flex-direction:column;gap:8px}.dep-card{background:var(--bg-card);border:1px solid var(--border-color);border-radius:var(--radius-lg);overflow:hidden;transition:border-color var(--transition)}.dep-card:hover{border-color:var(--border-color-strong)}.dep-card[data-risk=red]{border-left:3px solid var(--red)}.dep-card[data-risk=amber]{border-left:3px solid var(--amber)}.dep-card[data-risk=green]{border-left:3px solid var(--green)}.dep-summary{display:flex;align-items:center;gap:10px;padding:0 0 0 12px;cursor:pointer;list-style:none;transition:background var(--transition)}.dep-summary:hover{background:var(--bg-card-hover)}.dep-summary::-webkit-details-marker{display:none}.expand-icon{color:var(--text-muted);transition:transform var(--transition);flex-shrink:0}details[open] .expand-icon{transform:rotate(90deg)}.dep-name{font-family:var(--font-mono);font-size:14px;font-weight:600;color:var(--text-primary);padding:8px 0}.dep-version{font-weight:400;color:var(--text-secondary)}.dep-indicators{display:grid;grid-template-columns:repeat(5,1fr);margin-left:auto;flex-shrink:0;width:60%}.badge-card{display:flex;flex-direction:column;justify-content:center;min-height:38px;padding:4px 8px 4px 10px;background:var(--bg-primary);border-left:1px solid var(--border-color);position:relative;overflow:hidden}.badge-card:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--gray)}.badge-card.green:before{background:var(--green)}.badge-card.amber:before{background:var(--amber)}.badge-card.red:before{background:var(--red)}.badge-card.gray:before{background:var(--gray)}.badge-label{font-size:8px;font-weight:500;color:var(--text-muted);text-transform:uppercase;letter-spacing:.3px;line-height:1.1}.badge-value{font-size:11px;font-weight:500;color:var(--text-primary);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dep-details{padding:0 16px 16px;border-top:1px solid var(--border-color);animation:slideDown .2s ease-out}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.package-links{display:flex;flex-wrap:wrap;gap:8px;padding:12px 0;margin-bottom:4px;border-bottom:1px solid var(--border-color)}.package-link{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:var(--bg-hover);border:1px solid var(--border-color);border-radius:var(--radius-md);color:var(--text-primary);text-decoration:none;font-size:13px;font-weight:500;transition:all var(--transition)}.package-link:hover{background:var(--accent);border-color:var(--accent);color:#fff}.package-link svg{width:14px;height:14px;flex-shrink:0}.section,.section:first-child{margin-top:16px}.section-header{display:flex;align-items:center;gap:8px;margin-bottom:10px;padding-bottom:6px;border-bottom:1px solid var(--border-color)}.section-title{font-size:13px;font-weight:600;color:var(--text-primary);text-transform:uppercase;letter-spacing:.5px}.section-desc{font-size:11px;color:var(--text-muted)}.kv-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px}.kv-item{display:flex;flex-direction:column;gap:2px}.kv-label{font-size:12px;font-weight:500;color:var(--text-muted)}.kv-value{font-size:14px;color:var(--text-primary)}.kv-hint{font-size:11px;color:var(--text-muted);font-style:italic}.package-list{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}.package-tag{padding:2px 8px;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:4px;font-size:11px;font-family:var(--font-mono);color:var(--text-secondary)}.package-list-toggle{font-size:11px;color:var(--accent);background:none;border:none;cursor:pointer;padding:2px 4px}.package-list-toggle:hover{text-decoration:underline}.vuln-table{width:100%;border-collapse:collapse;font-size:13px}.vuln-table th,.vuln-table td{text-align:left;padding:8px 12px;border-bottom:1px solid var(--border-color)}.vuln-table th{font-weight:500;color:var(--text-muted);font-size:11px;text-transform:uppercase;letter-spacing:.5px}.vuln-table tr[data-severity=critical],.vuln-table tr[data-severity=high]{background:var(--red-bg)}.vuln-table tr[data-severity=moderate]{background:var(--amber-bg)}.vuln-table a{color:var(--accent);text-decoration:none}.vuln-table a:hover{text-decoration:underline}.no-vulns{font-size:13px;color:var(--text-secondary);padding:8px 0}.raw-data-toggle{margin-top:16px}.raw-data-toggle summary{font-size:12px;color:var(--text-muted);cursor:pointer;padding:8px 0}.raw-data-toggle pre{margin:8px 0 0;padding:12px;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:var(--radius);font-family:var(--font-mono);font-size:11px;color:var(--text-secondary);overflow-x:auto;max-height:300px}.empty-state{text-align:center;padding:48px 24px;color:var(--text-muted)}.empty-state-icon{font-size:48px;margin-bottom:12px}.empty-state-text{font-size:16px}@media (max-width: 768px){.top-header{padding:20px 16px}.header-row{flex-direction:column;align-items:flex-start;gap:16px}.header-content{gap:12px}.logo,.logo-wrapper{width:48px;height:48px}.header-text h1{font-size:22px}.header-meta{gap:6px}.meta-item{padding:3px 8px;font-size:11px}.cta-section{width:100%;max-width:none;text-align:left}.cta-benefits{display:none}.filter-bar{padding:10px 16px}.filter-bar-inner{flex-direction:column;align-items:stretch;gap:10px}.search-wrapper{max-width:none}.filter-group{justify-content:space-between}.theme-toggle{margin-left:0;justify-content:flex-end}.main-content{padding:12px 16px 32px}.dep-summary{flex-wrap:wrap;padding:8px 12px}.dep-name{font-size:13px}.dep-indicators{display:flex;flex-wrap:wrap;min-width:auto;width:100%;margin-left:0;margin-top:6px;padding-top:6px;border-top:1px solid var(--border-color);gap:4px}.badge-card{flex:1 1 calc(50% - 4px);min-width:0}.badge-value{font-size:10px}.badge-label{font-size:7px}}@media (max-width: 480px){.header-text h1{font-size:20px}.meta-item{font-size:10px;padding:2px 6px}.cta-link{width:100%;justify-content:center;padding:12px 16px}.badge-card{flex:1 1 100%}}
11
+ exports.CSS_CONTENT = `*,*:before,*:after{box-sizing:border-box}:root{--bg-primary: #0c1222;--bg-secondary: #151d2e;--bg-card: rgba(21, 29, 46, .95);--bg-card-hover: rgba(30, 41, 59, .95);--text-primary: #e8edf5;--text-secondary: #8b99b0;--text-muted: #5c6b82;--border-color: rgba(99, 120, 150, .2);--border-color-strong: rgba(99, 120, 150, .35);--accent: #06b6d4;--accent-hover: #22d3ee;--accent-subtle: rgba(6, 182, 212, .15);--title-gradient: linear-gradient(135deg, #06b6d4 0%, #10b981 100%);--green: #10b981;--green-bg: rgba(16, 185, 129, .15);--amber: #f59e0b;--amber-bg: rgba(245, 158, 11, .15);--red: #ef4444;--red-bg: rgba(239, 68, 68, .15);--gray: #64748b;--gray-bg: rgba(100, 116, 139, .15);--license-permissive: #10b981;--license-weak-copyleft: #f59e0b;--license-strong-copyleft: #ef4444;--license-unknown: #64748b;--font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;--transition: .2s ease;--radius: 8px;--radius-lg: 12px}:root.light{--bg-primary: #f5f7fa;--bg-secondary: #e8ecf2;--bg-card: rgba(255, 255, 255, .98);--bg-card-hover: rgba(248, 250, 252, 1);--text-primary: #0f172a;--text-secondary: #475569;--text-muted: #64748b;--border-color: rgba(100, 116, 139, .18);--border-color-strong: rgba(100, 116, 139, .3);--accent: #0891b2;--accent-hover: #06b6d4;--accent-subtle: rgba(8, 145, 178, .1);--title-gradient: linear-gradient(135deg, #0891b2 0%, #059669 100%)}html{scroll-behavior:smooth}body{font-family:var(--font-stack);background:var(--bg-primary);color:var(--text-primary);margin:0;padding:0;line-height:1.5;transition:background var(--transition),color var(--transition)}.top-header{padding:28px 24px 20px;max-width:1400px;margin:0 auto}.header-row{display:flex;align-items:flex-start;justify-content:space-between;gap:24px}.header-content{display:flex;align-items:flex-start;gap:18px}.logo,.logo-wrapper{display:block;width:6rem;height:6rem;flex-shrink:0}.logo svg{width:100%;height:100%}.header-text h1{margin:0;font-size:26px;font-weight:700;background:var(--title-gradient);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;letter-spacing:-.02em}.header-meta{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px;font-size:12px}.meta-item{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:6px;color:var(--text-secondary)}.meta-item strong{color:var(--text-primary);font-family:var(--font-mono);font-size:11px;font-weight:500}.meta-label{color:var(--text-muted);font-size:10px;text-transform:uppercase;letter-spacing:.3px}.header-disclaimer{display:block;width:100%;font-size:10px;color:var(--text-muted);margin-top:6px;padding-left:2px}.cta-section{flex-shrink:0;text-align:right;max-width:280px}.cta-link{display:inline-flex;align-items:center;gap:8px;padding:10px 18px;background:var(--accent);color:#fff;text-decoration:none;border-radius:var(--radius);font-size:13px;font-weight:600;transition:all var(--transition);box-shadow:0 2px 8px #06b6d440}.cta-link:hover{background:var(--accent-hover);transform:translateY(-1px);box-shadow:0 4px 12px #06b6d459}.cta-benefits{margin-top:8px;font-size:11px;color:var(--text-muted);line-height:1.5;text-align:left;padding-left:2px}.cta-benefits span{display:block;padding-left:12px;position:relative}.cta-benefits span:before{content:"→";position:absolute;left:0;color:var(--accent);font-size:10px}.cta-text{display:block;font-size:11px;color:var(--text-muted);margin-top:6px}.cta-arrow{font-size:14px;transition:transform var(--transition)}.cta-link:hover .cta-arrow{transform:translate(2px)}.filter-bar{position:sticky;top:0;z-index:100;background:var(--bg-secondary);border-bottom:1px solid var(--border-color);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);padding:12px 24px;transition:background var(--transition),border-color var(--transition)}.filter-bar-inner{max-width:1400px;margin:0 auto;display:flex;flex-wrap:wrap;align-items:center;gap:12px}.filter-group{display:flex;align-items:center;gap:6px}.filter-label{font-size:12px;font-weight:500;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.search-wrapper{position:relative;flex:1;min-width:180px;max-width:280px}.search-icon{position:absolute;left:10px;top:50%;transform:translateY(-50%);color:var(--text-muted);pointer-events:none}input[type=search]{width:100%;padding:8px 12px 8px 32px;border:1px solid var(--border-color);border-radius:var(--radius);background:var(--bg-primary);color:var(--text-primary);font-size:14px;transition:border-color var(--transition),background var(--transition)}input[type=search]:focus{outline:none;border-color:var(--accent)}input[type=search]::placeholder{color:var(--text-muted)}select{padding:8px 28px 8px 10px;border:1px solid var(--border-color);border-radius:var(--radius);background:var(--bg-primary);color:var(--text-primary);font-size:13px;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center;transition:border-color var(--transition),background var(--transition)}select:focus{outline:none;border-color:var(--accent)}.sort-wrapper{display:flex;align-items:center;gap:4px}.sort-direction-btn{padding:8px;border:1px solid var(--border-color);border-radius:var(--radius);background:var(--bg-primary);color:var(--text-secondary);cursor:pointer;font-size:14px;line-height:1;transition:all var(--transition)}.sort-direction-btn:hover{border-color:var(--accent);color:var(--accent)}.checkbox-filter{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--text-secondary);cursor:pointer}.checkbox-filter input[type=checkbox]{width:16px;height:16px;accent-color:var(--accent);cursor:pointer}.theme-toggle{margin-left:auto;display:flex;align-items:center;gap:8px}.theme-toggle-label{font-size:12px;color:var(--text-muted)}.theme-switch{position:relative;width:44px;height:24px;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:12px;cursor:pointer;transition:background var(--transition),border-color var(--transition)}.theme-switch:after{content:"";position:absolute;top:2px;left:2px;width:18px;height:18px;background:var(--text-secondary);border-radius:50%;transition:transform var(--transition),background var(--transition)}.theme-switch.light:after{transform:translate(20px);background:var(--accent)}.license-filter-toggle{padding:6px 12px;border:1px solid var(--border-color);border-radius:var(--radius);background:transparent;color:var(--text-secondary);font-size:12px;cursor:pointer;display:flex;align-items:center;gap:6px;transition:all var(--transition)}.license-filter-toggle:hover{border-color:var(--accent);color:var(--accent)}.license-filter-toggle .chevron{transition:transform var(--transition)}.license-filter-toggle.open .chevron{transform:rotate(180deg)}.license-filter-panel{max-height:0;overflow:hidden;transition:max-height .3s ease-out;background:var(--bg-secondary);border-bottom:1px solid transparent}.license-filter-panel.open{max-height:200px;border-bottom-color:var(--border-color)}.license-filter-inner{max-width:1400px;margin:0 auto;padding:12px 24px}.license-filter-header{display:flex;align-items:center;gap:12px;margin-bottom:8px}.license-filter-title{font-size:12px;font-weight:500;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px}.license-quick-actions{display:flex;gap:8px}.quick-action-btn{padding:4px 10px;font-size:11px;border:1px solid var(--border-color);border-radius:4px;background:transparent;color:var(--text-secondary);cursor:pointer;transition:all var(--transition)}.quick-action-btn:hover{border-color:var(--accent);color:var(--accent)}.license-groups{display:flex;flex-wrap:wrap;gap:16px}.license-group-checkbox{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--text-secondary);cursor:pointer}.license-group-checkbox input[type=checkbox]{width:16px;height:16px;accent-color:var(--accent);cursor:pointer}.license-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}.license-dot.permissive{background:var(--license-permissive)}.license-dot.weak-copyleft{background:var(--license-weak-copyleft)}.license-dot.strong-copyleft{background:var(--license-strong-copyleft)}.license-dot.unknown{background:var(--license-unknown)}.tool-errors{max-width:1400px;margin:16px auto;padding:12px 16px;background:var(--red-bg);border:1px solid var(--red);border-radius:var(--radius);color:var(--red)}.tool-errors:empty{display:none}.tool-errors strong{display:block;margin-bottom:8px}.main-content{max-width:1400px;margin:0 auto;padding:16px 24px 48px}.report-footer{max-width:1400px;margin:0 auto;padding:0 24px 40px;color:var(--text-secondary);font-size:12px}.report-footer p{margin:8px 0 0}.results-summary{margin-bottom:16px;font-size:14px;color:var(--text-secondary)}.results-summary strong{color:var(--text-primary)}.dependency-grid{display:flex;flex-direction:column;gap:8px}.dep-card{background:var(--bg-card);border:1px solid var(--border-color);border-radius:var(--radius-lg);overflow:hidden;transition:border-color var(--transition)}.dep-card:hover{border-color:var(--border-color-strong)}.dep-card[data-risk=red]{border-left:3px solid var(--red)}.dep-card[data-risk=amber]{border-left:3px solid var(--amber)}.dep-card[data-risk=green]{border-left:3px solid var(--green)}.dep-summary{display:flex;align-items:center;gap:10px;padding:0 0 0 12px;cursor:pointer;list-style:none;transition:background var(--transition)}.dep-summary:hover{background:var(--bg-card-hover)}.dep-summary::-webkit-details-marker{display:none}.expand-icon{width:16px;height:16px;flex-shrink:0;display:inline-block;color:var(--text-muted);transition:transform var(--transition);background:currentColor;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") no-repeat center / contain;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E") no-repeat center / contain}details[open]>summary .expand-icon{transform:rotate(90deg)}.dep-name{font-family:var(--font-mono);font-size:14px;font-weight:600;color:var(--text-primary);padding:8px 0}.dep-version{font-weight:400;color:var(--text-secondary)}.dep-indicators{display:grid;grid-template-columns:repeat(5,1fr);margin-left:auto;flex-shrink:0;width:60%}.badge-card{display:flex;flex-direction:column;justify-content:center;min-height:38px;padding:4px 8px 4px 10px;background:var(--bg-primary);border-left:1px solid var(--border-color);position:relative;overflow:hidden}.badge-card:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--gray)}.badge-card.green:before{background:var(--green)}.badge-card.amber:before{background:var(--amber)}.badge-card.red:before{background:var(--red)}.badge-card.gray:before{background:var(--gray)}.badge-label{font-size:8px;font-weight:500;color:var(--text-muted);text-transform:uppercase;letter-spacing:.3px;line-height:1.1}.badge-value{font-size:11px;font-weight:500;color:var(--text-primary);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dep-details{padding:0 16px 16px;border-top:1px solid var(--border-color);animation:slideDown .2s ease-out}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.package-links{display:flex;flex-wrap:wrap;gap:8px;padding:12px 0;margin-bottom:4px;border-bottom:1px solid var(--border-color)}.package-link{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:var(--bg-hover);border:1px solid var(--border-color);border-radius:var(--radius-md);color:var(--text-primary);text-decoration:none;font-size:13px;font-weight:500;transition:all var(--transition)}.package-link:hover{background:var(--accent);border-color:var(--accent);color:#fff}.package-link svg{width:14px;height:14px;flex-shrink:0}.section,.section:first-child{margin-top:16px}.section-header{display:flex;align-items:center;gap:8px;margin-bottom:10px;padding-bottom:6px;border-bottom:1px solid var(--border-color)}.section-title{font-size:13px;font-weight:600;color:var(--text-primary);text-transform:uppercase;letter-spacing:.5px}.section-desc{font-size:11px;color:var(--text-muted)}.kv-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px}.kv-grid-tight{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:10px}.kv-item{display:flex;flex-direction:column;gap:2px}.kv-label{font-size:12px;font-weight:500;color:var(--text-muted)}.kv-value{font-size:14px;color:var(--text-primary);overflow-wrap:anywhere;word-break:break-word}.risk-value{display:inline-flex;align-items:center;gap:6px}.risk-dot{width:8px;height:8px;border-radius:999px;background:var(--gray);flex-shrink:0}.risk-dot.green{background:var(--green)}.risk-dot.amber{background:var(--amber)}.risk-dot.red{background:var(--red)}.kv-hint{font-size:11px;color:var(--text-muted);font-style:italic}.micro-summary{display:grid;gap:6px;padding:6px 0 2px}.micro-line{font-size:13px;color:var(--text-primary)}.micro-sublist{margin-top:8px}.micro-subtitle{font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.4px;margin-bottom:4px}.section-block{margin-top:12px}.block-title{font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.4px;margin-bottom:6px}.section-note{font-size:12px;color:var(--text-secondary);margin:6px 0 12px}.subsection{padding:12px 0;border-top:1px solid var(--border-color)}.subsection:first-child{border-top:none;padding-top:0}.subsection-header{display:flex;align-items:baseline;gap:8px;margin-bottom:8px}.subsection-title{font-size:12px;font-weight:600;color:var(--text-primary);text-transform:uppercase;letter-spacing:.4px}.subsection-desc{font-size:11px;color:var(--text-muted)}.subsection.warning .subsection-title{color:var(--red)}.detail-list{margin-top:12px}.detail-title{font-size:11px;color:var(--text-muted);text-transform:uppercase;letter-spacing:.4px;margin-bottom:6px}.detail-items{list-style:none;padding:0;margin:0;display:grid;gap:6px}.detail-items.mono .detail-item{font-family:var(--font-mono)}.detail-item{font-size:12px;color:var(--text-secondary);overflow-wrap:anywhere;word-break:break-word}.detail-item.muted{color:var(--text-muted)}.declared-deps{display:grid;gap:8px}.declared-summary{font-size:12px;color:var(--text-secondary);margin:4px 0 8px}.declared-group{border:1px solid var(--border-color);border-radius:8px;background:var(--bg-primary);padding:8px 10px}.declared-group-summary{font-size:12px;font-weight:600;color:var(--text-primary);cursor:pointer;list-style:none;display:flex;align-items:center;gap:8px}.declared-group-summary::-webkit-details-marker{display:none}.declared-count{font-size:11px;color:var(--text-muted);font-weight:500}.declared-group-title{display:inline-flex;align-items:baseline;gap:6px}.declared-table{display:grid;gap:6px;margin-top:8px}.declared-row{display:grid;grid-template-columns:minmax(160px,1.3fr) minmax(120px,1fr) auto;gap:10px;align-items:center;padding:8px 10px;border:1px solid var(--border-color);border-radius:6px;background:var(--bg-primary)}.declared-name{font-size:12px;font-family:var(--font-mono);color:var(--text-primary);display:flex;align-items:center;gap:6px;overflow-wrap:anywhere}.declared-range{font-size:12px;color:var(--text-secondary);font-family:var(--font-mono);overflow-wrap:anywhere}.status-pill{display:inline-flex;align-items:center;justify-content:center;padding:2px 8px;border-radius:999px;font-size:11px;font-weight:600;text-decoration:none;border:1px solid transparent}.status-pill.installed{color:var(--green);border-color:var(--green);background:var(--green-bg)}.status-pill.missing{color:var(--text-muted);border-color:var(--border-color-strong);background:var(--gray-bg)}.bullet-list{margin:6px 0 0;padding-left:18px;color:var(--text-secondary)}.bullet-list li{margin-bottom:6px}.subtle-divider{height:1px;background:var(--border-color);margin:12px 0}.package-list{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}.package-tag{padding:2px 8px;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:4px;font-size:11px;font-family:var(--font-mono);color:var(--text-secondary)}.package-list-toggle{font-size:11px;color:var(--accent);background:none;border:none;cursor:pointer;padding:2px 4px}.package-list-toggle:hover{text-decoration:underline}.vuln-table{width:100%;border-collapse:collapse;font-size:13px}.vuln-table th,.vuln-table td{text-align:left;padding:8px 12px;border-bottom:1px solid var(--border-color);vertical-align:top;overflow-wrap:anywhere;word-break:break-word}.vuln-table th{font-weight:500;color:var(--text-muted);font-size:11px;text-transform:uppercase;letter-spacing:.5px}.vuln-table tr[data-severity=critical],.vuln-table tr[data-severity=high]{background:var(--red-bg)}.vuln-table tr[data-severity=moderate]{background:var(--amber-bg)}.vuln-table a{color:var(--accent);text-decoration:none}.vuln-table a:hover{text-decoration:underline}.no-vulns{font-size:13px;color:var(--text-secondary);padding:8px 0}.raw-data-toggle{margin-top:16px}.raw-data-toggle summary{font-size:12px;color:var(--text-muted);cursor:pointer;padding:8px 0;display:flex;align-items:center;gap:8px;list-style:none}.raw-data-toggle summary::-webkit-details-marker{display:none}.raw-data-pane{margin-top:8px;position:relative;display:flex;flex-direction:column;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:var(--radius);max-height:300px;overflow:auto}.raw-data-pane pre{margin:0;padding:12px 12px 44px;background:transparent;border:none;font-family:var(--font-mono);font-size:11px;color:var(--text-secondary);white-space:pre;overflow:visible}.copy-json-btn{position:sticky;bottom:8px;align-self:flex-end;margin:0 8px 8px;padding:6px 10px;border:1px solid var(--border-color);border-radius:4px;background:var(--bg-card);color:var(--text-primary);font-size:11px;cursor:pointer;transition:all var(--transition)}.raw-data-toggle:not([open]) .copy-json-btn{display:none}.copy-json-btn:hover{border-color:var(--accent);color:var(--accent)}.copy-json-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.copy-json-btn.copied{border-color:var(--green);color:var(--green)}.dep-loading{padding:2rem 0}.dep-loading-bar{position:relative;height:.25rem;background:var(--border-color);overflow:hidden;border-radius:999px}.dep-loading-bar:after{content:"";position:absolute;top:0;left:-40%;width:40%;height:100%;background:var(--accent);animation:dep-loading 1.2s ease-in-out infinite}@keyframes dep-loading{0%{transform:translate(0)}to{transform:translate(250%)}}.package-tag-link{text-decoration:none;color:var(--text-secondary);transition:all var(--transition)}.package-tag-link:hover{border-color:var(--accent);color:var(--accent)}.package-tag-link:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.empty-state{text-align:center;padding:48px 24px;color:var(--text-muted)}.empty-state-icon{font-size:48px;margin-bottom:12px}.empty-state-text{font-size:16px}@media (max-width: 768px){.top-header{padding:20px 16px}.header-row{flex-direction:column;align-items:flex-start;gap:16px}.header-content{gap:12px}.logo,.logo-wrapper{width:48px;height:48px}.header-text h1{font-size:22px}.header-meta{gap:6px}.meta-item{padding:3px 8px;font-size:11px}.cta-section{width:100%;max-width:none;text-align:left}.cta-benefits{display:none}.filter-bar{padding:10px 16px}.filter-bar-inner{flex-direction:column;align-items:stretch;gap:10px}.search-wrapper{max-width:none}.filter-group{justify-content:space-between}.theme-toggle{margin-left:0;justify-content:flex-end}.main-content{padding:12px 16px 32px}.report-footer{padding:0 16px 32px}.vuln-table thead{display:none}.vuln-table tr{display:block;border-bottom:1px solid var(--border-color)}.vuln-table td{display:flex;justify-content:space-between;gap:12px;padding:6px 8px}.vuln-table td:before{content:attr(data-label);font-size:10px;text-transform:uppercase;letter-spacing:.4px;color:var(--text-muted);min-width:120px}.dep-summary{flex-wrap:wrap;padding:8px 12px}.dep-name{font-size:13px}.dep-indicators{display:flex;flex-wrap:wrap;min-width:auto;width:100%;margin-left:0;margin-top:6px;padding-top:6px;border-top:1px solid var(--border-color);gap:4px}.badge-card{flex:1 1 calc(50% - 4px);min-width:0}.badge-value{font-size:10px}.badge-label{font-size:7px}.declared-row{grid-template-columns:1fr;gap:6px}}@media (max-width: 480px){.header-text h1{font-size:20px}.meta-item{font-size:10px;padding:2px 6px}.cta-link{width:100%;justify-content:center;padding:12px 16px}.badge-card{flex:1 1 100%}}
12
12
  `;
13
13
  /**
14
14
  * JavaScript content for the dependency radar HTML report
15
15
  * Built from report-ui/main.ts
16
16
  */
17
- exports.JS_CONTENT = `!function(){"use strict";const e={permissive:["MIT","ISC","BSD-2-Clause","BSD-3-Clause","Apache-2.0","Unlicense","0BSD","CC0-1.0","BSD","Apache","Apache 2.0","Apache License 2.0","MIT License","ISC License"],weakCopyleft:["LGPL-2.1","LGPL-3.0","LGPL-2.0","LGPL","MPL-2.0","MPL-1.1","MPL","EPL-1.0","EPL-2.0","EPL"],strongCopyleft:["GPL-2.0","GPL-3.0","GPL","AGPL-3.0","AGPL","GPL-2.0-only","GPL-3.0-only","GPL-2.0-or-later","GPL-3.0-or-later"]};function n(n){if(!n)return"unknown";const t=n.toUpperCase();for(const[s,i]of Object.entries(e))if(i.some(e=>t.includes(e.toUpperCase())))return s;return"unknown"}const t={none:0,low:1,moderate:2,high:3,critical:4};function s(e){var n;return(null==(n=e.vulnerabilities)?void 0:n.highestSeverity)||"none"}function i(e){if(!e)return"0 B";const n=["B","KB","MB","GB"];let t=e,s=0;for(;t>=1024&&s<n.length-1;)t/=1024,s++;return t.toFixed(t>=10?0:1)+" "+n[s]}function a(e){return e?"Yes":"No"}function o(e){return e?String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"):""}function r(e){return"imported"===e?"Imported":"not-imported"===e?"Not imported":"undeclared"===e?"Undeclared":"Unknown"}function l(e,n,t){return'<div class="badge-card '+t+'"><span class="badge-label">'+o(e)+'</span><span class="badge-value">'+o(n)+"</span></div>"}function c(e,n,t){let s='<div class="kv-item">';return s+='<span class="kv-label">'+o(e)+"</span>",s+='<span class="kv-value">'+o(String(n))+"</span>",t&&(s+='<span class="kv-hint">'+o(t)+"</span>"),s+="</div>",s}function d(e,n){if(!e||0===e.length)return'<span class="kv-value">None</span>';const t=e.slice(0,n),s=e.length-n;let i='<div class="package-list">';return t.forEach(e=>{i+='<span class="package-tag">'+o(e)+"</span>"}),s>0&&(i+='<span class="package-tag">+'+s+" more</span>"),i+="</div>",i}function u(e,n,t){let s='<div class="section">';return s+='<div class="section-header">',s+='<span class="section-title">'+o(e)+"</span>",n&&(s+='<span class="section-desc">'+o(n)+"</span>"),s+="</div>",s+=t,s+="</div>",s}function p(e,n,t){return u(e,n,'<div class="kv-grid">'+t.join("")+"</div>")}function m(e){const n='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M0 7.334v8h6.666v1.332H12v-1.332h12v-8H0zm6.666 6.664H5.334v-4H3.999v4H1.335V8.667h5.331v5.331zm4 0v1.336H8.001V8.667h5.334v5.332h-2.669v-.001zm12.001 0h-1.33v-4h-1.336v4h-1.335v-4h-1.33v4h-2.671V8.667h8.002v5.331zM10.665 10H12v2.667h-1.335V10z"/></svg>',t='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg>',s='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',i='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>';let a='<div class="package-links">';return a+='<a href="'+o(e.npm)+'" target="_blank" rel="noopener" class="package-link">'+n+"npm</a>",e.repository&&(a+='<a href="'+o(e.repository)+'" target="_blank" rel="noopener" class="package-link">'+t+"Repository</a>"),e.homepage&&(a+='<a href="'+o(e.homepage)+'" target="_blank" rel="noopener" class="package-link">'+i+"Homepage</a>"),e.bugs&&(a+='<a href="'+o(e.bugs)+'" target="_blank" rel="noopener" class="package-link">'+s+"Issues</a>"),a+="</div>",a}function g(e){var t,g;const h=e.license.license||"Unknown",v=n(h),y=function(e){const n=[e.vulnRisk,e.licenseRisk];return n.includes("red")?"red":n.includes("amber")?"amber":"green"}(e),f=s(e),k={permissive:{text:"Permissive",class:"green"},weakCopyleft:{text:"Weak Copyleft",class:"amber"},strongCopyleft:{text:"Strong Copyleft",class:"red"},unknown:{text:"Unknown",class:"gray"}},C=e.direct?"Dependency":"Sub-Dependency",L=e.direct?"green":"amber",B="runtime"===e.runtimeClass?"green":"build-time"===e.runtimeClass?"amber":"gray",S="undeclared"===e.usage.status?"red":"imported"===e.usage.status?"green":"not-imported"===e.usage.status?"amber":"gray",E=[l("Type",C,L),l("Runtime",(w=e.runtimeClass,"runtime"===w?"Runtime":"build-time"===w?"Build-time":"dev-only"===w?"Dev-only":w),B),l("License",h,k[v].class),l("Vulns",(b=f,b?b.charAt(0).toUpperCase()+b.slice(1):b),e.vulnRisk),l("Usage",r(e.usage.status),S)];var b,w;const I=['<summary class="dep-summary">','<svg class="expand-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m9 18 6-6-6-6"/></svg>','<span class="dep-name">'+o(e.name)+'<span class="dep-version">@'+o(e.version)+"</span></span>",'<div class="dep-indicators">',E.join(""),"</div>","</summary>"].join(""),P=e.vulnerabilities.items.map(e=>'<tr data-severity="'+e.severity+'"><td>'+o(e.title)+"</td><td>"+o(e.severity)+"</td><td>"+o(e.vulnerableRange||"")+'</td><td><a href="'+o(e.url||"#")+'" target="_blank" rel="noopener">Link</a></td></tr>').join(""),x=e.vulnerabilities.items.length?'<table class="vuln-table"><thead><tr><th>Title</th><th>Severity</th><th>Range</th><th>Ref</th></tr></thead><tbody>'+P+"</tbody></table>":'<p class="no-vulns">No known vulnerabilities.</p>',D=JSON.stringify(e,null,2),j=(e.parents||[]).map(e=>e.split("@")[0]),M=(e.rootCauses||[]).join(", ")||(e.direct?"package.json":"Unknown"),R=p("Overview","Dependency position and runtime classification",[c("Type",C,e.direct?"Listed in package.json":"Installed as a sub-dependency"),c("Depth",e.depth,"How deep this package is in the dependency tree"),c("Parents",j.join(", ")||"None (direct dependency)","Packages that directly depend on this"),c("Installed By",M,"Root dependency in package.json that causes this to be installed"),c("Runtime Class",e.runtimeClass,e.runtimeReason)]),T=p("License","License information for this package",[c("License",h,"The declared license"),c("Category",k[v].text,"Business-friendliness classification"),c("License File",e.license.licenseFile||"Not found","Path to license file if present")]),U=u("Vulnerabilities","Known security issues from npm audit",x),z=u("Maintenance","Package maintenance status",'<div class="kv-grid">'+c("Status",e.maintenance.status,e.maintenance.reason)+(e.maintenance.lastPublished?c("Last Published",e.maintenance.lastPublished,""):"")+"</div>"),A=u("Usage","Static import usage in your codebase",'<div class="kv-grid">'+c("Status",r(e.usage.status),e.usage.reason)+"</div>"),F=p("Identity & Metadata","Package metadata",[c("Deprecated",a(e.identity.deprecated),"Whether the author has deprecated this package"),c("Node Engine",e.identity.nodeEngine||"Any","Required Node.js version"),c("Repository",a(e.identity.hasRepository),"Whether source repo is linked"),c("Funding",a(e.identity.hasFunding),"Whether funding info is provided")]),G=p("Dependency Surface","What this package depends on",[c("Dependencies",e.dependencySurface.dependencies+" prod / "+e.dependencySurface.devDependencies+" dev / "+e.dependencySurface.peerDependencies+" peer / "+e.dependencySurface.optionalDependencies+" optional",""),c("Has Peer Dependencies",a(e.dependencySurface.hasPeerDependencies),"Peer deps can complicate upgrades")]),H=p("Size & Footprint","Disk space usage",[c("Installed Size",i(e.sizeFootprint.installedSize),"Total size on disk"),c("File Count",e.sizeFootprint.fileCount,"Number of files installed")]),N=p("Build & Platform","Build complexity indicators",[c("Native Code",a(e.buildPlatform.nativeBindings),"Requires compilation"),c("Install Scripts",a(e.buildPlatform.installScripts),"Runs code during install")]),O=p("Module System","Module format information",[c("Format",e.moduleSystem.format,"CommonJS, ESM, or dual"),c("Conditional Exports",a(e.moduleSystem.conditionalExports),"Uses exports field")]),V=p("TypeScript","Type definition support",[c("Types","bundled"===e.typescript.types?"Bundled":"None","Whether types are included")]),W=(null==(t=e.graph)?void 0:t.dependedOnBy)||[],q=(null==(g=e.graph)?void 0:g.dependsOn)||[],_=u("Graph Shape","Dependency graph connections",'<div class="kv-grid"><div class="kv-item"><span class="kv-label">Depended On By ('+e.graph.fanIn+")</span>"+d(W,8)+'</div><div class="kv-item"><span class="kv-label">Depends On ('+e.graph.fanOut+")</span>"+d(q,8)+"</div></div>");return['<details class="dep-card" data-risk="'+y+'">',I,'<div class="dep-details">',m(e.links),R,T,U,z,A,F,G,H,N,O,V,_,'<details class="raw-data-toggle"><summary>View raw data</summary><pre>'+o(D)+"</pre></details>","</div>","</details>"].join("")}async function h(){var e,i;const a=await async function(){const e=document.getElementById("radar-data");return e&&e.textContent&&"{}"!==e.textContent.trim()?JSON.parse(e.textContent):(await fetch("./sample-data.json")).json()}(),r=document.getElementById("dependency-list"),l=document.getElementById("results-summary"),c=document.getElementById("project-path");c&&(c.textContent=a.projectPath);const d=document.getElementById("git-branch-item"),u=document.getElementById("git-branch");a.gitBranch&&d&&u&&(u.textContent=a.gitBranch,d.style.display="");const p=document.getElementById("node-item"),m=document.getElementById("node-version"),h=document.getElementById("node-disclaimer");if((null==(e=a.environment)?void 0:e.node)&&p&&m){const e=(null==(i=a.environment.node.runtimeVersion)?void 0:i.replace(/^v/,""))||"unknown",n=a.environment.node.minRequiredMajor;m.textContent=e+(void 0!==n?\` (requires ≥\${n})\`:""),p.style.display="",void 0!==n&&h&&(h.textContent="Node requirement derived from dependency engine ranges.",h.style.display="")}const v=document.getElementById("formatted-date");if(v&&a.generatedAt)try{const e=new Date(a.generatedAt),n=new Intl.DateTimeFormat(void 0,{day:"numeric",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"}).format(e);v.textContent=n}catch{v.textContent=a.generatedAt}const y=document.getElementById("tool-errors");if(y&&a.toolErrors&&Object.keys(a.toolErrors).length>0){const e=Object.entries(a.toolErrors).map(([e,n])=>\`<div><strong>\${o(e)}:</strong> \${o(n)}</div>\`).join("");y.innerHTML=\`<strong>Some tools failed:</strong>\${e}\`}const f={search:document.getElementById("search"),direct:document.getElementById("direct-filter"),runtime:document.getElementById("runtime-filter"),sort:document.getElementById("sort-by"),sortDirection:document.getElementById("sort-direction"),hasVulns:document.getElementById("has-vulns"),unusedOnly:document.getElementById("unused-only"),themeSwitch:document.getElementById("theme-switch"),licenseToggle:document.getElementById("license-toggle"),licensePanel:document.getElementById("license-panel"),licensePermissive:document.getElementById("license-permissive"),licenseWeakCopyleft:document.getElementById("license-weak-copyleft"),licenseStrongCopyleft:document.getElementById("license-strong-copyleft"),licenseUnknown:document.getElementById("license-unknown"),licenseAll:document.getElementById("license-all"),licenseFriendly:document.getElementById("license-friendly")};let k=!0;function C(){const e=function(e){const n=f.sort.value,i=[...e];return"name"===n?i.sort((e,n)=>e.name.localeCompare(n.name)):"depth"===n?i.sort((e,n)=>e.depth-n.depth):"severity"===n?i.sort((e,n)=>t[s(n)]-t[s(e)]):"size"===n&&i.sort((e,n)=>{var t,s;return((null==(t=n.sizeFootprint)?void 0:t.installedSize)||0)-((null==(s=e.sizeFootprint)?void 0:s.installedSize)||0)}),k||i.reverse(),i}(function(){const e=(f.search.value||"").toLowerCase(),i=f.direct.value,o=f.runtime.value,r=f.hasVulns.checked,l=f.unusedOnly.checked,c=f.licensePermissive.checked,d=f.licenseWeakCopyleft.checked,u=f.licenseStrongCopyleft.checked,p=f.licenseUnknown.checked;return a.dependencies.filter(a=>{if(e&&!a.name.toLowerCase().includes(e)&&!(a.license.license||"").toLowerCase().includes(e))return!1;if("direct"===i&&!a.direct)return!1;if("transitive"===i&&a.direct)return!1;if("all"!==o&&a.runtimeClass!==o)return!1;if(r&&0===t[s(a)])return!1;if(l&&"not-imported"!==a.usage.status)return!1;const m=n(a.license.license);return!("permissive"===m&&!c||"weakCopyleft"===m&&!d||"strongCopyleft"===m&&!u||"unknown"===m&&!p)})}());l.innerHTML="Showing <strong>"+e.length+"</strong> of <strong>"+a.dependencies.length+"</strong> dependencies",0!==e.length?r.innerHTML=e.map(g).join(""):r.innerHTML='<div class="empty-state"><div class="empty-state-icon">📦</div><div class="empty-state-text">No dependencies match your filters</div></div>'}"light"===localStorage.getItem("dependency-radar-theme")&&(document.documentElement.classList.add("light"),f.themeSwitch.classList.add("light")),f.themeSwitch.addEventListener("click",()=>{document.documentElement.classList.toggle("light"),f.themeSwitch.classList.toggle("light");const e=document.documentElement.classList.contains("light");localStorage.setItem("dependency-radar-theme",e?"light":"dark")}),f.licenseToggle.addEventListener("click",()=>{f.licenseToggle.classList.toggle("open"),f.licensePanel.classList.toggle("open")}),f.sortDirection.addEventListener("click",()=>{k=!k,f.sortDirection.textContent=k?"↑":"↓",C()}),f.licenseAll.addEventListener("click",()=>{f.licensePermissive.checked=!0,f.licenseWeakCopyleft.checked=!0,f.licenseStrongCopyleft.checked=!0,f.licenseUnknown.checked=!0,C()}),f.licenseFriendly.addEventListener("click",()=>{f.licensePermissive.checked=!0,f.licenseWeakCopyleft.checked=!1,f.licenseStrongCopyleft.checked=!1,f.licenseUnknown.checked=!1,C()});[f.search,f.direct,f.runtime,f.sort,f.hasVulns,f.unusedOnly,f.licensePermissive,f.licenseWeakCopyleft,f.licenseStrongCopyleft,f.licenseUnknown].forEach(e=>{e&&(e.addEventListener("input",C),e.addEventListener("change",C))}),C()}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",h):h()}();
17
+ exports.JS_CONTENT = `!function(){"use strict";const e={permissive:["MIT","ISC","BSD-2-Clause","BSD-3-Clause","Apache-2.0","Unlicense","0BSD","CC0-1.0","BSD","Apache","Apache 2.0","Apache License 2.0","MIT License","ISC License"],weakCopyleft:["LGPL-2.1","LGPL-3.0","LGPL-2.0","LGPL","MPL-2.0","MPL-1.1","MPL","EPL-1.0","EPL-2.0","EPL"],strongCopyleft:["GPL-2.0","GPL-3.0","GPL","AGPL-3.0","AGPL","GPL-2.0-only","GPL-3.0-only","GPL-2.0-or-later","GPL-3.0-or-later"]},t={"network-access":"Accesses the network during install","dynamic-exec":"Uses dynamic execution","child-process":"Spawns child processes",encoding:"Uses encoding/decoding logic",obfuscated:"Contains obfuscated/minified install logic","reads-env":"Reads environment variables","reads-home":"Reads user home directory","uses-ssh":"Uses SSH configuration/keys"};function n(t){if(!t)return"unknown";const n=t.toUpperCase();for(const[s,a]of Object.entries(e))if(a.some(e=>n.includes(e.toUpperCase())))return s;return"unknown"}function s(e){var t,n;const s=e.compliance.license,a=(null==(t=s.declared)?void 0:t.valid)?s.declared.spdxId:void 0,i=null==(n=s.inferred)?void 0:n.spdxId;return a?{value:a,isInferred:!1}:i?{value:i,isInferred:!0}:{value:"Unknown",isInferred:!1}}function a(e){switch(e){case"declared-only":return"Declared";case"inferred-only":return"Inferred";case"match":return"Declared + Inferred (match)";case"mismatch":return"Declared + Inferred (mismatch)";case"invalid-spdx":return"Invalid SPDX";default:return"Unknown"}}const i={none:0,low:1,moderate:2,high:3,critical:4};function r(e){const t=e.security;if(null==t?void 0:t.summary)return{summary:t.summary,advisories:t.advisories};if(null==t?void 0:t.vulnerabilities){const e=t.vulnerabilities;return{summary:{critical:Number(e.critical||0),high:Number(e.high||0),moderate:Number(e.moderate||0),low:Number(e.low||0),highest:e.highest||"none",risk:t.vulnRisk||t.risk||"green"},advisories:t.advisories}}return{summary:{critical:0,high:0,moderate:0,low:0,highest:"none",risk:"green"},advisories:null==t?void 0:t.advisories}}function o(e){return(null==e?void 0:e.highest)||"none"}function c(e){return e?String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"):""}function l(e){return"runtime"===e?"Runtime":"dev"===e?"Dev":"optional"===e?"Optional":"peer"===e?"Peer":e}function d(e){return e?e.charAt(0).toUpperCase()+e.slice(1):e}function u(e){return e.split(/[\\s-_]+/).map(e=>e?d(e):e).join(" ")}function p(e,t,n){return'<div class="badge-card '+n+'"><span class="badge-label">'+c(e)+'</span><span class="badge-value">'+c(t)+"</span></div>"}function g(e,t,n){let s='<div class="kv-item">';return s+='<span class="kv-label">'+c(e)+"</span>",s+='<span class="kv-value">'+c(String(t))+"</span>",n&&(s+='<span class="kv-hint">'+c(n)+"</span>"),s+="</div>",s}function v(e,t){return'<span class="kv-value risk-value"><span class="risk-dot '+t+'"></span>'+c(String(e))+"</span>"}function m(e,t,n){let s='<div class="kv-item">';return s+='<span class="kv-label">'+c(e)+"</span>",s+=t,s+="</div>",s}function h(e,t){if(!e||0===e.length)return'<span class="kv-value">None</span>';const n=e.slice(0,t),s=e.length-t;let a='<div class="package-list">';return n.forEach(e=>{a+='<span class="package-tag">'+c(e)+"</span>"}),s>0&&(a+='<span class="package-tag">+'+s+" more</span>"),a+="</div>",a}function y(e,t,n){if(!e||0===e.length)return'<span class="kv-value">None</span>';const s=e.slice(0,t),a=e.length-t;let i='<div class="package-list">';return s.forEach(e=>{n.has(e)?i+='<a class="package-tag package-tag-link root-package-link" href="#'+c(f(e))+'" data-dep-key="'+c(e)+'" aria-label="Jump to dependency '+c(e)+'">'+c(e)+"</a>":i+='<span class="package-tag">'+c(e)+"</span>"}),a>0&&(i+='<span class="package-tag">+'+a+" more</span>"),i+="</div>",i}function k(e,t){return e+"@"+t}function f(e){return"dep-"+encodeURIComponent(e).replace(/%/g,"_")}function b(e,t,n){if(!e||0===e.length)return'<span class="kv-value">None</span>';const s=e.slice(0,t),a=e.length-t;let i='<div class="package-list">';return s.forEach(e=>{if("string"==typeof e)return void(i+='<span class="package-tag">'+c(e)+"</span>");const t=k(e.name,e.version),s=e.name+"@"+e.version;n.has(t)?i+='<a class="package-tag package-tag-link root-package-link" href="#'+c(f(t))+'" data-dep-key="'+c(t)+'" aria-label="Jump to dependency '+c(s)+'">'+c(s)+"</a>":i+='<span class="package-tag">'+c(s)+"</span>"}),a>0&&(i+='<span class="package-tag">+'+a+" more</span>"),i+="</div>",i}function w(e,t){const n=e.graph.subDeps;if(!n)return"";const s=[{title:"Dependencies",key:"dep"},{title:"Optional",key:"opt"},{title:"Peer",key:"peer"},{title:"Dev Dependencies",key:"dev"}];let a=0,i=0;for(const c of s){const e=n[c.key];if(e)for(const t of Object.values(e))a+=1,t[1]&&(i+=1)}if(0===a)return"";const r='<div class="declared-summary">Total: '+a+" • Installed: "+i+" • Not installed: "+(a-i)+"</div>",o=s.map(e=>{const s=n[e.key];if(!s||0===Object.keys(s).length)return"";let a=0,i=0;const r=Object.entries(s).sort(([e],[t])=>e.localeCompare(t)).map(([e,[n,s]])=>{a+=1,s&&(i+=1);const r='<div class="declared-name">'+c(e)+"</div>",o='<div class="declared-range">'+c(n)+"</div>",l=s?function(e,t){if(!t.has(e))return'<span class="status-pill installed">Installed</span>';return'<a class="status-pill installed root-package-link" href="#'+c(f(e))+'" data-dep-key="'+c(e)+'" aria-label="Jump to dependency '+c(e)+'">Installed</a>'}(s,t):'<span class="status-pill missing">Not installed</span>';return'<div class="declared-row">'+r+o+l+"</div>"}),o=i+" of "+a+" installed";return['<details class="declared-group">','<summary class="declared-group-summary"><span class="expand-icon" aria-hidden="true"></span><span class="declared-group-title">'+c(e.title)+' <span class="declared-count">('+o+")</span></span></summary>",'<div class="declared-table">'+r.join("")+"</div>","</details>"].join("")}).filter(Boolean);return C("Declared Dependencies","Dependencies declared by this package",r+'<div class="declared-deps">'+o.join("")+"</div>")}function C(e,t,n){let s='<div class="section">';return s+='<div class="section-header">',s+='<span class="section-title">'+c(e)+"</span>",t&&(s+='<span class="section-desc">'+c(t)+"</span>"),s+="</div>",s+=n,s+="</div>",s}function I(e,t,n,s){let a='<div class="subsection'+(s?" "+s:"")+'">';return a+='<div class="subsection-header">',a+='<span class="subsection-title">'+c(e)+"</span>",n&&(a+='<span class="subsection-desc">'+c(n)+"</span>"),a+="</div>",a+=t,a+="</div>",a}function x(e){return(null==e?void 0:e.risk)??"green"}function L(e){const t='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M0 7.334v8h6.666v1.332H12v-1.332h12v-8H0zm6.666 6.664H5.334v-4H3.999v4H1.335V8.667h5.331v5.331zm4 0v1.336H8.001V8.667h5.334v5.332h-2.669v-.001zm12.001 0h-1.33v-4h-1.336v4h-1.335v-4h-1.33v4h-2.671V8.667h8.002v5.331zM10.665 10H12v2.667h-1.335V10z"/></svg>',n='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg>',s='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>',a='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>';if(!(e.npm||e.repository||e.homepage||e.issues))return"";let i='<div class="package-links">';return e.npm&&(i+='<a href="'+c(e.npm)+'" target="_blank" rel="noopener" class="package-link">'+t+"npm</a>"),e.repository&&(i+='<a href="'+c(e.repository)+'" target="_blank" rel="noopener" class="package-link">'+n+"Repository</a>"),e.homepage&&(i+='<a href="'+c(e.homepage)+'" target="_blank" rel="noopener" class="package-link">'+a+"Homepage</a>"),e.issues&&(i+='<a href="'+c(e.issues)+'" target="_blank" rel="noopener" class="package-link">'+s+"Issues</a>"),i+="</div>",i}function E(e){const t=r(e).summary,a=s(e),i=a.isInferred?\`\${a.value} (inferred)\`:a.value,u=n(a.value),g=function(e,t){const n=[e.risk,t];return n.includes("red")?"red":n.includes("amber")?"amber":"green"}(t,e.compliance.licenseRisk),v=o(t),m=k(e.package.name,e.package.version),h=f(m),y=e.usage.direct?"Dependency":"Sub-Dependency",b=e.usage.direct?"green":"amber",w="runtime"===e.usage.scope?"green":"dev"===e.usage.scope||"optional"===e.usage.scope?"amber":"gray",C=x(e.execution),I=function(e){const t=x(e);return"red"===t?"High":"amber"===t?"Medium":"Low"}(e.execution),L=[p("Type",y,b),p("Scope",l(e.usage.scope),w),p("License",i,{permissive:{text:"Permissive",class:"green"},weakCopyleft:{text:"Weak Copyleft",class:"amber"},strongCopyleft:{text:"Strong Copyleft",class:"red"},unknown:{text:"Unknown",class:"gray"}}[u].class),p("Vulns",d(v),t.risk),p("Install",I,C)],E=['<summary class="dep-summary">','<span class="expand-icon" aria-hidden="true"></span>','<span class="dep-name">'+c(e.package.name)+'<span class="dep-version">@'+c(e.package.version)+"</span></span>",'<div class="dep-indicators">',L.join(""),"</div>","</summary>"].join("");return['<details class="dep-card" data-risk="'+g+'" data-dep-key="'+c(m)+'" id="'+c(h)+'">',E,'<div class="dep-details" data-rendered="false"></div>',"</details>"].join("")}function S(e,n){var i,o,p,k,f;const x=r(e),E=x.summary,S=s(e),D=S.isInferred?\`\${S.value} (inferred)\`:S.value,P=function(e){var t;const n=(null==(t=e.package)?void 0:t.links)||{},s=e.links||{};return{npm:n.npm||s.npm,repository:n.repository||s.repository||s.repo,homepage:n.homepage||s.homepage,issues:n.bugs||n.issues||s.bugs||s.issues}}(e),B=JSON.stringify(e,null,2),j=[e.usage.direct?"Direct dependency":"Indirect dependency (transitive)","Scope: "+l(e.usage.scope)];e.package.description&&j.unshift("Description: "+e.package.description),(null==(i=e.usage.origins.workspaces)?void 0:i.length)&&j.push("Used in "+e.usage.origins.workspaces.length+" workspaces"),e.usage.importUsage&&j.push("Imported in "+e.usage.importUsage.fileCount+" project files"),e.usage.introduction&&j.push("Introduced by: "+u(e.usage.introduction)),j.length<3&&j.push("Dependency depth: "+e.usage.depth);var N,A;const T=C("Overview","Summary and key context",'<div class="micro-summary">'+j.slice(0,5).map(e=>'<div class="micro-line">'+c(e)+"</div>").join("")+"</div>"+((null==(o=e.usage.origins.workspaces)?void 0:o.length)?'<div class="micro-sublist"><div class="micro-subtitle">Workspaces</div>'+h(e.usage.origins.workspaces,8)+"</div>":"")+('<div class="section-block"><div class="block-title">Key context</div><div class="kv-grid kv-grid-tight">'+[e.usage.runtimeImpact?g("Runtime impact (runtimeImpact)",(A=e.usage.runtimeImpact,A?u(A):"")):"",g("Dependency depth",e.usage.depth),m("Introduced via root packages (topRootPackages)",b(e.usage.origins.topRootPackages,8,n)),g("Direct roots (rootPackageCount)",e.usage.origins.rootPackageCount),m("Direct parents (topParentPackages)",y(e.usage.origins.topParentPackages,8,n)),g("Direct parents (parentPackageCount)",e.usage.origins.parentPackageCount??0),g("TypeScript types (tsTypes)",(N=e.usage.tsTypes,"bundled"===N?"Bundled":"definitelyTyped"===N?"DefinitelyTyped":"none"===N?"None":"Unknown"))].filter(Boolean).join("")+"</div></div>")+function(e,t,n,s){if(!t||0===t.length)return"";const a=t.slice(0,n),i=t.length-n;let r='<div class="detail-list">';return r+='<div class="detail-title">'+c(e)+"</div>",r+='<ul class="detail-items '+s+'">',a.forEach(e=>{r+='<li class="detail-item">'+c(e)+"</li>"}),i>0&&(r+='<li class="detail-item muted">+'+i+" more</li>"),r+="</ul></div>",r}("Top import locations (topFiles)",null==(p=e.usage.importUsage)?void 0:p.topFiles,5,"mono")),U=e.compliance.license,M=[m("Primary license",v(D,e.compliance.licenseRisk)),g("Status (status)",a(U.status))];if(U.declared){const e=[U.declared.valid?"valid":"invalid",U.declared.expression?"expression":void 0,U.declared.deprecated?"deprecated":void 0].filter(Boolean).join(", "),t=(null==(k=U.exception)?void 0:k.id)?\` WITH \${U.exception.id}\`:"";M.push(g("Declared SPDX (declared)",\`\${U.declared.spdxId}\${t}\${e?\` (\${e})\`:""}\`))}U.inferred&&M.push(g("Inferred from LICENSE (inferred)",\`\${U.inferred.spdxId} (\${U.inferred.confidence})\`)),"mismatch"===U.status&&M.push(g("Mismatch","Declared SPDX and LICENSE text do not match")),"invalid-spdx"===U.status&&M.push(g("Invalid SPDX","Package.json license is not a valid SPDX identifier or expression"));const H=I("License",'<div class="kv-grid">'+M.join("")+"</div>"),O=E.critical+E.high+E.moderate+E.low,V=[m("Known vulnerabilities",v(0===O?"None":String(O),E.risk)),g("Highest severity","none"===E.highest?"None":u(E.highest))],R=O>0?'<div class="kv-grid kv-grid-tight">'+[g("Critical",E.critical),g("High",E.high),g("Moderate",E.moderate),g("Low",E.low)].join("")+"</div>":"",G=function(e){if(!e||0===e.length)return"";let t='<table class="vuln-table"><thead><tr>';return t+="<th>Title</th><th>Severity</th><th>Affected range</th><th>Fix available</th><th>Reference</th>",t+="</tr></thead><tbody>",e.forEach(e=>{const n=c(e.title),s=e.url?'<a href="'+c(e.url)+'" target="_blank" rel="noopener">Link</a>':"";t+='<tr data-severity="'+c(e.severity)+'">',t+='<td data-label="Title">'+n+"</td>",t+='<td data-label="Severity">'+c(d(e.severity))+"</td>",t+='<td data-label="Affected range">'+c(e.vulnerableRange)+"</td>",t+='<td data-label="Fix available">'+c(e.fixAvailable?"Yes":"No")+"</td>",t+='<td data-label="Reference">'+s+"</td>",t+="</tr>"}),t+="</tbody></table>",t}(x.advisories),\$=I("VULNERABILITIES",['<div class="section-note">Based on npm audit findings (known disclosed issues).</div>','<div class="kv-grid">'+V.join("")+"</div>",R?'<div class="subtle-divider"></div>'+R:"",G?'<div class="subtle-divider"></div>'+G:""].join(""),"Known security issues from npm audit","vuln-block"),q=e.execution?function(e){var n,s,a,i,r;const o=[g("Execution risk (risk)",u(e.risk))];if(e.native&&o.push(g("Native build tooling detected (native)","Yes")),(null==(s=null==(n=e.scripts)?void 0:n.hooks)?void 0:s.length)&&o.push(m("Lifecycle hooks",h(e.scripts.hooks,6))),"number"==typeof(null==(a=e.scripts)?void 0:a.complexity)&&o.push(g("Heuristic complexity","Script complexity: "+e.scripts.complexity+" (complexity)")),null==(r=null==(i=e.scripts)?void 0:i.signals)?void 0:r.length){const n=e.scripts.signals.map(e=>\`\${t[e]} (\${e})\`);o.push(m("Install-time signals",h(n,6)))}return I("Install-time execution behaviour",'<div class="section-note">Install-time behaviour signals detected. These describe code that runs automatically during install and may warrant review in security-sensitive environments.</div><div class="kv-grid">'+o.join("")+"</div>")}(e.execution):"",J=C("Risk & Compliance","License, vulnerabilities, and install-time execution signals",H+\$+q),F=[g("Outdated status (outdatedStatus)",(W=e.upgrade.outdatedStatus,W?"unknown"===W?"Unknown":u(W):"Not reported"))];var W;e.upgrade.latestVersion&&F.push(g("Latest version (latestVersion)",e.upgrade.latestVersion));const _=I("Version",'<div class="section-note">Based on npm outdated findings.</div><div class="kv-grid">'+F.join("")+"</div>"),K=e.package.deprecated?I("Deprecated",'<div class="kv-grid">'+g("Deprecated (deprecated)","Yes","Declared by the package author.")+"</div>",void 0,"warning"):"",z=[g("Node engine constraint (nodeEngine)",e.upgrade.nodeEngine||"Any")];void 0!==e.upgrade.blocksNodeMajor&&z.push(g("Blocks Node major upgrade (blocksNodeMajor)",e.upgrade.blocksNodeMajor?"Yes":"No"));const X=I("Constraints",'<div class="kv-grid">'+z.join("")+"</div>"),Y=I("Blast radius",'<div class="kv-grid">'+[g("Used by other packages (fanIn)",e.graph.fanIn),g("Depends on packages (fanOut)",e.graph.fanOut)].join("")+"</div>"),Q={nodeEngine:"Node engine constraint (nodeEngine)",peerDependency:"Peer dependency constraints (peerDependency)",nativeBindings:"Native bindings/build tooling (nativeBindings)",deprecated:"Deprecated by author (deprecated)"},Z=C("Upgrade & Change Impact","Currency, constraints, and blast radius",_+K+X+Y+((null==(f=e.upgrade.blockers)?void 0:f.length)?'<div class="subsection"><div class="subsection-header"><span class="subsection-title">Upgrade blockers (blockers)</span></div><ul class="bullet-list">'+e.upgrade.blockers.map(e=>"<li>"+c(Q[e]||e)+"</li>").join("")+"</ul></div>":"")),ee=w(e,n);return[L(P),T,J,Z,ee,'<details class="raw-data-toggle"><summary><span class="expand-icon" aria-hidden="true"></span>View raw data</summary><div class="raw-data-pane"><pre>'+c(B)+'</pre><button type="button" class="copy-json-btn" aria-label="Copy raw JSON">Copy JSON</button></div></details>'].join("")}async function D(){var e,t;const a=await async function(){const e=document.getElementById("radar-data");return e&&e.textContent&&"{}"!==e.textContent.trim()?JSON.parse(e.textContent):(await fetch("./sample-data.json")).json()}(),c=document.getElementById("dependency-list"),l=document.getElementById("results-summary"),d=document.getElementById("project-path");d&&(d.textContent=a.project.projectDir);const u=document.getElementById("git-branch-item"),p=document.getElementById("git-branch");(null==(e=a.git)?void 0:e.branch)&&a.git.branch&&u&&p&&(p.textContent=a.git.branch,u.style.display="");const g=document.getElementById("node-item"),v=document.getElementById("node-version"),m=document.getElementById("node-disclaimer");if(a.environment&&g&&v){const e=(null==(t=a.environment.runtimeVersion)?void 0:t.replace(/^v/,""))||"unknown",n=a.environment.minRequiredMajor;v.textContent=e+(n&&n>0?\` (requires ≥\${n})\`:""),g.style.display="",n&&n>0&&m&&(m.textContent="Node requirement derived from dependency engine ranges.",m.style.display="")}const h=document.getElementById("formatted-date");if(h&&a.generatedAt)try{const e=new Date(a.generatedAt),t=new Intl.DateTimeFormat(void 0,{day:"numeric",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit"}).format(e);h.textContent=t}catch{h.textContent=a.generatedAt}const y={search:document.getElementById("search"),direct:document.getElementById("direct-filter"),runtime:document.getElementById("runtime-filter"),sort:document.getElementById("sort-by"),sortDirection:document.getElementById("sort-direction"),hasVulns:document.getElementById("has-vulns"),themeSwitch:document.getElementById("theme-switch"),licenseToggle:document.getElementById("license-toggle"),licensePanel:document.getElementById("license-panel"),licensePermissive:document.getElementById("license-permissive"),licenseWeakCopyleft:document.getElementById("license-weak-copyleft"),licenseStrongCopyleft:document.getElementById("license-strong-copyleft"),licenseUnknown:document.getElementById("license-unknown"),licenseAll:document.getElementById("license-all"),licenseFriendly:document.getElementById("license-friendly")};let f=!0;"light"===localStorage.getItem("dependency-radar-theme")&&(document.documentElement.classList.add("light"),y.themeSwitch.classList.add("light")),y.themeSwitch.addEventListener("click",()=>{document.documentElement.classList.toggle("light"),y.themeSwitch.classList.toggle("light");const e=document.documentElement.classList.contains("light");localStorage.setItem("dependency-radar-theme",e?"light":"dark")}),y.licenseToggle.addEventListener("click",()=>{y.licenseToggle.classList.toggle("open"),y.licensePanel.classList.toggle("open")}),y.sortDirection.addEventListener("click",()=>{f=!f,y.sortDirection.textContent=f?"↑":"↓",P()}),y.licenseAll.addEventListener("click",()=>{y.licensePermissive.checked=!0,y.licenseWeakCopyleft.checked=!0,y.licenseStrongCopyleft.checked=!0,y.licenseUnknown.checked=!0,P()}),y.licenseFriendly.addEventListener("click",()=>{y.licensePermissive.checked=!0,y.licenseWeakCopyleft.checked=!1,y.licenseStrongCopyleft.checked=!1,y.licenseUnknown.checked=!1,P()});const b=Object.values(a.dependencies||{}),w=new Map;b.forEach(e=>{w.set(k(e.package.name,e.package.version),e)});const C=new Set,I=new Map;let x=new Set;const L=(()=>{const e=document.getElementById("copy-announcer");if(e)return e;const t=document.createElement("div");return t.id="copy-announcer",t.className="sr-only",t.setAttribute("aria-live","polite"),document.body.appendChild(t),t})();function D(e){const t=e.dataset.depKey;if(!t)return;const n=e.querySelector(".dep-details");if(!n||"true"===n.dataset.rendered)return;const s=w.get(t);s&&(n.setAttribute("aria-busy","true"),n.innerHTML=['<div class="dep-loading" role="presentation">','<div class="dep-loading-bar"></div>',"</div>"].join(""),requestAnimationFrame(()=>{n.innerHTML=S(s,x),n.dataset.rendered="true",n.removeAttribute("aria-busy")}))}function P(){var e;const t=function(){const e=(y.search.value||"").toLowerCase(),t=y.direct.value,a=y.runtime.value,c=y.hasVulns.checked,l=y.licensePermissive.checked,d=y.licenseWeakCopyleft.checked,u=y.licenseStrongCopyleft.checked,p=y.licenseUnknown.checked;return b.filter(g=>{var v,m;const h=s(g),y=[h.value,null==(v=g.compliance.license.declared)?void 0:v.spdxId,null==(m=g.compliance.license.inferred)?void 0:m.spdxId].filter(Boolean).join(" ").toLowerCase();if(e&&!g.package.name.toLowerCase().includes(e)&&!y.includes(e))return!1;if("direct"===t&&!g.usage.direct)return!1;if("transitive"===t&&g.usage.direct)return!1;if("all"!==a&&g.usage.scope!==a)return!1;if(c&&0===i[o(r(g).summary)])return!1;const k=n(h.value);return!("permissive"===k&&!l||"weakCopyleft"===k&&!d||"strongCopyleft"===k&&!u||"unknown"===k&&!p)})}(),d=function(e){const t=y.sort.value,n=[...e];return"name"===t?n.sort((e,t)=>e.package.name.localeCompare(t.package.name)):"depth"===t?n.sort((e,t)=>e.usage.depth-t.usage.depth):"severity"===t&&n.sort((e,t)=>i[o(r(t).summary)]-i[o(r(e).summary)]),f||n.reverse(),n}(t);x=new Set(d.map(e=>k(e.package.name,e.package.version)));const u=(null==(e=a.summary)?void 0:e.dependencyCount)||b.length;l.innerHTML="Showing <strong>"+d.length+"</strong> of <strong>"+u+"</strong> dependencies",0!==d.length?(c.innerHTML=d.map(E).join(""),I.clear(),c.querySelectorAll("details.dep-card").forEach(e=>{const t=e.dataset.depKey;t&&I.set(t,e)}),C.forEach(e=>{const t=I.get(e);t&&(t.open||(t.open=!0),D(t))})):c.innerHTML='<div class="empty-state"><div class="empty-state-icon">📦</div><div class="empty-state-text">No dependencies match your filters</div></div>'}function B(e){const t=e.getAttribute("data-dep-key");if(!t)return;const n=I.get(t);if(!n)return;C.add(t),n.open||(n.open=!0),D(n),n.scrollIntoView({behavior:"smooth",block:"start"});const s=n.querySelector("summary");s&&s.focus({preventScroll:!0})}[y.search,y.direct,y.runtime,y.sort,y.hasVulns,y.licensePermissive,y.licenseWeakCopyleft,y.licenseStrongCopyleft,y.licenseUnknown].forEach(e=>{e&&(e.addEventListener("input",P),e.addEventListener("change",P))}),c.addEventListener("toggle",e=>{const t=e.target;if(!(t instanceof HTMLDetailsElement))return;if(!t.classList.contains("dep-card"))return;const n=t.dataset.depKey;n&&(t.open?(C.add(n),D(t)):C.delete(n))},!0),c.addEventListener("click",e=>{const t=e.target,n=t.closest(".root-package-link");if(n)return e.preventDefault(),void B(n);const s=t.closest(".copy-json-btn");s&&(e.preventDefault(),async function(e){var t;const n=e.closest(".raw-data-toggle"),s=null==n?void 0:n.querySelector("pre"),a=(null==s?void 0:s.textContent)??"";if(a)try{if(null==(t=navigator.clipboard)?void 0:t.writeText)await navigator.clipboard.writeText(a);else{const e=document.createElement("textarea");e.value=a,e.setAttribute("readonly","true"),e.style.position="absolute",e.style.left="-9999px",document.body.appendChild(e),e.select(),document.execCommand("copy"),document.body.removeChild(e)}const n=e.dataset.label||e.textContent||"Copy JSON";e.dataset.label=n,e.textContent="Copied",e.classList.add("copied"),L.textContent="Copied JSON to clipboard.",window.setTimeout(()=>{e.textContent=n,e.classList.remove("copied")},1500)}catch{L.textContent="Copy failed."}}(s))}),c.addEventListener("keydown",e=>{const t=e.target.closest(".root-package-link");t&&(" "!==e.key&&"Spacebar"!==e.key||(e.preventDefault(),B(t)))}),P()}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",D):D()}();
18
18
  `;