codebase-onboarder 0.5.0 → 0.7.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 (448) hide show
  1. package/README.md +196 -47
  2. package/bin/build-if-source.js +23 -0
  3. package/cli/commands.d.ts +26 -0
  4. package/cli/commands.js +836 -811
  5. package/cli/commands.js.map +1 -0
  6. package/cli/explorer/advanced.d.ts +14 -0
  7. package/cli/explorer/advanced.js +449 -0
  8. package/cli/explorer/advanced.js.map +1 -0
  9. package/cli/explorer/app.d.ts +1 -0
  10. package/cli/explorer/app.js +396 -229
  11. package/cli/explorer/app.js.map +1 -0
  12. package/cli/explorer/assistant.d.ts +9 -0
  13. package/cli/explorer/assistant.js +58 -0
  14. package/cli/explorer/assistant.js.map +1 -0
  15. package/cli/explorer/commands.d.ts +17 -0
  16. package/cli/explorer/commands.js +400 -162
  17. package/cli/explorer/commands.js.map +1 -0
  18. package/cli/explorer/featureViews.d.ts +124 -0
  19. package/cli/explorer/featureViews.js +179 -0
  20. package/cli/explorer/featureViews.js.map +1 -0
  21. package/cli/explorer/github.d.ts +21 -0
  22. package/cli/explorer/github.js +73 -0
  23. package/cli/explorer/github.js.map +1 -0
  24. package/cli/explorer/graphs.d.ts +7 -0
  25. package/cli/explorer/graphs.js +173 -0
  26. package/cli/explorer/graphs.js.map +1 -0
  27. package/cli/explorer/picker.d.ts +22 -0
  28. package/cli/explorer/picker.js +150 -0
  29. package/cli/explorer/picker.js.map +1 -0
  30. package/cli/explorer/report.d.ts +85 -0
  31. package/cli/explorer/report.js +60 -0
  32. package/cli/explorer/report.js.map +1 -0
  33. package/cli/explorer/session.d.ts +449 -0
  34. package/cli/explorer/session.js +184 -95
  35. package/cli/explorer/session.js.map +1 -0
  36. package/cli/explorer/views.d.ts +19 -0
  37. package/cli/explorer/views.js +496 -412
  38. package/cli/explorer/views.js.map +1 -0
  39. package/cli/explorer/wrap.d.ts +1 -0
  40. package/cli/explorer/wrap.js +33 -0
  41. package/cli/explorer/wrap.js.map +1 -0
  42. package/cli/main.d.ts +1 -0
  43. package/cli/main.js +235 -138
  44. package/cli/main.js.map +1 -0
  45. package/cli/prompt.d.ts +5 -0
  46. package/cli/prompt.js +84 -80
  47. package/cli/prompt.js.map +1 -0
  48. package/cli/scanOptions.d.ts +2 -0
  49. package/cli/scanOptions.js +11 -0
  50. package/cli/scanOptions.js.map +1 -0
  51. package/cli/ui.d.ts +33 -0
  52. package/cli/ui.js +55 -35
  53. package/cli/ui.js.map +1 -0
  54. package/cli/wizard.d.ts +187 -0
  55. package/cli/wizard.js +304 -284
  56. package/cli/wizard.js.map +1 -0
  57. package/package.json +15 -4
  58. package/public/app.d.ts +1 -0
  59. package/public/app.js +1057 -1009
  60. package/public/app.js.map +1 -0
  61. package/public/browser.d.ts +68 -0
  62. package/public/browser.js +2 -0
  63. package/public/browser.js.map +1 -0
  64. package/public/index.html +30 -13
  65. package/public/js/about.d.ts +6 -0
  66. package/public/js/about.js +165 -172
  67. package/public/js/about.js.map +1 -0
  68. package/public/js/aiDraft.d.ts +3 -0
  69. package/public/js/aiDraft.js +116 -124
  70. package/public/js/aiDraft.js.map +1 -0
  71. package/public/js/analysisPanel.d.ts +7 -0
  72. package/public/js/analysisPanel.js +166 -166
  73. package/public/js/analysisPanel.js.map +1 -0
  74. package/public/js/analysisReport.d.ts +38 -0
  75. package/public/js/analysisReport.js +105 -110
  76. package/public/js/analysisReport.js.map +1 -0
  77. package/public/js/api.d.ts +26 -0
  78. package/public/js/api.js +176 -167
  79. package/public/js/api.js.map +1 -0
  80. package/public/js/atlas.d.ts +6 -0
  81. package/public/js/atlas.js +50 -58
  82. package/public/js/atlas.js.map +1 -0
  83. package/public/js/blameView.d.ts +2 -0
  84. package/public/js/blameView.js +36 -37
  85. package/public/js/blameView.js.map +1 -0
  86. package/public/js/codeTab.d.ts +3 -0
  87. package/public/js/codeTab.js +175 -180
  88. package/public/js/codeTab.js.map +1 -0
  89. package/public/js/codeViewer.d.ts +5 -0
  90. package/public/js/codeViewer.js +162 -150
  91. package/public/js/codeViewer.js.map +1 -0
  92. package/public/js/components/FileChip.d.ts +9 -0
  93. package/public/js/components/FileChip.js +45 -49
  94. package/public/js/components/FileChip.js.map +1 -0
  95. package/public/js/components/MetricSparkline.d.ts +7 -0
  96. package/public/js/components/MetricSparkline.js +35 -44
  97. package/public/js/components/MetricSparkline.js.map +1 -0
  98. package/public/js/components/RiskBadge.d.ts +9 -0
  99. package/public/js/components/RiskBadge.js +55 -63
  100. package/public/js/components/RiskBadge.js.map +1 -0
  101. package/public/js/deepAnalysisView.d.ts +99 -0
  102. package/public/js/deepAnalysisView.js +282 -302
  103. package/public/js/deepAnalysisView.js.map +1 -0
  104. package/public/js/diagramPane.d.ts +8 -0
  105. package/public/js/diagramPane.js +133 -135
  106. package/public/js/diagramPane.js.map +1 -0
  107. package/public/js/diffView.d.ts +6 -0
  108. package/public/js/diffView.js +222 -209
  109. package/public/js/diffView.js.map +1 -0
  110. package/public/js/docsView.d.ts +2 -0
  111. package/public/js/docsView.js +441 -442
  112. package/public/js/docsView.js.map +1 -0
  113. package/public/js/dom.d.ts +189 -0
  114. package/public/js/dom.js +5 -0
  115. package/public/js/dom.js.map +1 -0
  116. package/public/js/fileSourceBrowser.d.ts +5 -0
  117. package/public/js/fileSourceBrowser.js +33 -41
  118. package/public/js/fileSourceBrowser.js.map +1 -0
  119. package/public/js/flameGraph.d.ts +5 -0
  120. package/public/js/flameGraph.js +62 -72
  121. package/public/js/flameGraph.js.map +1 -0
  122. package/public/js/forceGraph.d.ts +10 -0
  123. package/public/js/forceGraph.js +581 -556
  124. package/public/js/forceGraph.js.map +1 -0
  125. package/public/js/heatmap.d.ts +4 -0
  126. package/public/js/heatmap.js +142 -164
  127. package/public/js/heatmap.js.map +1 -0
  128. package/public/js/highlight.d.ts +2 -0
  129. package/public/js/highlight.js +116 -107
  130. package/public/js/highlight.js.map +1 -0
  131. package/public/js/html.d.ts +2 -0
  132. package/public/js/html.js +14 -44
  133. package/public/js/html.js.map +1 -0
  134. package/public/js/insightsView.d.ts +5 -0
  135. package/public/js/insightsView.js +93 -111
  136. package/public/js/insightsView.js.map +1 -0
  137. package/public/js/inspector.d.ts +37 -0
  138. package/public/js/inspector.js +416 -445
  139. package/public/js/inspector.js.map +1 -0
  140. package/public/js/llm.d.ts +113 -0
  141. package/public/js/llm.js +233 -272
  142. package/public/js/llm.js.map +1 -0
  143. package/public/js/mapView.d.ts +3 -0
  144. package/public/js/mapView.js +121 -120
  145. package/public/js/mapView.js.map +1 -0
  146. package/public/js/markdown.d.ts +3 -0
  147. package/public/js/markdown.js +84 -91
  148. package/public/js/markdown.js.map +1 -0
  149. package/public/js/mindmap.d.ts +32 -0
  150. package/public/js/mindmap.js +244 -259
  151. package/public/js/mindmap.js.map +1 -0
  152. package/public/js/mobilePanels.d.ts +5 -0
  153. package/public/js/mobilePanels.js +50 -0
  154. package/public/js/mobilePanels.js.map +1 -0
  155. package/public/js/repoFiles.d.ts +12 -0
  156. package/public/js/repoFiles.js +28 -27
  157. package/public/js/repoFiles.js.map +1 -0
  158. package/public/js/reviewView.d.ts +28 -0
  159. package/public/js/reviewView.js +256 -0
  160. package/public/js/reviewView.js.map +1 -0
  161. package/public/js/sbomView.d.ts +3 -0
  162. package/public/js/sbomView.js +59 -67
  163. package/public/js/sbomView.js.map +1 -0
  164. package/public/js/scanCache.d.ts +16 -0
  165. package/public/js/scanCache.js +67 -65
  166. package/public/js/scanCache.js.map +1 -0
  167. package/public/js/search.d.ts +7 -0
  168. package/public/js/search.js +868 -800
  169. package/public/js/search.js.map +1 -0
  170. package/public/js/searchLocal.d.ts +42 -0
  171. package/public/js/searchLocal.js +87 -0
  172. package/public/js/searchLocal.js.map +1 -0
  173. package/public/js/serverSettings.d.ts +5 -0
  174. package/public/js/serverSettings.js +153 -164
  175. package/public/js/serverSettings.js.map +1 -0
  176. package/public/js/state.d.ts +798 -0
  177. package/public/js/state.js +114 -122
  178. package/public/js/state.js.map +1 -0
  179. package/public/js/tour.d.ts +6 -0
  180. package/public/js/tour.js +5 -7
  181. package/public/js/tour.js.map +1 -0
  182. package/public/js/transitions.d.ts +2 -0
  183. package/public/js/transitions.js +9 -10
  184. package/public/js/transitions.js.map +1 -0
  185. package/public/js/tree.d.ts +12 -0
  186. package/public/js/tree.js +157 -154
  187. package/public/js/tree.js.map +1 -0
  188. package/public/js/workflowsView.d.ts +3 -0
  189. package/public/js/workflowsView.js +15 -22
  190. package/public/js/workflowsView.js.map +1 -0
  191. package/public/search.css +495 -0
  192. package/public/styles.css +163 -346
  193. package/public/workbench.css +166 -0
  194. package/server/apiAuth.d.ts +3 -0
  195. package/server/apiAuth.js +18 -20
  196. package/server/apiAuth.js.map +1 -0
  197. package/server/apiDiff.d.ts +2 -0
  198. package/server/apiDiff.js +20 -18
  199. package/server/apiDiff.js.map +1 -0
  200. package/server/apiDocs.d.ts +2 -0
  201. package/server/apiDocs.js +38 -40
  202. package/server/apiDocs.js.map +1 -0
  203. package/server/apiFile.d.ts +1 -0
  204. package/server/apiFile.js +14 -17
  205. package/server/apiFile.js.map +1 -0
  206. package/server/apiGitBlame.d.ts +2 -0
  207. package/server/apiGitBlame.js +50 -51
  208. package/server/apiGitBlame.js.map +1 -0
  209. package/server/apiMcp.d.ts +4 -0
  210. package/server/apiMcp.js +64 -66
  211. package/server/apiMcp.js.map +1 -0
  212. package/server/apiReview.d.ts +2 -0
  213. package/server/apiReview.js +45 -0
  214. package/server/apiReview.js.map +1 -0
  215. package/server/apiScan.d.ts +5 -0
  216. package/server/apiScan.js +90 -71
  217. package/server/apiScan.js.map +1 -0
  218. package/server/apiSearch.d.ts +33 -0
  219. package/server/apiSearch.js +184 -200
  220. package/server/apiSearch.js.map +1 -0
  221. package/server/apiSettings.d.ts +4 -0
  222. package/server/apiSettings.js +84 -85
  223. package/server/apiSettings.js.map +1 -0
  224. package/server/apiTools.d.ts +3 -0
  225. package/server/apiTools.js +55 -56
  226. package/server/apiTools.js.map +1 -0
  227. package/server/auth.d.ts +5 -0
  228. package/server/auth.js +54 -51
  229. package/server/auth.js.map +1 -0
  230. package/server/config.d.ts +42 -0
  231. package/server/config.js +189 -194
  232. package/server/config.js.map +1 -0
  233. package/server/daemon.d.ts +12 -0
  234. package/server/daemon.js +124 -114
  235. package/server/daemon.js.map +1 -0
  236. package/server/fileSourceNode.d.ts +2 -0
  237. package/server/fileSourceNode.js +34 -36
  238. package/server/fileSourceNode.js.map +1 -0
  239. package/server/gitClone.d.ts +9 -0
  240. package/server/gitClone.js +59 -61
  241. package/server/gitClone.js.map +1 -0
  242. package/server/gitDiff.d.ts +36 -0
  243. package/server/gitDiff.js +271 -169
  244. package/server/gitDiff.js.map +1 -0
  245. package/server/gitHistory.d.ts +12 -0
  246. package/server/gitHistory.js +80 -80
  247. package/server/gitHistory.js.map +1 -0
  248. package/server/gitRemote.d.ts +12 -0
  249. package/server/gitRemote.js +60 -0
  250. package/server/gitRemote.js.map +1 -0
  251. package/server/htmlText.d.ts +4 -0
  252. package/server/htmlText.js +16 -23
  253. package/server/htmlText.js.map +1 -0
  254. package/server/http.d.ts +5 -0
  255. package/server/http.js +27 -30
  256. package/server/http.js.map +1 -0
  257. package/server/httpGuards.d.ts +2 -0
  258. package/server/httpGuards.js +47 -43
  259. package/server/httpGuards.js.map +1 -0
  260. package/server/https.d.ts +34 -0
  261. package/server/https.js +121 -111
  262. package/server/https.js.map +1 -0
  263. package/server/index.d.ts +40 -0
  264. package/server/index.js +139 -147
  265. package/server/index.js.map +1 -0
  266. package/server/layout.d.ts +26 -0
  267. package/server/layout.js +59 -37
  268. package/server/layout.js.map +1 -0
  269. package/server/llmProxy.d.ts +3 -0
  270. package/server/llmProxy.js +137 -135
  271. package/server/llmProxy.js.map +1 -0
  272. package/server/logger.d.ts +38 -0
  273. package/server/logger.js +198 -211
  274. package/server/logger.js.map +1 -0
  275. package/server/mcp/analysis.d.ts +29 -0
  276. package/server/mcp/analysis.js +99 -120
  277. package/server/mcp/analysis.js.map +1 -0
  278. package/server/mcp/http.d.ts +9 -0
  279. package/server/mcp/http.js +128 -137
  280. package/server/mcp/http.js.map +1 -0
  281. package/server/mcp/runner.d.ts +68 -0
  282. package/server/mcp/runner.js +208 -218
  283. package/server/mcp/runner.js.map +1 -0
  284. package/server/mcp/server.d.ts +29 -0
  285. package/server/mcp/server.js +166 -179
  286. package/server/mcp/server.js.map +1 -0
  287. package/server/mcp/standalone.d.ts +1 -0
  288. package/server/mcp/standalone.js +8 -10
  289. package/server/mcp/standalone.js.map +1 -0
  290. package/server/mcp/tools.d.ts +2020 -0
  291. package/server/mcp/tools.js +523 -574
  292. package/server/mcp/tools.js.map +1 -0
  293. package/server/paths.d.ts +3 -0
  294. package/server/paths.js +17 -15
  295. package/server/paths.js.map +1 -0
  296. package/server/pidfile.d.ts +9 -0
  297. package/server/pidfile.js +43 -45
  298. package/server/pidfile.js.map +1 -0
  299. package/server/review.d.ts +5 -0
  300. package/server/review.js +35 -0
  301. package/server/review.js.map +1 -0
  302. package/server/router.d.ts +33 -0
  303. package/server/router.js +191 -197
  304. package/server/router.js.map +1 -0
  305. package/server/scanRequest.d.ts +3 -0
  306. package/server/scanRequest.js +36 -0
  307. package/server/scanRequest.js.map +1 -0
  308. package/server/searchIndex.d.ts +17 -0
  309. package/server/searchIndex.js +83 -80
  310. package/server/searchIndex.js.map +1 -0
  311. package/server/sessions.d.ts +14 -0
  312. package/server/sessions.js +62 -70
  313. package/server/sessions.js.map +1 -0
  314. package/server/startup.d.ts +118 -0
  315. package/server/startup.js +143 -148
  316. package/server/startup.js.map +1 -0
  317. package/server/static.d.ts +6 -0
  318. package/server/static.js +28 -31
  319. package/server/static.js.map +1 -0
  320. package/server/tools/install.d.ts +4 -0
  321. package/server/tools/install.js +176 -185
  322. package/server/tools/install.js.map +1 -0
  323. package/server/tools/parse.d.ts +8 -0
  324. package/server/tools/parse.js +112 -114
  325. package/server/tools/parse.js.map +1 -0
  326. package/server/tools/platform.d.ts +9 -0
  327. package/server/tools/platform.js +49 -47
  328. package/server/tools/platform.js.map +1 -0
  329. package/server/tools/registry.d.ts +137 -0
  330. package/server/tools/registry.js +173 -172
  331. package/server/tools/registry.js.map +1 -0
  332. package/server/tools/scan.d.ts +34 -0
  333. package/server/tools/scan.js +89 -98
  334. package/server/tools/scan.js.map +1 -0
  335. package/server/tools.d.ts +34 -0
  336. package/server/tools.js +94 -107
  337. package/server/tools.js.map +1 -0
  338. package/server/tunnel.d.ts +29 -0
  339. package/server/tunnel.js +61 -66
  340. package/server/tunnel.js.map +1 -0
  341. package/shared/analyzer/docs.d.ts +16 -0
  342. package/shared/analyzer/docs.js +99 -93
  343. package/shared/analyzer/docs.js.map +1 -0
  344. package/shared/analyzer/explainLocal.d.ts +4 -0
  345. package/shared/analyzer/explainLocal.js +122 -142
  346. package/shared/analyzer/explainLocal.js.map +1 -0
  347. package/shared/analyzer/github.d.ts +37 -0
  348. package/shared/analyzer/github.js +79 -0
  349. package/shared/analyzer/github.js.map +1 -0
  350. package/shared/analyzer/graph.d.ts +41 -0
  351. package/shared/analyzer/graph.js +393 -400
  352. package/shared/analyzer/graph.js.map +1 -0
  353. package/shared/analyzer/health.d.ts +33 -0
  354. package/shared/analyzer/health.js +197 -193
  355. package/shared/analyzer/health.js.map +1 -0
  356. package/shared/analyzer/history.d.ts +29 -0
  357. package/shared/analyzer/history.js +110 -111
  358. package/shared/analyzer/history.js.map +1 -0
  359. package/shared/analyzer/jsonConfig.d.ts +2 -0
  360. package/shared/analyzer/jsonConfig.js +61 -0
  361. package/shared/analyzer/jsonConfig.js.map +1 -0
  362. package/shared/analyzer/languages/csharp.d.ts +26 -0
  363. package/shared/analyzer/languages/csharp.js +83 -88
  364. package/shared/analyzer/languages/csharp.js.map +1 -0
  365. package/shared/analyzer/languages/generic.d.ts +23 -0
  366. package/shared/analyzer/languages/generic.js +94 -105
  367. package/shared/analyzer/languages/generic.js.map +1 -0
  368. package/shared/analyzer/languages/go.d.ts +24 -0
  369. package/shared/analyzer/languages/go.js +45 -54
  370. package/shared/analyzer/languages/go.js.map +1 -0
  371. package/shared/analyzer/languages/index.d.ts +6 -0
  372. package/shared/analyzer/languages/index.js +19 -20
  373. package/shared/analyzer/languages/index.js.map +1 -0
  374. package/shared/analyzer/languages/java.d.ts +20 -0
  375. package/shared/analyzer/languages/java.js +73 -78
  376. package/shared/analyzer/languages/java.js.map +1 -0
  377. package/shared/analyzer/languages/javascript.d.ts +12 -0
  378. package/shared/analyzer/languages/javascript.js +258 -209
  379. package/shared/analyzer/languages/javascript.js.map +1 -0
  380. package/shared/analyzer/languages/python.d.ts +23 -0
  381. package/shared/analyzer/languages/python.js +92 -100
  382. package/shared/analyzer/languages/python.js.map +1 -0
  383. package/shared/analyzer/languages/rust.d.ts +17 -0
  384. package/shared/analyzer/languages/rust.js +96 -98
  385. package/shared/analyzer/languages/rust.js.map +1 -0
  386. package/shared/analyzer/languages/typescript.d.ts +11 -0
  387. package/shared/analyzer/languages/typescript.js +117 -116
  388. package/shared/analyzer/languages/typescript.js.map +1 -0
  389. package/shared/analyzer/licenses.d.ts +18 -0
  390. package/shared/analyzer/licenses.js +130 -133
  391. package/shared/analyzer/licenses.js.map +1 -0
  392. package/shared/analyzer/metrics.d.ts +20 -0
  393. package/shared/analyzer/metrics.js +112 -104
  394. package/shared/analyzer/metrics.js.map +1 -0
  395. package/shared/analyzer/pathUtil.d.ts +10 -0
  396. package/shared/analyzer/pathUtil.js +29 -35
  397. package/shared/analyzer/pathUtil.js.map +1 -0
  398. package/shared/analyzer/patterns.d.ts +11 -0
  399. package/shared/analyzer/patterns.js +231 -253
  400. package/shared/analyzer/patterns.js.map +1 -0
  401. package/shared/analyzer/scan.d.ts +62 -0
  402. package/shared/analyzer/scan.js +451 -442
  403. package/shared/analyzer/scan.js.map +1 -0
  404. package/shared/analyzer/scanControl.d.ts +11 -0
  405. package/shared/analyzer/scanControl.js +62 -0
  406. package/shared/analyzer/scanControl.js.map +1 -0
  407. package/shared/analyzer/security.d.ts +18 -0
  408. package/shared/analyzer/security.js +159 -159
  409. package/shared/analyzer/security.js.map +1 -0
  410. package/shared/analyzer/services.d.ts +5 -0
  411. package/shared/analyzer/services.js +141 -138
  412. package/shared/analyzer/services.js.map +1 -0
  413. package/shared/analyzer/stack.d.ts +6 -0
  414. package/shared/analyzer/stack.js +134 -141
  415. package/shared/analyzer/stack.js.map +1 -0
  416. package/shared/analyzer/tour.d.ts +2 -0
  417. package/shared/analyzer/tour.js +45 -53
  418. package/shared/analyzer/tour.js.map +1 -0
  419. package/shared/analyzer/util.d.ts +8 -0
  420. package/shared/analyzer/util.js +130 -76
  421. package/shared/analyzer/util.js.map +1 -0
  422. package/shared/analyzer/workflows.d.ts +8 -0
  423. package/shared/analyzer/workflows.js +139 -134
  424. package/shared/analyzer/workflows.js.map +1 -0
  425. package/shared/contracts.d.ts +250 -0
  426. package/shared/contracts.js +2 -0
  427. package/shared/contracts.js.map +1 -0
  428. package/shared/diagram/aiFacts.d.ts +35 -0
  429. package/shared/diagram/aiFacts.js +102 -105
  430. package/shared/diagram/aiFacts.js.map +1 -0
  431. package/shared/diagram/aiMermaid.d.ts +5 -0
  432. package/shared/diagram/aiMermaid.js +46 -45
  433. package/shared/diagram/aiMermaid.js.map +1 -0
  434. package/shared/diagram/atlas.d.ts +16 -0
  435. package/shared/diagram/atlas.js +51 -60
  436. package/shared/diagram/atlas.js.map +1 -0
  437. package/shared/diagram/mermaid.d.ts +43 -0
  438. package/shared/diagram/mermaid.js +348 -370
  439. package/shared/diagram/mermaid.js.map +1 -0
  440. package/shared/review/contracts.d.ts +95 -0
  441. package/shared/review/contracts.js +2 -0
  442. package/shared/review/contracts.js.map +1 -0
  443. package/shared/review/review.d.ts +10 -0
  444. package/shared/review/review.js +184 -0
  445. package/shared/review/review.js.map +1 -0
  446. package/shared/search/query.d.ts +32 -0
  447. package/shared/search/query.js +395 -388
  448. package/shared/search/query.js.map +1 -0
