webmcp-cli 1.2.2 → 1.2.3

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 (330) hide show
  1. package/dist/analysis/form-to-tool-mapper.d.ts +61 -0
  2. package/dist/analysis/form-to-tool-mapper.js +360 -0
  3. package/dist/analysis/form-to-tool-mapper.js.map +1 -0
  4. package/dist/analysis/index.d.ts +84 -0
  5. package/dist/analysis/index.js +81 -0
  6. package/dist/analysis/index.js.map +1 -0
  7. package/dist/analysis/missing-tool-analyzer.d.ts +35 -0
  8. package/dist/analysis/missing-tool-analyzer.js +617 -0
  9. package/dist/analysis/missing-tool-analyzer.js.map +1 -0
  10. package/dist/audit/run-multi-page-audit.d.ts +34 -0
  11. package/dist/audit/run-multi-page-audit.js +233 -0
  12. package/dist/audit/run-multi-page-audit.js.map +1 -0
  13. package/dist/cli/commands/potential.d.ts +8 -0
  14. package/dist/cli/commands/potential.js +323 -0
  15. package/dist/cli/commands/potential.js.map +1 -0
  16. package/dist/cli/commands/report.d.ts +12 -0
  17. package/dist/cli/commands/report.js +89 -0
  18. package/dist/cli/commands/report.js.map +1 -0
  19. package/dist/cli/index.js +35 -0
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/config/defaults.d.ts +36 -0
  22. package/dist/config/defaults.js +33 -0
  23. package/dist/config/defaults.js.map +1 -0
  24. package/dist/config/index.d.ts +7 -0
  25. package/dist/config/index.js +7 -0
  26. package/dist/config/index.js.map +1 -0
  27. package/dist/config/loader.d.ts +22 -0
  28. package/dist/config/loader.js +91 -0
  29. package/dist/config/loader.js.map +1 -0
  30. package/dist/config/schema.d.ts +280 -0
  31. package/dist/config/schema.js +42 -0
  32. package/dist/config/schema.js.map +1 -0
  33. package/dist/core/types/audit.d.ts +1 -1
  34. package/dist/core/types/index.d.ts +1 -0
  35. package/dist/core/types/index.js +1 -0
  36. package/dist/core/types/index.js.map +1 -1
  37. package/dist/core/types/recon.d.ts +265 -0
  38. package/dist/core/types/recon.js +5 -0
  39. package/dist/core/types/recon.js.map +1 -0
  40. package/dist/core/types/rule.d.ts +1 -1
  41. package/dist/core/types/rule.js +7 -5
  42. package/dist/core/types/rule.js.map +1 -1
  43. package/dist/crawler/depth-crawler.d.ts +29 -0
  44. package/dist/crawler/depth-crawler.js +212 -0
  45. package/dist/crawler/depth-crawler.js.map +1 -0
  46. package/dist/crawler/index.d.ts +2 -0
  47. package/dist/crawler/index.js +3 -0
  48. package/dist/crawler/index.js.map +1 -0
  49. package/dist/crawler/link-extractor.d.ts +1 -0
  50. package/dist/crawler/link-extractor.js +49 -0
  51. package/dist/crawler/link-extractor.js.map +1 -0
  52. package/dist/generators/index.d.ts +10 -0
  53. package/dist/generators/index.js +8 -0
  54. package/dist/generators/index.js.map +1 -0
  55. package/dist/generators/report-html.d.ts +12 -0
  56. package/dist/generators/report-html.js +470 -0
  57. package/dist/generators/report-html.js.map +1 -0
  58. package/dist/generators/report-json.d.ts +95 -0
  59. package/dist/generators/report-json.js +144 -0
  60. package/dist/generators/report-json.js.map +1 -0
  61. package/dist/generators/report-manager.d.ts +31 -0
  62. package/dist/generators/report-manager.js +208 -0
  63. package/dist/generators/report-manager.js.map +1 -0
  64. package/dist/generators/tool-code-generator.d.ts +31 -0
  65. package/dist/generators/tool-code-generator.js +201 -0
  66. package/dist/generators/tool-code-generator.js.map +1 -0
  67. package/dist/potential/ai-recommender.d.ts +33 -0
  68. package/dist/potential/ai-recommender.js +414 -0
  69. package/dist/potential/ai-recommender.js.map +1 -0
  70. package/dist/potential/analyzer.d.ts +32 -0
  71. package/dist/potential/analyzer.js +383 -0
  72. package/dist/potential/analyzer.js.map +1 -0
  73. package/dist/potential/index.d.ts +3 -0
  74. package/dist/potential/index.js +4 -0
  75. package/dist/potential/index.js.map +1 -0
  76. package/dist/potential/prompts.d.ts +20 -0
  77. package/dist/potential/prompts.js +42 -0
  78. package/dist/potential/prompts.js.map +1 -0
  79. package/dist/potential/types.d.ts +40 -0
  80. package/dist/potential/types.js +2 -0
  81. package/dist/potential/types.js.map +1 -0
  82. package/dist/recon/index.d.ts +20 -0
  83. package/dist/recon/index.js +143 -0
  84. package/dist/recon/index.js.map +1 -0
  85. package/dist/recon/manifest.d.ts +16 -0
  86. package/dist/recon/manifest.js +108 -0
  87. package/dist/recon/manifest.js.map +1 -0
  88. package/dist/recon/meta-extractor.d.ts +11 -0
  89. package/dist/recon/meta-extractor.js +276 -0
  90. package/dist/recon/meta-extractor.js.map +1 -0
  91. package/dist/recon/robots.d.ts +16 -0
  92. package/dist/recon/robots.js +158 -0
  93. package/dist/recon/robots.js.map +1 -0
  94. package/dist/recon/route-discovery.d.ts +25 -0
  95. package/dist/recon/route-discovery.js +303 -0
  96. package/dist/recon/route-discovery.js.map +1 -0
  97. package/dist/recon/sitemap.d.ts +12 -0
  98. package/dist/recon/sitemap.js +177 -0
  99. package/dist/recon/sitemap.js.map +1 -0
  100. package/dist/rules/accessibility/AXE-001.d.ts +9 -0
  101. package/dist/rules/accessibility/AXE-001.js +109 -0
  102. package/dist/rules/accessibility/AXE-001.js.map +1 -0
  103. package/dist/rules/accessibility/AXE-002.d.ts +8 -0
  104. package/dist/rules/accessibility/AXE-002.js +85 -0
  105. package/dist/rules/accessibility/AXE-002.js.map +1 -0
  106. package/dist/rules/accessibility/AXE-003.d.ts +8 -0
  107. package/dist/rules/accessibility/AXE-003.js +94 -0
  108. package/dist/rules/accessibility/AXE-003.js.map +1 -0
  109. package/dist/rules/accessibility/AXE-004.d.ts +8 -0
  110. package/dist/rules/accessibility/AXE-004.js +101 -0
  111. package/dist/rules/accessibility/AXE-004.js.map +1 -0
  112. package/dist/rules/accessibility/AXE-005.d.ts +9 -0
  113. package/dist/rules/accessibility/AXE-005.js +89 -0
  114. package/dist/rules/accessibility/AXE-005.js.map +1 -0
  115. package/dist/rules/best-practices/BP-004.d.ts +9 -0
  116. package/dist/rules/best-practices/BP-004.js +96 -0
  117. package/dist/rules/best-practices/BP-004.js.map +1 -0
  118. package/dist/rules/best-practices/BP-005.d.ts +8 -0
  119. package/dist/rules/best-practices/BP-005.js +94 -0
  120. package/dist/rules/best-practices/BP-005.js.map +1 -0
  121. package/dist/rules/best-practices/BP-006.d.ts +8 -0
  122. package/dist/rules/best-practices/BP-006.js +80 -0
  123. package/dist/rules/best-practices/BP-006.js.map +1 -0
  124. package/dist/rules/best-practices/BP-007.d.ts +8 -0
  125. package/dist/rules/best-practices/BP-007.js +92 -0
  126. package/dist/rules/best-practices/BP-007.js.map +1 -0
  127. package/dist/rules/best-practices/BP-008.d.ts +12 -0
  128. package/dist/rules/best-practices/BP-008.js +86 -0
  129. package/dist/rules/best-practices/BP-008.js.map +1 -0
  130. package/dist/rules/best-practices/BP-009.d.ts +9 -0
  131. package/dist/rules/best-practices/BP-009.js +77 -0
  132. package/dist/rules/best-practices/BP-009.js.map +1 -0
  133. package/dist/rules/best-practices/BP-010.d.ts +8 -0
  134. package/dist/rules/best-practices/BP-010.js +85 -0
  135. package/dist/rules/best-practices/BP-010.js.map +1 -0
  136. package/dist/rules/coverage/COV-002.d.ts +8 -0
  137. package/dist/rules/coverage/COV-002.js +68 -0
  138. package/dist/rules/coverage/COV-002.js.map +1 -0
  139. package/dist/rules/coverage/COV-003.d.ts +8 -0
  140. package/dist/rules/coverage/COV-003.js +68 -0
  141. package/dist/rules/coverage/COV-003.js.map +1 -0
  142. package/dist/rules/coverage/COV-004.d.ts +8 -0
  143. package/dist/rules/coverage/COV-004.js +89 -0
  144. package/dist/rules/coverage/COV-004.js.map +1 -0
  145. package/dist/rules/coverage/COV-005.d.ts +8 -0
  146. package/dist/rules/coverage/COV-005.js +67 -0
  147. package/dist/rules/coverage/COV-005.js.map +1 -0
  148. package/dist/rules/coverage/COV-006.d.ts +9 -0
  149. package/dist/rules/coverage/COV-006.js +76 -0
  150. package/dist/rules/coverage/COV-006.js.map +1 -0
  151. package/dist/rules/coverage/COV-007.d.ts +8 -0
  152. package/dist/rules/coverage/COV-007.js +67 -0
  153. package/dist/rules/coverage/COV-007.js.map +1 -0
  154. package/dist/rules/coverage/COV-008.d.ts +9 -0
  155. package/dist/rules/coverage/COV-008.js +87 -0
  156. package/dist/rules/coverage/COV-008.js.map +1 -0
  157. package/dist/rules/coverage/COV-009.d.ts +8 -0
  158. package/dist/rules/coverage/COV-009.js +73 -0
  159. package/dist/rules/coverage/COV-009.js.map +1 -0
  160. package/dist/rules/coverage/COV-010.d.ts +9 -0
  161. package/dist/rules/coverage/COV-010.js +82 -0
  162. package/dist/rules/coverage/COV-010.js.map +1 -0
  163. package/dist/rules/description/DESC-001.d.ts +9 -0
  164. package/dist/rules/description/DESC-001.js +88 -0
  165. package/dist/rules/description/DESC-001.js.map +1 -0
  166. package/dist/rules/description/DESC-002.d.ts +10 -0
  167. package/dist/rules/description/DESC-002.js +99 -0
  168. package/dist/rules/description/DESC-002.js.map +1 -0
  169. package/dist/rules/description/DESC-006.d.ts +9 -0
  170. package/dist/rules/description/DESC-006.js +78 -0
  171. package/dist/rules/description/DESC-006.js.map +1 -0
  172. package/dist/rules/description/DESC-007.d.ts +9 -0
  173. package/dist/rules/description/DESC-007.js +70 -0
  174. package/dist/rules/description/DESC-007.js.map +1 -0
  175. package/dist/rules/description/DESC-008.d.ts +9 -0
  176. package/dist/rules/description/DESC-008.js +70 -0
  177. package/dist/rules/description/DESC-008.js.map +1 -0
  178. package/dist/rules/description/DESC-009.d.ts +8 -0
  179. package/dist/rules/description/DESC-009.js +55 -0
  180. package/dist/rules/description/DESC-009.js.map +1 -0
  181. package/dist/rules/description/DESC-010.d.ts +9 -0
  182. package/dist/rules/description/DESC-010.js +92 -0
  183. package/dist/rules/description/DESC-010.js.map +1 -0
  184. package/dist/rules/description/DESC-011.d.ts +9 -0
  185. package/dist/rules/description/DESC-011.js +81 -0
  186. package/dist/rules/description/DESC-011.js.map +1 -0
  187. package/dist/rules/description/DESC-012.d.ts +9 -0
  188. package/dist/rules/description/DESC-012.js +98 -0
  189. package/dist/rules/description/DESC-012.js.map +1 -0
  190. package/dist/rules/implementation/IMP-002.d.ts +9 -0
  191. package/dist/rules/implementation/IMP-002.js +59 -0
  192. package/dist/rules/implementation/IMP-002.js.map +1 -0
  193. package/dist/rules/implementation/IMP-006.d.ts +9 -0
  194. package/dist/rules/implementation/IMP-006.js +48 -0
  195. package/dist/rules/implementation/IMP-006.js.map +1 -0
  196. package/dist/rules/implementation/IMP-008.d.ts +9 -0
  197. package/dist/rules/implementation/IMP-008.js +46 -0
  198. package/dist/rules/implementation/IMP-008.js.map +1 -0
  199. package/dist/rules/implementation/IMP-009.d.ts +9 -0
  200. package/dist/rules/implementation/IMP-009.js +48 -0
  201. package/dist/rules/implementation/IMP-009.js.map +1 -0
  202. package/dist/rules/implementation/IMP-010.d.ts +9 -0
  203. package/dist/rules/implementation/IMP-010.js +66 -0
  204. package/dist/rules/implementation/IMP-010.js.map +1 -0
  205. package/dist/rules/implementation/IMP-011.d.ts +9 -0
  206. package/dist/rules/implementation/IMP-011.js +82 -0
  207. package/dist/rules/implementation/IMP-011.js.map +1 -0
  208. package/dist/rules/implementation/IMP-012.d.ts +9 -0
  209. package/dist/rules/implementation/IMP-012.js +88 -0
  210. package/dist/rules/implementation/IMP-012.js.map +1 -0
  211. package/dist/rules/implementation/IMP-014.d.ts +9 -0
  212. package/dist/rules/implementation/IMP-014.js +58 -0
  213. package/dist/rules/implementation/IMP-014.js.map +1 -0
  214. package/dist/rules/implementation/IMP-015.d.ts +9 -0
  215. package/dist/rules/implementation/IMP-015.js +64 -0
  216. package/dist/rules/implementation/IMP-015.js.map +1 -0
  217. package/dist/rules/implementation/IMP-016.d.ts +9 -0
  218. package/dist/rules/implementation/IMP-016.js +52 -0
  219. package/dist/rules/implementation/IMP-016.js.map +1 -0
  220. package/dist/rules/implementation/IMP-017.d.ts +8 -0
  221. package/dist/rules/implementation/IMP-017.js +51 -0
  222. package/dist/rules/implementation/IMP-017.js.map +1 -0
  223. package/dist/rules/implementation/IMP-018.d.ts +8 -0
  224. package/dist/rules/implementation/IMP-018.js +52 -0
  225. package/dist/rules/implementation/IMP-018.js.map +1 -0
  226. package/dist/rules/implementation/IMP-019.d.ts +8 -0
  227. package/dist/rules/implementation/IMP-019.js +53 -0
  228. package/dist/rules/implementation/IMP-019.js.map +1 -0
  229. package/dist/rules/implementation/IMP-020.d.ts +9 -0
  230. package/dist/rules/implementation/IMP-020.js +62 -0
  231. package/dist/rules/implementation/IMP-020.js.map +1 -0
  232. package/dist/rules/implementation/IMP-021.d.ts +8 -0
  233. package/dist/rules/implementation/IMP-021.js +64 -0
  234. package/dist/rules/implementation/IMP-021.js.map +1 -0
  235. package/dist/rules/implementation/IMP-022.d.ts +8 -0
  236. package/dist/rules/implementation/IMP-022.js +70 -0
  237. package/dist/rules/implementation/IMP-022.js.map +1 -0
  238. package/dist/rules/index.d.ts +73 -6
  239. package/dist/rules/index.js +141 -6
  240. package/dist/rules/index.js.map +1 -1
  241. package/dist/rules/schema/SCHEMA-004.d.ts +9 -0
  242. package/dist/rules/schema/SCHEMA-004.js +57 -0
  243. package/dist/rules/schema/SCHEMA-004.js.map +1 -0
  244. package/dist/rules/schema/SCHEMA-005.d.ts +9 -0
  245. package/dist/rules/schema/SCHEMA-005.js +61 -0
  246. package/dist/rules/schema/SCHEMA-005.js.map +1 -0
  247. package/dist/rules/schema/SCHEMA-006.d.ts +10 -0
  248. package/dist/rules/schema/SCHEMA-006.js +85 -0
  249. package/dist/rules/schema/SCHEMA-006.js.map +1 -0
  250. package/dist/rules/schema/SCHEMA-007.d.ts +9 -0
  251. package/dist/rules/schema/SCHEMA-007.js +73 -0
  252. package/dist/rules/schema/SCHEMA-007.js.map +1 -0
  253. package/dist/rules/schema/SCHEMA-008.d.ts +9 -0
  254. package/dist/rules/schema/SCHEMA-008.js +70 -0
  255. package/dist/rules/schema/SCHEMA-008.js.map +1 -0
  256. package/dist/rules/schema/SCHEMA-009.d.ts +10 -0
  257. package/dist/rules/schema/SCHEMA-009.js +80 -0
  258. package/dist/rules/schema/SCHEMA-009.js.map +1 -0
  259. package/dist/rules/schema/SCHEMA-010.d.ts +9 -0
  260. package/dist/rules/schema/SCHEMA-010.js +96 -0
  261. package/dist/rules/schema/SCHEMA-010.js.map +1 -0
  262. package/dist/rules/schema/SCHEMA-012.d.ts +9 -0
  263. package/dist/rules/schema/SCHEMA-012.js +65 -0
  264. package/dist/rules/schema/SCHEMA-012.js.map +1 -0
  265. package/dist/rules/security/SEC-002.d.ts +8 -0
  266. package/dist/rules/security/SEC-002.js +81 -0
  267. package/dist/rules/security/SEC-002.js.map +1 -0
  268. package/dist/rules/security/SEC-003.d.ts +8 -0
  269. package/dist/rules/security/SEC-003.js +85 -0
  270. package/dist/rules/security/SEC-003.js.map +1 -0
  271. package/dist/rules/security/SEC-004.d.ts +9 -0
  272. package/dist/rules/security/SEC-004.js +87 -0
  273. package/dist/rules/security/SEC-004.js.map +1 -0
  274. package/dist/rules/security/SEC-005.d.ts +8 -0
  275. package/dist/rules/security/SEC-005.js +87 -0
  276. package/dist/rules/security/SEC-005.js.map +1 -0
  277. package/dist/rules/security/SEC-006.d.ts +10 -0
  278. package/dist/rules/security/SEC-006.js +108 -0
  279. package/dist/rules/security/SEC-006.js.map +1 -0
  280. package/dist/rules/security/SEC-007.d.ts +9 -0
  281. package/dist/rules/security/SEC-007.js +108 -0
  282. package/dist/rules/security/SEC-007.js.map +1 -0
  283. package/dist/rules/security/SEC-008.d.ts +8 -0
  284. package/dist/rules/security/SEC-008.js +109 -0
  285. package/dist/rules/security/SEC-008.js.map +1 -0
  286. package/dist/rules/security/SEC-009.d.ts +9 -0
  287. package/dist/rules/security/SEC-009.js +93 -0
  288. package/dist/rules/security/SEC-009.js.map +1 -0
  289. package/dist/rules/security/SEC-010.d.ts +8 -0
  290. package/dist/rules/security/SEC-010.js +78 -0
  291. package/dist/rules/security/SEC-010.js.map +1 -0
  292. package/dist/rules/security/SEC-011.d.ts +8 -0
  293. package/dist/rules/security/SEC-011.js +93 -0
  294. package/dist/rules/security/SEC-011.js.map +1 -0
  295. package/dist/rules/security/SEC-012.d.ts +8 -0
  296. package/dist/rules/security/SEC-012.js +79 -0
  297. package/dist/rules/security/SEC-012.js.map +1 -0
  298. package/dist/rules/security/SEC-013.d.ts +9 -0
  299. package/dist/rules/security/SEC-013.js +107 -0
  300. package/dist/rules/security/SEC-013.js.map +1 -0
  301. package/dist/scoring/calculator.js +1 -0
  302. package/dist/scoring/calculator.js.map +1 -1
  303. package/dist/ui/ink/components/AIRecommendationCard.d.ts +11 -0
  304. package/dist/ui/ink/components/AIRecommendationCard.js +23 -0
  305. package/dist/ui/ink/components/AIRecommendationCard.js.map +1 -0
  306. package/dist/ui/ink/components/OpportunityList.d.ts +10 -0
  307. package/dist/ui/ink/components/OpportunityList.js +48 -0
  308. package/dist/ui/ink/components/OpportunityList.js.map +1 -0
  309. package/dist/ui/ink/components/PotentialPageCard.d.ts +13 -0
  310. package/dist/ui/ink/components/PotentialPageCard.js +43 -0
  311. package/dist/ui/ink/components/PotentialPageCard.js.map +1 -0
  312. package/dist/ui/ink/components/PotentialProgress.d.ts +16 -0
  313. package/dist/ui/ink/components/PotentialProgress.js +44 -0
  314. package/dist/ui/ink/components/PotentialProgress.js.map +1 -0
  315. package/dist/ui/ink/components/PotentialSummary.d.ts +10 -0
  316. package/dist/ui/ink/components/PotentialSummary.js +86 -0
  317. package/dist/ui/ink/components/PotentialSummary.js.map +1 -0
  318. package/dist/ui/ink/components/SuggestionCard.d.ts +34 -0
  319. package/dist/ui/ink/components/SuggestionCard.js +36 -0
  320. package/dist/ui/ink/components/SuggestionCard.js.map +1 -0
  321. package/dist/ui/ink/components/views/MultiPageCrawlView.d.ts +21 -0
  322. package/dist/ui/ink/components/views/MultiPageCrawlView.js +55 -0
  323. package/dist/ui/ink/components/views/MultiPageCrawlView.js.map +1 -0
  324. package/dist/ui/ink/components/views/PotentialView.d.ts +18 -0
  325. package/dist/ui/ink/components/views/PotentialView.js +74 -0
  326. package/dist/ui/ink/components/views/PotentialView.js.map +1 -0
  327. package/dist/ui/ink/components/views/ReconView.d.ts +22 -0
  328. package/dist/ui/ink/components/views/ReconView.js +30 -0
  329. package/dist/ui/ink/components/views/ReconView.js.map +1 -0
  330. package/package.json +2 -1
