universal-ast-mapper 1.27.0 → 2.0.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.
Files changed (55) hide show
  1. package/BLUEPRINT.md +230 -230
  2. package/CHANGELOG.md +466 -321
  3. package/README.md +878 -877
  4. package/package.json +48 -47
  5. package/scripts/install-skill.mjs +187 -187
  6. package/dist/analysis.js +0 -134
  7. package/dist/callgraph.js +0 -467
  8. package/dist/check.js +0 -112
  9. package/dist/cli.js +0 -1275
  10. package/dist/complexity.js +0 -98
  11. package/dist/config.js +0 -53
  12. package/dist/contextpack.js +0 -79
  13. package/dist/coupling.js +0 -35
  14. package/dist/crosslang.js +0 -425
  15. package/dist/diskcache.js +0 -97
  16. package/dist/explorer.js +0 -123
  17. package/dist/extractors/c.js +0 -204
  18. package/dist/extractors/common.js +0 -56
  19. package/dist/extractors/cpp.js +0 -272
  20. package/dist/extractors/csharp.js +0 -209
  21. package/dist/extractors/go.js +0 -212
  22. package/dist/extractors/java.js +0 -152
  23. package/dist/extractors/kotlin.js +0 -159
  24. package/dist/extractors/php.js +0 -208
  25. package/dist/extractors/python.js +0 -153
  26. package/dist/extractors/ruby.js +0 -146
  27. package/dist/extractors/rust.js +0 -249
  28. package/dist/extractors/swift.js +0 -192
  29. package/dist/extractors/typescript.js +0 -577
  30. package/dist/gitdiff.js +0 -178
  31. package/dist/graph-analysis.js +0 -279
  32. package/dist/graph.js +0 -165
  33. package/dist/html.js +0 -326
  34. package/dist/index.js +0 -1407
  35. package/dist/layers.js +0 -36
  36. package/dist/modulecoupling.js +0 -0
  37. package/dist/parser.js +0 -84
  38. package/dist/pool.js +0 -114
  39. package/dist/prompts.js +0 -67
  40. package/dist/registry.js +0 -87
  41. package/dist/report.js +0 -187
  42. package/dist/resolver.js +0 -222
  43. package/dist/roots.js +0 -47
  44. package/dist/search.js +0 -68
  45. package/dist/semantic.js +0 -365
  46. package/dist/sfc.js +0 -27
  47. package/dist/skeleton.js +0 -132
  48. package/dist/sourcemap.js +0 -60
  49. package/dist/testmap.js +0 -167
  50. package/dist/tsconfig.js +0 -212
  51. package/dist/typeflow.js +0 -124
  52. package/dist/types.js +0 -5
  53. package/dist/unused-params.js +0 -127
  54. package/dist/worker.js +0 -27
  55. package/dist/workspace.js +0 -330