@@ -2,121 +2,130 @@
2
2
  // regex tokenizing, so highlighting is linear-time even on pathological
3
3
  // input (an earlier master-regex version could stall on real files).
4
4
  // Runs in Node (tests) and the browser.
5
-
6
5
  import { escapeHtml } from './html.js';
7
-
8
6
  const KEYWORDS = {
9
- js: 'const let var function return import export from default if else for while do class extends new await async try catch finally throw typeof instanceof of in switch case break continue yield static get set super this null undefined true false void delete',
10
- py: 'def class return import from as if elif else for while in not and or is None True False try except finally raise with lambda pass break continue yield global nonlocal assert async await del',
11
- go: 'func package import return if else for range var const type struct interface map chan go defer select switch case break continue fallthrough default nil true false iota',
12
- c: 'int void char float double long short unsigned signed const static return if else for while do switch case break continue struct union enum typedef sizeof include define extern volatile register goto',
7
+ js: 'const let var function return import export from default if else for while do class extends new await async try catch finally throw typeof instanceof of in switch case break continue yield static get set super this null undefined true false void delete',
8
+ py: 'def class return import from as if elif else for while in not and or is None True False try except finally raise with lambda pass break continue yield global nonlocal assert async await del',
9
+ go: 'func package import return if else for range var const type struct interface map chan go defer select switch case break continue fallthrough default nil true false iota',
10
+ c: 'int void char float double long short unsigned signed const static return if else for while do switch case break continue struct union enum typedef sizeof include define extern volatile register goto',
13
11
  };
