mcp-vector-search 0.12.0__py3-none-any.whl → 0.12.2__py3-none-any.whl
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.
Potentially problematic release.
This version of mcp-vector-search might be problematic. Click here for more details.
- mcp_vector_search/__init__.py +2 -2
- mcp_vector_search/cli/commands/index.py +15 -24
- mcp_vector_search/cli/commands/install.py +502 -523
- mcp_vector_search/cli/commands/install_old.py +696 -0
- mcp_vector_search/cli/commands/status.py +7 -5
- mcp_vector_search/cli/commands/uninstall.py +485 -0
- mcp_vector_search/cli/commands/visualize.py +417 -121
- mcp_vector_search/cli/didyoumean.py +10 -0
- mcp_vector_search/cli/main.py +39 -21
- mcp_vector_search/core/connection_pool.py +49 -11
- mcp_vector_search/core/database.py +7 -9
- mcp_vector_search/core/directory_index.py +26 -11
- mcp_vector_search/core/indexer.py +89 -29
- mcp_vector_search/core/models.py +4 -1
- mcp_vector_search/core/project.py +16 -5
- mcp_vector_search/parsers/base.py +54 -18
- mcp_vector_search/parsers/javascript.py +41 -20
- mcp_vector_search/parsers/python.py +19 -11
- mcp_vector_search/parsers/registry.py +3 -2
- mcp_vector_search/utils/gitignore.py +3 -1
- mcp_vector_search/visualization/favicon-v1-1024.png +0 -0
- mcp_vector_search/visualization/favicon-v1-128.png +0 -0
- mcp_vector_search/visualization/favicon-v1-16.png +0 -0
- mcp_vector_search/visualization/favicon-v1-256.png +0 -0
- mcp_vector_search/visualization/favicon-v1-32.png +0 -0
- mcp_vector_search/visualization/favicon-v1-512.png +0 -0
- mcp_vector_search/visualization/favicon-v1-64.png +0 -0
- mcp_vector_search/visualization/favicon-v1.ico +0 -0
- mcp_vector_search/visualization/favicon-v2-1024.png +0 -0
- mcp_vector_search/visualization/favicon-v2-128.png +0 -0
- mcp_vector_search/visualization/favicon-v2-16.png +0 -0
- mcp_vector_search/visualization/favicon-v2-256.png +0 -0
- mcp_vector_search/visualization/favicon-v2-32.png +0 -0
- mcp_vector_search/visualization/favicon-v2-512.png +0 -0
- mcp_vector_search/visualization/favicon-v2-64.png +0 -0
- mcp_vector_search/visualization/favicon-v2.ico +0 -0
- mcp_vector_search/visualization/favicon-v3-1024.png +0 -0
- mcp_vector_search/visualization/favicon-v3-128.png +0 -0
- mcp_vector_search/visualization/favicon-v3-16.png +0 -0
- mcp_vector_search/visualization/favicon-v3-256.png +0 -0
- mcp_vector_search/visualization/favicon-v3-32.png +0 -0
- mcp_vector_search/visualization/favicon-v3-512.png +0 -0
- mcp_vector_search/visualization/favicon-v3-64.png +0 -0
- mcp_vector_search/visualization/favicon-v3.ico +0 -0
- mcp_vector_search/visualization/index.html +522 -172
- {mcp_vector_search-0.12.0.dist-info → mcp_vector_search-0.12.2.dist-info}/METADATA +148 -25
- mcp_vector_search-0.12.2.dist-info/RECORD +93 -0
- mcp_vector_search-0.12.0.dist-info/RECORD +0 -67
- {mcp_vector_search-0.12.0.dist-info → mcp_vector_search-0.12.2.dist-info}/WHEEL +0 -0
- {mcp_vector_search-0.12.0.dist-info → mcp_vector_search-0.12.2.dist-info}/entry_points.txt +0 -0
- {mcp_vector_search-0.12.0.dist-info → mcp_vector_search-0.12.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,10 +2,15 @@
|
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
|
-
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
|
6
|
-
<meta http-equiv="Pragma" content="no-cache">
|
|
7
|
-
<meta http-equiv="Expires" content="0">
|
|
8
5
|
<title>Code Chunk Relationship Graph</title>
|
|
6
|
+
|
|
7
|
+
<!-- Favicon -->
|
|
8
|
+
<link rel="icon" type="image/x-icon" href="favicon-v1.ico">
|
|
9
|
+
<link rel="icon" type="image/png" sizes="16x16" href="favicon-v1-16.png">
|
|
10
|
+
<link rel="icon" type="image/png" sizes="32x32" href="favicon-v1-32.png">
|
|
11
|
+
<link rel="icon" type="image/png" sizes="64x64" href="favicon-v1-64.png">
|
|
12
|
+
<link rel="apple-touch-icon" sizes="180x180" href="favicon-v1-512.png">
|
|
13
|
+
|
|
9
14
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
|
10
15
|
<style>
|
|
11
16
|
body {
|
|
@@ -80,26 +85,43 @@
|
|
|
80
85
|
cursor: pointer;
|
|
81
86
|
stroke: #c9d1d9;
|
|
82
87
|
stroke-width: 1.5px;
|
|
88
|
+
transition: all 0.2s ease;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.node circle:hover,
|
|
92
|
+
.node rect:hover {
|
|
93
|
+
stroke-width: 3px !important;
|
|
94
|
+
filter: brightness(1.2);
|
|
95
|
+
cursor: pointer;
|
|
83
96
|
}
|
|
84
97
|
|
|
85
|
-
.node.directory circle { fill: #ffa657; }
|
|
86
|
-
.node.file circle { fill: #58a6ff; }
|
|
87
98
|
.node.module circle { fill: #238636; }
|
|
88
99
|
.node.class circle { fill: #1f6feb; }
|
|
89
100
|
.node.function circle { fill: #d29922; }
|
|
90
101
|
.node.method circle { fill: #8957e5; }
|
|
91
|
-
.node.imports circle { fill: #6e7681; }
|
|
92
|
-
.node.text circle { fill: #6e7681; }
|
|
93
102
|
.node.code circle { fill: #6e7681; }
|
|
103
|
+
.node.file circle {
|
|
104
|
+
fill: none;
|
|
105
|
+
stroke: #58a6ff;
|
|
106
|
+
stroke-width: 2px;
|
|
107
|
+
stroke-dasharray: 5,3;
|
|
108
|
+
opacity: 0.6;
|
|
109
|
+
}
|
|
110
|
+
.node.directory circle {
|
|
111
|
+
fill: none;
|
|
112
|
+
stroke: #79c0ff;
|
|
113
|
+
stroke-width: 2px;
|
|
114
|
+
stroke-dasharray: 3,3;
|
|
115
|
+
opacity: 0.5;
|
|
116
|
+
}
|
|
94
117
|
.node.subproject circle { fill: #da3633; stroke-width: 3px; }
|
|
95
118
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
font-weight: bold;
|
|
119
|
+
/* Non-code document nodes - squares */
|
|
120
|
+
.node.docstring rect { fill: #8b949e; }
|
|
121
|
+
.node.comment rect { fill: #6e7681; }
|
|
122
|
+
.node rect {
|
|
123
|
+
stroke: #c9d1d9;
|
|
124
|
+
stroke-width: 1.5px;
|
|
103
125
|
}
|
|
104
126
|
|
|
105
127
|
.node text {
|
|
@@ -110,10 +132,19 @@
|
|
|
110
132
|
user-select: none;
|
|
111
133
|
}
|
|
112
134
|
|
|
135
|
+
.node-icon {
|
|
136
|
+
font-size: 35px !important;
|
|
137
|
+
text-anchor: middle;
|
|
138
|
+
pointer-events: none;
|
|
139
|
+
user-select: none;
|
|
140
|
+
fill: #0d1117;
|
|
141
|
+
font-weight: bold;
|
|
142
|
+
}
|
|
143
|
+
|
|
113
144
|
.link {
|
|
114
|
-
stroke: #
|
|
115
|
-
stroke-opacity: 0.
|
|
116
|
-
stroke-width:
|
|
145
|
+
stroke: #30363d;
|
|
146
|
+
stroke-opacity: 0.6;
|
|
147
|
+
stroke-width: 1.5px;
|
|
117
148
|
}
|
|
118
149
|
|
|
119
150
|
.link.dependency {
|
|
@@ -144,73 +175,141 @@
|
|
|
144
175
|
color: #8b949e;
|
|
145
176
|
}
|
|
146
177
|
|
|
147
|
-
#
|
|
148
|
-
position:
|
|
149
|
-
top:
|
|
150
|
-
right:
|
|
151
|
-
width:
|
|
152
|
-
|
|
153
|
-
background: rgba(13, 17, 23, 0.
|
|
154
|
-
border: 1px solid #30363d;
|
|
155
|
-
border-radius: 6px;
|
|
156
|
-
padding: 16px;
|
|
178
|
+
#content-pane {
|
|
179
|
+
position: fixed;
|
|
180
|
+
top: 0;
|
|
181
|
+
right: 0;
|
|
182
|
+
width: 600px;
|
|
183
|
+
height: 100vh;
|
|
184
|
+
background: rgba(13, 17, 23, 0.98);
|
|
185
|
+
border-left: 1px solid #30363d;
|
|
157
186
|
overflow-y: auto;
|
|
158
|
-
box-shadow: 0
|
|
159
|
-
|
|
187
|
+
box-shadow: -4px 0 24px rgba(0, 0, 0, 0.5);
|
|
188
|
+
transform: translateX(100%);
|
|
189
|
+
transition: transform 0.3s ease-in-out;
|
|
190
|
+
z-index: 1000;
|
|
160
191
|
}
|
|
161
192
|
|
|
162
|
-
#
|
|
163
|
-
|
|
193
|
+
#content-pane.visible {
|
|
194
|
+
transform: translateX(0);
|
|
164
195
|
}
|
|
165
196
|
|
|
166
|
-
#
|
|
167
|
-
|
|
168
|
-
|
|
197
|
+
#content-pane .pane-header {
|
|
198
|
+
position: sticky;
|
|
199
|
+
top: 0;
|
|
200
|
+
background: rgba(13, 17, 23, 0.98);
|
|
201
|
+
padding: 20px;
|
|
169
202
|
border-bottom: 1px solid #30363d;
|
|
203
|
+
z-index: 1;
|
|
170
204
|
}
|
|
171
205
|
|
|
172
|
-
#
|
|
173
|
-
font-size:
|
|
206
|
+
#content-pane .pane-title {
|
|
207
|
+
font-size: 16px;
|
|
174
208
|
font-weight: bold;
|
|
175
209
|
color: #58a6ff;
|
|
176
|
-
margin-bottom:
|
|
210
|
+
margin-bottom: 8px;
|
|
211
|
+
padding-right: 30px;
|
|
177
212
|
}
|
|
178
213
|
|
|
179
|
-
#
|
|
180
|
-
font-size:
|
|
214
|
+
#content-pane .pane-meta {
|
|
215
|
+
font-size: 12px;
|
|
181
216
|
color: #8b949e;
|
|
182
217
|
}
|
|
183
218
|
|
|
184
|
-
#
|
|
185
|
-
|
|
219
|
+
#content-pane .collapse-btn {
|
|
220
|
+
position: absolute;
|
|
221
|
+
top: 20px;
|
|
222
|
+
right: 20px;
|
|
186
223
|
cursor: pointer;
|
|
187
224
|
color: #8b949e;
|
|
188
|
-
font-size:
|
|
225
|
+
font-size: 24px;
|
|
189
226
|
line-height: 1;
|
|
190
|
-
|
|
227
|
+
background: none;
|
|
228
|
+
border: none;
|
|
229
|
+
padding: 0;
|
|
230
|
+
transition: color 0.2s;
|
|
191
231
|
}
|
|
192
232
|
|
|
193
|
-
#
|
|
233
|
+
#content-pane .collapse-btn:hover {
|
|
194
234
|
color: #c9d1d9;
|
|
195
235
|
}
|
|
196
236
|
|
|
197
|
-
#
|
|
237
|
+
#content-pane .pane-content {
|
|
238
|
+
padding: 20px;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
#content-pane pre {
|
|
198
242
|
margin: 0;
|
|
199
|
-
padding:
|
|
243
|
+
padding: 16px;
|
|
200
244
|
background: #0d1117;
|
|
201
245
|
border: 1px solid #30363d;
|
|
202
246
|
border-radius: 6px;
|
|
203
247
|
overflow-x: auto;
|
|
204
|
-
font-size:
|
|
205
|
-
line-height: 1.
|
|
248
|
+
font-size: 12px;
|
|
249
|
+
line-height: 1.6;
|
|
206
250
|
}
|
|
207
251
|
|
|
208
|
-
#
|
|
252
|
+
#content-pane code {
|
|
209
253
|
color: #c9d1d9;
|
|
210
254
|
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
211
255
|
}
|
|
212
256
|
|
|
213
|
-
.
|
|
257
|
+
#content-pane .directory-list {
|
|
258
|
+
list-style: none;
|
|
259
|
+
padding: 0;
|
|
260
|
+
margin: 0;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
#content-pane .directory-list li {
|
|
264
|
+
padding: 8px 12px;
|
|
265
|
+
margin: 4px 0;
|
|
266
|
+
background: #161b22;
|
|
267
|
+
border: 1px solid #30363d;
|
|
268
|
+
border-radius: 4px;
|
|
269
|
+
font-size: 12px;
|
|
270
|
+
display: flex;
|
|
271
|
+
align-items: center;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
#content-pane .directory-list .item-icon {
|
|
275
|
+
margin-right: 8px;
|
|
276
|
+
font-size: 14px;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
#content-pane .directory-list .item-type {
|
|
280
|
+
margin-left: auto;
|
|
281
|
+
padding-left: 12px;
|
|
282
|
+
font-size: 10px;
|
|
283
|
+
color: #8b949e;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
#content-pane .import-details {
|
|
287
|
+
background: #161b22;
|
|
288
|
+
border: 1px solid #30363d;
|
|
289
|
+
border-radius: 6px;
|
|
290
|
+
padding: 16px;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
#content-pane .import-details .import-statement {
|
|
294
|
+
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
295
|
+
font-size: 12px;
|
|
296
|
+
color: #79c0ff;
|
|
297
|
+
margin-bottom: 12px;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
#content-pane .import-details .detail-row {
|
|
301
|
+
font-size: 11px;
|
|
302
|
+
color: #8b949e;
|
|
303
|
+
margin: 4px 0;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
#content-pane .import-details .detail-label {
|
|
307
|
+
color: #c9d1d9;
|
|
308
|
+
font-weight: 600;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.node.highlighted circle,
|
|
312
|
+
.node.highlighted rect {
|
|
214
313
|
stroke: #f0e68c;
|
|
215
314
|
stroke-width: 3px;
|
|
216
315
|
filter: drop-shadow(0 0 8px #f0e68c);
|
|
@@ -228,25 +327,37 @@
|
|
|
228
327
|
<h3>Legend</h3>
|
|
229
328
|
<div class="legend">
|
|
230
329
|
<div class="legend-item">
|
|
231
|
-
|
|
330
|
+
<span class="legend-color" style="background: #da3633;"></span> Subproject
|
|
331
|
+
</div>
|
|
332
|
+
<div class="legend-item">
|
|
333
|
+
<span class="legend-color" style="border: 2px dashed #79c0ff; border-radius: 50%; background: transparent;"></span> Directory
|
|
334
|
+
</div>
|
|
335
|
+
<div class="legend-item">
|
|
336
|
+
<span class="legend-color" style="border: 2px dashed #58a6ff; border-radius: 50%; background: transparent;"></span> File
|
|
337
|
+
</div>
|
|
338
|
+
<div class="legend-item">
|
|
339
|
+
<span class="legend-color" style="background: #238636;"></span> Module
|
|
232
340
|
</div>
|
|
233
341
|
<div class="legend-item">
|
|
234
|
-
|
|
342
|
+
<span class="legend-color" style="background: #1f6feb;"></span> Class
|
|
235
343
|
</div>
|
|
236
344
|
<div class="legend-item">
|
|
237
|
-
|
|
345
|
+
<span class="legend-color" style="background: #d29922;"></span> Function
|
|
238
346
|
</div>
|
|
239
347
|
<div class="legend-item">
|
|
240
|
-
|
|
348
|
+
<span class="legend-color" style="background: #8957e5;"></span> Method
|
|
241
349
|
</div>
|
|
242
350
|
<div class="legend-item">
|
|
243
|
-
|
|
351
|
+
<span class="legend-color" style="background: #6e7681;"></span> Code
|
|
352
|
+
</div>
|
|
353
|
+
<div class="legend-item" style="font-style: italic; color: #79c0ff;">
|
|
354
|
+
<span class="legend-color" style="background: #6e7681;"></span> Import
|
|
244
355
|
</div>
|
|
245
356
|
<div class="legend-item">
|
|
246
|
-
|
|
357
|
+
<span class="legend-color" style="background: #8b949e; border-radius: 2px;"></span> Docstring ▢
|
|
247
358
|
</div>
|
|
248
359
|
<div class="legend-item">
|
|
249
|
-
|
|
360
|
+
<span class="legend-color" style="background: #6e7681; border-radius: 2px;"></span> Comment ▢
|
|
250
361
|
</div>
|
|
251
362
|
</div>
|
|
252
363
|
|
|
@@ -261,13 +372,13 @@
|
|
|
261
372
|
<svg id="graph"></svg>
|
|
262
373
|
<div id="tooltip" class="tooltip"></div>
|
|
263
374
|
|
|
264
|
-
<div id="
|
|
265
|
-
<div class="header">
|
|
266
|
-
<
|
|
267
|
-
<div class="title" id="
|
|
268
|
-
<div class="meta" id="
|
|
375
|
+
<div id="content-pane">
|
|
376
|
+
<div class="pane-header">
|
|
377
|
+
<button class="collapse-btn" onclick="closeContentPane()">×</button>
|
|
378
|
+
<div class="pane-title" id="pane-title"></div>
|
|
379
|
+
<div class="pane-meta" id="pane-meta"></div>
|
|
269
380
|
</div>
|
|
270
|
-
<
|
|
381
|
+
<div class="pane-content" id="pane-content"></div>
|
|
271
382
|
</div>
|
|
272
383
|
|
|
273
384
|
<script>
|
|
@@ -286,7 +397,6 @@
|
|
|
286
397
|
let simulation;
|
|
287
398
|
let allNodes = [];
|
|
288
399
|
let allLinks = [];
|
|
289
|
-
let allLinksOriginal = []; // Keep original link structure before D3 modifies it
|
|
290
400
|
let visibleNodes = new Set();
|
|
291
401
|
let collapsedNodes = new Set();
|
|
292
402
|
let highlightedNode = null;
|
|
@@ -296,8 +406,6 @@
|
|
|
296
406
|
|
|
297
407
|
allNodes = data.nodes;
|
|
298
408
|
allLinks = data.links;
|
|
299
|
-
// Deep copy links before D3 modifies them
|
|
300
|
-
allLinksOriginal = JSON.parse(JSON.stringify(data.links));
|
|
301
409
|
|
|
302
410
|
// Find root nodes - start with only top-level nodes
|
|
303
411
|
let rootNodes;
|
|
@@ -305,21 +413,36 @@
|
|
|
305
413
|
// In monorepos, subproject nodes are roots
|
|
306
414
|
rootNodes = allNodes.filter(n => n.type === 'subproject');
|
|
307
415
|
} else {
|
|
308
|
-
// Regular projects:
|
|
416
|
+
// Regular projects: Find root nodes by graph structure
|
|
309
417
|
const dirNodes = allNodes.filter(n => n.type === 'directory');
|
|
310
418
|
const fileNodes = allNodes.filter(n => n.type === 'file');
|
|
311
419
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
420
|
+
// Find minimum depth for directories and files (for fallback)
|
|
421
|
+
let minDirDepth = Infinity;
|
|
422
|
+
let minFileDepth = Infinity;
|
|
423
|
+
|
|
424
|
+
dirNodes.forEach(d => {
|
|
425
|
+
if (d.depth < minDirDepth) minDirDepth = d.depth;
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
fileNodes.forEach(f => {
|
|
429
|
+
if (f.depth < minFileDepth) minFileDepth = f.depth;
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
// CORRECT: Find root nodes by checking graph structure
|
|
433
|
+
// Root nodes are nodes with no incoming links (no parent)
|
|
434
|
+
const targetIds = new Set(allLinks.map(link => link.target));
|
|
435
|
+
rootNodes = allNodes.filter(node => !targetIds.has(node.id));
|
|
436
|
+
|
|
437
|
+
console.log(`Root nodes found via links: ${rootNodes.length}`, rootNodes.map(n => n.name));
|
|
438
|
+
|
|
439
|
+
// Fallback only if we got 0 root nodes (shouldn't happen with correct data)
|
|
440
|
+
if (rootNodes.length === 0) {
|
|
441
|
+
console.warn('No root nodes found via links, falling back to depth-based detection');
|
|
442
|
+
rootNodes = [
|
|
443
|
+
...dirNodes.filter(n => n.depth === minDirDepth),
|
|
444
|
+
...fileNodes.filter(n => n.depth === minFileDepth)
|
|
445
|
+
];
|
|
323
446
|
}
|
|
324
447
|
}
|
|
325
448
|
|
|
@@ -327,58 +450,35 @@
|
|
|
327
450
|
visibleNodes = new Set(rootNodes.map(n => n.id));
|
|
328
451
|
collapsedNodes = new Set(rootNodes.map(n => n.id));
|
|
329
452
|
|
|
453
|
+
console.log('=== INITIAL STATE ===');
|
|
454
|
+
console.log(`Total nodes: ${allNodes.length}`);
|
|
455
|
+
console.log(`Total links: ${allLinks.length}`);
|
|
456
|
+
console.log(`Root nodes: ${rootNodes.length}`, rootNodes.map(n => n.name));
|
|
457
|
+
console.log(`Initial visibleNodes:`, Array.from(visibleNodes));
|
|
458
|
+
console.log(`Initial collapsedNodes:`, Array.from(collapsedNodes));
|
|
459
|
+
|
|
330
460
|
renderGraph();
|
|
331
461
|
}
|
|
332
462
|
|
|
333
463
|
function renderGraph() {
|
|
464
|
+
console.log('=== renderGraph() called ===');
|
|
465
|
+
console.log(`visibleNodes.size: ${visibleNodes.size}`);
|
|
466
|
+
console.log(`collapsedNodes.size: ${collapsedNodes.size}`);
|
|
467
|
+
|
|
334
468
|
const visibleNodesList = allNodes.filter(n => visibleNodes.has(n.id));
|
|
469
|
+
console.log(`Rendering ${visibleNodesList.length} visible nodes`);
|
|
470
|
+
|
|
335
471
|
const visibleLinks = allLinks.filter(l =>
|
|
336
472
|
visibleNodes.has(l.source.id || l.source) &&
|
|
337
473
|
visibleNodes.has(l.target.id || l.target)
|
|
338
474
|
);
|
|
339
|
-
|
|
340
|
-
// Dynamic collision radius based on node type
|
|
341
|
-
const getNodeRadius = (d) => {
|
|
342
|
-
if (d.type === 'directory') return 35;
|
|
343
|
-
if (d.type === 'file') return 32;
|
|
344
|
-
if (d.type === 'subproject') return 38;
|
|
345
|
-
return d.complexity ? Math.min(20 + d.complexity * 2, 35) : 25;
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
// Dynamic link distance based on node types
|
|
349
|
-
const getLinkDistance = (link) => {
|
|
350
|
-
const source = typeof link.source === 'object' ? link.source : visibleNodesList.find(n => n.id === link.source);
|
|
351
|
-
const target = typeof link.target === 'object' ? link.target : visibleNodesList.find(n => n.id === link.target);
|
|
352
|
-
|
|
353
|
-
if (!source || !target) return 150;
|
|
354
|
-
|
|
355
|
-
// Longer distances for directory relationships
|
|
356
|
-
if (source.type === 'directory' || target.type === 'directory') return 200;
|
|
357
|
-
if (source.type === 'file' || target.type === 'file') return 150;
|
|
358
|
-
return 100;
|
|
359
|
-
};
|
|
475
|
+
console.log(`Rendering ${visibleLinks.length} visible links`);
|
|
360
476
|
|
|
361
477
|
simulation = d3.forceSimulation(visibleNodesList)
|
|
362
|
-
.force("link", d3.forceLink(visibleLinks)
|
|
363
|
-
|
|
364
|
-
.distance(getLinkDistance)
|
|
365
|
-
.strength(0.5))
|
|
366
|
-
.force("charge", d3.forceManyBody()
|
|
367
|
-
.strength(d => {
|
|
368
|
-
// Stronger repulsion for directories and files
|
|
369
|
-
if (d.type === 'directory') return -800;
|
|
370
|
-
if (d.type === 'file') return -600;
|
|
371
|
-
return -400;
|
|
372
|
-
})
|
|
373
|
-
.distanceMax(500))
|
|
478
|
+
.force("link", d3.forceLink(visibleLinks).id(d => d.id).distance(100))
|
|
479
|
+
.force("charge", d3.forceManyBody().strength(-400))
|
|
374
480
|
.force("center", d3.forceCenter(width / 2, height / 2))
|
|
375
|
-
.force("collision", d3.forceCollide()
|
|
376
|
-
.radius(getNodeRadius)
|
|
377
|
-
.strength(0.9))
|
|
378
|
-
.force("x", d3.forceX(width / 2).strength(0.05))
|
|
379
|
-
.force("y", d3.forceY(height / 2).strength(0.05))
|
|
380
|
-
.alphaDecay(0.02)
|
|
381
|
-
.velocityDecay(0.3);
|
|
481
|
+
.force("collision", d3.forceCollide().radius(40));
|
|
382
482
|
|
|
383
483
|
g.selectAll("*").remove();
|
|
384
484
|
|
|
@@ -404,16 +504,59 @@
|
|
|
404
504
|
.on("mouseover", showTooltip)
|
|
405
505
|
.on("mouseout", hideTooltip);
|
|
406
506
|
|
|
407
|
-
// Add circles
|
|
408
|
-
|
|
507
|
+
// Add shapes based on node type (circles for code, squares for docs)
|
|
508
|
+
const isDocNode = d => ['docstring', 'comment'].includes(d.type);
|
|
509
|
+
|
|
510
|
+
// Add circles for code nodes
|
|
511
|
+
node.filter(d => !isDocNode(d))
|
|
512
|
+
.append("circle")
|
|
409
513
|
.attr("r", d => {
|
|
410
|
-
if (d.type === '
|
|
411
|
-
if (d.type === '
|
|
412
|
-
if (d.type === '
|
|
413
|
-
return d.complexity ? Math.min(
|
|
514
|
+
if (d.type === 'subproject') return 20;
|
|
515
|
+
if (d.type === 'directory') return 40; // Largest for directory containers
|
|
516
|
+
if (d.type === 'file') return 30; // Larger transparent circle for files
|
|
517
|
+
return d.complexity ? Math.min(8 + d.complexity * 2, 25) : 12;
|
|
518
|
+
})
|
|
519
|
+
.attr("stroke", d => hasChildren(d) ? "#ffffff" : "none")
|
|
520
|
+
.attr("stroke-width", d => hasChildren(d) ? 3 : 0)
|
|
521
|
+
.style("fill", d => d.color || null); // Use custom color if available
|
|
522
|
+
|
|
523
|
+
// Add rectangles for document nodes
|
|
524
|
+
node.filter(d => isDocNode(d))
|
|
525
|
+
.append("rect")
|
|
526
|
+
.attr("width", d => {
|
|
527
|
+
const size = d.complexity ? Math.min(8 + d.complexity * 2, 25) : 12;
|
|
528
|
+
return size * 2;
|
|
529
|
+
})
|
|
530
|
+
.attr("height", d => {
|
|
531
|
+
const size = d.complexity ? Math.min(8 + d.complexity * 2, 25) : 12;
|
|
532
|
+
return size * 2;
|
|
414
533
|
})
|
|
534
|
+
.attr("x", d => {
|
|
535
|
+
const size = d.complexity ? Math.min(8 + d.complexity * 2, 25) : 12;
|
|
536
|
+
return -size;
|
|
537
|
+
})
|
|
538
|
+
.attr("y", d => {
|
|
539
|
+
const size = d.complexity ? Math.min(8 + d.complexity * 2, 25) : 12;
|
|
540
|
+
return -size;
|
|
541
|
+
})
|
|
542
|
+
.attr("rx", 2) // Rounded corners
|
|
543
|
+
.attr("ry", 2)
|
|
544
|
+
.attr("stroke", d => hasChildren(d) ? "#ffffff" : "none")
|
|
545
|
+
.attr("stroke-width", d => hasChildren(d) ? 3 : 0)
|
|
415
546
|
.style("fill", d => d.color || null);
|
|
416
547
|
|
|
548
|
+
// Add expand/collapse indicator
|
|
549
|
+
node.filter(d => hasChildren(d))
|
|
550
|
+
.append("text")
|
|
551
|
+
.attr("class", "expand-indicator")
|
|
552
|
+
.attr("text-anchor", "middle")
|
|
553
|
+
.attr("dy", 5)
|
|
554
|
+
.style("font-size", "16px")
|
|
555
|
+
.style("font-weight", "bold")
|
|
556
|
+
.style("fill", "#ffffff")
|
|
557
|
+
.style("pointer-events", "none")
|
|
558
|
+
.text(d => collapsedNodes.has(d.id) ? "+" : "−");
|
|
559
|
+
|
|
417
560
|
// Add icons based on node type
|
|
418
561
|
node.append("text")
|
|
419
562
|
.attr("class", "node-icon")
|
|
@@ -426,24 +569,27 @@
|
|
|
426
569
|
if (d.type === 'method') return 'm';
|
|
427
570
|
if (d.type === 'module') return 'M';
|
|
428
571
|
if (d.type === 'imports') return '⇄';
|
|
572
|
+
if (d.type === 'docstring') return '📝';
|
|
573
|
+
if (d.type === 'comment') return '💬';
|
|
574
|
+
if (d.type === 'subproject') return '📦';
|
|
429
575
|
return '•';
|
|
430
576
|
});
|
|
431
577
|
|
|
432
|
-
// Add
|
|
433
|
-
node.filter(d => hasChildren(d))
|
|
434
|
-
.append("text")
|
|
435
|
-
.attr("class", "expand-indicator")
|
|
436
|
-
.attr("text-anchor", "middle")
|
|
437
|
-
.attr("dy", -20)
|
|
438
|
-
.style("font-size", "14px")
|
|
439
|
-
.style("font-weight", "bold")
|
|
440
|
-
.style("fill", "#58a6ff")
|
|
441
|
-
.style("pointer-events", "none")
|
|
442
|
-
.text(d => collapsedNodes.has(d.id) ? "+" : "−");
|
|
443
|
-
|
|
444
|
-
// Add labels
|
|
578
|
+
// Add labels (show actual import statement for import nodes)
|
|
445
579
|
node.append("text")
|
|
446
|
-
.text(d =>
|
|
580
|
+
.text(d => {
|
|
581
|
+
// Import nodes have type === 'imports'
|
|
582
|
+
if (d.type === 'imports') {
|
|
583
|
+
if (d.content) {
|
|
584
|
+
// Extract first line of import statement
|
|
585
|
+
const importLine = d.content.split('\n')[0].trim();
|
|
586
|
+
// Truncate if too long (max 60 chars)
|
|
587
|
+
return importLine.length > 60 ? importLine.substring(0, 57) + '...' : importLine;
|
|
588
|
+
}
|
|
589
|
+
return d.name; // Fallback to name if no content
|
|
590
|
+
}
|
|
591
|
+
return d.name;
|
|
592
|
+
})
|
|
447
593
|
.attr("dy", 30);
|
|
448
594
|
|
|
449
595
|
simulation.on("tick", () => {
|
|
@@ -460,50 +606,87 @@
|
|
|
460
606
|
}
|
|
461
607
|
|
|
462
608
|
function hasChildren(node) {
|
|
463
|
-
//
|
|
464
|
-
|
|
609
|
+
// Handle both pre-mutation (string IDs) and post-mutation (object references)
|
|
610
|
+
const result = allLinks.some(l => {
|
|
611
|
+
const sourceId = typeof l.source === 'object' ? l.source.id : l.source;
|
|
612
|
+
return sourceId === node.id;
|
|
613
|
+
});
|
|
614
|
+
console.log(`hasChildren(${node.name}):`, result,
|
|
615
|
+
`Checking ${allLinks.length} links for node ID: ${node.id}`);
|
|
616
|
+
return result;
|
|
465
617
|
}
|
|
466
618
|
|
|
467
619
|
function handleNodeClick(event, d) {
|
|
620
|
+
console.log('=== NODE CLICKED ===');
|
|
621
|
+
console.log('Node:', d.name, 'Type:', d.type, 'ID:', d.id);
|
|
622
|
+
console.log('Event:', event);
|
|
623
|
+
|
|
468
624
|
event.stopPropagation();
|
|
469
625
|
|
|
470
|
-
//
|
|
471
|
-
|
|
472
|
-
|
|
626
|
+
// Always show content pane when clicking any node
|
|
627
|
+
showContentPane(d);
|
|
628
|
+
|
|
629
|
+
// If node has children, also toggle expansion
|
|
630
|
+
const nodeHasChildren = hasChildren(d);
|
|
631
|
+
console.log('Node has children:', nodeHasChildren);
|
|
632
|
+
|
|
633
|
+
if (nodeHasChildren) {
|
|
634
|
+
const isCollapsed = collapsedNodes.has(d.id);
|
|
635
|
+
console.log('Node is collapsed:', isCollapsed);
|
|
636
|
+
|
|
637
|
+
if (isCollapsed) {
|
|
638
|
+
console.log('Expanding node...');
|
|
473
639
|
expandNode(d);
|
|
474
640
|
} else {
|
|
641
|
+
console.log('Collapsing node...');
|
|
475
642
|
collapseNode(d);
|
|
476
643
|
}
|
|
644
|
+
console.log('Calling renderGraph()...');
|
|
477
645
|
renderGraph();
|
|
646
|
+
console.log('renderGraph() complete');
|
|
478
647
|
} else {
|
|
479
|
-
|
|
480
|
-
showCodeViewer(d);
|
|
648
|
+
console.log('Node has no children, skipping expansion');
|
|
481
649
|
}
|
|
482
650
|
}
|
|
483
651
|
|
|
484
652
|
function expandNode(node) {
|
|
653
|
+
console.log(`expandNode(${node.name}):`, 'Removing from collapsedNodes');
|
|
485
654
|
collapsedNodes.delete(node.id);
|
|
486
655
|
|
|
487
|
-
// Find direct children
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
|
|
656
|
+
// Find direct children
|
|
657
|
+
const childLinks = allLinks.filter(l => (l.source.id || l.source) === node.id);
|
|
658
|
+
console.log(` Found ${childLinks.length} child links for node ${node.id}`);
|
|
659
|
+
|
|
660
|
+
const children = childLinks
|
|
661
|
+
.map(l => {
|
|
662
|
+
const targetId = l.target.id || l.target;
|
|
663
|
+
const child = allNodes.find(n => n.id === targetId);
|
|
664
|
+
if (!child) {
|
|
665
|
+
console.warn(` Could not find child node with ID: ${targetId}`);
|
|
666
|
+
}
|
|
667
|
+
return child;
|
|
668
|
+
})
|
|
491
669
|
.filter(n => n);
|
|
492
670
|
|
|
671
|
+
console.log(` Found ${children.length} child nodes:`, children.map(c => c.name));
|
|
672
|
+
|
|
493
673
|
children.forEach(child => {
|
|
674
|
+
console.log(` Adding child to visibleNodes: ${child.name} (${child.id})`);
|
|
494
675
|
visibleNodes.add(child.id);
|
|
495
676
|
collapsedNodes.add(child.id); // Children start collapsed
|
|
496
677
|
});
|
|
678
|
+
|
|
679
|
+
console.log(` visibleNodes now has ${visibleNodes.size} items`);
|
|
497
680
|
}
|
|
498
681
|
|
|
499
682
|
function collapseNode(node) {
|
|
500
683
|
collapsedNodes.add(node.id);
|
|
501
684
|
|
|
502
|
-
// Hide all descendants recursively
|
|
685
|
+
// Hide all descendants recursively
|
|
503
686
|
function hideDescendants(parentId) {
|
|
504
|
-
const children =
|
|
505
|
-
.filter(l => l.source === parentId)
|
|
506
|
-
.map(l => l.target);
|
|
687
|
+
const children = allLinks
|
|
688
|
+
.filter(l => (l.source.id || l.source) === parentId)
|
|
689
|
+
.map(l => l.target.id || l.target);
|
|
507
690
|
|
|
508
691
|
children.forEach(childId => {
|
|
509
692
|
visibleNodes.delete(childId);
|
|
@@ -586,19 +769,30 @@
|
|
|
586
769
|
}
|
|
587
770
|
}
|
|
588
771
|
|
|
589
|
-
function
|
|
772
|
+
function showContentPane(node) {
|
|
590
773
|
// Highlight the node
|
|
591
774
|
highlightedNode = node;
|
|
592
775
|
renderGraph();
|
|
593
776
|
|
|
594
|
-
// Populate
|
|
595
|
-
const
|
|
596
|
-
const title = document.getElementById('
|
|
597
|
-
const meta = document.getElementById('
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
title
|
|
777
|
+
// Populate content pane
|
|
778
|
+
const pane = document.getElementById('content-pane');
|
|
779
|
+
const title = document.getElementById('pane-title');
|
|
780
|
+
const meta = document.getElementById('pane-meta');
|
|
781
|
+
const content = document.getElementById('pane-content');
|
|
782
|
+
|
|
783
|
+
// Set title with actual import statement for import nodes
|
|
784
|
+
if (node.type === 'imports') {
|
|
785
|
+
if (node.content) {
|
|
786
|
+
const importLine = node.content.split('\n')[0].trim();
|
|
787
|
+
title.textContent = importLine;
|
|
788
|
+
} else {
|
|
789
|
+
title.textContent = `Import: ${node.name}`;
|
|
790
|
+
}
|
|
791
|
+
} else {
|
|
792
|
+
title.textContent = node.name;
|
|
793
|
+
}
|
|
601
794
|
|
|
795
|
+
// Set metadata
|
|
602
796
|
let metaText = `${node.type} • ${node.file_path}`;
|
|
603
797
|
if (node.start_line) {
|
|
604
798
|
metaText += ` • Lines ${node.start_line}-${node.end_line}`;
|
|
@@ -608,22 +802,178 @@
|
|
|
608
802
|
}
|
|
609
803
|
meta.textContent = metaText;
|
|
610
804
|
|
|
611
|
-
//
|
|
805
|
+
// Display content based on node type
|
|
806
|
+
if (node.type === 'directory') {
|
|
807
|
+
showDirectoryContents(node, content);
|
|
808
|
+
} else if (node.type === 'file') {
|
|
809
|
+
showFileContents(node, content);
|
|
810
|
+
} else if (node.type === 'imports') {
|
|
811
|
+
// Import nodes show import details
|
|
812
|
+
showImportDetails(node, content);
|
|
813
|
+
} else {
|
|
814
|
+
// Class, function, method, code nodes
|
|
815
|
+
showCodeContent(node, content);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
pane.classList.add('visible');
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
function showDirectoryContents(node, container) {
|
|
822
|
+
// Find all direct children of this directory
|
|
823
|
+
const children = allLinks
|
|
824
|
+
.filter(l => (l.source.id || l.source) === node.id)
|
|
825
|
+
.map(l => allNodes.find(n => n.id === (l.target.id || l.target)))
|
|
826
|
+
.filter(n => n);
|
|
827
|
+
|
|
828
|
+
if (children.length === 0) {
|
|
829
|
+
container.innerHTML = '<p style="color: #8b949e;">Empty directory</p>';
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// Group by type
|
|
834
|
+
const files = children.filter(n => n.type === 'file');
|
|
835
|
+
const subdirs = children.filter(n => n.type === 'directory');
|
|
836
|
+
const chunks = children.filter(n => n.type !== 'file' && n.type !== 'directory');
|
|
837
|
+
|
|
838
|
+
let html = '<ul class="directory-list">';
|
|
839
|
+
|
|
840
|
+
// Show subdirectories first
|
|
841
|
+
subdirs.forEach(child => {
|
|
842
|
+
html += `
|
|
843
|
+
<li>
|
|
844
|
+
<span class="item-icon">📁</span>
|
|
845
|
+
${child.name}
|
|
846
|
+
<span class="item-type">directory</span>
|
|
847
|
+
</li>
|
|
848
|
+
`;
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
// Then files
|
|
852
|
+
files.forEach(child => {
|
|
853
|
+
html += `
|
|
854
|
+
<li>
|
|
855
|
+
<span class="item-icon">📄</span>
|
|
856
|
+
${child.name}
|
|
857
|
+
<span class="item-type">file</span>
|
|
858
|
+
</li>
|
|
859
|
+
`;
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
// Then code chunks
|
|
863
|
+
chunks.forEach(child => {
|
|
864
|
+
const icon = child.type === 'class' ? '🔷' : child.type === 'function' ? '⚡' : '📝';
|
|
865
|
+
html += `
|
|
866
|
+
<li>
|
|
867
|
+
<span class="item-icon">${icon}</span>
|
|
868
|
+
${child.name}
|
|
869
|
+
<span class="item-type">${child.type}</span>
|
|
870
|
+
</li>
|
|
871
|
+
`;
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
html += '</ul>';
|
|
875
|
+
|
|
876
|
+
// Add summary
|
|
877
|
+
const summary = `<p style="color: #8b949e; font-size: 11px; margin-top: 16px;">
|
|
878
|
+
Total: ${children.length} items (${subdirs.length} directories, ${files.length} files, ${chunks.length} code chunks)
|
|
879
|
+
</p>`;
|
|
880
|
+
|
|
881
|
+
container.innerHTML = html + summary;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
function showFileContents(node, container) {
|
|
885
|
+
// Find all chunks in this file
|
|
886
|
+
const fileChunks = allLinks
|
|
887
|
+
.filter(l => (l.source.id || l.source) === node.id)
|
|
888
|
+
.map(l => allNodes.find(n => n.id === (l.target.id || l.target)))
|
|
889
|
+
.filter(n => n);
|
|
890
|
+
|
|
891
|
+
if (fileChunks.length === 0) {
|
|
892
|
+
container.innerHTML = '<p style="color: #8b949e;">No code chunks found in this file</p>';
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// Collect all content from chunks and sort by line number
|
|
897
|
+
const sortedChunks = fileChunks
|
|
898
|
+
.filter(c => c.content)
|
|
899
|
+
.sort((a, b) => a.start_line - b.start_line);
|
|
900
|
+
|
|
901
|
+
if (sortedChunks.length === 0) {
|
|
902
|
+
container.innerHTML = '<p style="color: #8b949e;">File content not available</p>';
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// Combine all chunks to show full file
|
|
907
|
+
const fullContent = sortedChunks.map(c => c.content).join('\n\n');
|
|
908
|
+
|
|
909
|
+
container.innerHTML = `
|
|
910
|
+
<p style="color: #8b949e; font-size: 11px; margin-bottom: 12px;">
|
|
911
|
+
Contains ${fileChunks.length} code chunks
|
|
912
|
+
</p>
|
|
913
|
+
<pre><code>${escapeHtml(fullContent)}</code></pre>
|
|
914
|
+
`;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
function showImportDetails(node, container) {
|
|
918
|
+
// Import nodes (type === 'imports') - show import content prominently
|
|
919
|
+
const importHtml = `
|
|
920
|
+
<div class="import-details">
|
|
921
|
+
${node.content ? `
|
|
922
|
+
<div style="margin-bottom: 16px;">
|
|
923
|
+
<div class="detail-label" style="margin-bottom: 8px;">Import Statement:</div>
|
|
924
|
+
<pre><code>${escapeHtml(node.content)}</code></pre>
|
|
925
|
+
</div>
|
|
926
|
+
` : '<p style="color: #8b949e;">No import content available</p>'}
|
|
927
|
+
<div class="detail-row">
|
|
928
|
+
<span class="detail-label">File:</span> ${node.file_path}
|
|
929
|
+
</div>
|
|
930
|
+
${node.start_line ? `
|
|
931
|
+
<div class="detail-row">
|
|
932
|
+
<span class="detail-label">Location:</span> Lines ${node.start_line}-${node.end_line}
|
|
933
|
+
</div>
|
|
934
|
+
` : ''}
|
|
935
|
+
${node.language ? `
|
|
936
|
+
<div class="detail-row">
|
|
937
|
+
<span class="detail-label">Language:</span> ${node.language}
|
|
938
|
+
</div>
|
|
939
|
+
` : ''}
|
|
940
|
+
</div>
|
|
941
|
+
`;
|
|
942
|
+
|
|
943
|
+
container.innerHTML = importHtml;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
function showCodeContent(node, container) {
|
|
947
|
+
// Show code for function, class, method, or code chunks
|
|
948
|
+
let html = '';
|
|
949
|
+
|
|
950
|
+
if (node.docstring) {
|
|
951
|
+
html += `
|
|
952
|
+
<div style="margin-bottom: 16px; padding: 12px; background: #161b22; border: 1px solid #30363d; border-radius: 6px;">
|
|
953
|
+
<div style="font-size: 11px; color: #8b949e; margin-bottom: 8px; font-weight: 600;">DOCSTRING</div>
|
|
954
|
+
<pre style="margin: 0; padding: 0; background: transparent; border: none;"><code>${escapeHtml(node.docstring)}</code></pre>
|
|
955
|
+
</div>
|
|
956
|
+
`;
|
|
957
|
+
}
|
|
958
|
+
|
|
612
959
|
if (node.content) {
|
|
613
|
-
|
|
614
|
-
} else if (node.docstring) {
|
|
615
|
-
code.textContent = `// Docstring:
|
|
616
|
-
${node.docstring}`;
|
|
960
|
+
html += `<pre><code>${escapeHtml(node.content)}</code></pre>`;
|
|
617
961
|
} else {
|
|
618
|
-
|
|
962
|
+
html += '<p style="color: #8b949e;">No content available</p>';
|
|
619
963
|
}
|
|
620
964
|
|
|
621
|
-
|
|
965
|
+
container.innerHTML = html;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
function escapeHtml(text) {
|
|
969
|
+
const div = document.createElement('div');
|
|
970
|
+
div.textContent = text;
|
|
971
|
+
return div.innerHTML;
|
|
622
972
|
}
|
|
623
973
|
|
|
624
|
-
function
|
|
625
|
-
const
|
|
626
|
-
|
|
974
|
+
function closeContentPane() {
|
|
975
|
+
const pane = document.getElementById('content-pane');
|
|
976
|
+
pane.classList.remove('visible');
|
|
627
977
|
|
|
628
978
|
// Remove highlight
|
|
629
979
|
highlightedNode = null;
|
|
@@ -634,7 +984,7 @@ ${node.docstring}`;
|
|
|
634
984
|
window.addEventListener('DOMContentLoaded', () => {
|
|
635
985
|
const loadingEl = document.getElementById('loading');
|
|
636
986
|
|
|
637
|
-
fetch(
|
|
987
|
+
fetch("chunk-graph.json")
|
|
638
988
|
.then(response => {
|
|
639
989
|
if (!response.ok) {
|
|
640
990
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|