package/dist/html.js DELETED
@@ -1,326 +0,0 @@
1
- const KIND_COLORS = {
2
- class: "#7c3aed",
3
- interface: "#0ea5e9",
4
- struct: "#0d9488",
5
- function: "#2563eb",
6
- method: "#4f46e5",
7
- type: "#db2777",
8
- enum: "#ea580c",
9
- const: "#65a30d",
10
- var: "#ca8a04",
11
- field: "#64748b",
12
- namespace: "#9333ea",
13
- };
14
- function esc(s) {
15
- return s
16
- .replace(/&/g, "&")
17
- .replace(/</g, "&lt;")
18
- .replace(/>/g, "&gt;")
19
- .replace(/"/g, "&quot;");
20
- }
21
- function badge(kind) {
22
- const color = KIND_COLORS[kind] ?? "#64748b";
23
- return `<span class="badge" style="background:${color}1a;color:${color};border:1px solid ${color}55;">${kind}</span>`;
24
- }
25
- function renderSymbol(sym) {
26
- const vis = sym.visibility === "private"
27
- ? `<span class="vis priv" title="private">private</span>`
28
- : "";
29
- const exported = sym.exported ? `<span class="vis exp" title="exported">export</span>` : "";
30
- const sig = sym.signature
31
- ? `<code class="sig">${esc(sym.signature)}</code>`
32
- : "";
33
- const lines = `<span class="lines">L${sym.range.startLine}–${sym.range.endLine}</span>`;
34
- const doc = sym.doc ? `<div class="doc">${esc(sym.doc)}</div>` : "";
35
- const head = `${badge(sym.kind)}<span class="name">${esc(sym.name)}</span>${exported}${vis}${sig}${lines}`;
36
- if (sym.children.length > 0) {
37
- const kids = sym.children.map(renderSymbol).join("");
38
- return `<details open class="node"><summary>${head}</summary>${doc}<div class="children">${kids}</div></details>`;
39
- }
40
- return `<div class="node leaf">${head}${doc}</div>`;
41
- }
42
- function collectSymbolNames(symbols) {
43
- const names = [];
44
- for (const sym of symbols) {
45
- names.push(sym.name);
46
- if (sym.children.length > 0)
47
- names.push(...collectSymbolNames(sym.children));
48
- }
49
- return names;
50
- }
51
- function renderFileSection(skel, index) {
52
- const body = skel.symbols.length > 0
53
- ? skel.symbols.map(renderSymbol).join("")
54
- : `<p class="empty">No top-level symbols found.</p>`;
55
- return `<details id="file-${index}" class="file-section" open>
56
- <summary class="file-summary">
57
- <span class="fs-path">${esc(skel.file)}</span>
58
- <span class="fs-meta">${esc(skel.language)} &middot; ${skel.symbolCount} symbols &middot; <time>${esc(skel.generatedAt)}</time></span>
59
- </summary>
60
- <div class="fs-body"><div class="tree">${body}</div></div>
61
- </details>`;
62
- }
63
- export function renderCombinedHtml(skeletons) {
64
- const sections = skeletons.map((s, i) => renderFileSection(s, i)).join("\n");
65
- const totalSymbols = skeletons.reduce((n, s) => n + s.symbolCount, 0);
66
- const generatedAt = new Date().toISOString();
67
- // Compact per-file data for client-side search and tree rendering.
68
- const fileData = JSON.stringify(skeletons.map((s, i) => ({
69
- id: i,
70
- file: s.file,
71
- lang: s.language,
72
- n: s.symbolCount,
73
- syms: collectSymbolNames(s.symbols).join(" "),
74
- })));
75
- return `<!doctype html>
76
- <html lang="en">
77
- <head>
78
- <meta charset="utf-8">
79
- <meta name="viewport" content="width=device-width,initial-scale=1">
80
- <title>Codebase Skeleton (${skeletons.length} files)</title>
81
- <style>
82
- :root{color-scheme:light dark;--bg:#f8fafc;--bg2:#fff;--fg:#0f172a;--fg2:#475569;--bdr:#e2e8f0;--hover:#f1f5f9;--sb-bg:#fff;--sb-w:260px;--accent:#6366f1;}
83
- @media(prefers-color-scheme:dark){:root{--bg:#0b1120;--bg2:#111827;--fg:#e2e8f0;--fg2:#94a3b8;--bdr:#1f2937;--hover:#111827;--sb-bg:#0f172a;}}
84
- *{box-sizing:border-box;margin:0;padding:0;}
85
- body{font:13px/1.5 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;background:var(--bg);color:var(--fg);display:flex;flex-direction:column;height:100vh;overflow:hidden;}
86
- /* topbar */
87
- .topbar{display:flex;align-items:center;gap:12px;padding:8px 16px;background:var(--bg2);border-bottom:1px solid var(--bdr);flex-shrink:0;flex-wrap:wrap;}
88
- .topbar-title{font-weight:700;font-size:14px;}
89
- .topbar-meta{font-size:12px;color:var(--fg2);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
90
- .topbar-actions{display:flex;gap:6px;flex-shrink:0;}
91
- button{font:inherit;cursor:pointer;border:1px solid var(--bdr);background:transparent;color:inherit;border-radius:8px;padding:3px 10px;font-size:12px;}
92
- button:hover{background:var(--hover);}
93
- /* layout */
94
- .layout{display:flex;flex:1;min-height:0;}
95
- /* sidebar */
96
- .sidebar{width:var(--sb-w);flex-shrink:0;background:var(--sb-bg);border-right:1px solid var(--bdr);display:flex;flex-direction:column;overflow:hidden;}
97
- .search-wrap{padding:8px;border-bottom:1px solid var(--bdr);}
98
- #search{width:100%;font:inherit;font-size:12px;padding:5px 8px;border:1px solid var(--bdr);border-radius:8px;background:var(--bg);color:var(--fg);outline:none;}
99
- #search:focus{border-color:var(--accent);}
100
- .nav-tree{flex:1;overflow-y:auto;padding:6px 4px;}
101
- /* nav tree nodes */
102
- .dir-node{margin:1px 0;}
103
- .dir-node>summary{list-style:none;cursor:pointer;padding:3px 6px;border-radius:6px;font-size:12px;font-weight:600;color:var(--fg2);display:flex;align-items:center;gap:4px;user-select:none;}
104
- .dir-node>summary::-webkit-details-marker{display:none;}
105
- .dir-node>summary::before{content:"\\25B8";font-size:10px;opacity:.5;transition:transform .12s;flex-shrink:0;}
106
- .dir-node[open]>summary::before{transform:rotate(90deg);}
107
- .dir-node>summary:hover{background:var(--hover);}
108
- .dir-children{padding-left:12px;}
109
- a.file-link{display:flex;align-items:center;justify-content:space-between;padding:3px 8px;border-radius:6px;text-decoration:none;color:var(--fg);font-size:12px;cursor:pointer;gap:4px;}
110
- a.file-link:hover{background:var(--hover);}
111
- a.file-link.active{background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent);}
112
- .fname{font-family:ui-monospace,monospace;font-size:11px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
113
- .fmeta{font-size:10px;color:var(--fg2);flex-shrink:0;}
114
- /* main panel */
115
- .main-panel{flex:1;overflow-y:auto;padding:16px;}
116
- /* file sections */
117
- details.file-section{border:1px solid var(--bdr);border-radius:12px;margin-bottom:14px;background:var(--bg2);}
118
- summary.file-summary{list-style:none;cursor:pointer;padding:10px 14px;display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;border-radius:12px;}
119
- summary.file-summary::-webkit-details-marker{display:none;}
120
- summary.file-summary::before{content:"\\25B8";opacity:.4;transition:transform .15s;flex-shrink:0;}
121
- details.file-section[open]>summary.file-summary::before{transform:rotate(90deg);}
122
- summary.file-summary:hover{background:var(--hover);}
123
- .fs-path{font-family:ui-monospace,monospace;font-weight:700;font-size:13px;}
124
- .fs-meta{font-size:11px;color:var(--fg2);margin-left:auto;}
125
- .fs-body{padding:8px 14px 14px;}
126
- /* symbol tree (reused styles) */
127
- .tree{display:flex;flex-direction:column;gap:4px;}
128
- details.node{border:1px solid var(--bdr);border-radius:10px;padding:2px 4px;}
129
- summary{list-style:none;cursor:pointer;padding:6px 8px;border-radius:8px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
130
- summary::-webkit-details-marker{display:none;}
131
- summary::before{content:"\\25B8";opacity:.5;transition:transform .15s;}
132
- details[open]>summary::before{transform:rotate(90deg);}
133
- .leaf{padding:6px 8px 6px 24px;border-radius:8px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
134
- summary:hover,.leaf:hover{background:var(--hover);}
135
- .children{margin:2px 0 6px 18px;padding-left:10px;border-left:2px solid #e2e8f033;display:flex;flex-direction:column;gap:4px;}
136
- .badge{font-size:11px;font-weight:600;padding:1px 7px;border-radius:999px;text-transform:uppercase;letter-spacing:.03em;}
137
- .name{font-family:ui-monospace,monospace;font-weight:600;}
138
- .vis{font-size:10px;padding:1px 6px;border-radius:6px;}
139
- .vis.priv{background:#ef44441a;color:#ef4444;}
140
- .vis.exp{background:#22c55e1a;color:#16a34a;}
141
- .sig{font-family:ui-monospace,monospace;font-size:12px;background:var(--hover);padding:1px 6px;border-radius:6px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
142
- .lines{font-size:11px;opacity:.55;margin-left:auto;font-family:ui-monospace,monospace;}
143
- .doc{font-size:12px;opacity:.8;margin:2px 0 6px 28px;white-space:pre-wrap;font-style:italic;}
144
- .empty{opacity:.6;}
145
- .no-match{padding:40px;text-align:center;color:var(--fg2);font-size:13px;}
146
- </style>
147
- </head>
148
- <body>
149
- <header class="topbar">
150
- <span class="topbar-title">Codebase Skeleton</span>
151
- <span class="topbar-meta">${skeletons.length} files &middot; ${totalSymbols} symbols &middot; ${esc(generatedAt)}</span>
152
- <div class="topbar-actions">
153
- <button id="btn-expand">Expand all</button>
154
- <button id="btn-collapse">Collapse all</button>
155
- </div>
156
- </header>
157
- <div class="layout">
158
- <nav class="sidebar">
159
- <div class="search-wrap">
160
- <input id="search" type="search" placeholder="Search files or symbols…" autocomplete="off" spellcheck="false">
161
- </div>
162
- <div id="nav-tree" class="nav-tree"></div>
163
- </nav>
164
- <main id="main" class="main-panel">
165
- ${sections}
166
- <div id="no-match" class="no-match" style="display:none">No matching files or symbols.</div>
167
- </main>
168
- </div>
169
- <script>
170
- (function(){
171
- const FILES=${fileData};
172
-
173
- // ── folder tree ──────────────────────────────────────────────────────────────
174
- function buildTreeData(files){
175
- const root={dirs:{},files:[]};
176
- for(const f of files){
177
- const parts=f.file.split('/');
178
- let node=root;
179
- for(let i=0;i<parts.length-1;i++){
180
- if(!node.dirs[parts[i]])node.dirs[parts[i]]={dirs:{},files:[]};
181
- node=node.dirs[parts[i]];
182
- }
183
- node.files.push(f);
184
- }
185
- return root;
186
- }
187
-
188
- function e(s){return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}
189
-
190
- const linkMap=new Map(); // id -> <a>
191
- function renderTreeNode(node,container){
192
- const dirs=Object.entries(node.dirs).sort(([a],[b])=>a.localeCompare(b));
193
- for(const[name,child]of dirs){
194
- const det=document.createElement('details');
195
- det.className='dir-node';
196
- det.open=true;
197
- const sum=document.createElement('summary');
198
- sum.textContent=name;
199
- det.appendChild(sum);
200
- const inner=document.createElement('div');
201
- inner.className='dir-children';
202
- renderTreeNode(child,inner);
203
- det.appendChild(inner);
204
- container.appendChild(det);
205
- }
206
- for(const f of node.files){
207
- const a=document.createElement('a');
208
- a.href='#file-'+f.id;
209
- a.className='file-link';
210
- a.dataset.id=String(f.id);
211
- const fname=f.file.split('/').pop()||f.file;
212
- a.innerHTML='<span class="fname">'+e(fname)+'</span><span class="fmeta">'+f.n+'</span>';
213
- container.appendChild(a);
214
- linkMap.set(f.id,a);
215
- }
216
- }
217
-
218
- const navTree=document.getElementById('nav-tree');
219
- renderTreeNode(buildTreeData(FILES),navTree);
220
-
221
- // ── search ───────────────────────────────────────────────────────────────────
222
- const searchEl=document.getElementById('search');
223
- const mainEl=document.getElementById('main');
224
- const noMatch=document.getElementById('no-match');
225
- const sections=Array.from(document.querySelectorAll('details.file-section'));
226
-
227
- searchEl.addEventListener('input',applyFilter);
228
- function applyFilter(){
229
- const q=searchEl.value.trim().toLowerCase();
230
- let visCount=0;
231
- FILES.forEach(f=>{
232
- const sec=document.getElementById('file-'+f.id);
233
- if(!sec)return;
234
- const match=!q||f.file.toLowerCase().includes(q)||f.syms.toLowerCase().includes(q);
235
- sec.style.display=match?'':'none';
236
- const link=linkMap.get(f.id);
237
- if(link)link.style.display=match?'':'none';
238
- if(match)visCount++;
239
- });
240
- noMatch.style.display=visCount===0&&q?'':'none';
241
- }
242
-
243
- // ── expand / collapse ────────────────────────────────────────────────────────
244
- document.getElementById('btn-expand').addEventListener('click',()=>{
245
- document.querySelectorAll('details').forEach(d=>d.open=true);
246
- });
247
- document.getElementById('btn-collapse').addEventListener('click',()=>{
248
- document.querySelectorAll('details').forEach(d=>d.open=false);
249
- });
250
-
251
- // ── active sidebar link on scroll ────────────────────────────────────────────
252
- const io=new IntersectionObserver(entries=>{
253
- for(const en of entries){
254
- if(en.isIntersecting){
255
- const idx=parseInt(en.target.id.replace('file-',''),10);
256
- linkMap.forEach((a,id)=>a.classList.toggle('active',id===idx));
257
- }
258
- }
259
- },{root:mainEl,threshold:0.15});
260
- sections.forEach(s=>io.observe(s));
261
- })();
262
- </script>
263
- </body>
264
- </html>`;
265
- }
266
- export function renderHtml(skel) {
267
- const body = skel.symbols.length > 0
268
- ? skel.symbols.map(renderSymbol).join("")
269
- : `<p class="empty">No top-level symbols found.</p>`;
270
- return `<!doctype html>
271
- <html lang="en">
272
- <head>
273
- <meta charset="utf-8">
274
- <meta name="viewport" content="width=device-width, initial-scale=1">
275
- <title>Skeleton — ${esc(skel.file)}</title>
276
- <style>
277
- :root { color-scheme: light dark; }
278
- * { box-sizing: border-box; }
279
- body { font: 14px/1.5 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
280
- margin: 0; padding: 24px; background: #f8fafc; color: #0f172a; }
281
- @media (prefers-color-scheme: dark) { body { background:#0b1120; color:#e2e8f0; } header.meta{background:#111827;border-color:#1f2937;} .node{border-color:#1f2937;} summary:hover,.leaf:hover{background:#111827;} .sig{background:#111827;color:#93c5fd;} .doc{color:#94a3b8;} }
282
- header.meta { background:#fff; border:1px solid #e2e8f0; border-radius:12px; padding:16px 20px; margin-bottom:20px; }
283
- header.meta h1 { font-size:16px; margin:0 0 6px; font-family:ui-monospace,monospace; }
284
- header.meta .sub { font-size:12px; opacity:.7; }
285
- .toolbar { margin:14px 0; display:flex; gap:8px; }
286
- button { font:inherit; cursor:pointer; border:1px solid #cbd5e1; background:transparent; color:inherit;
287
- border-radius:8px; padding:4px 10px; }
288
- .tree { display:flex; flex-direction:column; gap:4px; }
289
- details.node { border:1px solid #e2e8f0; border-radius:10px; padding:2px 4px; }
290
- summary { list-style:none; cursor:pointer; padding:6px 8px; border-radius:8px; display:flex; align-items:center;
291
- gap:8px; flex-wrap:wrap; }
292
- summary::-webkit-details-marker { display:none; }
293
- summary::before { content:"\\25B8"; opacity:.5; transition:transform .15s; }
294
- details[open] > summary::before { transform:rotate(90deg); }
295
- .leaf { padding:6px 8px 6px 24px; border-radius:8px; display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
296
- summary:hover,.leaf:hover { background:#f1f5f9; }
297
- .children { margin:2px 0 6px 18px; padding-left:10px; border-left:2px solid #e2e8f033; display:flex;
298
- flex-direction:column; gap:4px; }
299
- .badge { font-size:11px; font-weight:600; padding:1px 7px; border-radius:999px; text-transform:uppercase;
300
- letter-spacing:.03em; }
301
- .name { font-family:ui-monospace,monospace; font-weight:600; }
302
- .vis { font-size:10px; padding:1px 6px; border-radius:6px; }
303
- .vis.priv { background:#ef44441a; color:#ef4444; }
304
- .vis.exp { background:#22c55e1a; color:#16a34a; }
305
- .sig { font-family:ui-monospace,monospace; font-size:12px; background:#f1f5f9; padding:1px 6px; border-radius:6px;
306
- max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
307
- .lines { font-size:11px; opacity:.55; margin-left:auto; font-family:ui-monospace,monospace; }
308
- .doc { font-size:12px; opacity:.8; margin:2px 0 6px 28px; white-space:pre-wrap; font-style:italic; }
309
- .empty { opacity:.6; }
310
- </style>
311
- </head>
312
- <body>
313
- <header class="meta">
314
- <h1>${esc(skel.file)}</h1>
315
- <div class="sub">${esc(skel.language)} &middot; ${skel.symbolCount} symbols &middot; parser: ${esc(skel.parser.grammar)} &middot; ${esc(skel.generatedAt)}</div>
316
- </header>
317
- <div class="toolbar">
318
- <button onclick="document.querySelectorAll('details').forEach(d=>d.open=true)">Expand all</button>
319
- <button onclick="document.querySelectorAll('details').forEach(d=>d.open=false)">Collapse all</button>
320
- </div>
321
- <div class="tree">
322
- ${body}
323
- </div>
324
- </body>
325
- </html>`;
326
- }