14
-
15
12
  export function langOf(path) {
16
- const ext = (path.match(/\.([A-Za-z0-9]+)$/) || [, ''])[1].toLowerCase();
17
- if (['js', 'jsx', 'ts', 'tsx', 'mjs', 'cjs', 'json'].includes(ext)) return 'js';
18
- if (['py', 'pyi'].includes(ext)) return 'py';
19
- if (ext === 'go') return 'go';
20
- if (['c', 'h', 'cpp', 'cc', 'java', 'rs', 'rb', 'php', 'cs', 'swift', 'kt', 'css'].includes(ext)) return 'c';
21
- return null; // markdown, yaml, toml, plain text — shown unadorned
13
+ const ext = (path.match(/\.([A-Za-z0-9]+)$/) || [, ''])[1].toLowerCase();
14
+ if (['js', 'jsx', 'ts', 'tsx', 'mjs', 'cjs', 'json'].includes(ext))
15
+ return 'js';
16
+ if (['py', 'pyi'].includes(ext))
17
+ return 'py';
18
+ if (ext === 'go')
19
+ return 'go';
20
+ if (['c', 'h', 'cpp', 'cc', 'java', 'rs', 'rb', 'php', 'cs', 'swift', 'kt', 'css'].includes(ext))
21
+ return 'c';
22
+ return null; // markdown, yaml, toml, plain text — shown unadorned
22
23
  }