@@ -0,0 +1,49 @@
1
+ import * as cheerio from 'cheerio';
2
+ const NON_PAGE_EXTENSIONS = /\.(?:avif|bmp|gif|ico|jpe?g|png|svg|webp|pdf|docx?|pptx?|xlsx?|zip|rar|7z|tar|gz|mp3|mp4|mpe?g|mov|avi|wmv|ogg|wav|css|js|json|xml|txt|woff2?|ttf|eot)$/i;
3
+ const BLOCKED_PROTOCOLS = /^(?:mailto:|tel:|javascript:|data:)/i;
4
+ function normalizeLink(url, baseUrl, allowedOrigin) {
5
+ const trimmed = url.trim();
6
+ if (!trimmed || trimmed.startsWith('#') || BLOCKED_PROTOCOLS.test(trimmed)) {
7
+ return null;
8
+ }
9
+ try {
10
+ const resolved = new URL(trimmed, baseUrl);
11
+ if (resolved.origin !== allowedOrigin) {
12
+ return null;
13
+ }
14
+ // Skip static assets and known non-page resources
15
+ if (NON_PAGE_EXTENSIONS.test(resolved.pathname)) {
16
+ return null;
17
+ }
18
+ resolved.hash = '';
19
+ if (resolved.pathname.length > 1 && resolved.pathname.endsWith('/')) {
20
+ resolved.pathname = resolved.pathname.slice(0, -1);
21
+ }
22
+ return resolved.href;
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ export function extractInternalLinks(html, baseUrl) {
29
+ let allowedOrigin;
30
+ try {
31
+ allowedOrigin = new URL(baseUrl).origin;
32
+ }
33
+ catch {
34
+ return [];
35
+ }
36
+ const $ = cheerio.load(html);
37
+ const links = new Set();
38
+ $('a[href]').each((_index, element) => {
39
+ const href = $(element).attr('href');
40
+ if (!href)
41
+ return;
42
+ const normalized = normalizeLink(href, baseUrl, allowedOrigin);
43
+ if (normalized) {
44
+ links.add(normalized);
45
+ }
46
+ });
47
+ return [...links];
48
+ }
49
+ //# sourceMappingURL=link-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-extractor.js","sourceRoot":"","sources":["../../src/crawler/link-extractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAEnC,MAAM,mBAAmB,GAAG,0JAA0J,CAAC;AACvL,MAAM,iBAAiB,GAAG,sCAAsC,CAAC;AAEjE,SAAS,aAAa,CAAC,GAAW,EAAE,OAAe,EAAE,aAAqB;IACxE,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAE3C,IAAI,QAAQ,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,kDAAkD;QAClD,IAAI,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC;QACnB,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACpE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,OAAe;IAChE,IAAI,aAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,aAAa,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QACpC,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC;QAC/D,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Report Generators
3
+ */
4
+ export { generateJsonReport } from './report-json.js';
5
+ export type { AuditReportJson } from './report-json.js';
6
+ export { generateHtmlReport } from './report-html.js';
7
+ export { generateReports } from './report-manager.js';
8
+ export type { ReportOptions, ReportOutput } from './report-manager.js';
9
+ export { generateToolCode, generateAllToolCode, generateCombinedCode, } from './tool-code-generator.js';
10
+ export type { GeneratedCode } from './tool-code-generator.js';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Report Generators
3
+ */
4
+ export { generateJsonReport } from './report-json.js';
5
+ export { generateHtmlReport } from './report-html.js';
6
+ export { generateReports } from './report-manager.js';
7
+ export { generateToolCode, generateAllToolCode, generateCombinedCode, } from './tool-code-generator.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generators/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * HTML Report Generator
3
+ *
4
+ * Generates a standalone, self-contained HTML audit report with embedded CSS/JS.
5
+ */
6
+ import type { AuditResult } from '../core/types/index.js';
7
+ /**
8
+ * Generate a self-contained HTML audit report.
9
+ *
10
+ * @returns Absolute path to the written file.
11
+ */
12
+ export declare function generateHtmlReport(auditResult: AuditResult, outputDir: string): Promise<string>;
@@ -0,0 +1,470 @@
1
+ /**
2
+ * HTML Report Generator
3
+ *
4
+ * Generates a standalone, self-contained HTML audit report with embedded CSS/JS.
5
+ */
6
+ import { writeFile } from 'fs/promises';
7
+ import { join } from 'path';
8
+ /* ------------------------------------------------------------------ */
9
+ /* Helpers */
10
+ /* ------------------------------------------------------------------ */
11
+ function escapeHtml(text) {
12
+ return text
13
+ .replace(/&/g, '&amp;')
14
+ .replace(/</g, '&lt;')
15
+ .replace(/>/g, '&gt;')
16
+ .replace(/"/g, '&quot;')
17
+ .replace(/'/g, '&#039;');
18
+ }
19
+ function severityColor(severity) {
20
+ switch (severity) {
21
+ case 'critical':
22
+ return '#ef4444';
23
+ case 'warning':
24
+ return '#f59e0b';
25
+ case 'info':
26
+ return '#3b82f6';
27
+ default:
28
+ return '#6b7280';
29
+ }
30
+ }
31
+ function severityBg(severity) {
32
+ switch (severity) {
33
+ case 'critical':
34
+ return '#fef2f2';
35
+ case 'warning':
36
+ return '#fffbeb';
37
+ case 'info':
38
+ return '#eff6ff';
39
+ default:
40
+ return '#f9fafb';
41
+ }
42
+ }
43
+ function gradeColor(grade) {
44
+ if (grade.startsWith('A'))
45
+ return '#22c55e';
46
+ if (grade.startsWith('B'))
47
+ return '#84cc16';
48
+ if (grade.startsWith('C'))
49
+ return '#f59e0b';
50
+ if (grade === 'D')
51
+ return '#f97316';
52
+ return '#ef4444';
53
+ }
54
+ function formatDuration(ms) {
55
+ if (ms < 1000)
56
+ return `${ms}ms`;
57
+ return `${(ms / 1000).toFixed(1)}s`;
58
+ }
59
+ /* ------------------------------------------------------------------ */
60
+ /* Section Renderers */
61
+ /* ------------------------------------------------------------------ */
62
+ function renderCss() {
63
+ return `
64
+ :root {
65
+ --bg: #0f172a;
66
+ --surface: #1e293b;
67
+ --surface-2: #334155;
68
+ --border: #475569;
69
+ --text: #f1f5f9;
70
+ --text-dim: #94a3b8;
71
+ --accent: #38bdf8;
72
+ --green: #22c55e;
73
+ --red: #ef4444;
74
+ --yellow: #f59e0b;
75
+ --blue: #3b82f6;
76
+ --orange: #f97316;
77
+ }
78
+ * { margin: 0; padding: 0; box-sizing: border-box; }
79
+ body {
80
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
81
+ background: var(--bg);
82
+ color: var(--text);
83
+ line-height: 1.6;
84
+ padding: 2rem;
85
+ max-width: 1100px;
86
+ margin: 0 auto;
87
+ }
88
+ h1, h2, h3 { font-weight: 600; }
89
+ h1 { font-size: 1.5rem; color: var(--accent); }
90
+ h2 { font-size: 1.25rem; margin-bottom: 1rem; color: var(--text); border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; }
91
+ h3 { font-size: 1rem; color: var(--text-dim); }
92
+ a { color: var(--accent); text-decoration: none; }
93
+ a:hover { text-decoration: underline; }
94
+
95
+ .header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2rem; }
96
+ .header-left { display: flex; align-items: center; gap: 1rem; }
97
+ .header-meta { color: var(--text-dim); font-size: 0.85rem; }
98
+
99
+ .grade-badge {
100
+ display: inline-flex; align-items: center; justify-content: center;
101
+ width: 72px; height: 72px; border-radius: 50%;
102
+ font-size: 1.75rem; font-weight: 700;
103
+ border: 3px solid;
104
+ }
105
+ .score-number { font-size: 2.5rem; font-weight: 700; }
106
+
107
+ .summary-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2rem; }
108
+ .card {
109
+ background: var(--surface); border-radius: 8px; padding: 1.25rem;
110
+ border: 1px solid var(--border);
111
+ }
112
+ .card-label { font-size: 0.8rem; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.25rem; }
113
+ .card-value { font-size: 1.5rem; font-weight: 700; }
114
+
115
+ .section { background: var(--surface); border-radius: 8px; padding: 1.5rem; margin-bottom: 1.5rem; border: 1px solid var(--border); }
116
+
117
+ .cat-bar { margin-bottom: 0.75rem; }
118
+ .cat-bar-header { display: flex; justify-content: space-between; font-size: 0.85rem; margin-bottom: 0.25rem; }
119
+ .cat-bar-track { background: var(--surface-2); border-radius: 4px; height: 8px; overflow: hidden; }
120
+ .cat-bar-fill { height: 100%; border-radius: 4px; transition: width 0.6s ease; }
121
+
122
+ table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
123
+ th { text-align: left; padding: 0.5rem 0.75rem; color: var(--text-dim); font-weight: 500; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; border-bottom: 1px solid var(--border); }
124
+ td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--surface-2); vertical-align: top; }
125
+ tr:last-child td { border-bottom: none; }
126
+
127
+ .severity-badge {
128
+ display: inline-block; padding: 0.15rem 0.5rem; border-radius: 4px;
129
+ font-size: 0.75rem; font-weight: 600; text-transform: uppercase;
130
+ }
131
+
132
+ .tool-card { background: var(--surface-2); border-radius: 6px; padding: 1rem; margin-bottom: 0.75rem; }
133
+ .tool-name { font-weight: 600; color: var(--accent); }
134
+ .tool-source { font-size: 0.75rem; padding: 0.1rem 0.4rem; border-radius: 3px; background: var(--surface); color: var(--text-dim); }
135
+ .tool-desc { color: var(--text-dim); font-size: 0.9rem; margin: 0.25rem 0; }
136
+ .param-list { list-style: none; font-size: 0.85rem; color: var(--text-dim); margin-top: 0.5rem; }
137
+ .param-list li { padding: 0.15rem 0; }
138
+ .param-list li::before { content: '\\251C\\2500\\2500 '; font-family: monospace; color: var(--border); }
139
+ .param-list li:last-child::before { content: '\\2514\\2500\\2500 '; }
140
+
141
+ .rec-list { list-style: none; counter-reset: rec; }
142
+ .rec-item { padding: 0.75rem 0; border-bottom: 1px solid var(--surface-2); display: flex; gap: 0.75rem; align-items: flex-start; }
143
+ .rec-item:last-child { border-bottom: none; }
144
+ .rec-num { display: flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; background: var(--accent); color: var(--bg); font-weight: 700; font-size: 0.85rem; flex-shrink: 0; }
145
+ .rec-impact { color: var(--green); font-weight: 600; font-size: 0.85rem; }
146
+ .rec-effort { font-size: 0.75rem; padding: 0.1rem 0.4rem; border-radius: 3px; }
147
+
148
+ .filters { display: flex; gap: 0.5rem; margin-bottom: 1rem; flex-wrap: wrap; }
149
+ .filter-btn {
150
+ padding: 0.3rem 0.75rem; border-radius: 4px; border: 1px solid var(--border);
151
+ background: transparent; color: var(--text-dim); cursor: pointer; font-size: 0.8rem;
152
+ transition: all 0.2s;
153
+ }
154
+ .filter-btn:hover, .filter-btn.active { background: var(--accent); color: var(--bg); border-color: var(--accent); }
155
+
156
+ .collapsible summary {
157
+ cursor: pointer; list-style: none; display: flex; align-items: center; gap: 0.5rem;
158
+ }
159
+ .collapsible summary::before { content: '\\25B6'; font-size: 0.7rem; transition: transform 0.2s; }
160
+ .collapsible[open] summary::before { transform: rotate(90deg); }
161
+ .collapsible-content { padding-top: 0.75rem; }
162
+
163
+ .footer { text-align: center; color: var(--text-dim); font-size: 0.8rem; margin-top: 2rem; padding-top: 1rem; border-top: 1px solid var(--border); }
164
+
165
+ @media print {
166
+ body { background: #fff; color: #000; }
167
+ .section { border-color: #ddd; }
168
+ .filter-btn { display: none; }
169
+ }
170
+ `;
171
+ }
172
+ function renderJs() {
173
+ return `
174
+ document.addEventListener('DOMContentLoaded', () => {
175
+ // Severity filters
176
+ const filterBtns = document.querySelectorAll('.filter-btn[data-severity]');
177
+ const findingRows = document.querySelectorAll('.finding-row');
178
+
179
+ let activeFilters = new Set(['critical', 'warning', 'info']);
180
+
181
+ filterBtns.forEach(btn => {
182
+ btn.classList.add('active');
183
+ btn.addEventListener('click', () => {
184
+ const severity = btn.dataset.severity;
185
+ if (severity === 'all') {
186
+ activeFilters = new Set(['critical', 'warning', 'info']);
187
+ filterBtns.forEach(b => b.classList.add('active'));
188
+ } else {
189
+ if (activeFilters.has(severity)) {
190
+ activeFilters.delete(severity);
191
+ btn.classList.remove('active');
192
+ } else {
193
+ activeFilters.add(severity);
194
+ btn.classList.add('active');
195
+ }
196
+ // Update "all" button
197
+ const allBtn = document.querySelector('.filter-btn[data-severity="all"]');
198
+ if (allBtn) {
199
+ allBtn.classList.toggle('active', activeFilters.size === 3);
200
+ }
201
+ }
202
+
203
+ findingRows.forEach(row => {
204
+ row.style.display = activeFilters.has(row.dataset.severity) ? '' : 'none';
205
+ });
206
+ });
207
+ });
208
+ });
209
+ `;
210
+ }
211
+ function renderExecutiveSummary(result) {
212
+ const gc = gradeColor(result.score.grade);
213
+ const { critical, warning, info } = result.score.issueCount;
214
+ return `
215
+ <div class="header">
216
+ <div class="header-left">
217
+ <div>
218
+ <h1>WebMCP Audit Report</h1>
219
+ <div class="header-meta">
220
+ <a href="${escapeHtml(result.url)}" target="_blank">${escapeHtml(result.url)}</a><br>
221
+ ${escapeHtml(result.startedAt.toLocaleString())} &middot; ${formatDuration(result.duration)} &middot; v${escapeHtml(result.cliVersion)}
222
+ </div>
223
+ </div>
224
+ </div>
225
+ <div style="text-align:center">
226
+ <div class="grade-badge" style="color:${gc}; border-color:${gc};">${escapeHtml(result.score.grade)}</div>
227
+ <div class="score-number" style="color:${gc};">${result.score.total}</div>
228
+ <div style="color:var(--text-dim); font-size:0.8rem;">out of 100</div>
229
+ </div>
230
+ </div>
231
+
232
+ <div class="summary-cards">
233
+ <div class="card">
234
+ <div class="card-label">Tools Detected</div>
235
+ <div class="card-value" style="color:var(--accent);">${result.tools.length}</div>
236
+ </div>
237
+ <div class="card">
238
+ <div class="card-label">Opportunities</div>
239
+ <div class="card-value" style="color:var(--yellow);">${result.opportunities.length}</div>
240
+ </div>
241
+ <div class="card">
242
+ <div class="card-label">Critical Issues</div>
243
+ <div class="card-value" style="color:var(--red);">${critical}</div>
244
+ </div>
245
+ <div class="card">
246
+ <div class="card-label">Warnings</div>
247
+ <div class="card-value" style="color:var(--yellow);">${warning}</div>
248
+ </div>
249
+ <div class="card">
250
+ <div class="card-label">Info</div>
251
+ <div class="card-value" style="color:var(--blue);">${info}</div>
252
+ </div>
253
+ <div class="card">
254
+ <div class="card-label">WebMCP API</div>
255
+ <div class="card-value" style="color:${result.hasWebMCP ? 'var(--green)' : 'var(--red)'};">${result.hasWebMCP ? 'Detected' : 'Not Found'}</div>
256
+ </div>
257
+ </div>
258
+ `;
259
+ }
260
+ function renderCategoryBars(categories) {
261
+ const bars = categories
262
+ .map((cat) => {
263
+ const pct = cat.percentage;
264
+ const color = pct >= 80 ? 'var(--green)' : pct >= 60 ? 'var(--yellow)' : 'var(--red)';
265
+ return `
266
+ <div class="cat-bar">
267
+ <div class="cat-bar-header">
268
+ <span>${escapeHtml(cat.name)}</span>
269
+ <span>${pct}% (${cat.score}/${cat.maxScore})</span>
270
+ </div>
271
+ <div class="cat-bar-track">
272
+ <div class="cat-bar-fill" style="width:${pct}%; background:${color};"></div>
273
+ </div>
274
+ </div>
275
+ `;
276
+ })
277
+ .join('');
278
+ return `
279
+ <div class="section">
280
+ <h2>Score Breakdown</h2>
281
+ ${bars}
282
+ </div>
283
+ `;
284
+ }
285
+ function renderFindings(findings) {
286
+ if (findings.length === 0) {
287
+ return `
288
+ <div class="section">
289
+ <h2>Findings</h2>
290
+ <p style="color:var(--green);">No issues found. Great job!</p>
291
+ </div>
292
+ `;
293
+ }
294
+ const rows = findings
295
+ .map((f) => {
296
+ const sc = severityColor(f.severity);
297
+ const sb = severityBg(f.severity);
298
+ return `
299
+ <tr class="finding-row" data-severity="${f.severity}">
300
+ <td><span class="severity-badge" style="background:${sb}; color:${sc};">${escapeHtml(f.severity)}</span></td>
301
+ <td style="font-family:monospace; font-size:0.8rem;">${escapeHtml(f.ruleId)}</td>
302
+ <td>${escapeHtml(f.message)}</td>
303
+ <td style="color:var(--text-dim);">${escapeHtml(f.tool ?? f.page ?? '—')}</td>
304
+ <td style="color:var(--text-dim);">${f.fix ? escapeHtml(f.fix) : '—'}</td>
305
+ <td style="text-align:right;">${f.scoreImpact > 0 ? `<span style="color:var(--red);">-${f.scoreImpact}</span>` : '—'}</td>
306
+ </tr>
307
+ `;
308
+ })
309
+ .join('');
310
+ return `
311
+ <div class="section">
312
+ <h2>Findings (${findings.length})</h2>
313
+ <div class="filters">
314
+ <button class="filter-btn active" data-severity="all">All</button>
315
+ <button class="filter-btn active" data-severity="critical">Critical</button>
316
+ <button class="filter-btn active" data-severity="warning">Warning</button>
317
+ <button class="filter-btn active" data-severity="info">Info</button>
318
+ </div>
319
+ <table>
320
+ <thead>
321
+ <tr>
322
+ <th>Severity</th>
323
+ <th>Rule</th>
324
+ <th>Issue</th>
325
+ <th>Tool / Page</th>
326
+ <th>Suggested Fix</th>
327
+ <th style="text-align:right;">Impact</th>
328
+ </tr>
329
+ </thead>
330
+ <tbody>
331
+ ${rows}
332
+ </tbody>
333
+ </table>
334
+ </div>
335
+ `;
336
+ }
337
+ function renderToolCard(tool) {
338
+ const params = tool.inputSchema?.properties
339
+ ? Object.entries(tool.inputSchema.properties)
340
+ .map(([name, schema]) => {
341
+ const s = schema;
342
+ const required = tool.inputSchema?.required?.includes(name);
343
+ return `<li><code>${escapeHtml(name)}</code> <span style="color:var(--text-dim);">(${escapeHtml(String(s['type'] ?? 'any'))}${required ? ', required' : ''})</span>${s['description'] ? ` — ${escapeHtml(String(s['description']))}` : ''}</li>`;
344
+ })
345
+ .join('')
346
+ : '<li style="color:var(--text-dim);">No parameters defined</li>';
347
+ return `
348
+ <div class="tool-card">
349
+ <div style="display:flex; align-items:center; gap:0.5rem;">
350
+ <span class="tool-name">${escapeHtml(tool.name)}</span>
351
+ <span class="tool-source">${escapeHtml(tool.source)}</span>
352
+ ${tool.hasExecute ? '<span class="tool-source" style="color:var(--green);">executable</span>' : ''}
353
+ </div>
354
+ <div class="tool-desc">${escapeHtml(tool.description || '(no description)')}</div>
355
+ <ul class="param-list">${params}</ul>
356
+ </div>
357
+ `;
358
+ }
359
+ function renderToolInventory(tools) {
360
+ if (tools.length === 0) {
361
+ return `
362
+ <div class="section">
363
+ <h2>Tool Inventory</h2>
364
+ <p style="color:var(--text-dim);">No tools detected on this site.</p>
365
+ </div>
366
+ `;
367
+ }
368
+ const imperative = tools.filter((t) => t.source === 'imperative');
369
+ const declarative = tools.filter((t) => t.source === 'declarative');
370
+ let content = '<h2>Tool Inventory (' + tools.length + ')</h2>';
371
+ if (imperative.length > 0) {
372
+ content += `<h3 style="margin:0.75rem 0 0.5rem;">Imperative (JavaScript API) — ${imperative.length}</h3>`;
373
+ content += imperative.map(renderToolCard).join('');
374
+ }
375
+ if (declarative.length > 0) {
376
+ content += `<h3 style="margin:0.75rem 0 0.5rem;">Declarative (HTML Forms) — ${declarative.length}</h3>`;
377
+ content += declarative.map(renderToolCard).join('');
378
+ }
379
+ return `<div class="section">${content}</div>`;
380
+ }
381
+ function renderRecommendations(recs) {
382
+ if (recs.length === 0)
383
+ return '';
384
+ const effortColor = (e) => e === 'low' ? 'var(--green)' : e === 'medium' ? 'var(--yellow)' : 'var(--red)';
385
+ const items = recs
386
+ .slice(0, 10)
387
+ .map((r) => `
388
+ <div class="rec-item">
389
+ <div class="rec-num">${r.priority}</div>
390
+ <div style="flex:1;">
391
+ <div>${escapeHtml(r.action)}</div>
392
+ <div style="margin-top:0.25rem;">
393
+ <span class="rec-impact">+${r.scoreImpact} pts</span>
394
+ <span class="rec-effort" style="background:var(--surface-2); color:${effortColor(r.effort)}; margin-left:0.5rem;">${r.effort} effort</span>
395
+ <span style="color:var(--text-dim); font-size:0.8rem; margin-left:0.5rem;">${escapeHtml(r.ruleId)}</span>
396
+ </div>
397
+ </div>
398
+ </div>
399
+ `)
400
+ .join('');
401
+ return `
402
+ <div class="section">
403
+ <h2>Top Recommendations</h2>
404
+ <div class="rec-list">${items}</div>
405
+ </div>
406
+ `;
407
+ }
408
+ function renderPages(result) {
409
+ if (result.pages.length <= 1)
410
+ return '';
411
+ const rows = result.pages
412
+ .map((p) => `
413
+ <details class="collapsible" style="margin-bottom:0.5rem;">
414
+ <summary>
415
+ <span style="color:${p.hasWebMCP ? 'var(--green)' : 'var(--text-dim)'};">${p.hasWebMCP ? '●' : '○'}</span>
416
+ <span>${escapeHtml(p.title || p.url)}</span>
417
+ <span style="color:var(--text-dim); font-size:0.8rem;">${p.toolCount} tools, ${p.formCount} forms</span>
418
+ </summary>
419
+ <div class="collapsible-content" style="padding-left:1.5rem; font-size:0.85rem; color:var(--text-dim);">
420
+ <div>URL: <a href="${escapeHtml(p.url)}" target="_blank">${escapeHtml(p.url)}</a></div>
421
+ <div>WebMCP: ${p.hasWebMCP ? 'Yes' : 'No'} · Tools: ${p.toolCount} · Forms: ${p.formCount} · Opportunities: ${p.opportunityCount}</div>
422
+ </div>
423
+ </details>
424
+ `)
425
+ .join('');
426
+ return `
427
+ <div class="section">
428
+ <h2>Pages Analyzed (${result.pages.length})</h2>
429
+ ${rows}
430
+ </div>
431
+ `;
432
+ }
433
+ /* ------------------------------------------------------------------ */
434
+ /* Main Generator */
435
+ /* ------------------------------------------------------------------ */
436
+ /**
437
+ * Generate a self-contained HTML audit report.
438
+ *
439
+ * @returns Absolute path to the written file.
440
+ */
441
+ export async function generateHtmlReport(auditResult, outputDir) {
442
+ const html = `<!DOCTYPE html>
443
+ <html lang="en">
444
+ <head>
445
+ <meta charset="UTF-8">
446
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
447
+ <title>WebMCP Audit — ${escapeHtml(auditResult.url)} — ${auditResult.score.grade} (${auditResult.score.total}/100)</title>
448
+ <style>${renderCss()}</style>
449
+ </head>
450
+ <body>
451
+ ${renderExecutiveSummary(auditResult)}
452
+ ${renderCategoryBars(auditResult.score.categories)}
453
+ ${renderFindings(auditResult.findings)}
454
+ ${renderToolInventory(auditResult.tools)}
455
+ ${renderRecommendations(auditResult.recommendations)}
456
+ ${renderPages(auditResult)}
457
+
458
+ <div class="footer">
459
+ Generated by <strong>webmcp-cli</strong> v${escapeHtml(auditResult.cliVersion)} &middot;
460
+ <a href="https://webmcp.org" target="_blank">webmcp.org</a>
461
+ </div>
462
+
463
+ <script>${renderJs()}</script>
464
+ </body>
465
+ </html>`;
466
+ const filePath = join(outputDir, 'audit-report.html');
467
+ await writeFile(filePath, html, 'utf-8');
468
+ return filePath;
469
+ }
470
+ //# sourceMappingURL=report-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-html.js","sourceRoot":"","sources":["../../src/generators/report-html.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * JSON Report Generator
3
+ *
4
+ * Generates a machine-readable JSON audit report.
5
+ */
6
+ import type { AuditResult } from '../core/types/index.js';
7
+ export interface AuditReportJson {
8
+ meta: {
9
+ tool: string;
10
+ version: string;
11
+ timestamp: string;
12
+ targetUrl: string;
13
+ auditDuration: number;
14
+ };
15
+ score: {
16
+ total: number;
17
+ grade: string;
18
+ categories: Record<string, {
19
+ score: number;
20
+ maxScore: number;
21
+ percentage: number;
22
+ weight: number;
23
+ rulesChecked: number;
24
+ rulesPassed: number;
25
+ }>;
26
+ };
27
+ pages: Array<{
28
+ url: string;
29
+ title: string;
30
+ hasWebMCP: boolean;
31
+ toolCount: number;
32
+ formCount: number;
33
+ opportunityCount: number;
34
+ }>;
35
+ tools: {
36
+ existing: SerializedTool[];
37
+ opportunities: SerializedOpportunity[];
38
+ };
39
+ findings: SerializedFinding[];
40
+ recommendations: SerializedRecommendation[];
41
+ summary: {
42
+ totalFindings: number;
43
+ critical: number;
44
+ warnings: number;
45
+ info: number;
46
+ topActions: string[];
47
+ };
48
+ }
49
+ interface SerializedTool {
50
+ name: string;
51
+ description: string;
52
+ source: 'imperative' | 'declarative';
53
+ pageUrl: string;
54
+ hasExecute?: boolean;
55
+ registrationMethod?: string;
56
+ inputSchema?: Record<string, unknown>;
57
+ annotations?: Record<string, unknown>;
58
+ }
59
+ interface SerializedOpportunity {
60
+ index: number;
61
+ sensitivity: string;
62
+ agenticValue: string;
63
+ fieldCount: number;
64
+ contextClues: {
65
+ formAction: string | null;
66
+ formMethod: string;
67
+ submitText: string | null;
68
+ nearestHeading: string | null;
69
+ fieldNames: string[];
70
+ };
71
+ }
72
+ interface SerializedFinding {
73
+ ruleId: string;
74
+ severity: string;
75
+ message: string;
76
+ tool?: string;
77
+ page?: string;
78
+ fix?: string;
79
+ scoreImpact: number;
80
+ }
81
+ interface SerializedRecommendation {
82
+ priority: number;
83
+ action: string;
84
+ scoreImpact: number;
85
+ effort: string;
86
+ ruleId: string;
87
+ affectedTools?: string[];
88
+ }
89
+ /**
90
+ * Generate machine-readable JSON report file.
91
+ *
92
+ * @returns Absolute path to the written file.
93
+ */
94
+ export declare function generateJsonReport(auditResult: AuditResult, outputDir: string): Promise<string>;
95
+ export {};