uxinspect 0.2.0 → 0.11.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 (493) hide show
  1. package/README.md +332 -22
  2. package/dist/a11y-filter.d.ts +15 -0
  3. package/dist/a11y-filter.d.ts.map +1 -0
  4. package/dist/a11y-filter.js +107 -0
  5. package/dist/a11y-filter.js.map +1 -0
  6. package/dist/ab-compare.d.ts +23 -0
  7. package/dist/ab-compare.d.ts.map +1 -0
  8. package/dist/ab-compare.js +340 -0
  9. package/dist/ab-compare.js.map +1 -0
  10. package/dist/ai-codegen.d.ts +30 -0
  11. package/dist/ai-codegen.d.ts.map +1 -0
  12. package/dist/ai-codegen.js +296 -0
  13. package/dist/ai-codegen.js.map +1 -0
  14. package/dist/ai-triage.d.ts +26 -0
  15. package/dist/ai-triage.d.ts.map +1 -0
  16. package/dist/ai-triage.js +207 -0
  17. package/dist/ai-triage.js.map +1 -0
  18. package/dist/amp.d.ts +32 -0
  19. package/dist/amp.d.ts.map +1 -0
  20. package/dist/amp.js +179 -0
  21. package/dist/amp.js.map +1 -0
  22. package/dist/animation-audit.d.ts +25 -0
  23. package/dist/animation-audit.d.ts.map +1 -0
  24. package/dist/animation-audit.js +296 -0
  25. package/dist/animation-audit.js.map +1 -0
  26. package/dist/api.d.ts +3 -0
  27. package/dist/api.d.ts.map +1 -0
  28. package/dist/api.js +85 -0
  29. package/dist/api.js.map +1 -0
  30. package/dist/aria-audit.d.ts +20 -0
  31. package/dist/aria-audit.d.ts.map +1 -0
  32. package/dist/aria-audit.js +445 -0
  33. package/dist/aria-audit.js.map +1 -0
  34. package/dist/assertions.d.ts +30 -0
  35. package/dist/assertions.d.ts.map +1 -0
  36. package/dist/assertions.js +342 -0
  37. package/dist/assertions.js.map +1 -0
  38. package/dist/autofix.d.ts +40 -0
  39. package/dist/autofix.d.ts.map +1 -0
  40. package/dist/autofix.js +244 -0
  41. package/dist/autofix.js.map +1 -0
  42. package/dist/badge.d.ts +27 -0
  43. package/dist/badge.d.ts.map +1 -0
  44. package/dist/badge.js +183 -0
  45. package/dist/badge.js.map +1 -0
  46. package/dist/baseline-drift.d.ts +43 -0
  47. package/dist/baseline-drift.d.ts.map +1 -0
  48. package/dist/baseline-drift.js +208 -0
  49. package/dist/baseline-drift.js.map +1 -0
  50. package/dist/bdd.d.ts +31 -0
  51. package/dist/bdd.d.ts.map +1 -0
  52. package/dist/bdd.js +316 -0
  53. package/dist/bdd.js.map +1 -0
  54. package/dist/bisect.d.ts +32 -0
  55. package/dist/bisect.d.ts.map +1 -0
  56. package/dist/bisect.js +253 -0
  57. package/dist/bisect.js.map +1 -0
  58. package/dist/budget-diff.d.ts +37 -0
  59. package/dist/budget-diff.d.ts.map +1 -0
  60. package/dist/budget-diff.js +273 -0
  61. package/dist/budget-diff.js.map +1 -0
  62. package/dist/budget-file.d.ts +15 -0
  63. package/dist/budget-file.d.ts.map +1 -0
  64. package/dist/budget-file.js +185 -0
  65. package/dist/budget-file.js.map +1 -0
  66. package/dist/bundle-size.d.ts +36 -0
  67. package/dist/bundle-size.d.ts.map +1 -0
  68. package/dist/bundle-size.js +347 -0
  69. package/dist/bundle-size.js.map +1 -0
  70. package/dist/cache-headers.d.ts +33 -0
  71. package/dist/cache-headers.d.ts.map +1 -0
  72. package/dist/cache-headers.js +270 -0
  73. package/dist/cache-headers.js.map +1 -0
  74. package/dist/canonical-audit.d.ts +19 -0
  75. package/dist/canonical-audit.d.ts.map +1 -0
  76. package/dist/canonical-audit.js +196 -0
  77. package/dist/canonical-audit.js.map +1 -0
  78. package/dist/chaos.d.ts +38 -0
  79. package/dist/chaos.d.ts.map +1 -0
  80. package/dist/chaos.js +348 -0
  81. package/dist/chaos.js.map +1 -0
  82. package/dist/cli.js +201 -23
  83. package/dist/cli.js.map +1 -1
  84. package/dist/clickjacking-audit.d.ts +18 -0
  85. package/dist/clickjacking-audit.d.ts.map +1 -0
  86. package/dist/clickjacking-audit.js +231 -0
  87. package/dist/clickjacking-audit.js.map +1 -0
  88. package/dist/cls-culprit.d.ts +36 -0
  89. package/dist/cls-culprit.d.ts.map +1 -0
  90. package/dist/cls-culprit.js +203 -0
  91. package/dist/cls-culprit.js.map +1 -0
  92. package/dist/cls-timeline.d.ts +30 -0
  93. package/dist/cls-timeline.d.ts.map +1 -0
  94. package/dist/cls-timeline.js +61 -0
  95. package/dist/cls-timeline.js.map +1 -0
  96. package/dist/codegen-converter.d.ts +19 -0
  97. package/dist/codegen-converter.d.ts.map +1 -0
  98. package/dist/codegen-converter.js +464 -0
  99. package/dist/codegen-converter.js.map +1 -0
  100. package/dist/compression.d.ts +14 -0
  101. package/dist/compression.d.ts.map +1 -0
  102. package/dist/compression.js +150 -0
  103. package/dist/compression.js.map +1 -0
  104. package/dist/console-errors.d.ts +24 -0
  105. package/dist/console-errors.d.ts.map +1 -0
  106. package/dist/console-errors.js +96 -0
  107. package/dist/console-errors.js.map +1 -0
  108. package/dist/content-quality.d.ts +34 -0
  109. package/dist/content-quality.d.ts.map +1 -0
  110. package/dist/content-quality.js +124 -0
  111. package/dist/content-quality.js.map +1 -0
  112. package/dist/contract-openapi.d.ts +74 -0
  113. package/dist/contract-openapi.d.ts.map +1 -0
  114. package/dist/contract-openapi.js +305 -0
  115. package/dist/contract-openapi.js.map +1 -0
  116. package/dist/cookie-banner.d.ts +27 -0
  117. package/dist/cookie-banner.d.ts.map +1 -0
  118. package/dist/cookie-banner.js +285 -0
  119. package/dist/cookie-banner.js.map +1 -0
  120. package/dist/cookie-flags-audit.d.ts +35 -0
  121. package/dist/cookie-flags-audit.d.ts.map +1 -0
  122. package/dist/cookie-flags-audit.js +167 -0
  123. package/dist/cookie-flags-audit.js.map +1 -0
  124. package/dist/cpu-throttle.d.ts +34 -0
  125. package/dist/cpu-throttle.d.ts.map +1 -0
  126. package/dist/cpu-throttle.js +149 -0
  127. package/dist/cpu-throttle.js.map +1 -0
  128. package/dist/crawl.d.ts +29 -0
  129. package/dist/crawl.d.ts.map +1 -0
  130. package/dist/crawl.js +153 -0
  131. package/dist/crawl.js.map +1 -0
  132. package/dist/critical-css.d.ts +25 -0
  133. package/dist/critical-css.d.ts.map +1 -0
  134. package/dist/critical-css.js +353 -0
  135. package/dist/critical-css.js.map +1 -0
  136. package/dist/cross-browser.d.ts +44 -0
  137. package/dist/cross-browser.d.ts.map +1 -0
  138. package/dist/cross-browser.js +300 -0
  139. package/dist/cross-browser.js.map +1 -0
  140. package/dist/csrf-audit.d.ts +33 -0
  141. package/dist/csrf-audit.d.ts.map +1 -0
  142. package/dist/csrf-audit.js +276 -0
  143. package/dist/csrf-audit.js.map +1 -0
  144. package/dist/css-coverage.d.ts +20 -0
  145. package/dist/css-coverage.d.ts.map +1 -0
  146. package/dist/css-coverage.js +91 -0
  147. package/dist/css-coverage.js.map +1 -0
  148. package/dist/csv-exporter.d.ts +34 -0
  149. package/dist/csv-exporter.d.ts.map +1 -0
  150. package/dist/csv-exporter.js +241 -0
  151. package/dist/csv-exporter.js.map +1 -0
  152. package/dist/dark-mode-audit.d.ts +31 -0
  153. package/dist/dark-mode-audit.d.ts.map +1 -0
  154. package/dist/dark-mode-audit.js +236 -0
  155. package/dist/dark-mode-audit.js.map +1 -0
  156. package/dist/dead-images.d.ts +18 -0
  157. package/dist/dead-images.d.ts.map +1 -0
  158. package/dist/dead-images.js +236 -0
  159. package/dist/dead-images.js.map +1 -0
  160. package/dist/deadclicks.d.ts +19 -0
  161. package/dist/deadclicks.d.ts.map +1 -0
  162. package/dist/deadclicks.js +109 -0
  163. package/dist/deadclicks.js.map +1 -0
  164. package/dist/discord-formatter.d.ts +39 -0
  165. package/dist/discord-formatter.d.ts.map +1 -0
  166. package/dist/discord-formatter.js +191 -0
  167. package/dist/discord-formatter.js.map +1 -0
  168. package/dist/dom-audit.d.ts +23 -0
  169. package/dist/dom-audit.d.ts.map +1 -0
  170. package/dist/dom-audit.js +111 -0
  171. package/dist/dom-audit.js.map +1 -0
  172. package/dist/driver.d.ts.map +1 -1
  173. package/dist/driver.js +10 -0
  174. package/dist/driver.js.map +1 -1
  175. package/dist/error-page-audit.d.ts +26 -0
  176. package/dist/error-page-audit.d.ts.map +1 -0
  177. package/dist/error-page-audit.js +219 -0
  178. package/dist/error-page-audit.js.map +1 -0
  179. package/dist/event-listener-audit.d.ts +22 -0
  180. package/dist/event-listener-audit.d.ts.map +1 -0
  181. package/dist/event-listener-audit.js +156 -0
  182. package/dist/event-listener-audit.js.map +1 -0
  183. package/dist/exposed-paths.d.ts +21 -0
  184. package/dist/exposed-paths.d.ts.map +1 -0
  185. package/dist/exposed-paths.js +116 -0
  186. package/dist/exposed-paths.js.map +1 -0
  187. package/dist/favicon-audit.d.ts +28 -0
  188. package/dist/favicon-audit.d.ts.map +1 -0
  189. package/dist/favicon-audit.js +358 -0
  190. package/dist/favicon-audit.js.map +1 -0
  191. package/dist/flaky-detector.d.ts +32 -0
  192. package/dist/flaky-detector.d.ts.map +1 -0
  193. package/dist/flaky-detector.js +254 -0
  194. package/dist/flaky-detector.js.map +1 -0
  195. package/dist/flaky.d.ts +28 -0
  196. package/dist/flaky.d.ts.map +1 -0
  197. package/dist/flaky.js +106 -0
  198. package/dist/flaky.js.map +1 -0
  199. package/dist/focus-trap-audit.d.ts +29 -0
  200. package/dist/focus-trap-audit.d.ts.map +1 -0
  201. package/dist/focus-trap-audit.js +285 -0
  202. package/dist/focus-trap-audit.js.map +1 -0
  203. package/dist/font-loading.d.ts +29 -0
  204. package/dist/font-loading.d.ts.map +1 -0
  205. package/dist/font-loading.js +216 -0
  206. package/dist/font-loading.js.map +1 -0
  207. package/dist/forms-audit.d.ts +23 -0
  208. package/dist/forms-audit.d.ts.map +1 -0
  209. package/dist/forms-audit.js +147 -0
  210. package/dist/forms-audit.js.map +1 -0
  211. package/dist/github-annotations.d.ts +17 -0
  212. package/dist/github-annotations.d.ts.map +1 -0
  213. package/dist/github-annotations.js +264 -0
  214. package/dist/github-annotations.js.map +1 -0
  215. package/dist/graphql.d.ts +60 -0
  216. package/dist/graphql.d.ts.map +1 -0
  217. package/dist/graphql.js +188 -0
  218. package/dist/graphql.js.map +1 -0
  219. package/dist/har-waterfall.d.ts +37 -0
  220. package/dist/har-waterfall.d.ts.map +1 -0
  221. package/dist/har-waterfall.js +376 -0
  222. package/dist/har-waterfall.js.map +1 -0
  223. package/dist/heading-hierarchy.d.ts +20 -0
  224. package/dist/heading-hierarchy.d.ts.map +1 -0
  225. package/dist/heading-hierarchy.js +112 -0
  226. package/dist/heading-hierarchy.js.map +1 -0
  227. package/dist/headless-detect.d.ts +22 -0
  228. package/dist/headless-detect.d.ts.map +1 -0
  229. package/dist/headless-detect.js +167 -0
  230. package/dist/headless-detect.js.map +1 -0
  231. package/dist/history-timeline.d.ts +13 -0
  232. package/dist/history-timeline.d.ts.map +1 -0
  233. package/dist/history-timeline.js +327 -0
  234. package/dist/history-timeline.js.map +1 -0
  235. package/dist/hreflang-audit.d.ts +26 -0
  236. package/dist/hreflang-audit.d.ts.map +1 -0
  237. package/dist/hreflang-audit.js +273 -0
  238. package/dist/hreflang-audit.js.map +1 -0
  239. package/dist/hydration-audit.d.ts +21 -0
  240. package/dist/hydration-audit.d.ts.map +1 -0
  241. package/dist/hydration-audit.js +277 -0
  242. package/dist/hydration-audit.js.map +1 -0
  243. package/dist/image-audit.d.ts +41 -0
  244. package/dist/image-audit.d.ts.map +1 -0
  245. package/dist/image-audit.js +229 -0
  246. package/dist/image-audit.js.map +1 -0
  247. package/dist/index.d.ts +119 -0
  248. package/dist/index.d.ts.map +1 -1
  249. package/dist/index.js +708 -2
  250. package/dist/index.js.map +1 -1
  251. package/dist/init-wizard.d.ts +33 -0
  252. package/dist/init-wizard.d.ts.map +1 -0
  253. package/dist/init-wizard.js +289 -0
  254. package/dist/init-wizard.js.map +1 -0
  255. package/dist/inp-audit.d.ts +26 -0
  256. package/dist/inp-audit.d.ts.map +1 -0
  257. package/dist/inp-audit.js +202 -0
  258. package/dist/inp-audit.js.map +1 -0
  259. package/dist/js-coverage.d.ts +20 -0
  260. package/dist/js-coverage.d.ts.map +1 -0
  261. package/dist/js-coverage.js +81 -0
  262. package/dist/js-coverage.js.map +1 -0
  263. package/dist/json-schema.d.ts +27 -0
  264. package/dist/json-schema.d.ts.map +1 -0
  265. package/dist/json-schema.js +284 -0
  266. package/dist/json-schema.js.map +1 -0
  267. package/dist/keyboard.d.ts +21 -0
  268. package/dist/keyboard.d.ts.map +1 -0
  269. package/dist/keyboard.js +119 -0
  270. package/dist/keyboard.js.map +1 -0
  271. package/dist/lang-audit.d.ts +24 -0
  272. package/dist/lang-audit.d.ts.map +1 -0
  273. package/dist/lang-audit.js +141 -0
  274. package/dist/lang-audit.js.map +1 -0
  275. package/dist/lcp-element.d.ts +22 -0
  276. package/dist/lcp-element.d.ts.map +1 -0
  277. package/dist/lcp-element.js +240 -0
  278. package/dist/lcp-element.js.map +1 -0
  279. package/dist/longtasks.d.ts +38 -0
  280. package/dist/longtasks.d.ts.map +1 -0
  281. package/dist/longtasks.js +97 -0
  282. package/dist/longtasks.js.map +1 -0
  283. package/dist/mailbox.d.ts +35 -0
  284. package/dist/mailbox.d.ts.map +1 -0
  285. package/dist/mailbox.js +207 -0
  286. package/dist/mailbox.js.map +1 -0
  287. package/dist/media-audit.d.ts +20 -0
  288. package/dist/media-audit.d.ts.map +1 -0
  289. package/dist/media-audit.js +182 -0
  290. package/dist/media-audit.js.map +1 -0
  291. package/dist/metrics-exporter.d.ts +23 -0
  292. package/dist/metrics-exporter.d.ts.map +1 -0
  293. package/dist/metrics-exporter.js +297 -0
  294. package/dist/metrics-exporter.js.map +1 -0
  295. package/dist/mixed-content.d.ts +19 -0
  296. package/dist/mixed-content.d.ts.map +1 -0
  297. package/dist/mixed-content.js +86 -0
  298. package/dist/mixed-content.js.map +1 -0
  299. package/dist/motion-prefs.d.ts +21 -0
  300. package/dist/motion-prefs.d.ts.map +1 -0
  301. package/dist/motion-prefs.js +170 -0
  302. package/dist/motion-prefs.js.map +1 -0
  303. package/dist/open-graph.d.ts +40 -0
  304. package/dist/open-graph.d.ts.map +1 -0
  305. package/dist/open-graph.js +200 -0
  306. package/dist/open-graph.js.map +1 -0
  307. package/dist/orphan-assets.d.ts +17 -0
  308. package/dist/orphan-assets.d.ts.map +1 -0
  309. package/dist/orphan-assets.js +174 -0
  310. package/dist/orphan-assets.js.map +1 -0
  311. package/dist/page-object.d.ts +18 -0
  312. package/dist/page-object.d.ts.map +1 -0
  313. package/dist/page-object.js +346 -0
  314. package/dist/page-object.js.map +1 -0
  315. package/dist/pagination-audit.d.ts +24 -0
  316. package/dist/pagination-audit.d.ts.map +1 -0
  317. package/dist/pagination-audit.js +285 -0
  318. package/dist/pagination-audit.js.map +1 -0
  319. package/dist/passive-security.d.ts +19 -0
  320. package/dist/passive-security.d.ts.map +1 -0
  321. package/dist/passive-security.js +149 -0
  322. package/dist/passive-security.js.map +1 -0
  323. package/dist/pr-comment.d.ts +13 -0
  324. package/dist/pr-comment.d.ts.map +1 -0
  325. package/dist/pr-comment.js +316 -0
  326. package/dist/pr-comment.js.map +1 -0
  327. package/dist/precommit.d.ts +24 -0
  328. package/dist/precommit.d.ts.map +1 -0
  329. package/dist/precommit.js +239 -0
  330. package/dist/precommit.js.map +1 -0
  331. package/dist/prerender-audit.d.ts +22 -0
  332. package/dist/prerender-audit.d.ts.map +1 -0
  333. package/dist/prerender-audit.js +158 -0
  334. package/dist/prerender-audit.js.map +1 -0
  335. package/dist/print-audit.d.ts +21 -0
  336. package/dist/print-audit.d.ts.map +1 -0
  337. package/dist/print-audit.js +281 -0
  338. package/dist/print-audit.js.map +1 -0
  339. package/dist/protocol-audit.d.ts +17 -0
  340. package/dist/protocol-audit.d.ts.map +1 -0
  341. package/dist/protocol-audit.js +128 -0
  342. package/dist/protocol-audit.js.map +1 -0
  343. package/dist/reading-level.d.ts +37 -0
  344. package/dist/reading-level.d.ts.map +1 -0
  345. package/dist/reading-level.js +220 -0
  346. package/dist/reading-level.js.map +1 -0
  347. package/dist/redirects.d.ts +24 -0
  348. package/dist/redirects.d.ts.map +1 -0
  349. package/dist/redirects.js +119 -0
  350. package/dist/redirects.js.map +1 -0
  351. package/dist/report.d.ts +1 -1
  352. package/dist/report.d.ts.map +1 -1
  353. package/dist/report.js +736 -1
  354. package/dist/report.js.map +1 -1
  355. package/dist/reporter-plugin.d.ts +32 -0
  356. package/dist/reporter-plugin.d.ts.map +1 -0
  357. package/dist/reporter-plugin.js +120 -0
  358. package/dist/reporter-plugin.js.map +1 -0
  359. package/dist/resource-hints.d.ts +23 -0
  360. package/dist/resource-hints.d.ts.map +1 -0
  361. package/dist/resource-hints.js +225 -0
  362. package/dist/resource-hints.js.map +1 -0
  363. package/dist/retire.d.ts +22 -0
  364. package/dist/retire.d.ts.map +1 -0
  365. package/dist/retire.js +140 -0
  366. package/dist/retire.js.map +1 -0
  367. package/dist/retry.d.ts +20 -0
  368. package/dist/retry.d.ts.map +1 -0
  369. package/dist/retry.js +120 -0
  370. package/dist/retry.js.map +1 -0
  371. package/dist/robots-audit.d.ts +24 -0
  372. package/dist/robots-audit.d.ts.map +1 -0
  373. package/dist/robots-audit.js +206 -0
  374. package/dist/robots-audit.js.map +1 -0
  375. package/dist/rum.d.ts +35 -0
  376. package/dist/rum.d.ts.map +1 -0
  377. package/dist/rum.js +219 -0
  378. package/dist/rum.js.map +1 -0
  379. package/dist/schedule.d.ts +30 -0
  380. package/dist/schedule.d.ts.map +1 -0
  381. package/dist/schedule.js +238 -0
  382. package/dist/schedule.js.map +1 -0
  383. package/dist/secret-scan.d.ts +24 -0
  384. package/dist/secret-scan.d.ts.map +1 -0
  385. package/dist/secret-scan.js +202 -0
  386. package/dist/secret-scan.js.map +1 -0
  387. package/dist/service-worker.d.ts +26 -0
  388. package/dist/service-worker.d.ts.map +1 -0
  389. package/dist/service-worker.js +179 -0
  390. package/dist/service-worker.js.map +1 -0
  391. package/dist/shard.d.ts +14 -0
  392. package/dist/shard.d.ts.map +1 -0
  393. package/dist/shard.js +72 -0
  394. package/dist/shard.js.map +1 -0
  395. package/dist/sitemap-flows.d.ts +13 -0
  396. package/dist/sitemap-flows.d.ts.map +1 -0
  397. package/dist/sitemap-flows.js +157 -0
  398. package/dist/sitemap-flows.js.map +1 -0
  399. package/dist/sitemap.d.ts +27 -0
  400. package/dist/sitemap.d.ts.map +1 -0
  401. package/dist/sitemap.js +137 -0
  402. package/dist/sitemap.js.map +1 -0
  403. package/dist/slack-formatter.d.ts +35 -0
  404. package/dist/slack-formatter.d.ts.map +1 -0
  405. package/dist/slack-formatter.js +193 -0
  406. package/dist/slack-formatter.js.map +1 -0
  407. package/dist/sourcemap-scan.d.ts +24 -0
  408. package/dist/sourcemap-scan.d.ts.map +1 -0
  409. package/dist/sourcemap-scan.js +232 -0
  410. package/dist/sourcemap-scan.js.map +1 -0
  411. package/dist/sri-audit.d.ts +23 -0
  412. package/dist/sri-audit.d.ts.map +1 -0
  413. package/dist/sri-audit.js +180 -0
  414. package/dist/sri-audit.js.map +1 -0
  415. package/dist/storage-audit.d.ts +28 -0
  416. package/dist/storage-audit.d.ts.map +1 -0
  417. package/dist/storage-audit.js +263 -0
  418. package/dist/storage-audit.js.map +1 -0
  419. package/dist/storybook.d.ts +48 -0
  420. package/dist/storybook.d.ts.map +1 -0
  421. package/dist/storybook.js +191 -0
  422. package/dist/storybook.js.map +1 -0
  423. package/dist/structured-data.d.ts +25 -0
  424. package/dist/structured-data.d.ts.map +1 -0
  425. package/dist/structured-data.js +164 -0
  426. package/dist/structured-data.js.map +1 -0
  427. package/dist/svg-audit.d.ts +20 -0
  428. package/dist/svg-audit.d.ts.map +1 -0
  429. package/dist/svg-audit.js +213 -0
  430. package/dist/svg-audit.js.map +1 -0
  431. package/dist/table-audit.d.ts +18 -0
  432. package/dist/table-audit.d.ts.map +1 -0
  433. package/dist/table-audit.js +188 -0
  434. package/dist/table-audit.js.map +1 -0
  435. package/dist/teams-formatter.d.ts +66 -0
  436. package/dist/teams-formatter.d.ts.map +1 -0
  437. package/dist/teams-formatter.js +194 -0
  438. package/dist/teams-formatter.js.map +1 -0
  439. package/dist/third-party.d.ts +35 -0
  440. package/dist/third-party.d.ts.map +1 -0
  441. package/dist/third-party.js +175 -0
  442. package/dist/third-party.js.map +1 -0
  443. package/dist/tls.d.ts +33 -0
  444. package/dist/tls.d.ts.map +1 -0
  445. package/dist/tls.js +122 -0
  446. package/dist/tls.js.map +1 -0
  447. package/dist/touchtargets.d.ts +22 -0
  448. package/dist/touchtargets.d.ts.map +1 -0
  449. package/dist/touchtargets.js +80 -0
  450. package/dist/touchtargets.js.map +1 -0
  451. package/dist/tracker-sniff.d.ts +25 -0
  452. package/dist/tracker-sniff.d.ts.map +1 -0
  453. package/dist/tracker-sniff.js +355 -0
  454. package/dist/tracker-sniff.js.map +1 -0
  455. package/dist/types.d.ts +265 -1
  456. package/dist/types.d.ts.map +1 -1
  457. package/dist/visual-mask.d.ts +33 -0
  458. package/dist/visual-mask.d.ts.map +1 -0
  459. package/dist/visual-mask.js +102 -0
  460. package/dist/visual-mask.js.map +1 -0
  461. package/dist/visual-ssim.d.ts +26 -0
  462. package/dist/visual-ssim.d.ts.map +1 -0
  463. package/dist/visual-ssim.js +153 -0
  464. package/dist/visual-ssim.js.map +1 -0
  465. package/dist/watch-mode.d.ts +10 -0
  466. package/dist/watch-mode.d.ts.map +1 -0
  467. package/dist/watch-mode.js +156 -0
  468. package/dist/watch-mode.js.map +1 -0
  469. package/dist/web-worker-audit.d.ts +27 -0
  470. package/dist/web-worker-audit.d.ts.map +1 -0
  471. package/dist/web-worker-audit.js +324 -0
  472. package/dist/web-worker-audit.js.map +1 -0
  473. package/dist/webfonts.d.ts +26 -0
  474. package/dist/webfonts.d.ts.map +1 -0
  475. package/dist/webfonts.js +244 -0
  476. package/dist/webfonts.js.map +1 -0
  477. package/dist/webhook-reporter.d.ts +20 -0
  478. package/dist/webhook-reporter.d.ts.map +1 -0
  479. package/dist/webhook-reporter.js +124 -0
  480. package/dist/webhook-reporter.js.map +1 -0
  481. package/dist/websocket.d.ts +39 -0
  482. package/dist/websocket.d.ts.map +1 -0
  483. package/dist/websocket.js +233 -0
  484. package/dist/websocket.js.map +1 -0
  485. package/dist/worker-runtime.d.ts +129 -0
  486. package/dist/worker-runtime.d.ts.map +1 -0
  487. package/dist/worker-runtime.js +414 -0
  488. package/dist/worker-runtime.js.map +1 -0
  489. package/dist/zindex-audit.d.ts +28 -0
  490. package/dist/zindex-audit.d.ts.map +1 -0
  491. package/dist/zindex-audit.js +291 -0
  492. package/dist/zindex-audit.js.map +1 -0
  493. package/package.json +10 -2