23
-
24
24
  const isWordStart = (c) => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c === '_' || c === '$';
25
25
  const isWordPart = (c) => isWordStart(c) || (c >= '0' && c <= '9');
26
26
  const isDigit = (c) => c >= '0' && c <= '9';
27
-
28
27
  export function highlightCode(source, lang) {
29
- if (!lang || !KEYWORDS[lang]) return escapeHtml(source);
30
- const kw = new Set(KEYWORDS[lang].split(' '));
31
- const hashComment = lang === 'py';
32
- const out = [];
33
- let plain = '';
34
-
35
- const flushPlain = () => {
36
- if (plain) { out.push(escapeHtml(plain)); plain = ''; }
37
- };
38
- const emit = (cls, text) => {
39
- flushPlain();
40
- out.push(`<span class="${cls}">${escapeHtml(text)}</span>`);
41
- };
42
-
43
- const n = source.length;
44
- let i = 0;
45
- while (i < n) {
46
- const c = source[i];
47
-
48
- // Line comments: # for python, // elsewhere.
49
- if ((hashComment && c === '#') || (!hashComment && c === '/' && source[i + 1] === '/')) {
50
- let j = source.indexOf('\n', i);
51
- if (j === -1) j = n;
52
- emit('tok-com', source.slice(i, j));
53
- i = j;
54
- continue;
55
- }
56
-
57
- // Block comments (and preprocessor lines for the C family).
58
- if (!hashComment && c === '/' && source[i + 1] === '*') {
59
- const end = source.indexOf('*/', i + 2);
60
- const j = end === -1 ? n : end + 2;
61
- emit('tok-com', source.slice(i, j));
62
- i = j;
63
- continue;
64
- }
65
- if (lang === 'c' && c === '#' && (i === 0 || source[i - 1] === '\n')) {
66
- let j = source.indexOf('\n', i);
67
- if (j === -1) j = n;
68
- emit('tok-com', source.slice(i, j));
69
- i = j;
70
- continue;
71
- }
72
-
73
- // Strings. Python triple quotes first; backticks are multiline in js/go.
74
- if (lang === 'py' && (source.startsWith("'''", i) || source.startsWith('"""', i))) {
75
- const q = source.slice(i, i + 3);
76
- const end = source.indexOf(q, i + 3);
77
- const j = end === -1 ? n : end + 3;
78
- emit('tok-str', source.slice(i, j));
79
- i = j;
80
- continue;
28
+ if (!lang || !KEYWORDS[lang])
29
+ return escapeHtml(source);
30
+ const kw = new Set(KEYWORDS[lang].split(' '));
31
+ const hashComment = lang === 'py';
32
+ const out = [];
33
+ let plain = '';
34
+ const flushPlain = () => {
35
+ if (plain) {
36
+ out.push(escapeHtml(plain));
37
+ plain = '';
38
+ }
39
+ };
40
+ const emit = (cls, text) => {
41
+ flushPlain();
42
+ out.push(`<span class="${cls}">${escapeHtml(text)}</span>`);
43
+ };
44
+ const n = source.length;
45
+ let i = 0;
46
+ while (i < n) {
47
+ const c = source[i];
48
+ // Line comments: # for python, // elsewhere.
49
+ if ((hashComment && c === '#') || (!hashComment && c === '/' && source[i + 1] === '/')) {
50
+ let j = source.indexOf('\n', i);
51
+ if (j === -1)
52
+ j = n;
53
+ emit('tok-com', source.slice(i, j));
54
+ i = j;
55
+ continue;
56
+ }
57
+ // Block comments (and preprocessor lines for the C family).
58
+ if (!hashComment && c === '/' && source[i + 1] === '*') {
59
+ const end = source.indexOf('*/', i + 2);
60
+ const j = end === -1 ? n : end + 2;
61
+ emit('tok-com', source.slice(i, j));
62
+ i = j;
63
+ continue;
64
+ }
65
+ if (lang === 'c' && c === '#' && (i === 0 || source[i - 1] === '\n')) {
66
+ let j = source.indexOf('\n', i);
67
+ if (j === -1)
68
+ j = n;
69
+ emit('tok-com', source.slice(i, j));
70
+ i = j;
71
+ continue;
72
+ }
73
+ // Strings. Python triple quotes first; backticks are multiline in js/go.
74
+ if (lang === 'py' && (source.startsWith("'''", i) || source.startsWith('"""', i))) {
75
+ const q = source.slice(i, i + 3);
76
+ const end = source.indexOf(q, i + 3);
77
+ const j = end === -1 ? n : end + 3;
78
+ emit('tok-str', source.slice(i, j));
79
+ i = j;
80
+ continue;
81
+ }
82
+ if (c === "'" || c === '"' || (c === '`' && lang !== 'py' && lang !== 'c')) {
83
+ const multiline = c === '`' || lang === 'py';
84
+ let j = i + 1;
85
+ while (j < n) {
86
+ const d = source[j];
87
+ if (d === '\\') {
88
+ j += 2;
89
+ continue;
90
+ }
91
+ if (d === c) {
92
+ j++;
93
+ break;
94
+ }
95
+ if (d === '\n' && !multiline)
96
+ break; // unterminated: stop at the line end
97
+ j++;
98
+ }
99
+ emit('tok-str', source.slice(i, j));
100
+ i = j;
101
+ continue;
102
+ }
103
+ // Words → keywords when the language claims them.
104
+ if (isWordStart(c)) {
105
+ let j = i + 1;
106
+ while (j < n && isWordPart(source[j]))
107
+ j++;
108
+ const w = source.slice(i, j);
109
+ if (kw.has(w))
110
+ emit('tok-kw', w);
111
+ else
112
+ plain += w;
113
+ i = j;
114
+ continue;
115
+ }
116
+ // Numbers.
117
+ if (isDigit(c)) {
118
+ let j = i + 1;
119
+ while (j < n && (isDigit(source[j]) || source[j] === '.' || source[j] === '_'))
120
+ j++;
121
+ emit('tok-num', source.slice(i, j));
122
+ i = j;
123
+ continue;
124
+ }
125
+ plain += c;
126
+ i++;
81
127
  }
82
- if (c === "'" || c === '"' || (c === '`' && lang !== 'py' && lang !== 'c')) {
83
- const multiline = c === '`' || lang === 'py';
84
- let j = i + 1;
85
- while (j < n) {
86
- const d = source[j];
87
- if (d === '\\') { j += 2; continue; }
88
- if (d === c) { j++; break; }
89
- if (d === '\n' && !multiline) break; // unterminated: stop at the line end
90
- j++;
91
- }
92
- emit('tok-str', source.slice(i, j));
93
- i = j;
94
- continue;
95
- }
96
-
97
- // Words → keywords when the language claims them.
98
- if (isWordStart(c)) {
99
- let j = i + 1;
100
- while (j < n && isWordPart(source[j])) j++;
101
- const w = source.slice(i, j);
102
- if (kw.has(w)) emit('tok-kw', w);
103
- else plain += w;
104
- i = j;
105
- continue;
106
- }
107
-
108
- // Numbers.
109
- if (isDigit(c)) {
110
- let j = i + 1;
111
- while (j < n && (isDigit(source[j]) || source[j] === '.' || source[j] === '_')) j++;
112
- emit('tok-num', source.slice(i, j));
113
- i = j;
114
- continue;
115
- }
116
-
117
- plain += c;
118
- i++;
119
- }
120
- flushPlain();
121
- return out.join('');
128
+ flushPlain();
129
+ return out.join('');
122
130
  }
131
+ //# sourceMappingURL=highlight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"highlight.js","sourceRoot":"","sources":["../../src/public/js/highlight.ts"],"names":[],"mappings":"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","sourcesContent":["// Hand-rolled syntax highlighting — a single left-to-right scanner, no\n// regex tokenizing, so highlighting is linear-time even on pathological\n// input (an earlier master-regex version could stall on real files).\n// Runs in Node (tests) and the browser.\n\nimport { escapeHtml } from './html.js';\n\nconst KEYWORDS = {\n js: 'const let var function return import export from default if else for while do class extends new await async try catch finally throw typeof instanceof of in switch case break continue yield static get set super this null undefined true false void delete',\n py: 'def class return import from as if elif else for while in not and or is None True False try except finally raise with lambda pass break continue yield global nonlocal assert async await del',\n go: 'func package import return if else for range var const type struct interface map chan go defer select switch case break continue fallthrough default nil true false iota',\n c: 'int void char float double long short unsigned signed const static return if else for while do switch case break continue struct union enum typedef sizeof include define extern volatile register goto',\n};\n\nexport function langOf(path) {\n const ext = (path.match(/\\.([A-Za-z0-9]+)$/) || [, ''])[1].toLowerCase();\n if (['js', 'jsx', 'ts', 'tsx', 'mjs', 'cjs', 'json'].includes(ext)) return 'js';\n if (['py', 'pyi'].includes(ext)) return 'py';\n if (ext === 'go') return 'go';\n if (['c', 'h', 'cpp', 'cc', 'java', 'rs', 'rb', 'php', 'cs', 'swift', 'kt', 'css'].includes(ext)) return 'c';\n return null; // markdown, yaml, toml, plain text — shown unadorned\n}\n\nconst isWordStart = (c) => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c === '_' || c === '$';\nconst isWordPart = (c) => isWordStart(c) || (c >= '0' && c <= '9');\nconst isDigit = (c) => c >= '0' && c <= '9';\n\nexport function highlightCode(source, lang) {\n if (!lang || !KEYWORDS[lang]) return escapeHtml(source);\n const kw = new Set(KEYWORDS[lang].split(' '));\n const hashComment = lang === 'py';\n const out = [];\n let plain = '';\n\n const flushPlain = () => {\n if (plain) { out.push(escapeHtml(plain)); plain = ''; }\n };\n const emit = (cls, text) => {\n flushPlain();\n out.push(`<span class=\"${cls}\">${escapeHtml(text)}</span>`);\n };\n\n const n = source.length;\n let i = 0;\n while (i < n) {\n const c = source[i];\n\n // Line comments: # for python, // elsewhere.\n if ((hashComment && c === '#') || (!hashComment && c === '/' && source[i + 1] === '/')) {\n let j = source.indexOf('\\n', i);\n if (j === -1) j = n;\n emit('tok-com', source.slice(i, j));\n i = j;\n continue;\n }\n\n // Block comments (and preprocessor lines for the C family).\n if (!hashComment && c === '/' && source[i + 1] === '*') {\n const end = source.indexOf('*/', i + 2);\n const j = end === -1 ? n : end + 2;\n emit('tok-com', source.slice(i, j));\n i = j;\n continue;\n }\n if (lang === 'c' && c === '#' && (i === 0 || source[i - 1] === '\\n')) {\n let j = source.indexOf('\\n', i);\n if (j === -1) j = n;\n emit('tok-com', source.slice(i, j));\n i = j;\n continue;\n }\n\n // Strings. Python triple quotes first; backticks are multiline in js/go.\n if (lang === 'py' && (source.startsWith(\"'''\", i) || source.startsWith('\"\"\"', i))) {\n const q = source.slice(i, i + 3);\n const end = source.indexOf(q, i + 3);\n const j = end === -1 ? n : end + 3;\n emit('tok-str', source.slice(i, j));\n i = j;\n continue;\n }\n if (c === \"'\" || c === '\"' || (c === '`' && lang !== 'py' && lang !== 'c')) {\n const multiline = c === '`' || lang === 'py';\n let j = i + 1;\n while (j < n) {\n const d = source[j];\n if (d === '\\\\') { j += 2; continue; }\n if (d === c) { j++; break; }\n if (d === '\\n' && !multiline) break; // unterminated: stop at the line end\n j++;\n }\n emit('tok-str', source.slice(i, j));\n i = j;\n continue;\n }\n\n // Words → keywords when the language claims them.\n if (isWordStart(c)) {\n let j = i + 1;\n while (j < n && isWordPart(source[j])) j++;\n const w = source.slice(i, j);\n if (kw.has(w)) emit('tok-kw', w);\n else plain += w;\n i = j;\n continue;\n }\n\n // Numbers.\n if (isDigit(c)) {\n let j = i + 1;\n while (j < n && (isDigit(source[j]) || source[j] === '.' || source[j] === '_')) j++;\n emit('tok-num', source.slice(i, j));\n i = j;\n continue;\n }\n\n plain += c;\n i++;\n }\n flushPlain();\n return out.join('');\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function escapeHtml(value: unknown): string;
2
+ export declare function safeUrl(value: unknown): string;
package/public/js/html.js CHANGED
@@ -1,50 +1,20 @@
1
- // Escaping at the boundary — one implementation, used everywhere.
2
- //
3
- // Onboarder renders content it does not control: file and folder names from a
4
- // repository that may have been cloned from an arbitrary git URL, READMEs,
5
- // GitHub API fields, and model output. All of it reaches the DOM as HTML
6
- // strings, and a good deal of it lands inside attributes
7
- // (`title="…"`, `data-path="…"`). So quotes matter as much as angle brackets:
8
- // a file named `x" onmouseover="…` closes the attribute and opens a handler,
9
- // and double quotes are legal in filenames on macOS and Linux.
10
- //
11
- // This used to be five near-copies — four of which escaped only & < > — with
12
- // the attribute call sites quietly relying on the one that didn't. Now there
13
- // is one function and it escapes all five characters.
14
- //
15
- // Single pass, one regex, one lookup per match: strictly cheaper than the
16
- // chain of four .replace() calls it replaces, which matters because the
17
- // syntax highlighter runs this over every token of every file.
18
-
1
+ // Escape untrusted repository data at the boundary before placing it in HTML.
19
2
  const ESCAPES = {
20
- '&': '&amp;',
21
- '<': '&lt;',
22
- '>': '&gt;',
23
- '"': '&quot;',
24
- "'": '&#39;',
3
+ '&': '&amp;',
4
+ '<': '&lt;',
5
+ '>': '&gt;',
6
+ '"': '&quot;',
7
+ "'": '&#39;',
25
8
  };
26
-
27
9
  const NEEDS_ESCAPE = /[&<>"']/g;
28
-
29
- /**
30
- * Make a string safe to interpolate into HTML — as text, or inside a
31
- * double- or single-quoted attribute value.
32
- */
33
- export function escapeHtml(s) {
34
- return String(s ?? '').replace(NEEDS_ESCAPE, (c) => ESCAPES[c]);
10
+ export function escapeHtml(value) {
11
+ return String(value ?? '').replace(NEEDS_ESCAPE, (character) => ESCAPES[character]);
35
12
  }
36
-
37
- // Whitespace and C0/C1 control characters, which browsers ignore when they
38
- // parse a URL scheme — so `java\tscript:alert(1)` is a live javascript: URL.
39
13
  const URL_NOISE = /[\s\u0000-\u001F\u007F-\u009F]/g;
40
-
41
- /**
42
- * A URL safe to put in an href. Anything that isn't plainly http(s) comes back
43
- * empty, which keeps `javascript:`, `data:` and `vbscript:` out of the DOM
44
- * even when the surrounding markup is assembled by hand.
45
- */
46
- export function safeUrl(url) {
47
- const raw = String(url ?? '').trim();
48
- if (!/^https?:\/\//i.test(raw.replace(URL_NOISE, ''))) return '';
49
- return escapeHtml(raw);
14
+ export function safeUrl(value) {
15
+ const raw = String(value ?? '').trim();
16
+ if (!/^https?:\/\//i.test(raw.replace(URL_NOISE, '')))
17
+ return '';
18
+ return escapeHtml(raw);
50
19
  }
20
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/public/js/html.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,OAAO,GAA2B;IACtC,GAAG,EAAE,OAAO;IACZ,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,QAAQ;IACb,GAAG,EAAE,OAAO;CACb,CAAC;AAEF,MAAM,YAAY,GAAG,UAAU,CAAC;AAEhC,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,SAAS,GAAG,iCAAiC,CAAC;AAEpD,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IACjE,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC","sourcesContent":["// Escape untrusted repository data at the boundary before placing it in HTML.\nconst ESCAPES: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n};\n\nconst NEEDS_ESCAPE = /[&<>\"']/g;\n\nexport function escapeHtml(value: unknown): string {\n return String(value ?? '').replace(NEEDS_ESCAPE, (character) => ESCAPES[character]);\n}\n\nconst URL_NOISE = /[\\s\\u0000-\\u001F\\u007F-\\u009F]/g;\n\nexport function safeUrl(value: unknown): string {\n const raw = String(value ?? '').trim();\n if (!/^https?:\\/\\//i.test(raw.replace(URL_NOISE, ''))) return '';\n return escapeHtml(raw);\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export declare function renderInsights(container: any, { scan, facts, history }: {
2
+ facts: any;
3
+ history: any;
4
+ scan: any;
5
+ }): void;
@@ -1,42 +1,37 @@
1
1
  // GitHub Insights & Pulse View.
2
2
  // Renders 52-week contribution heatmap, contributor leaderboard, punchcard, and release timeline.
3
-
4
3
  import { escapeHtml } from './html.js';
5
-
6
4
  export function renderInsights(container, { scan, facts, history }) {
7
- if (!container) return;
8
-
9
- const commits = history?.commits || [];
10
- const authorMap = new Map();
11
- const dayHourMatrix = Array.from({ length: 7 }, () => Array(24).fill(0));
12
- const dayCounts = new Map();
13
-
14
- // Process commit dates & authors
15
- for (const c of commits) {
16
- const { key, name } = authorIdentity(c.author);
17
- if (!authorMap.has(key)) {
18
- authorMap.set(key, { name, commits: 0, additions: 0, deletions: 0, firstDate: c.date, lastDate: c.date, files: new Set() });
5
+ if (!container)
6
+ return;
7
+ const commits = history?.commits || [];
8
+ const authorMap = new Map();
9
+ const dayHourMatrix = Array.from({ length: 7 }, () => Array(24).fill(0));
10
+ const dayCounts = new Map();
11
+ // Process commit dates & authors
12
+ for (const c of commits) {
13
+ const { key, name } = authorIdentity(c.author);
14
+ if (!authorMap.has(key)) {
15
+ authorMap.set(key, { name, commits: 0, additions: 0, deletions: 0, firstDate: c.date, lastDate: c.date, files: new Set() });
16
+ }
17
+ const a = authorMap.get(key);
18
+ a.commits++;
19
+ if (c.date < a.firstDate)
20
+ a.firstDate = c.date;
21
+ if (c.date > a.lastDate)
22
+ a.lastDate = c.date;
23
+ const d = new Date(c.date || Date.now());
24
+ if (!isNaN(d.getTime())) {
25
+ const day = d.getDay(); // 0 = Sun, 6 = Sat
26
+ const hour = d.getHours();
27
+ dayHourMatrix[day][hour]++;
28
+ const ymd = d.toISOString().slice(0, 10);
29
+ dayCounts.set(ymd, (dayCounts.get(ymd) || 0) + 1);
30
+ }
19
31
  }
20
- const a = authorMap.get(key);
21
- a.commits++;
22
- if (c.date < a.firstDate) a.firstDate = c.date;
23
- if (c.date > a.lastDate) a.lastDate = c.date;
24
-
25
- const d = new Date(c.date || Date.now());
26
- if (!isNaN(d.getTime())) {
27
- const day = d.getDay(); // 0 = Sun, 6 = Sat
28
- const hour = d.getHours();
29
- dayHourMatrix[day][hour]++;
30
-
31
- const ymd = d.toISOString().slice(0, 10);
32
- dayCounts.set(ymd, (dayCounts.get(ymd) || 0) + 1);
33
- }
34
- }
35
-
36
- const sortedAuthors = [...authorMap.values()].sort((a, b) => b.commits - a.commits);
37
- const totalCommits = commits.length || 1;
38
-
39
- container.innerHTML = `
32
+ const sortedAuthors = [...authorMap.values()].sort((a, b) => b.commits - a.commits);
33
+ const totalCommits = commits.length || 1;
34
+ container.innerHTML = `
40
35
  <div class="insights-layout">
41
36
  <section class="insights-hero">
42
37
  <div class="insights-stat-card">
@@ -106,63 +101,54 @@ export function renderInsights(container, { scan, facts, history }) {
106
101
  </div>
107
102
  `;
108
103
  }
109
-
110
104
  // gitHistory shapes commit.author as { name, email }; a bare string is also
111
105
  // tolerated so older cached payloads don't break the view. Commits are grouped
112
106
  // by email when present — the same person with two name spellings is one
113
107
  // contributor, like shared/analyzer/history.js does server-side.
114
108
  function authorIdentity(author) {
115
- if (author && typeof author === 'object') {
116
- const name = author.name || author.email || 'Anonymous';
117
- return { key: author.email || name, name };
118
- }
119
- const name = author || 'Anonymous';
120
- return { key: name, name };
109
+ if (author && typeof author === 'object') {
110
+ const name = author.name || author.email || 'Anonymous';
111
+ return { key: author.email || name, name };
112
+ }
113
+ const name = author || 'Anonymous';
114
+ return { key: name, name };
121
115
  }
122
-
123
-
124
116
  function renderCalendarHeatmap(dayCounts) {
125
- const weeks = 52;
126
- const daysPerWeek = 7;
127
- const cellSize = 12;
128
- const cellGap = 3;
129
-
130
- const now = new Date();
131
- const cells = [];
132
- const oneDayMs = 24 * 60 * 60 * 1000;
133
-
134
- // Align to end on current day
135
- const endDay = new Date(now);
136
- const startDay = new Date(endDay.getTime() - (weeks * 7) * oneDayMs);
137
-
138
- let maxCount = 1;
139
- for (const c of dayCounts.values()) if (c > maxCount) maxCount = c;
140
-
141
- const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
142
-
143
- for (let w = 0; w < weeks; w++) {
144
- for (let d = 0; d < 7; d++) {
145
- const cur = new Date(startDay.getTime() + (w * 7 + d) * oneDayMs);
146
- const ymd = cur.toISOString().slice(0, 10);
147
- const count = dayCounts.get(ymd) || 0;
148
- let level = 0;
149
- if (count > 0) level = Math.min(4, Math.ceil((count / maxCount) * 4));
150
-
151
- const x = w * (cellSize + cellGap) + 30;
152
- const y = d * (cellSize + cellGap) + 20;
153
-
154
- cells.push(`
117
+ const weeks = 52;
118
+ const daysPerWeek = 7;
119
+ const cellSize = 12;
120
+ const cellGap = 3;
121
+ const now = new Date();
122
+ const cells = [];
123
+ const oneDayMs = 24 * 60 * 60 * 1000;
124
+ // Align to end on current day
125
+ const endDay = new Date(now);
126
+ const startDay = new Date(endDay.getTime() - (weeks * 7) * oneDayMs);
127
+ let maxCount = 1;
128
+ for (const c of dayCounts.values())
129
+ if (c > maxCount)
130
+ maxCount = c;
131
+ const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
132
+ for (let w = 0; w < weeks; w++) {
133
+ for (let d = 0; d < 7; d++) {
134
+ const cur = new Date(startDay.getTime() + (w * 7 + d) * oneDayMs);
135
+ const ymd = cur.toISOString().slice(0, 10);
136
+ const count = dayCounts.get(ymd) || 0;
137
+ let level = 0;
138
+ if (count > 0)
139
+ level = Math.min(4, Math.ceil((count / maxCount) * 4));
140
+ const x = w * (cellSize + cellGap) + 30;
141
+ const y = d * (cellSize + cellGap) + 20;
142
+ cells.push(`
155
143
  <rect class="cal-cell lvl-${level}" x="${x}" y="${y}" width="${cellSize}" height="${cellSize}" rx="2">
156
144
  <title>${ymd}: ${count} commit${count === 1 ? '' : 's'}</title>
157
145
  </rect>
158
146
  `);
147
+ }
159
148
  }
160
- }
161
-
162
- const svgWidth = weeks * (cellSize + cellGap) + 40;
163
- const svgHeight = 7 * (cellSize + cellGap) + 30;
164
-
165
- return `
149
+ const svgWidth = weeks * (cellSize + cellGap) + 40;
150
+ const svgHeight = 7 * (cellSize + cellGap) + 30;
151
+ return `
166
152
  <div class="cal-scroll-wrap">
167
153
  <svg class="cal-heatmap-svg" viewBox="0 0 ${svgWidth} ${svgHeight}" style="max-width: 100%; height: auto;">
168
154
  <text class="cal-label" x="5" y="42">Mon</text>
@@ -182,49 +168,44 @@ function renderCalendarHeatmap(dayCounts) {
182
168
  </div>
183
169
  `;
184
170
  }
185
-
186
171
  function renderPunchcardSvg(matrix) {
187
- const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
188
- const cellW = 20;
189
- const cellH = 20;
190
- const padLeft = 40;
191
- const padTop = 20;
192
- let max = 1;
193
-
194
- for (let d = 0; d < 7; d++) {
195
- for (let h = 0; h < 24; h++) {
196
- if (matrix[d][h] > max) max = matrix[d][h];
172
+ const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
173
+ const cellW = 20;
174
+ const cellH = 20;
175
+ const padLeft = 40;
176
+ const padTop = 20;
177
+ let max = 1;
178
+ for (let d = 0; d < 7; d++) {
179
+ for (let h = 0; h < 24; h++) {
180
+ if (matrix[d][h] > max)
181
+ max = matrix[d][h];
182
+ }
197
183
  }
198
- }
199
-
200
- const dots = [];
201
- for (let d = 0; d < 7; d++) {
202
- for (let h = 0; h < 24; h++) {
203
- const val = matrix[d][h];
204
- if (val === 0) continue;
205
- const r = Math.max(2, Math.min(8, (val / max) * 8));
206
- const cx = padLeft + h * cellW + cellW / 2;
207
- const cy = padTop + d * cellH + cellH / 2;
208
- dots.push(`
184
+ const dots = [];
185
+ for (let d = 0; d < 7; d++) {
186
+ for (let h = 0; h < 24; h++) {
187
+ const val = matrix[d][h];
188
+ if (val === 0)
189
+ continue;
190
+ const r = Math.max(2, Math.min(8, (val / max) * 8));
191
+ const cx = padLeft + h * cellW + cellW / 2;
192
+ const cy = padTop + d * cellH + cellH / 2;
193
+ dots.push(`
209
194
  <circle cx="${cx}" cy="${cy}" r="${r}" class="punch-dot">
210
195
  <title>${days[d]} ${h}:00 - ${val} commit${val === 1 ? '' : 's'}</title>
211
196
  </circle>
212
197
  `);
198
+ }
213
199
  }
214
- }
215
-
216
- const hoursHeader = [0, 4, 8, 12, 16, 20].map((h) => `
200
+ const hoursHeader = [0, 4, 8, 12, 16, 20].map((h) => `
217
201
  <text class="punch-lbl" x="${padLeft + h * cellW + cellW / 2}" y="12" text-anchor="middle">${h}h</text>
218
202
  `).join('');
219
-
220
- const daysHeader = days.map((day, idx) => `
203
+ const daysHeader = days.map((day, idx) => `
221
204
  <text class="punch-lbl" x="5" y="${padTop + idx * cellH + cellH / 2 + 4}">${day}</text>
222
205
  `).join('');
223
-
224
- const svgW = padLeft + 24 * cellW + 10;
225
- const svgH = padTop + 7 * cellH + 10;
226
-
227
- return `
206
+ const svgW = padLeft + 24 * cellW + 10;
207
+ const svgH = padTop + 7 * cellH + 10;
208
+ return `
228
209
  <div class="cal-scroll-wrap">
229
210
  <svg class="punch-svg" viewBox="0 0 ${svgW} ${svgH}">
230
211
  ${hoursHeader}
@@ -234,3 +215,4 @@ function renderPunchcardSvg(matrix) {
234
215
  </div>
235
216
  `;
236
217
  }
218
+ //# sourceMappingURL=insightsView.js.map