@@ -0,0 +1,342 @@
1
+ const SUPPORTED_OPS = ['<=', '>=', '==', '!=', '<', '>'];
2
+ const SUPPORTED_PATHS = [
3
+ 'perf.lcp',
4
+ 'perf.cls',
5
+ 'perf.tbt',
6
+ 'perf.fcp',
7
+ 'perf.si',
8
+ 'perf.scores.performance',
9
+ 'perf.scores.accessibility',
10
+ 'perf.scores.bestPractices',
11
+ 'perf.scores.seo',
12
+ 'a11y.critical',
13
+ 'a11y.serious',
14
+ 'a11y.moderate',
15
+ 'a11y.minor',
16
+ 'a11y.total',
17
+ 'visual.maxDiffRatio',
18
+ 'visual.failed',
19
+ 'flows.failed',
20
+ 'flows.total',
21
+ 'flows.passed',
22
+ 'links.broken',
23
+ 'consoleErrors.count',
24
+ 'consoleErrors.errors',
25
+ 'consoleErrors.warnings',
26
+ 'passed',
27
+ ];
28
+ export function listSupportedPaths() {
29
+ return SUPPORTED_PATHS;
30
+ }
31
+ export function parseAssertion(expr) {
32
+ if (typeof expr !== 'string')
33
+ throw new Error(`invalid assertion: ${String(expr)}`);
34
+ const raw = expr.trim();
35
+ if (!raw)
36
+ throw new Error(`invalid assertion: ${expr}`);
37
+ let op;
38
+ let rest = '';
39
+ for (const candidate of SUPPORTED_OPS) {
40
+ if (raw.startsWith(candidate)) {
41
+ op = candidate;
42
+ rest = raw.slice(candidate.length).trim();
43
+ break;
44
+ }
45
+ }
46
+ if (!op)
47
+ throw new Error(`invalid assertion: ${expr}`);
48
+ if (!rest)
49
+ throw new Error(`invalid assertion: ${expr}`);
50
+ const lower = rest.toLowerCase();
51
+ if (lower === 'true' || lower === 'false')
52
+ return { op, threshold: lower === 'true' };
53
+ if (lower === 'null')
54
+ return { op, threshold: null };
55
+ const unitMatch = rest.match(/^(-?\d+(?:\.\d+)?)(ms|s|%)?$/i);
56
+ if (unitMatch) {
57
+ const num = Number(unitMatch[1]);
58
+ if (!Number.isFinite(num))
59
+ throw new Error(`invalid assertion: ${expr}`);
60
+ const unit = unitMatch[2]?.toLowerCase();
61
+ if (unit === 's')
62
+ return { op, threshold: num * 1000, unit: 's' };
63
+ if (unit === '%')
64
+ return { op, threshold: num / 100, unit: '%' };
65
+ if (unit === 'ms')
66
+ return { op, threshold: num, unit: 'ms' };
67
+ return { op, threshold: num };
68
+ }
69
+ const stringMatch = rest.match(/^['"](.*)['"]$/);
70
+ if (stringMatch)
71
+ return { op, threshold: stringMatch[1] };
72
+ throw new Error(`invalid assertion: ${expr}`);
73
+ }
74
+ function mean(values) {
75
+ if (!values.length)
76
+ return undefined;
77
+ let sum = 0;
78
+ for (const v of values)
79
+ sum += v;
80
+ return sum / values.length;
81
+ }
82
+ function sum(values) {
83
+ let total = 0;
84
+ for (const v of values)
85
+ total += v;
86
+ return total;
87
+ }
88
+ function perfMetric(perf, key) {
89
+ if (!perf || !perf.length)
90
+ return undefined;
91
+ return mean(perf.map((p) => p.metrics[key]));
92
+ }
93
+ function perfScore(perf, key) {
94
+ if (!perf || !perf.length)
95
+ return undefined;
96
+ return mean(perf.map((p) => p.scores[key]));
97
+ }
98
+ function a11yCount(a11y, impact) {
99
+ if (!a11y)
100
+ return 0;
101
+ let count = 0;
102
+ for (const r of a11y) {
103
+ for (const v of r.violations) {
104
+ if (v.impact === impact)
105
+ count++;
106
+ }
107
+ }
108
+ return count;
109
+ }
110
+ function a11yTotal(a11y) {
111
+ if (!a11y)
112
+ return 0;
113
+ let count = 0;
114
+ for (const r of a11y)
115
+ count += r.violations.length;
116
+ return count;
117
+ }
118
+ function visualMaxDiff(visual) {
119
+ if (!visual || !visual.length)
120
+ return undefined;
121
+ let max = 0;
122
+ for (const v of visual) {
123
+ if (v.diffRatio > max)
124
+ max = v.diffRatio;
125
+ }
126
+ return max;
127
+ }
128
+ function visualFailed(visual) {
129
+ if (!visual)
130
+ return 0;
131
+ return visual.filter((v) => v.passed === false).length;
132
+ }
133
+ function flowsFailed(flows) {
134
+ if (!flows)
135
+ return 0;
136
+ return flows.filter((f) => f.passed === false).length;
137
+ }
138
+ function flowsPassed(flows) {
139
+ if (!flows)
140
+ return 0;
141
+ return flows.filter((f) => f.passed === true).length;
142
+ }
143
+ export function resolveMetric(result, path) {
144
+ switch (path) {
145
+ case 'perf.lcp':
146
+ return perfMetric(result.perf, 'lcp');
147
+ case 'perf.cls':
148
+ return perfMetric(result.perf, 'cls');
149
+ case 'perf.tbt':
150
+ return perfMetric(result.perf, 'tbt');
151
+ case 'perf.fcp':
152
+ return perfMetric(result.perf, 'fcp');
153
+ case 'perf.si':
154
+ return perfMetric(result.perf, 'si');
155
+ case 'perf.scores.performance':
156
+ return perfScore(result.perf, 'performance');
157
+ case 'perf.scores.accessibility':
158
+ return perfScore(result.perf, 'accessibility');
159
+ case 'perf.scores.bestPractices':
160
+ return perfScore(result.perf, 'bestPractices');
161
+ case 'perf.scores.seo':
162
+ return perfScore(result.perf, 'seo');
163
+ case 'a11y.critical':
164
+ return a11yCount(result.a11y, 'critical');
165
+ case 'a11y.serious':
166
+ return a11yCount(result.a11y, 'serious');
167
+ case 'a11y.moderate':
168
+ return a11yCount(result.a11y, 'moderate');
169
+ case 'a11y.minor':
170
+ return a11yCount(result.a11y, 'minor');
171
+ case 'a11y.total':
172
+ return a11yTotal(result.a11y);
173
+ case 'visual.maxDiffRatio':
174
+ return visualMaxDiff(result.visual);
175
+ case 'visual.failed':
176
+ return visualFailed(result.visual);
177
+ case 'flows.failed':
178
+ return flowsFailed(result.flows);
179
+ case 'flows.total':
180
+ return result.flows?.length ?? 0;
181
+ case 'flows.passed':
182
+ return flowsPassed(result.flows);
183
+ case 'links.broken': {
184
+ const links = result.links;
185
+ if (!links)
186
+ return 0;
187
+ return sum(links.map((l) => l.broken.length));
188
+ }
189
+ case 'consoleErrors.count': {
190
+ const ce = result.consoleErrors;
191
+ if (!ce)
192
+ return 0;
193
+ return sum(ce.map((c) => c.issues.length));
194
+ }
195
+ case 'consoleErrors.errors': {
196
+ const ce = result.consoleErrors;
197
+ if (!ce)
198
+ return 0;
199
+ return sum(ce.map((c) => c.errorCount));
200
+ }
201
+ case 'consoleErrors.warnings': {
202
+ const ce = result.consoleErrors;
203
+ if (!ce)
204
+ return 0;
205
+ return sum(ce.map((c) => c.warningCount));
206
+ }
207
+ case 'passed':
208
+ return result.passed;
209
+ default:
210
+ return undefined;
211
+ }
212
+ }
213
+ function compareNumbers(actual, op, threshold) {
214
+ switch (op) {
215
+ case '<': return actual < threshold;
216
+ case '<=': return actual <= threshold;
217
+ case '>': return actual > threshold;
218
+ case '>=': return actual >= threshold;
219
+ case '==': return actual === threshold;
220
+ case '!=': return actual !== threshold;
221
+ }
222
+ }
223
+ function compareBooleans(actual, op, threshold) {
224
+ if (op === '==')
225
+ return actual === threshold;
226
+ if (op === '!=')
227
+ return actual !== threshold;
228
+ throw new Error(`operator ${op} not allowed for boolean values`);
229
+ }
230
+ function compareStrings(actual, op, threshold) {
231
+ if (op === '==')
232
+ return actual === threshold;
233
+ if (op === '!=')
234
+ return actual !== threshold;
235
+ throw new Error(`operator ${op} not allowed for string values`);
236
+ }
237
+ function compareNulls(actual, op) {
238
+ if (op === '==')
239
+ return actual === null;
240
+ if (op === '!=')
241
+ return actual !== null;
242
+ throw new Error(`operator ${op} not allowed for null values`);
243
+ }
244
+ function evaluateOne(path, expr, actual, parsed) {
245
+ const { op, threshold, unit } = parsed;
246
+ if (threshold === null) {
247
+ const ok = compareNulls(actual, op);
248
+ if (ok)
249
+ return undefined;
250
+ return { path, expected: expr, actual, op, threshold, unit };
251
+ }
252
+ if (actual === undefined) {
253
+ return { path, expected: expr, actual: undefined, op, threshold, unit };
254
+ }
255
+ if (typeof threshold === 'boolean') {
256
+ if (typeof actual !== 'boolean') {
257
+ return { path, expected: expr, actual, op, threshold, unit };
258
+ }
259
+ if (compareBooleans(actual, op, threshold))
260
+ return undefined;
261
+ return { path, expected: expr, actual, op, threshold, unit };
262
+ }
263
+ if (typeof threshold === 'string') {
264
+ if (typeof actual !== 'string') {
265
+ return { path, expected: expr, actual, op, threshold, unit };
266
+ }
267
+ if (compareStrings(actual, op, threshold))
268
+ return undefined;
269
+ return { path, expected: expr, actual, op, threshold, unit };
270
+ }
271
+ if (typeof threshold === 'number') {
272
+ if (typeof actual !== 'number' || !Number.isFinite(actual)) {
273
+ return { path, expected: expr, actual, op, threshold, unit };
274
+ }
275
+ if (compareNumbers(actual, op, threshold))
276
+ return undefined;
277
+ return { path, expected: expr, actual, op, threshold, unit };
278
+ }
279
+ return { path, expected: expr, actual, op, threshold, unit };
280
+ }
281
+ export function evaluateAssertions(result, spec) {
282
+ const violations = [];
283
+ for (const path of Object.keys(spec)) {
284
+ const expr = spec[path];
285
+ if (typeof expr !== 'string') {
286
+ violations.push({ path, expected: String(expr), actual: undefined, op: '==', threshold: null });
287
+ continue;
288
+ }
289
+ let parsed;
290
+ try {
291
+ parsed = parseAssertion(expr);
292
+ }
293
+ catch {
294
+ violations.push({ path, expected: expr, actual: undefined, op: '==', threshold: null });
295
+ continue;
296
+ }
297
+ const actual = resolveMetric(result, path);
298
+ let violation;
299
+ try {
300
+ violation = evaluateOne(path, expr, actual, parsed);
301
+ }
302
+ catch {
303
+ violation = { path, expected: expr, actual, op: parsed.op, threshold: parsed.threshold, unit: parsed.unit };
304
+ }
305
+ if (violation)
306
+ violations.push(violation);
307
+ }
308
+ return { passed: violations.length === 0, violations };
309
+ }
310
+ function formatValue(v, unit) {
311
+ if (v === undefined)
312
+ return '<unavailable>';
313
+ if (v === null)
314
+ return 'null';
315
+ if (typeof v === 'boolean')
316
+ return v ? 'true' : 'false';
317
+ if (typeof v === 'string')
318
+ return JSON.stringify(v);
319
+ if (typeof v === 'number') {
320
+ const rounded = Number.isInteger(v) ? v.toString() : v.toFixed(3);
321
+ if (unit === 'ms')
322
+ return `${rounded}ms`;
323
+ if (unit === 's')
324
+ return `${rounded}ms`;
325
+ if (unit === '%')
326
+ return rounded;
327
+ return rounded;
328
+ }
329
+ return String(v);
330
+ }
331
+ export function formatAssertionFailures(violations) {
332
+ if (!violations.length)
333
+ return '';
334
+ const lines = [];
335
+ lines.push(`${violations.length} assertion${violations.length === 1 ? '' : 's'} failed:`);
336
+ for (const v of violations) {
337
+ const actualStr = formatValue(v.actual, v.unit);
338
+ lines.push(` - ${v.path} expected ${v.expected}, got ${actualStr}`);
339
+ }
340
+ return lines.join('\n');
341
+ }
342
+ //# sourceMappingURL=assertions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertions.js","sourceRoot":"","sources":["../src/assertions.ts"],"names":[],"mappings":"AA6BA,MAAM,aAAa,GAAe,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAErE,MAAM,eAAe,GAAsB;IACzC,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,SAAS;IACT,yBAAyB;IACzB,2BAA2B;IAC3B,2BAA2B;IAC3B,iBAAiB;IACjB,eAAe;IACf,cAAc;IACd,eAAe;IACf,YAAY;IACZ,YAAY;IACZ,qBAAqB;IACrB,eAAe;IACf,cAAc;IACd,aAAa;IACb,cAAc;IACd,cAAc;IACd,qBAAqB;IACrB,sBAAsB;IACtB,wBAAwB;IACxB,QAAQ;CACA,CAAC;AAEX,MAAM,UAAU,kBAAkB;IAChC,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpF,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACxB,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;IACxD,IAAI,EAAwB,CAAC;IAC7B,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,KAAK,MAAM,SAAS,IAAI,aAAa,EAAE,CAAC;QACtC,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,EAAE,GAAG,SAAS,CAAC;YACf,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1C,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;IACvD,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,KAAK,MAAM,EAAE,CAAC;IACtF,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACrD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC9D,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;QACzE,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QACzC,IAAI,IAAI,KAAK,GAAG;YAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,GAAG,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAClE,IAAI,IAAI,KAAK,GAAG;YAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QACjE,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC7D,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;IAChC,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACjD,IAAI,WAAW;QAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1D,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,IAAI,CAAC,MAAgB;IAC5B,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACrC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,GAAG,IAAI,CAAC,CAAC;IACjC,OAAO,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;AAC7B,CAAC;AAED,SAAS,GAAG,CAAC,MAAgB;IAC3B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,KAAK,IAAI,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CAAC,IAAuC,EAAE,GAAgC;IAC3F,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,SAAS,CAAC,IAAuC,EAAE,GAA+B;IACzF,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,SAAS,CAAC,IAAuC,EAAE,MAAqD;IAC/G,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC;IACpB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;YAC7B,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;gBAAE,KAAK,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,SAAS,CAAC,IAAuC;IACxD,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC;IACpB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,IAAI;QAAE,KAAK,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC;IACnD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CAAC,MAA2C;IAChE,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAChD,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;YAAE,GAAG,GAAG,CAAC,CAAC,SAAS,CAAC;IAC3C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,YAAY,CAAC,MAA2C;IAC/D,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC;AACzD,CAAC;AAED,SAAS,WAAW,CAAC,KAAwC;IAC3D,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC;AACxD,CAAC;AAED,SAAS,WAAW,CAAC,KAAwC;IAC3D,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAqB,EAAE,IAAY;IAC/D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU;YACb,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxC,KAAK,UAAU;YACb,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxC,KAAK,UAAU;YACb,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxC,KAAK,UAAU;YACb,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxC,KAAK,SAAS;YACZ,OAAO,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACvC,KAAK,yBAAyB;YAC5B,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QAC/C,KAAK,2BAA2B;YAC9B,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QACjD,KAAK,2BAA2B;YAC9B,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QACjD,KAAK,iBAAiB;YACpB,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvC,KAAK,eAAe;YAClB,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC5C,KAAK,cAAc;YACjB,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC3C,KAAK,eAAe;YAClB,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC5C,KAAK,YAAY;YACf,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzC,KAAK,YAAY;YACf,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChC,KAAK,qBAAqB;YACxB,OAAO,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtC,KAAK,eAAe;YAClB,OAAO,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACrC,KAAK,cAAc;YACjB,OAAO,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,KAAK,aAAa;YAChB,OAAO,MAAM,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC;QACnC,KAAK,cAAc;YACjB,OAAO,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnC,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAC3B,IAAI,CAAC,KAAK;gBAAE,OAAO,CAAC,CAAC;YACrB,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAChD,CAAC;QACD,KAAK,qBAAqB,CAAC,CAAC,CAAC;YAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;YAChC,IAAI,CAAC,EAAE;gBAAE,OAAO,CAAC,CAAC;YAClB,OAAO,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,KAAK,sBAAsB,CAAC,CAAC,CAAC;YAC5B,MAAM,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;YAChC,IAAI,CAAC,EAAE;gBAAE,OAAO,CAAC,CAAC;YAClB,OAAO,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QAC1C,CAAC;QACD,KAAK,wBAAwB,CAAC,CAAC,CAAC;YAC9B,MAAM,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC;YAChC,IAAI,CAAC,EAAE;gBAAE,OAAO,CAAC,CAAC;YAClB,OAAO,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;QAC5C,CAAC;QACD,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,EAAY,EAAE,SAAiB;IACrE,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,GAAG,CAAC,CAAC,OAAO,MAAM,GAAG,SAAS,CAAC;QACpC,KAAK,IAAI,CAAC,CAAC,OAAO,MAAM,IAAI,SAAS,CAAC;QACtC,KAAK,GAAG,CAAC,CAAC,OAAO,MAAM,GAAG,SAAS,CAAC;QACpC,KAAK,IAAI,CAAC,CAAC,OAAO,MAAM,IAAI,SAAS,CAAC;QACtC,KAAK,IAAI,CAAC,CAAC,OAAO,MAAM,KAAK,SAAS,CAAC;QACvC,KAAK,IAAI,CAAC,CAAC,OAAO,MAAM,KAAK,SAAS,CAAC;IACzC,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,MAAe,EAAE,EAAY,EAAE,SAAkB;IACxE,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,MAAM,KAAK,SAAS,CAAC;IAC7C,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,MAAM,KAAK,SAAS,CAAC;IAC7C,MAAM,IAAI,KAAK,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,EAAY,EAAE,SAAiB;IACrE,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,MAAM,KAAK,SAAS,CAAC;IAC7C,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,MAAM,KAAK,SAAS,CAAC;IAC7C,MAAM,IAAI,KAAK,CAAC,YAAY,EAAE,gCAAgC,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,YAAY,CAAC,MAA+B,EAAE,EAAY;IACjE,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,MAAM,KAAK,IAAI,CAAC;IACxC,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,IAAI,KAAK,CAAC,YAAY,EAAE,8BAA8B,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,WAAW,CAClB,IAAY,EACZ,IAAY,EACZ,MAA+B,EAC/B,MAAuB;IAEvB,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IAEvC,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACpC,IAAI,EAAE;YAAE,OAAO,SAAS,CAAC;QACzB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC/D,CAAC;IAED,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC1E,CAAC;IAED,IAAI,OAAO,SAAS,KAAK,SAAS,EAAE,CAAC;QACnC,IAAI,OAAO,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAC/D,CAAC;QACD,IAAI,eAAe,CAAC,MAAM,EAAE,EAAE,EAAE,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAC7D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC/D,CAAC;IAED,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAC/D,CAAC;QACD,IAAI,cAAc,CAAC,MAAM,EAAE,EAAE,EAAE,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAC5D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC/D,CAAC;IAED,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QAC/D,CAAC;QACD,IAAI,cAAc,CAAC,MAAM,EAAE,EAAE,EAAE,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAC5D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC/D,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAqB,EAAE,IAAmB;IAC3E,MAAM,UAAU,GAAyB,EAAE,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAChG,SAAS;QACX,CAAC;QACD,IAAI,MAAuB,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACxF,SAAS;QACX,CAAC;QACD,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,SAAyC,CAAC;QAC9C,IAAI,CAAC;YACH,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9G,CAAC;QACD,IAAI,SAAS;YAAE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;AACzD,CAAC;AAED,SAAS,WAAW,CAAC,CAA0B,EAAE,IAAa;IAC5D,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,eAAe,CAAC;IAC5C,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAC9B,IAAI,OAAO,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IACxD,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACpD,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAClE,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,GAAG,OAAO,IAAI,CAAC;QACzC,IAAI,IAAI,KAAK,GAAG;YAAE,OAAO,GAAG,OAAO,IAAI,CAAC;QACxC,IAAI,IAAI,KAAK,GAAG;YAAE,OAAO,OAAO,CAAC;QACjC,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,UAAgC;IACtE,IAAI,CAAC,UAAU,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,MAAM,aAAa,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC;IAC1F,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC,QAAQ,SAAS,SAAS,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,40 @@
1
+ export type FixLang = 'html' | 'css' | 'jsx' | 'vue' | 'attr';
2
+ export interface AutoFixPatch {
3
+ issueId: string;
4
+ category: 'a11y' | 'seo' | 'perf' | 'security' | 'forms' | 'images' | 'headings' | 'structured-data';
5
+ severity: 'info' | 'warn' | 'error';
6
+ selector?: string;
7
+ before?: string;
8
+ after?: string;
9
+ lang: FixLang;
10
+ rationale: string;
11
+ confidence: number;
12
+ docsRef?: string;
13
+ }
14
+ export interface A11yNode {
15
+ html: string;
16
+ target: string[];
17
+ }
18
+ export interface A11yViolation {
19
+ id: string;
20
+ impact: string;
21
+ nodes: A11yNode[];
22
+ }
23
+ export interface IssueRecord {
24
+ type: string;
25
+ selector?: string;
26
+ snippet?: string;
27
+ }
28
+ export interface PageIssues {
29
+ page: string;
30
+ issues: IssueRecord[];
31
+ }
32
+ export interface AutoFixInput {
33
+ a11y?: A11yViolation[];
34
+ headings?: PageIssues[];
35
+ forms?: PageIssues[];
36
+ images?: PageIssues[];
37
+ }
38
+ export declare function generateAutoFixes(input: AutoFixInput): AutoFixPatch[];
39
+ export declare function autoFixesToMarkdown(patches: AutoFixPatch[]): string;
40
+ //# sourceMappingURL=autofix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autofix.d.ts","sourceRoot":"","sources":["../src/autofix.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,iBAAiB,CAAC;IACrG,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;CAAE;AAC7D,MAAM,WAAW,aAAa;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,EAAE,CAAC;CAAE;AACjF,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAAE;AACnF,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAC;CAAE;AAEpE,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB;AAqQD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,EAAE,CA+CrE;AAQD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CA4BnE"}
@@ -0,0 +1,244 @@
1
+ function ensureAttr(snippet, attr, value) {
2
+ const fallback = `<element ${attr}="${value}"></element>`;
3
+ if (!snippet)
4
+ return fallback;
5
+ const tagMatch = snippet.match(/^<([a-zA-Z][a-zA-Z0-9-]*)([^>]*)>/);
6
+ if (!tagMatch)
7
+ return snippet.replace(/<([a-zA-Z][a-zA-Z0-9-]*)/, `<$1 ${attr}="${value}"`);
8
+ const [full, tag, attrs] = tagMatch;
9
+ if (new RegExp(`\\b${attr}=`).test(attrs)) {
10
+ const replaced = attrs.replace(new RegExp(`${attr}="[^"]*"`), `${attr}="${value}"`);
11
+ return snippet.replace(full, `<${tag}${replaced}>`);
12
+ }
13
+ return snippet.replace(full, `<${tag}${attrs} ${attr}="${value}">`);
14
+ }
15
+ function wrapWithLabel(snippet, text) {
16
+ return `<label>${text} ${snippet ?? '<input type="text" name="field">'}</label>`;
17
+ }
18
+ function demoteHeading(snippet, from, to) {
19
+ if (!snippet)
20
+ return `<h${to}>Section title</h${to}>`;
21
+ return snippet
22
+ .replace(new RegExp(`<h${from}([^>]*)>`, 'g'), `<h${to}$1>`)
23
+ .replace(new RegExp(`</h${from}>`, 'g'), `</h${to}>`);
24
+ }
25
+ function severityFromImpact(impact) {
26
+ if (impact === 'critical' || impact === 'serious')
27
+ return 'error';
28
+ if (impact === 'moderate')
29
+ return 'warn';
30
+ return 'info';
31
+ }
32
+ function attrRule(category, severity, fallbackBefore, attr, value, rationale, confidence, docsRef, lang = 'html') {
33
+ return {
34
+ category, severity, lang, rationale, confidence, docsRef,
35
+ build: (snippet) => ({
36
+ before: snippet ?? fallbackBefore,
37
+ after: ensureAttr(snippet ?? fallbackBefore, attr, value),
38
+ }),
39
+ };
40
+ }
41
+ function staticRule(category, severity, before, after, rationale, confidence, docsRef, lang = 'html') {
42
+ return {
43
+ category, severity, lang, rationale, confidence, docsRef,
44
+ build: (snippet) => ({ before: snippet ?? before, after }),
45
+ };
46
+ }
47
+ const A11Y_RULES = {
48
+ 'image-alt': attrRule('a11y', 'error', '<img src="foo.jpg">', 'alt', 'Description of image', 'WCAG 1.1.1 — images need text alternatives so screen readers can describe them.', 0.7, 'WCAG 1.1.1'),
49
+ 'label': {
50
+ category: 'a11y', severity: 'error', lang: 'html', confidence: 0.7, docsRef: 'WCAG 1.3.1, 4.1.2',
51
+ rationale: 'Form controls need programmatically associated labels for assistive tech.',
52
+ build: (s) => ({ before: s ?? '<input type="text" name="q">', after: wrapWithLabel(s, 'Search') }),
53
+ },
54
+ 'color-contrast': staticRule('a11y', 'error', '.text { color: #999; background: #fff; }', '.text { color: #595959; background: #fff; } /* contrast ratio >= 4.5:1 */', 'Increase foreground/background contrast to meet WCAG AA 4.5:1 for normal text.', 0.7, 'WCAG 1.4.3', 'css'),
55
+ 'heading-order': staticRule('a11y', 'warn', '<h1>Title</h1><h3>Sub</h3>', '<h1>Title</h1><h2>Sub</h2>', 'Heading levels should not skip (h1 -> h3). Use sequential levels for outline clarity.', 0.95, 'WCAG 1.3.1'),
56
+ 'link-name': attrRule('a11y', 'error', '<a href="/x"><i class="icon"></i></a>', 'aria-label', 'Descriptive link text', 'Links must have discernible text for screen reader users.', 0.95, 'WCAG 2.4.4, 4.1.2'),
57
+ 'button-name': attrRule('a11y', 'error', '<button><i class="icon"></i></button>', 'aria-label', 'Button purpose', 'Buttons must have an accessible name describing their action.', 0.95, 'WCAG 4.1.2'),
58
+ 'html-has-lang': staticRule('a11y', 'error', '<html>', '<html lang="en">', 'Root element needs lang attribute so assistive tech can pronounce content correctly.', 0.95, 'WCAG 3.1.1'),
59
+ 'html-lang-valid': staticRule('a11y', 'error', '<html lang="english">', '<html lang="en">', 'lang attribute must use a valid BCP 47 language code.', 0.95, 'WCAG 3.1.1'),
60
+ 'document-title': staticRule('a11y', 'error', '<head></head>', '<head><title>Page title — Site name</title></head>', 'Pages need a unique, descriptive title for orientation and tab labels.', 0.95, 'WCAG 2.4.2'),
61
+ 'duplicate-id': staticRule('a11y', 'error', '<div id="x"></div>...<div id="x"></div>', '<div id="x-1"></div>...<div id="x-2"></div>', 'IDs must be unique within a document; duplicates break label/aria associations.', 0.95, 'WCAG 4.1.1'),
62
+ 'aria-roles': attrRule('a11y', 'error', '<div role="buton">', 'role', 'button', 'role attribute must use a valid ARIA role from the spec.', 0.95, 'WCAG 4.1.2'),
63
+ 'aria-required-attr': attrRule('a11y', 'error', '<div role="checkbox"></div>', 'aria-checked', 'false', 'Elements with ARIA roles need their required ARIA attributes set.', 0.95, 'WAI-ARIA 1.2'),
64
+ 'aria-valid-attr-value': attrRule('a11y', 'error', '<div aria-expanded="yes">', 'aria-expanded', 'true', 'ARIA attributes must use valid values per the WAI-ARIA spec.', 0.95, 'WAI-ARIA 1.2'),
65
+ 'frame-title': attrRule('a11y', 'error', '<iframe src="/x"></iframe>', 'title', 'Embedded content description', 'Frames need a title attribute so users know what they contain.', 0.95, 'WCAG 2.4.1, 4.1.2'),
66
+ 'list': staticRule('a11y', 'warn', '<ul><div>item</div></ul>', '<ul><li>item</li></ul>', 'ul/ol must contain only li (or script/template) children.', 0.95, 'WCAG 1.3.1'),
67
+ 'listitem': staticRule('a11y', 'warn', '<li>orphan</li>', '<ul><li>orphan</li></ul>', 'li elements must be wrapped in a ul or ol parent.', 0.95, 'WCAG 1.3.1'),
68
+ 'meta-viewport': staticRule('a11y', 'error', '<meta name="viewport" content="user-scalable=no">', '<meta name="viewport" content="width=device-width, initial-scale=1">', 'Disabling user-scalable blocks pinch-zoom and harms low-vision users.', 0.95, 'WCAG 1.4.4'),
69
+ 'tabindex': attrRule('a11y', 'warn', '<div tabindex="5">', 'tabindex', '0', 'Avoid tabindex > 0; it disrupts natural tab order.', 0.95, 'WCAG 2.4.3'),
70
+ 'region': staticRule('a11y', 'warn', '<div>page content</div>', '<main>page content</main>', 'Wrap primary page content in a landmark element so assistive tech can navigate.', 0.7, 'WCAG 1.3.1, 2.4.1'),
71
+ 'landmark-one-main': staticRule('a11y', 'warn', '<body><div>...</div></body>', '<body><main>...</main></body>', 'Each page should have exactly one main landmark.', 0.95, 'WCAG 1.3.1'),
72
+ 'bypass': staticRule('a11y', 'warn', '<body><nav>...</nav><main>...</main></body>', '<body><a href="#main" class="skip-link">Skip to main content</a><nav>...</nav><main id="main">...</main></body>', 'Provide a skip link so keyboard users can bypass repeated navigation.', 0.95, 'WCAG 2.4.1'),
73
+ };
74
+ const FORM_RULES = {
75
+ 'missing-label': {
76
+ category: 'forms', severity: 'error', lang: 'html', confidence: 0.7, docsRef: 'WCAG 1.3.1, 3.3.2',
77
+ rationale: 'Form controls need programmatically associated labels.',
78
+ build: (s) => ({ before: s ?? '<input type="email" name="email">', after: wrapWithLabel(s, 'Email address') }),
79
+ },
80
+ 'missing-autocomplete': {
81
+ category: 'forms', severity: 'warn', lang: 'html', confidence: 0.95, docsRef: 'WCAG 1.3.5',
82
+ rationale: 'Autocomplete tokens help users (and password managers) fill known data.',
83
+ build: (s) => {
84
+ const snip = s ?? '<input type="email" name="email">';
85
+ const guess = /email/i.test(snip) ? 'email' : /tel|phone/i.test(snip) ? 'tel' : /name/i.test(snip) ? 'name' : 'on';
86
+ return { before: snip, after: ensureAttr(snip, 'autocomplete', guess) };
87
+ },
88
+ },
89
+ 'missing-required-indicator': attrRule('forms', 'warn', '<input required>', 'aria-required', 'true', 'Required fields should be visually and programmatically indicated.', 0.95, 'WCAG 3.3.2'),
90
+ 'missing-error-message': staticRule('forms', 'error', '<input aria-invalid="true">', '<input aria-invalid="true" aria-describedby="err-1"><span id="err-1" role="alert">Please enter a valid value.</span>', 'Invalid inputs should reference a visible error message via aria-describedby.', 0.95, 'WCAG 3.3.1, 3.3.3'),
91
+ 'missing-fieldset': staticRule('forms', 'warn', '<input type="radio" name="r"><input type="radio" name="r">', '<fieldset><legend>Choose one</legend><input type="radio" name="r"><input type="radio" name="r"></fieldset>', 'Group related radio/checkbox controls in a fieldset with a legend.', 0.95, 'WCAG 1.3.1'),
92
+ 'missing-input-mode': attrRule('forms', 'info', '<input type="text" name="otp">', 'inputmode', 'numeric', 'Set inputmode to surface the right virtual keyboard on mobile.', 0.7),
93
+ 'submit-without-button': staticRule('forms', 'warn', '<form>...</form>', '<form>...<button type="submit">Submit</button></form>', 'Forms should have an explicit submit button for keyboard users.', 0.95, 'WCAG 2.1.1'),
94
+ };
95
+ const HEADING_RULES = {
96
+ 'multiple-h1': {
97
+ category: 'headings', severity: 'warn', lang: 'html', confidence: 0.95, docsRef: 'WCAG 1.3.1, 2.4.6',
98
+ rationale: 'Each page should have a single h1 representing its main topic.',
99
+ build: (s) => ({
100
+ before: s ?? '<h1>Primary</h1>...<h1>Secondary</h1>',
101
+ after: demoteHeading(s ?? '<h1>Secondary</h1>', 1, 2),
102
+ }),
103
+ },
104
+ 'missing-h1': staticRule('headings', 'error', '<body><h2>Welcome</h2></body>', '<body><h1>Welcome</h1></body>', 'Pages need a top-level h1 to anchor the document outline.', 0.95, 'WCAG 2.4.6'),
105
+ 'skipped-level': staticRule('headings', 'warn', '<h1>Title</h1><h3>Sub</h3>', '<h1>Title</h1><h2>Sub</h2>', 'Heading levels should not skip; promote h3 to h2 to maintain hierarchy.', 0.95, 'WCAG 1.3.1'),
106
+ 'empty-heading': staticRule('headings', 'error', '<h2></h2>', '<h2>Section title</h2>', 'Empty headings confuse screen reader navigation; remove or fill them.', 0.7, 'WCAG 1.3.1, 2.4.6'),
107
+ };
108
+ const IMAGE_RULES = {
109
+ 'missing-alt': attrRule('images', 'error', '<img src="hero.jpg">', 'alt', 'Describe the image content', 'Add alt text for informative images, or alt="" for decorative ones.', 0.7, 'WCAG 1.1.1'),
110
+ 'decorative-needs-empty-alt': attrRule('images', 'warn', '<img src="bg.svg">', 'alt', '', 'Decorative images should have alt="" so screen readers skip them.', 0.95, 'WCAG 1.1.1'),
111
+ 'missing-dimensions': {
112
+ category: 'images', severity: 'warn', lang: 'html', confidence: 0.95, docsRef: 'web.dev/optimize-cls',
113
+ rationale: 'Width/height attributes prevent layout shift (CLS) while images load.',
114
+ build: (s) => {
115
+ const snip = s ?? '<img src="hero.jpg" alt="Hero">';
116
+ return { before: snip, after: ensureAttr(ensureAttr(snip, 'width', '1200'), 'height', '630') };
117
+ },
118
+ },
119
+ 'missing-lazy': attrRule('images', 'info', '<img src="below-fold.jpg" alt="">', 'loading', 'lazy', 'Lazy-load below-the-fold images to defer network and decode work.', 0.95, 'web.dev/browser-level-image-lazy-loading'),
120
+ 'wrong-format': staticRule('images', 'info', '<img src="hero.png" alt="Hero">', '<picture><source type="image/avif" srcset="hero.avif"><source type="image/webp" srcset="hero.webp"><img src="hero.png" alt="Hero" width="1200" height="630"></picture>', 'Serve modern formats (AVIF/WebP) with picture for smaller payloads.', 0.7, 'web.dev/serve-images-webp'),
121
+ 'missing-srcset': {
122
+ category: 'images', severity: 'info', lang: 'html', confidence: 0.7, docsRef: 'web.dev/serve-responsive-images',
123
+ rationale: 'Provide srcset/sizes so the browser picks the best resolution per device.',
124
+ build: (s) => {
125
+ const snip = s ?? '<img src="hero.jpg" alt="Hero">';
126
+ const withSrcset = ensureAttr(snip, 'srcset', 'hero-800.jpg 800w, hero-1600.jpg 1600w');
127
+ return { before: snip, after: ensureAttr(withSrcset, 'sizes', '(max-width: 800px) 100vw, 800px') };
128
+ },
129
+ },
130
+ 'missing-eager-lcp': {
131
+ category: 'images', severity: 'warn', lang: 'html', confidence: 0.95, docsRef: 'web.dev/optimize-lcp',
132
+ rationale: 'LCP image should load eagerly with high fetch priority to improve LCP.',
133
+ build: (s) => {
134
+ const snip = s ?? '<img src="hero.jpg" alt="Hero">';
135
+ return { before: snip, after: ensureAttr(ensureAttr(snip, 'fetchpriority', 'high'), 'loading', 'eager') };
136
+ },
137
+ },
138
+ 'svg-missing-title': staticRule('images', 'warn', '<svg viewBox="0 0 24 24"><path d="..."/></svg>', '<svg viewBox="0 0 24 24" role="img" aria-labelledby="t1"><title id="t1">Icon description</title><path d="..."/></svg>', 'Inline SVGs need a title (and role="img") so screen readers announce them.', 0.95, 'WCAG 1.1.1'),
139
+ };
140
+ const STRUCTURED_DATA_TEMPLATE = `<script type="application/ld+json">
141
+ {
142
+ "@context": "https://schema.org",
143
+ "@type": "WebSite",
144
+ "name": "Site name",
145
+ "url": "https://example.com"
146
+ }
147
+ </script>`;
148
+ function makePatch(rule, issueId, selector, snippet) {
149
+ const built = rule.build(snippet);
150
+ return {
151
+ issueId,
152
+ category: rule.category,
153
+ severity: rule.severity,
154
+ selector,
155
+ before: built.before,
156
+ after: built.after,
157
+ lang: rule.lang,
158
+ rationale: rule.rationale,
159
+ confidence: rule.confidence,
160
+ docsRef: rule.docsRef,
161
+ };
162
+ }
163
+ export function generateAutoFixes(input) {
164
+ const patches = [];
165
+ if (input.a11y) {
166
+ input.a11y.forEach((violation, vIdx) => {
167
+ const rule = A11Y_RULES[violation.id];
168
+ if (!rule)
169
+ return;
170
+ violation.nodes.forEach((node, nIdx) => {
171
+ const selector = node.target.join(' ');
172
+ const patch = makePatch(rule, `a11y:${violation.id}:${vIdx}-${nIdx}`, selector, node.html);
173
+ patch.severity = severityFromImpact(violation.impact);
174
+ patches.push(patch);
175
+ });
176
+ });
177
+ }
178
+ const collect = (pages, rules, prefix) => {
179
+ if (!pages)
180
+ return;
181
+ pages.forEach((page) => {
182
+ page.issues.forEach((issue, idx) => {
183
+ const rule = rules[issue.type];
184
+ if (!rule)
185
+ return;
186
+ const id = `${prefix}:${page.page}:${issue.type}:${idx}`;
187
+ patches.push(makePatch(rule, id, issue.selector, issue.snippet));
188
+ });
189
+ });
190
+ };
191
+ collect(input.headings, HEADING_RULES, 'headings');
192
+ collect(input.forms, FORM_RULES, 'forms');
193
+ collect(input.images, IMAGE_RULES, 'images');
194
+ if (!patches.some((p) => p.category === 'structured-data')) {
195
+ patches.push({
196
+ issueId: 'structured-data:missing-website:0',
197
+ category: 'structured-data',
198
+ severity: 'info',
199
+ lang: 'html',
200
+ before: '<head>...</head>',
201
+ after: `<head>...${STRUCTURED_DATA_TEMPLATE}</head>`,
202
+ rationale: 'Add WebSite JSON-LD so search engines understand the site identity.',
203
+ confidence: 0.7,
204
+ docsRef: 'schema.org/WebSite',
205
+ });
206
+ }
207
+ return patches;
208
+ }
209
+ function fence(lang, body) {
210
+ if (!body)
211
+ return '';
212
+ const tag = lang === 'attr' ? 'html' : lang;
213
+ return '```' + tag + '\n' + body + '\n```';
214
+ }
215
+ export function autoFixesToMarkdown(patches) {
216
+ return patches.map((patch) => {
217
+ const lines = [];
218
+ lines.push(`### ${patch.category}: ${patch.issueId}`);
219
+ lines.push('');
220
+ lines.push(`**${patch.severity}** | confidence ${patch.confidence}`);
221
+ lines.push('');
222
+ if (patch.selector) {
223
+ lines.push(`Selector: \`${patch.selector}\``);
224
+ lines.push('');
225
+ }
226
+ if (patch.before) {
227
+ lines.push('**Before:**');
228
+ lines.push(fence(patch.lang, patch.before));
229
+ lines.push('');
230
+ }
231
+ if (patch.after) {
232
+ lines.push('**After:**');
233
+ lines.push(fence(patch.lang, patch.after));
234
+ lines.push('');
235
+ }
236
+ lines.push(`**Why:** ${patch.rationale}`);
237
+ if (patch.docsRef) {
238
+ lines.push('');
239
+ lines.push(`Reference: ${patch.docsRef}`);
240
+ }
241
+ return lines.join('\n');
242
+ }).join('\n\n');
243
+ }
244
+ //# sourceMappingURL=autofix.js.map