@stacksjs/stx 0.2.95 → 0.2.96

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 (612) hide show
  1. package/dist/a11y.js +598 -2
  2. package/dist/analytics.js +159 -2
  3. package/dist/analyzer.js +240 -2
  4. package/dist/animation.js +688 -2
  5. package/dist/app-shell.js +220 -2
  6. package/dist/app.js +79 -2
  7. package/dist/assets.js +155 -2
  8. package/dist/ast.js +630 -2
  9. package/dist/async-components.js +428 -2
  10. package/dist/auth.js +12 -2
  11. package/dist/broadcasting.js +102 -2
  12. package/dist/browser-composables.js +565 -2
  13. package/dist/build-assets.js +29 -2
  14. package/dist/build-mode-detector.js +50 -2
  15. package/dist/build-optimizer.js +433 -2
  16. package/dist/build-views.js +180 -2
  17. package/dist/build.js +33 -2
  18. package/dist/builtins/drawer.js +37 -2
  19. package/dist/builtins/escape.js +3 -2
  20. package/dist/builtins/icon.js +83 -2
  21. package/dist/builtins/index.js +34 -2
  22. package/dist/builtins/modal.js +38 -2
  23. package/dist/builtins/safe-image.js +51 -2
  24. package/dist/builtins/stx-image.js +200 -2
  25. package/dist/builtins/stx-link.js +41 -2
  26. package/dist/builtins/stx-loading-indicator.js +35 -2
  27. package/dist/builtins/suspense.js +24 -2
  28. package/dist/builtins/toast.js +42 -2
  29. package/dist/builtins/tooltip.js +106 -2
  30. package/dist/builtins/transition-group.js +22 -2
  31. package/dist/bundle-analyzer/collector.js +233 -2
  32. package/dist/bundle-analyzer/index.js +82 -2
  33. package/dist/bundle-analyzer/report.js +318 -2
  34. package/dist/bundle-analyzer/treemap.js +594 -2
  35. package/dist/caching.js +131 -2
  36. package/dist/cli.js +11317 -10982
  37. package/dist/client/directive.js +14 -2
  38. package/dist/client/index.js +2 -2
  39. package/dist/client-helpers.js +312 -2
  40. package/dist/client-script-bundler.js +216 -6
  41. package/dist/client-script.js +754 -2
  42. package/dist/client.js +73 -4
  43. package/dist/component-hmr.js +585 -2
  44. package/dist/component-library.d.ts +6 -0
  45. package/dist/component-library.js +683 -0
  46. package/dist/component-processing.js +613 -2
  47. package/dist/component-registry.js +90 -2
  48. package/dist/component-renderer.js +660 -2
  49. package/dist/components.js +213 -2
  50. package/dist/composables/index.js +220 -2
  51. package/dist/composables/use-battery.js +101 -2
  52. package/dist/composables/use-broadcast-channel.js +80 -2
  53. package/dist/composables/use-channel.js +124 -2
  54. package/dist/composables/use-clipboard.js +79 -2
  55. package/dist/composables/use-color-mode.js +131 -2
  56. package/dist/composables/use-cookie.js +86 -2
  57. package/dist/composables/use-device-orientation.js +181 -2
  58. package/dist/composables/use-event-listener.js +27 -2
  59. package/dist/composables/use-event-source.js +166 -2
  60. package/dist/composables/use-eye-dropper.js +142 -2
  61. package/dist/composables/use-fetch.js +223 -2
  62. package/dist/composables/use-fullscreen.js +110 -2
  63. package/dist/composables/use-geolocation.js +101 -2
  64. package/dist/composables/use-idle.js +182 -2
  65. package/dist/composables/use-intersection-observer.js +168 -2
  66. package/dist/composables/use-keyboard.js +224 -2
  67. package/dist/composables/use-media-query.js +62 -2
  68. package/dist/composables/use-meta.js +48 -2
  69. package/dist/composables/use-mouse.js +286 -2
  70. package/dist/composables/use-mutation-observer.js +129 -2
  71. package/dist/composables/use-network.js +85 -2
  72. package/dist/composables/use-notification.js +94 -2
  73. package/dist/composables/use-permissions.js +132 -2
  74. package/dist/composables/use-query.js +0 -1
  75. package/dist/composables/use-resize-observer.js +157 -2
  76. package/dist/composables/use-router.js +51 -2
  77. package/dist/composables/use-share.js +104 -2
  78. package/dist/composables/use-speech.js +294 -2
  79. package/dist/composables/use-storage.js +130 -2
  80. package/dist/composables/use-text-selection.js +205 -4
  81. package/dist/composables/use-timer.js +183 -2
  82. package/dist/composables/use-utilities.js +176 -2
  83. package/dist/composables/use-wake-lock.js +122 -2
  84. package/dist/composables/use-websocket.js +165 -2
  85. package/dist/composables/use-window.js +163 -2
  86. package/dist/composables.js +552 -2
  87. package/dist/composition-api.js +190 -2
  88. package/dist/computed.js +376 -8
  89. package/dist/conditionals.js +599 -2
  90. package/dist/config.js +751 -2
  91. package/dist/craft-bridge.js +432 -2
  92. package/dist/craft-compiler.js +810 -2
  93. package/dist/craft-components.js +945 -2
  94. package/dist/craft-entry.js +5 -2
  95. package/dist/craft-ssr.js +559 -2
  96. package/dist/csp.js +220 -2
  97. package/dist/csrf.js +38 -2
  98. package/dist/custom-directives.js +136 -2
  99. package/dist/defer.js +156 -2
  100. package/dist/deploy/config-generators.js +214 -2
  101. package/dist/deploy/index.js +203 -2
  102. package/dist/deploy/netlify.js +167 -2
  103. package/dist/dev-server/crosswind.js +379 -2
  104. package/dist/dev-server/index.js +7 -2
  105. package/dist/dev-server/keyboard-shortcuts.js +81 -2
  106. package/dist/dev-server/native-window.js +91 -2
  107. package/dist/dev-server/port-utils.js +40 -2
  108. package/dist/dev-server/serve-app.js +682 -2
  109. package/dist/dev-server/serve-file.js +439 -2
  110. package/dist/dev-server/serve-markdown.js +281 -2
  111. package/dist/dev-server/serve-multi.js +579 -2
  112. package/dist/dev-server/terminal-colors.js +45 -2
  113. package/dist/dev-server/theme-selector.js +111 -2
  114. package/dist/dev-server/types.js +43 -2
  115. package/dist/dev-server.js +4 -2
  116. package/dist/devtools.js +462 -18
  117. package/dist/directive-api.js +355 -2
  118. package/dist/docs.js +567 -2
  119. package/dist/doctor.js +123 -2
  120. package/dist/document-shell.js +105 -2
  121. package/dist/dynamic-components.js +78 -2
  122. package/dist/edge-runtime.js +539 -2
  123. package/dist/env.js +9 -2
  124. package/dist/error-boundaries.js +62 -12
  125. package/dist/error-handling.js +1 -2
  126. package/dist/errors/codes.js +97 -2
  127. package/dist/errors/formatter.js +196 -2
  128. package/dist/errors/index.js +44 -2
  129. package/dist/errors/logger.js +250 -2
  130. package/dist/errors/sanitizer.js +181 -2
  131. package/dist/errors/types.js +86 -2
  132. package/dist/events.js +382 -2
  133. package/dist/expressions.js +650 -2
  134. package/dist/formatter.js +265 -2
  135. package/dist/forms-validation.js +510 -4
  136. package/dist/forms.js +709 -2
  137. package/dist/head.js +224 -2
  138. package/dist/heatmap.js +566 -2
  139. package/dist/hot-reload.js +367 -2
  140. package/dist/html-masking.js +73 -2
  141. package/dist/hydration-runtime.js +195 -2
  142. package/dist/hydration.js +654 -2
  143. package/dist/i18n.js +633 -2
  144. package/dist/image-optimization/auto-sibling.js +88 -2
  145. package/dist/image-optimization/build-plugin.js +241 -2
  146. package/dist/image-optimization/component.js +244 -2
  147. package/dist/image-optimization/directive.js +203 -2
  148. package/dist/image-optimization/index.js +54 -2
  149. package/dist/image-optimization/processor.js +262 -2
  150. package/dist/image-optimization/serve.js +102 -2
  151. package/dist/includes.js +733 -2
  152. package/dist/index.d.ts +1 -0
  153. package/dist/index.js +134 -2
  154. package/dist/init.js +505 -2
  155. package/dist/inline-assets.js +82 -2
  156. package/dist/interactive.js +383 -2
  157. package/dist/internal-markdown.js +141 -2
  158. package/dist/island-chunking.js +52 -2
  159. package/dist/js-ts.js +57 -2
  160. package/dist/jsx-runtime.js +289 -2
  161. package/dist/keep-alive.js +421 -2
  162. package/dist/lazy-loader.js +245 -2
  163. package/dist/loading-indicator.js +322 -2
  164. package/dist/loops.js +643 -2
  165. package/dist/manifest.js +31 -2
  166. package/dist/markdown.js +68 -2
  167. package/dist/media/client/blur-up.js +217 -2
  168. package/dist/media/client/index.js +53 -2
  169. package/dist/media/client/lazy-load.js +283 -2
  170. package/dist/media/client/upload-handler.js +354 -2
  171. package/dist/media/image/component.js +574 -2
  172. package/dist/media/image/directive.js +160 -2
  173. package/dist/media/image/editing.js +193 -2
  174. package/dist/media/image/index.js +80 -2
  175. package/dist/media/image/placeholder.js +188 -2
  176. package/dist/media/image/processor/cache.js +51 -2
  177. package/dist/media/image/processor/index.js +3 -2
  178. package/dist/media/image/processor/optimizer.js +202 -2
  179. package/dist/media/image/processor/responsive.js +162 -2
  180. package/dist/media/image/srcset.js +194 -2
  181. package/dist/media/index.js +198 -2
  182. package/dist/media/manager/embed.js +253 -2
  183. package/dist/media/protected/component.js +235 -2
  184. package/dist/media/protected/index.js +20 -2
  185. package/dist/media/protected/signature.js +205 -2
  186. package/dist/media/shared/cache.js +132 -2
  187. package/dist/media/shared/hash.js +35 -2
  188. package/dist/media/shared/index.js +2 -2
  189. package/dist/media/types.js +0 -1
  190. package/dist/media/upload/component.js +320 -2
  191. package/dist/media/upload/index.js +1 -2
  192. package/dist/media/video/directive.js +142 -2
  193. package/dist/media/video/index.js +583 -2
  194. package/dist/media/video/processor/cache.js +52 -2
  195. package/dist/media/video/processor/index.js +4 -2
  196. package/dist/media/video/processor/streaming.js +197 -2
  197. package/dist/media/video/processor/thumbnail.js +134 -2
  198. package/dist/media/video/processor/transcoder.js +283 -2
  199. package/dist/method-spoofing.js +17 -2
  200. package/dist/middleware.js +40 -2
  201. package/dist/misc-directives.js +222 -2
  202. package/dist/native-build.js +511 -2
  203. package/dist/parser/directive-parser.js +239 -2
  204. package/dist/parser/expression-parser.js +358 -2
  205. package/dist/parser/index.js +23 -2
  206. package/dist/parser/tokenizer.js +534 -2
  207. package/dist/partial-hydration.js +427 -2
  208. package/dist/performance-utils.js +430 -2
  209. package/dist/placeholder.js +35 -2
  210. package/dist/plugin-system.js +214 -2
  211. package/dist/plugin.js +173 -2
  212. package/dist/precompiler.js +660 -81
  213. package/dist/process.js +711 -2
  214. package/dist/production-build.js +596 -2
  215. package/dist/production-builder.js +132 -2
  216. package/dist/production-server.js +188 -2
  217. package/dist/props.js +224 -2
  218. package/dist/public-env.js +19 -2
  219. package/dist/pwa/audit.js +255 -2
  220. package/dist/pwa/directives.js +332 -2
  221. package/dist/pwa/icons.js +109 -2
  222. package/dist/pwa/index.js +47 -2
  223. package/dist/pwa/inject.js +102 -2
  224. package/dist/pwa/manifest.js +186 -2
  225. package/dist/pwa/offline.js +259 -2
  226. package/dist/pwa/precache.js +116 -2
  227. package/dist/pwa/service-worker.js +860 -2
  228. package/dist/pwa/workbox-strategies.js +167 -2
  229. package/dist/pwa/workbox.js +382 -2
  230. package/dist/pwa.js +427 -427
  231. package/dist/reactive-bindings.js +266 -2
  232. package/dist/reactive.js +569 -2
  233. package/dist/reactivity.js +559 -2
  234. package/dist/release.js +1 -2
  235. package/dist/render.js +165 -2
  236. package/dist/route-middleware.js +17 -2
  237. package/dist/router.js +9 -2
  238. package/dist/routes.js +14 -2
  239. package/dist/runtime-injection.js +120 -2
  240. package/dist/runtime.js +94 -2
  241. package/dist/safe-evaluator.js +444 -2
  242. package/dist/scaffolding.js +897 -2
  243. package/dist/screenshot.js +87 -2
  244. package/dist/script-classifier.js +32 -2
  245. package/dist/script-validation.js +158 -2
  246. package/dist/seo.js +457 -2
  247. package/dist/serve.js +237 -2
  248. package/dist/server-bindings.js +108 -2
  249. package/dist/server-components.js +338 -11
  250. package/dist/signal-processing.js +946 -2
  251. package/dist/signals-api.js +154 -2
  252. package/dist/signals.js +5287 -2
  253. package/dist/site-builder/build.js +224 -2
  254. package/dist/site-builder/i18n.js +140 -2
  255. package/dist/site-builder/index.js +15 -2
  256. package/dist/site-builder/robots.js +26 -2
  257. package/dist/site-builder/router.js +27 -2
  258. package/dist/site-builder/seo.js +36 -2
  259. package/dist/site-builder/sitemap.js +26 -2
  260. package/dist/site-builder/theme.js +33 -2
  261. package/dist/site-builder/types.js +0 -1
  262. package/dist/slots.js +201 -2
  263. package/dist/source-maps.js +350 -2
  264. package/dist/spa-shell.js +34 -2
  265. package/dist/ssg.js +389 -389
  266. package/dist/ssr.js +355 -2
  267. package/dist/state-management.js +533 -2
  268. package/dist/store-imports.js +13 -2
  269. package/dist/store-loader.js +72 -5
  270. package/dist/stores-client.js +132 -2
  271. package/dist/story/addons.js +261 -2
  272. package/dist/story/analytics.js +235 -2
  273. package/dist/story/auto-stories.js +158 -2
  274. package/dist/story/bookmarks.js +277 -2
  275. package/dist/story/bun-test.js +102 -2
  276. package/dist/story/cli.js +155 -2
  277. package/dist/story/collect/analyzer.js +305 -2
  278. package/dist/story/collect/index.js +27 -2
  279. package/dist/story/collect/parser.js +129 -2
  280. package/dist/story/collect/scanner.js +101 -2
  281. package/dist/story/collect/tree.js +110 -2
  282. package/dist/story/commands/build.js +172 -2
  283. package/dist/story/commands/dev.js +78 -2
  284. package/dist/story/commands/index.js +3 -2
  285. package/dist/story/commands/preview.js +56 -2
  286. package/dist/story/compiled-output.js +151 -2
  287. package/dist/story/composition.js +261 -2
  288. package/dist/story/config-watcher.js +67 -2
  289. package/dist/story/config.js +64 -2
  290. package/dist/story/context.js +27 -2
  291. package/dist/story/controls/index.js +320 -2
  292. package/dist/story/crosswind.js +189 -2
  293. package/dist/story/desktop-preview.js +105 -2
  294. package/dist/story/docs-generator.js +186 -2
  295. package/dist/story/errors.js +239 -2
  296. package/dist/story/figma-export.js +224 -2
  297. package/dist/story/generator.js +165 -2
  298. package/dist/story/hmr.js +131 -2
  299. package/dist/story/hot-swap.js +207 -2
  300. package/dist/story/index.js +49 -2
  301. package/dist/story/interactions.js +225 -2
  302. package/dist/story/keyboard-shortcuts.js +345 -2
  303. package/dist/story/output.js +153 -2
  304. package/dist/story/performance.js +252 -2
  305. package/dist/story/presets.js +289 -2
  306. package/dist/story/props-validation.js +215 -2
  307. package/dist/story/renderer.js +209 -2
  308. package/dist/story/search-index.js +106 -2
  309. package/dist/story/search.js +140 -2
  310. package/dist/story/server.js +965 -2
  311. package/dist/story/setup.js +78 -2
  312. package/dist/story/snapshots.js +170 -2
  313. package/dist/story/testing.js +163 -2
  314. package/dist/story/theme.js +170 -2
  315. package/dist/story/types.js +0 -2
  316. package/dist/story/ui/code-panel.js +175 -2
  317. package/dist/story/ui/controls-panel.js +168 -2
  318. package/dist/story/ui/index.js +4 -2
  319. package/dist/story/ui/navigation.js +250 -2
  320. package/dist/story/ui/preview.js +251 -2
  321. package/dist/story/visual-testing.js +247 -2
  322. package/dist/streaming.js +537 -2
  323. package/dist/strict-lint.js +288 -2
  324. package/dist/style-scoping.js +50 -2
  325. package/dist/suspense.js +398 -2
  326. package/dist/teleport.js +109 -2
  327. package/dist/template-compiler.js +63 -2
  328. package/dist/template-hydrator.js +82 -2
  329. package/dist/template-tag-balance.js +93 -2
  330. package/dist/testing.js +581 -2
  331. package/dist/transitions.js +443 -2
  332. package/dist/type-checker.js +581 -2
  333. package/dist/types/component-types.d.ts +54 -0
  334. package/dist/types/component-types.js +0 -1
  335. package/dist/types/config-types.js +0 -1
  336. package/dist/types/context-types.js +0 -1
  337. package/dist/types/csp-types.js +0 -1
  338. package/dist/types/directive-types.js +3 -2
  339. package/dist/types/index.d.ts +5 -0
  340. package/dist/types/index.js +1 -2
  341. package/dist/types/pwa-types.js +0 -1
  342. package/dist/types.js +1 -2
  343. package/dist/typescript-templates.js +386 -4
  344. package/dist/utils.js +942 -2
  345. package/dist/validator.js +171 -2
  346. package/dist/variable-extractor.js +1094 -2
  347. package/dist/view-composers.js +29 -2
  348. package/dist/virtual-scrolling.js +454 -2
  349. package/dist/visual-editor.js +688 -28
  350. package/dist/vue-template.js +475 -2
  351. package/dist/web-components/css-scoping.js +177 -2
  352. package/dist/web-components/index.js +13 -2
  353. package/dist/web-components/reactive-generator.js +121 -56
  354. package/dist/web-components.js +1447 -2
  355. package/dist/x-element.js +17 -5
  356. package/package.json +5 -6
  357. package/dist/chunk-04n64bnt.js +0 -5
  358. package/dist/chunk-06w68hyg.js +0 -7
  359. package/dist/chunk-07y6m5xx.js +0 -3
  360. package/dist/chunk-095s3972.js +0 -99
  361. package/dist/chunk-09k66d8a.js +0 -3
  362. package/dist/chunk-0a61y94n.js +0 -24
  363. package/dist/chunk-0b9w2w1y.js +0 -1
  364. package/dist/chunk-0dx4q6yq.js +0 -3
  365. package/dist/chunk-0dz85jrp.js +0 -3
  366. package/dist/chunk-0jd0pndq.js +0 -3
  367. package/dist/chunk-0p0nyq50.js +0 -6
  368. package/dist/chunk-0p1h3p3w.js +0 -3
  369. package/dist/chunk-0qakwen3.js +0 -1
  370. package/dist/chunk-0qnz93q2.js +0 -3
  371. package/dist/chunk-10debkj5.js +0 -71
  372. package/dist/chunk-15nesxgt.js +0 -5224
  373. package/dist/chunk-1sr54zp8.js +0 -3
  374. package/dist/chunk-1v49fwr5.js +0 -3
  375. package/dist/chunk-1xz0w746.js +0 -1539
  376. package/dist/chunk-1z5nhbjt.js +0 -90
  377. package/dist/chunk-1zgsgk4b.js +0 -1
  378. package/dist/chunk-20swzkx3.js +0 -216
  379. package/dist/chunk-27zsyhrd.js +0 -4
  380. package/dist/chunk-29y0hk5z.js +0 -3
  381. package/dist/chunk-2cdvw21b.js +0 -274
  382. package/dist/chunk-2j21d3ka.js +0 -161
  383. package/dist/chunk-2jxbwnkz.js +0 -2
  384. package/dist/chunk-31dr4bys.js +0 -6
  385. package/dist/chunk-35faj94w.js +0 -15
  386. package/dist/chunk-39gm08bn.js +0 -39
  387. package/dist/chunk-3a4qsygv.js +0 -51
  388. package/dist/chunk-3te20hqw.js +0 -3
  389. package/dist/chunk-43t7faps.js +0 -24
  390. package/dist/chunk-44hd3kab.js +0 -1
  391. package/dist/chunk-47kpewks.js +0 -71
  392. package/dist/chunk-4aj7ftqb.js +0 -1
  393. package/dist/chunk-4d2y57k7.js +0 -3
  394. package/dist/chunk-4deg33rw.js +0 -57
  395. package/dist/chunk-4k7d8p8d.js +0 -188
  396. package/dist/chunk-4qcy5tx6.js +0 -53
  397. package/dist/chunk-4x7kae4j.js +0 -3
  398. package/dist/chunk-55nwdnsd.js +0 -3
  399. package/dist/chunk-55yp0q8t.js +0 -201
  400. package/dist/chunk-5f43yz6z.js +0 -12
  401. package/dist/chunk-5shey2e4.js +0 -3
  402. package/dist/chunk-6b5k6w2q.js +0 -7
  403. package/dist/chunk-6djzdes9.js +0 -14
  404. package/dist/chunk-6e4c6g46.js +0 -3
  405. package/dist/chunk-6eqbxcrd.js +0 -8
  406. package/dist/chunk-7074g241.js +0 -3
  407. package/dist/chunk-7b6s3g65.js +0 -179
  408. package/dist/chunk-7cgmq685.js +0 -33
  409. package/dist/chunk-7dkz6z2s.js +0 -3
  410. package/dist/chunk-7ed3tean.js +0 -3
  411. package/dist/chunk-7gd339hd.js +0 -109
  412. package/dist/chunk-7j5e8sdj.js +0 -3
  413. package/dist/chunk-7n8g0nfn.js +0 -38
  414. package/dist/chunk-7sqdeqsw.js +0 -1
  415. package/dist/chunk-80g54ncj.js +0 -3
  416. package/dist/chunk-8a5bxece.js +0 -4
  417. package/dist/chunk-8ahwt6a4.js +0 -721
  418. package/dist/chunk-8b3z0zd5.js +0 -8
  419. package/dist/chunk-8dhdpa5h.js +0 -4
  420. package/dist/chunk-8n9nnqr6.js +0 -3
  421. package/dist/chunk-8qc1bsym.js +0 -3
  422. package/dist/chunk-8va64c9n.js +0 -3
  423. package/dist/chunk-8vtm0m84.js +0 -3
  424. package/dist/chunk-8xj7c3mf.js +0 -8
  425. package/dist/chunk-988dw6q3.js +0 -9
  426. package/dist/chunk-9b6cec0v.js +0 -321
  427. package/dist/chunk-9cf97f9p.js +0 -3
  428. package/dist/chunk-9ecv8aqj.js +0 -14
  429. package/dist/chunk-9eq3ht5f.js +0 -8
  430. package/dist/chunk-9jtj77jx.js +0 -3
  431. package/dist/chunk-9t14se2t.js +0 -83
  432. package/dist/chunk-9wmq2272.js +0 -3
  433. package/dist/chunk-9zbk5zx5.js +0 -57
  434. package/dist/chunk-a2g2qb2y.js +0 -386
  435. package/dist/chunk-a3hyn4we.js +0 -79
  436. package/dist/chunk-a87qqft6.js +0 -194
  437. package/dist/chunk-ah88wzbg.js +0 -10
  438. package/dist/chunk-akf1r75r.js +0 -102
  439. package/dist/chunk-amaa1bev.js +0 -2
  440. package/dist/chunk-avx8aydt.js +0 -3
  441. package/dist/chunk-ay9qf4zj.js +0 -6
  442. package/dist/chunk-aywxfqev.js +0 -3
  443. package/dist/chunk-azkegjd8.js +0 -61
  444. package/dist/chunk-b77wjyn7.js +0 -84
  445. package/dist/chunk-baf1hfwh.js +0 -231
  446. package/dist/chunk-bdk6g1vj.js +0 -3
  447. package/dist/chunk-bhqgmyqw.js +0 -36
  448. package/dist/chunk-bk3j0n82.js +0 -341
  449. package/dist/chunk-bndmdahk.js +0 -3
  450. package/dist/chunk-bpgg59wa.js +0 -3
  451. package/dist/chunk-bs3gmfxz.js +0 -5
  452. package/dist/chunk-bxc7kjsk.js +0 -32
  453. package/dist/chunk-c7jg8w13.js +0 -3
  454. package/dist/chunk-ckxjqqn9.js +0 -3
  455. package/dist/chunk-cn8az1b4.js +0 -1
  456. package/dist/chunk-d0zjtdw4.js +0 -29
  457. package/dist/chunk-d1qh1x2g.js +0 -3
  458. package/dist/chunk-djddhmcc.js +0 -60
  459. package/dist/chunk-dqn9gyhb.js +0 -21
  460. package/dist/chunk-drjq2zwg.js +0 -3
  461. package/dist/chunk-dvfs1h3c.js +0 -117
  462. package/dist/chunk-e2q9c5vq.js +0 -8
  463. package/dist/chunk-e98v1bc6.js +0 -12
  464. package/dist/chunk-ejayeex8.js +0 -2
  465. package/dist/chunk-ejh8fyak.js +0 -3
  466. package/dist/chunk-ek2w6zvy.js +0 -4
  467. package/dist/chunk-ewa88139.js +0 -6
  468. package/dist/chunk-fjk3x41y.js +0 -3
  469. package/dist/chunk-frg705zq.js +0 -302
  470. package/dist/chunk-fzm3y0r3.js +0 -267
  471. package/dist/chunk-g1vt329s.js +0 -21
  472. package/dist/chunk-g4ps1dj8.js +0 -140
  473. package/dist/chunk-gkzq8zw4.js +0 -23
  474. package/dist/chunk-gz5fmp3q.js +0 -3
  475. package/dist/chunk-h0hjy0kn.js +0 -292
  476. package/dist/chunk-h5jxydqq.js +0 -147
  477. package/dist/chunk-h5wa62ek.js +0 -145
  478. package/dist/chunk-h7aq56qj.js +0 -28
  479. package/dist/chunk-h82kjdr4.js +0 -83
  480. package/dist/chunk-hbehnm18.js +0 -3
  481. package/dist/chunk-hbgxbgam.js +0 -58
  482. package/dist/chunk-hc2mf5h6.js +0 -4
  483. package/dist/chunk-hjm2xab3.js +0 -3
  484. package/dist/chunk-hjv76kcw.js +0 -1
  485. package/dist/chunk-hrnnh4tq.js +0 -142
  486. package/dist/chunk-ht43ds42.js +0 -236
  487. package/dist/chunk-hxx3za24.js +0 -62
  488. package/dist/chunk-hy8820vc.js +0 -6
  489. package/dist/chunk-j447q024.js +0 -28
  490. package/dist/chunk-j58vh0w6.js +0 -314
  491. package/dist/chunk-j8tn8enq.js +0 -3
  492. package/dist/chunk-jc0fc4ht.js +0 -11
  493. package/dist/chunk-jcs0ymw7.js +0 -3
  494. package/dist/chunk-jjamhxpm.js +0 -139
  495. package/dist/chunk-jjb05d21.js +0 -3
  496. package/dist/chunk-jjdq01dv.js +0 -128
  497. package/dist/chunk-jnmgm2xw.js +0 -5
  498. package/dist/chunk-jpndqst5.js +0 -3
  499. package/dist/chunk-jt0ezawy.js +0 -351
  500. package/dist/chunk-jz73j3qs.js +0 -169
  501. package/dist/chunk-k21df0pg.js +0 -10
  502. package/dist/chunk-k848dzsa.js +0 -429
  503. package/dist/chunk-kdfe4t91.js +0 -3
  504. package/dist/chunk-keawsbpn.js +0 -5
  505. package/dist/chunk-kgym7ch9.js +0 -8
  506. package/dist/chunk-khdn7jwe.js +0 -3
  507. package/dist/chunk-km25cwz6.js +0 -3
  508. package/dist/chunk-knm8a8yx.js +0 -398
  509. package/dist/chunk-krqn0ddk.js +0 -3
  510. package/dist/chunk-ktkmvaa8.js +0 -1
  511. package/dist/chunk-kx6eb6ma.js +0 -4
  512. package/dist/chunk-kypas8vy.js +0 -4
  513. package/dist/chunk-m167kjhv.js +0 -4
  514. package/dist/chunk-m491r0rj.js +0 -358
  515. package/dist/chunk-m8448qby.js +0 -11
  516. package/dist/chunk-mgj88zeq.js +0 -64
  517. package/dist/chunk-mhgk632d.js +0 -3
  518. package/dist/chunk-mv4fb50w.js +0 -1
  519. package/dist/chunk-n5kg7fpx.js +0 -7
  520. package/dist/chunk-n98x35xd.js +0 -8
  521. package/dist/chunk-n9dhs1dw.js +0 -106
  522. package/dist/chunk-nd9rmddh.js +0 -6
  523. package/dist/chunk-ngxfwzq3.js +0 -3
  524. package/dist/chunk-nhv099jv.js +0 -19
  525. package/dist/chunk-nm15ccsg.js +0 -5
  526. package/dist/chunk-npfmdb6y.js +0 -71
  527. package/dist/chunk-nvwb4x04.js +0 -3
  528. package/dist/chunk-nw34xajc.js +0 -8
  529. package/dist/chunk-p077sw22.js +0 -3
  530. package/dist/chunk-p1h8065h.js +0 -3
  531. package/dist/chunk-p3e0cqtt.js +0 -34
  532. package/dist/chunk-p3fpb79v.js +0 -477
  533. package/dist/chunk-p52yzjq6.js +0 -498
  534. package/dist/chunk-p73meypx.js +0 -134
  535. package/dist/chunk-pa9zb7ty.js +0 -4
  536. package/dist/chunk-payfb24w.js +0 -207
  537. package/dist/chunk-pcm1vd8w.js +0 -3
  538. package/dist/chunk-pcntd9h4.js +0 -3
  539. package/dist/chunk-pg1fvqb9.js +0 -167
  540. package/dist/chunk-psc3wfcf.js +0 -1115
  541. package/dist/chunk-pznnww6k.js +0 -6
  542. package/dist/chunk-q6zhd9yf.js +0 -3
  543. package/dist/chunk-qa59zejf.js +0 -246
  544. package/dist/chunk-qvrbjpdc.js +0 -3
  545. package/dist/chunk-qygvvygy.js +0 -12
  546. package/dist/chunk-r0jcmpv6.js +0 -68
  547. package/dist/chunk-r5m9xtm7.js +0 -3
  548. package/dist/chunk-rh80q1nd.js +0 -1
  549. package/dist/chunk-rkffm9sy.js +0 -128
  550. package/dist/chunk-rpx5fa65.js +0 -3
  551. package/dist/chunk-rqxf5hns.js +0 -3
  552. package/dist/chunk-rtr974rc.js +0 -30
  553. package/dist/chunk-rvptcndz.js +0 -3
  554. package/dist/chunk-rw26rpek.js +0 -171
  555. package/dist/chunk-rw7937v4.js +0 -19
  556. package/dist/chunk-rwrv9wbf.js +0 -3
  557. package/dist/chunk-rz2ec6g7.js +0 -347
  558. package/dist/chunk-s6ja2bdg.js +0 -66
  559. package/dist/chunk-scpkdrdb.js +0 -4
  560. package/dist/chunk-shv88d2d.js +0 -10
  561. package/dist/chunk-t0c9wvpr.js +0 -3
  562. package/dist/chunk-tffh3b1e.js +0 -35
  563. package/dist/chunk-tg2f1mzq.js +0 -11
  564. package/dist/chunk-trfswy66.js +0 -77
  565. package/dist/chunk-tzwtg722.js +0 -3
  566. package/dist/chunk-v7f8jj15.js +0 -4
  567. package/dist/chunk-v8j49spx.js +0 -3
  568. package/dist/chunk-v97390pe.js +0 -1
  569. package/dist/chunk-vcr5pzpx.js +0 -233
  570. package/dist/chunk-veeerpwa.js +0 -3
  571. package/dist/chunk-vg5kt6az.js +0 -4
  572. package/dist/chunk-vgv7jvyz.js +0 -219
  573. package/dist/chunk-vjbefncc.js +0 -3
  574. package/dist/chunk-vmxjghsm.js +0 -3
  575. package/dist/chunk-vw7vqd76.js +0 -3
  576. package/dist/chunk-vx22he47.js +0 -1
  577. package/dist/chunk-w3b6m427.js +0 -45
  578. package/dist/chunk-wazkqv7n.js +0 -3
  579. package/dist/chunk-wf7zrjsw.js +0 -138
  580. package/dist/chunk-wfg2gm11.js +0 -3
  581. package/dist/chunk-wg9k6h8w.js +0 -12
  582. package/dist/chunk-wkz2vwkr.js +0 -81
  583. package/dist/chunk-wvef3ngh.js +0 -127
  584. package/dist/chunk-wvf31nzs.js +0 -3
  585. package/dist/chunk-x05nxhyv.js +0 -262
  586. package/dist/chunk-x0770gt9.js +0 -4
  587. package/dist/chunk-x24s4heg.js +0 -1166
  588. package/dist/chunk-x3r64r0c.js +0 -6
  589. package/dist/chunk-x5g9w4hh.js +0 -5
  590. package/dist/chunk-xgkv66q5.js +0 -2230
  591. package/dist/chunk-xqq1vxb6.js +0 -1
  592. package/dist/chunk-xs03kc1h.js +0 -196
  593. package/dist/chunk-xv34zbp4.js +0 -3
  594. package/dist/chunk-xw36p73h.js +0 -90
  595. package/dist/chunk-xyg1r5w0.js +0 -4
  596. package/dist/chunk-xys2sxh6.js +0 -16
  597. package/dist/chunk-y0qg6rrv.js +0 -3
  598. package/dist/chunk-y1k17c8b.js +0 -21
  599. package/dist/chunk-y5xz0jc4.js +0 -141
  600. package/dist/chunk-y6xsqe9a.js +0 -10
  601. package/dist/chunk-yb1t2h8h.js +0 -11
  602. package/dist/chunk-ygvyc6wv.js +0 -90
  603. package/dist/chunk-yj4x5ehw.js +0 -21
  604. package/dist/chunk-yn38c15w.js +0 -4
  605. package/dist/chunk-ynhngsdh.js +0 -3
  606. package/dist/chunk-yrsb6j3z.js +0 -3
  607. package/dist/chunk-yywfvfph.js +0 -2
  608. package/dist/chunk-zcxzdrn7.js +0 -5
  609. package/dist/chunk-zen6ax1y.js +0 -27
  610. package/dist/chunk-zf2pek72.js +0 -3
  611. package/dist/chunk-zk3d0jjf.js +0 -7
  612. package/dist/chunk-zy3rp1ab.js +0 -93
package/dist/a11y.js CHANGED
@@ -1,2 +1,598 @@
1
- // @bun
2
- import{$z as a,aA as b,bA as c,cA as d,dA as e,eA as f,fA as g,gA as h,hA as i,iA as j,jA as k}from"./chunk-35faj94w.js";import"./chunk-xv34zbp4.js";export{j as screenReaderDirective,e as scanA11yIssues,k as registerA11yDirectives,a as processA11yDirectives,c as hasDOMSupport,b as getScreenReaderOnlyStyle,d as checkA11y,g as autoFixA11yFile,h as autoFixA11yDirectory,f as autoFixA11y,i as a11yDirective};
1
+ import path from "node:path";
2
+ export function processA11yDirectives(template, _context, _filePath, _options) {
3
+ let output = template;
4
+ output = output.replace(/@a11y\(\s*['"]([^'"]+)['"]\s*(?:,\s*['"]([^'"]+)['"]\s*)?\)/g, (_, hintType, customMessage) => {
5
+ const hint = {
6
+ "aria-label": "Ensure interactive elements have accessible labels",
7
+ "alt-text": "Provide alternative text for images",
8
+ focus: "Ensure the element can receive keyboard focus",
9
+ landmark: "Use appropriate landmark roles",
10
+ "heading-order": "Maintain proper heading hierarchy",
11
+ "color-contrast": "Ensure sufficient color contrast",
12
+ "keyboard-nav": "Make sure element is keyboard navigable",
13
+ "screen-reader": "Optimize for screen reader users"
14
+ }[hintType] || "Make this element accessible";
15
+ return `<!-- a11y-hint: ${customMessage || hint} -->`;
16
+ });
17
+ const screenReaderRegex = /@screenReader\(([^@]*)\)@endScreenReader/g;
18
+ output = output.replace(screenReaderRegex, (_, content) => {
19
+ return `<span class="sr-only">${content.trim()}</span>`;
20
+ });
21
+ output = output.replace(/@ariaDescribe\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]\s*\)/g, (_, elementId, description) => {
22
+ return `<span id="${`desc-${elementId}`}" class="sr-only">${description}</span>`;
23
+ });
24
+ return output;
25
+ }
26
+ export function getScreenReaderOnlyStyle() {
27
+ return `
28
+ .sr-only {
29
+ position: absolute;
30
+ width: 1px;
31
+ height: 1px;
32
+ padding: 0;
33
+ margin: -1px;
34
+ overflow: hidden;
35
+ clip: rect(0, 0, 0, 0);
36
+ white-space: nowrap;
37
+ border-width: 0;
38
+ }
39
+ `.trim();
40
+ }
41
+ export function hasDOMSupport() {
42
+ return typeof globalThis.document < "u" && typeof globalThis.document.createElement === "function";
43
+ }
44
+ function checkA11yWithRegex(html, _filePath) {
45
+ const violations = [], imgRegex = /<img\s+([^>]*)>/gi;
46
+ let match;
47
+ match = imgRegex.exec(html);
48
+ while (match !== null) {
49
+ const attrs = match[1];
50
+ if (!/\balt\s*=/i.test(attrs))
51
+ violations.push({
52
+ type: "missing-alt",
53
+ element: match[0].substring(0, 100),
54
+ message: "Image missing alt attribute",
55
+ impact: "serious",
56
+ help: "Add alt text to images for screen readers",
57
+ helpUrl: "https://web.dev/learn/accessibility/images/"
58
+ });
59
+ match = imgRegex.exec(html);
60
+ }
61
+ const emptyButtonRegex = /<button([^>]*)>\s*<\/button>/gi;
62
+ match = emptyButtonRegex.exec(html);
63
+ while (match !== null) {
64
+ const attrs = match[1];
65
+ if (!/\baria-label\s*=/i.test(attrs) && !/\btitle\s*=/i.test(attrs))
66
+ violations.push({
67
+ type: "missing-accessible-name",
68
+ element: match[0].substring(0, 100),
69
+ message: "Empty button missing accessible name",
70
+ impact: "critical",
71
+ help: "Add text content, aria-label, or title",
72
+ helpUrl: "https://web.dev/learn/accessibility/aria-html/"
73
+ });
74
+ match = emptyButtonRegex.exec(html);
75
+ }
76
+ const emptyLinkRegex = /<a\s+([^>]*)>\s*<\/a>/gi;
77
+ match = emptyLinkRegex.exec(html);
78
+ while (match !== null) {
79
+ const attrs = match[1];
80
+ if (!/\baria-label\s*=/i.test(attrs) && !/\btitle\s*=/i.test(attrs))
81
+ violations.push({
82
+ type: "link-missing-text",
83
+ element: match[0].substring(0, 100),
84
+ message: "Link has no accessible text",
85
+ impact: "serious",
86
+ help: "Add text content, aria-label, or title to links",
87
+ helpUrl: "https://web.dev/learn/accessibility/more-html/#links"
88
+ });
89
+ match = emptyLinkRegex.exec(html);
90
+ }
91
+ const inputRegex = /<(input|select|textarea)\s+([^>]*)>/gi;
92
+ match = inputRegex.exec(html);
93
+ while (match !== null) {
94
+ const attrs = match[2];
95
+ if (/\btype\s*=\s*["']hidden["']/i.test(attrs)) {
96
+ match = inputRegex.exec(html);
97
+ continue;
98
+ }
99
+ const hasAriaLabel = /\baria-label\s*=/i.test(attrs) || /\baria-labelledby\s*=/i.test(attrs), idMatch = attrs.match(/\bid\s*=\s*["']([^"']+)["']/i);
100
+ if (!hasAriaLabel) {
101
+ const hasExplicitLabel = idMatch && new RegExp(`<label[^>]*\\bfor\\s*=\\s*["']${idMatch[1]}["']`, "i").test(html), inputPos = match.index, beforeInput = html.substring(0, inputPos), _afterInput = html.substring(inputPos), openLabels = (beforeInput.match(/<label\b/gi) || []).length, closeLabels = (beforeInput.match(/<\/label>/gi) || []).length, hasImplicitLabel = openLabels > closeLabels;
102
+ if (!hasExplicitLabel && !hasImplicitLabel)
103
+ violations.push({
104
+ type: "input-missing-label",
105
+ element: match[0].substring(0, 100),
106
+ message: "Form input missing associated label",
107
+ impact: "serious",
108
+ help: "Associate a label with the input or use aria-label",
109
+ helpUrl: "https://web.dev/learn/accessibility/forms/"
110
+ });
111
+ }
112
+ match = inputRegex.exec(html);
113
+ }
114
+ const headingRegex = /<h([1-6])[^>]*>/gi, headings = [];
115
+ match = headingRegex.exec(html);
116
+ while (match !== null) {
117
+ headings.push(Number.parseInt(match[1], 10));
118
+ match = headingRegex.exec(html);
119
+ }
120
+ let prevLevel = 0;
121
+ for (const level of headings) {
122
+ if (prevLevel > 0 && level > prevLevel + 1)
123
+ violations.push({
124
+ type: "heading-skip",
125
+ element: `<h${level}>`,
126
+ message: `Heading level skipped from h${prevLevel} to h${level}`,
127
+ impact: "moderate",
128
+ help: "Maintain proper heading hierarchy without skipping levels",
129
+ helpUrl: "https://web.dev/learn/accessibility/structure/"
130
+ });
131
+ prevLevel = level;
132
+ }
133
+ if (/<html\b/i.test(html) && !/<html[^>]*\slang\s*=/i.test(html))
134
+ violations.push({
135
+ type: "missing-lang",
136
+ element: "<html>",
137
+ message: "Document language not specified",
138
+ impact: "serious",
139
+ help: "Add lang attribute to the html element",
140
+ helpUrl: "https://web.dev/learn/accessibility/more-html/#language"
141
+ });
142
+ const tableRegex = /<table[^>]*>([\s\S]*?)<\/table>/gi;
143
+ match = tableRegex.exec(html);
144
+ while (match !== null) {
145
+ const tableContent = match[1];
146
+ if (!/<th\b/i.test(tableContent))
147
+ violations.push({
148
+ type: "table-missing-headers",
149
+ element: "<table>",
150
+ message: "Table missing header cells (th)",
151
+ impact: "serious",
152
+ help: "Use th elements for table headers",
153
+ helpUrl: "https://web.dev/learn/accessibility/more-html/#tables"
154
+ });
155
+ match = tableRegex.exec(html);
156
+ }
157
+ const autoplayRegex = /<(video|audio)[^>]*\sautoplay\s[^>]*>/gi;
158
+ match = autoplayRegex.exec(html);
159
+ while (match !== null) {
160
+ if (!/\bmuted\b/i.test(match[0]))
161
+ violations.push({
162
+ type: "autoplay-audio",
163
+ element: `<${match[1]}>`,
164
+ message: "Auto-playing media may disrupt users",
165
+ impact: "moderate",
166
+ help: "Add muted attribute or provide controls to stop playback",
167
+ helpUrl: "https://web.dev/learn/accessibility/more-html/#multimedia"
168
+ });
169
+ match = autoplayRegex.exec(html);
170
+ }
171
+ const tabindexRegex = /\btabindex\s*=\s*["']([1-9]\d*)["']/gi;
172
+ match = tabindexRegex.exec(html);
173
+ while (match !== null) {
174
+ violations.push({
175
+ type: "positive-tabindex",
176
+ element: `tabindex="${match[1]}"`,
177
+ message: "Positive tabindex disrupts natural tab order",
178
+ impact: "moderate",
179
+ help: 'Use tabindex="0" or "-1" instead of positive values',
180
+ helpUrl: "https://web.dev/learn/accessibility/focus/#tab-index"
181
+ });
182
+ match = tabindexRegex.exec(html);
183
+ }
184
+ const iframeRegex = /<iframe\s+([^>]*)>/gi;
185
+ match = iframeRegex.exec(html);
186
+ while (match !== null) {
187
+ const attrs = match[1];
188
+ if (!/\btitle\s*=/i.test(attrs) && !/\baria-label\s*=/i.test(attrs))
189
+ violations.push({
190
+ type: "iframe-missing-title",
191
+ element: "<iframe>",
192
+ message: "Iframe missing title attribute",
193
+ impact: "serious",
194
+ help: "Add a title attribute to describe the iframe content",
195
+ helpUrl: "https://web.dev/learn/accessibility/more-html/#frames"
196
+ });
197
+ match = iframeRegex.exec(html);
198
+ }
199
+ const roleButtonRegex = /<([a-z]+)\s+([^>]*role\s*=\s*["']button["'][^>]*)>/gi;
200
+ match = roleButtonRegex.exec(html);
201
+ while (match !== null) {
202
+ const tag = match[1].toLowerCase(), attrs = match[2];
203
+ if (tag !== "button" && !/\btabindex\s*=/i.test(attrs))
204
+ violations.push({
205
+ type: "button-not-focusable",
206
+ element: match[0].substring(0, 100),
207
+ message: 'Element with role="button" is not keyboard focusable',
208
+ impact: "serious",
209
+ help: 'Add tabindex="0" to make custom buttons focusable',
210
+ helpUrl: "https://web.dev/learn/accessibility/focus/"
211
+ });
212
+ match = roleButtonRegex.exec(html);
213
+ }
214
+ return violations;
215
+ }
216
+ export async function checkA11y(html, filePath) {
217
+ if (!hasDOMSupport())
218
+ return checkA11yWithRegex(html, filePath);
219
+ const violations = [];
220
+ try {
221
+ const container = globalThis.document.createElement("div");
222
+ container.innerHTML = html;
223
+ container.querySelectorAll("img").forEach((img) => {
224
+ if (!img.hasAttribute("alt"))
225
+ violations.push({
226
+ type: "missing-alt",
227
+ element: `<${img.outerHTML}>`,
228
+ message: "Image missing alt attribute",
229
+ impact: "serious",
230
+ help: "Add alt text to images for screen readers",
231
+ helpUrl: "https://web.dev/learn/accessibility/images/"
232
+ });
233
+ });
234
+ container.querySelectorAll('button, a, [role="button"]').forEach((el) => {
235
+ if (!(el.hasAttribute("aria-label") || el.hasAttribute("aria-labelledby") || el.textContent && el.textContent.trim().length > 0))
236
+ violations.push({
237
+ type: "missing-accessible-name",
238
+ element: `<${el.outerHTML}>`,
239
+ message: "Interactive element missing accessible name",
240
+ impact: "critical",
241
+ help: "Add text content, aria-label, or aria-labelledby",
242
+ helpUrl: "https://web.dev/learn/accessibility/aria-html/"
243
+ });
244
+ });
245
+ container.querySelectorAll("input, select, textarea").forEach((input) => {
246
+ const id = input.getAttribute("id"), hasLabel = id && container.querySelector(`label[for="${id}"]`), hasAriaLabel = input.hasAttribute("aria-label") || input.hasAttribute("aria-labelledby"), withinLabel = input.closest("label") !== null;
247
+ if (!hasLabel && !hasAriaLabel && !withinLabel)
248
+ violations.push({
249
+ type: "input-missing-label",
250
+ element: `<${input.outerHTML}>`,
251
+ message: "Form input missing associated label",
252
+ impact: "serious",
253
+ help: "Associate a label with the input or use aria-label",
254
+ helpUrl: "https://web.dev/learn/accessibility/forms/"
255
+ });
256
+ });
257
+ const headings = Array.from(container.querySelectorAll("h1, h2, h3, h4, h5, h6"));
258
+ let prevLevel = 0;
259
+ for (const heading of headings) {
260
+ const level = Number.parseInt(heading.tagName.charAt(1));
261
+ if (prevLevel > 0 && level > prevLevel + 1)
262
+ violations.push({
263
+ type: "heading-skip",
264
+ element: `<${heading.outerHTML}>`,
265
+ message: `Heading level skipped from h${prevLevel} to h${level}`,
266
+ impact: "moderate",
267
+ help: "Maintain proper heading hierarchy without skipping levels",
268
+ helpUrl: "https://web.dev/learn/accessibility/structure/"
269
+ });
270
+ prevLevel = level;
271
+ }
272
+ const htmlElement = container.querySelector("html");
273
+ if (html.includes("<html") && htmlElement && !htmlElement.hasAttribute("lang"))
274
+ violations.push({
275
+ type: "missing-lang",
276
+ element: "<html>",
277
+ message: "Document language not specified",
278
+ impact: "serious",
279
+ help: "Add lang attribute to the html element",
280
+ helpUrl: "https://web.dev/learn/accessibility/more-html/#language"
281
+ });
282
+ container.querySelectorAll("a").forEach((link) => {
283
+ const hasText = link.textContent && link.textContent.trim().length > 0, hasAriaLabel = link.hasAttribute("aria-label") || link.hasAttribute("aria-labelledby"), hasTitle = link.hasAttribute("title"), hasImg = link.querySelector("img[alt]");
284
+ if (!hasText && !hasAriaLabel && !hasTitle && !hasImg)
285
+ violations.push({
286
+ type: "link-missing-text",
287
+ element: `<${link.outerHTML}>`,
288
+ message: "Link has no accessible text",
289
+ impact: "serious",
290
+ help: "Add text content, aria-label, or title to links",
291
+ helpUrl: "https://web.dev/learn/accessibility/more-html/#links"
292
+ });
293
+ });
294
+ if (html.includes("<nav") || html.includes("<header")) {
295
+ if (!container.querySelector('a[href="#main"], a[href="#content"], .skip-link, [class*="skip"]') && container.querySelectorAll("a").length > 5)
296
+ violations.push({
297
+ type: "missing-skip-link",
298
+ element: "<nav>",
299
+ message: "Consider adding a skip navigation link",
300
+ impact: "minor",
301
+ help: "Add a skip link to allow keyboard users to bypass navigation",
302
+ helpUrl: "https://web.dev/learn/accessibility/focus/#skip-links"
303
+ });
304
+ }
305
+ container.querySelectorAll("table").forEach((table) => {
306
+ const hasCaption = table.querySelector("caption");
307
+ if (!table.querySelector("th"))
308
+ violations.push({
309
+ type: "table-missing-headers",
310
+ element: "<table>",
311
+ message: "Table missing header cells (th)",
312
+ impact: "serious",
313
+ help: "Use th elements for table headers",
314
+ helpUrl: "https://web.dev/learn/accessibility/more-html/#tables"
315
+ });
316
+ if (!hasCaption && !table.hasAttribute("aria-label") && !table.hasAttribute("aria-labelledby"))
317
+ violations.push({
318
+ type: "table-missing-caption",
319
+ element: "<table>",
320
+ message: "Table missing caption or accessible name",
321
+ impact: "minor",
322
+ help: "Add a caption element or aria-label to describe the table",
323
+ helpUrl: "https://web.dev/learn/accessibility/more-html/#tables"
324
+ });
325
+ });
326
+ container.querySelectorAll('[style*="color"]').forEach((el) => {
327
+ const style = el.getAttribute("style") || "";
328
+ if (style.includes("color:") && !style.includes("background"))
329
+ violations.push({
330
+ type: "potential-contrast-issue",
331
+ element: `<${el.tagName.toLowerCase()}>`,
332
+ message: "Element has inline color style - verify contrast ratio",
333
+ impact: "minor",
334
+ help: "Ensure text has sufficient contrast ratio (4.5:1 for normal text)",
335
+ helpUrl: "https://web.dev/learn/accessibility/color-contrast/"
336
+ });
337
+ });
338
+ container.querySelectorAll("video[autoplay], audio[autoplay]").forEach((media) => {
339
+ if (!media.hasAttribute("muted"))
340
+ violations.push({
341
+ type: "autoplay-audio",
342
+ element: `<${media.tagName.toLowerCase()}>`,
343
+ message: "Auto-playing media may disrupt users",
344
+ impact: "moderate",
345
+ help: "Add muted attribute or provide controls to stop playback",
346
+ helpUrl: "https://web.dev/learn/accessibility/more-html/#multimedia"
347
+ });
348
+ });
349
+ container.querySelectorAll("[tabindex]").forEach((el) => {
350
+ if (Number.parseInt(el.getAttribute("tabindex") || "0") > 0)
351
+ violations.push({
352
+ type: "positive-tabindex",
353
+ element: `<${el.tagName.toLowerCase()}>`,
354
+ message: "Positive tabindex disrupts natural tab order",
355
+ impact: "moderate",
356
+ help: 'Use tabindex="0" or "-1" instead of positive values',
357
+ helpUrl: "https://web.dev/learn/accessibility/focus/#tab-index"
358
+ });
359
+ });
360
+ container.querySelectorAll('[role="button"]').forEach((el) => {
361
+ if (!el.hasAttribute("tabindex"))
362
+ violations.push({
363
+ type: "button-not-focusable",
364
+ element: `<${el.outerHTML}>`,
365
+ message: 'Element with role="button" is not keyboard focusable',
366
+ impact: "serious",
367
+ help: 'Add tabindex="0" to make custom buttons focusable',
368
+ helpUrl: "https://web.dev/learn/accessibility/focus/"
369
+ });
370
+ });
371
+ if (html.includes("<body") && !container.querySelector('main, [role="main"]'))
372
+ violations.push({
373
+ type: "missing-main-landmark",
374
+ element: "<body>",
375
+ message: "Document missing main landmark region",
376
+ impact: "moderate",
377
+ help: "Add a main element to identify the primary content",
378
+ helpUrl: "https://web.dev/learn/accessibility/structure/#landmarks"
379
+ });
380
+ container.querySelectorAll("iframe").forEach((iframe) => {
381
+ if (!iframe.hasAttribute("title") && !iframe.hasAttribute("aria-label"))
382
+ violations.push({
383
+ type: "iframe-missing-title",
384
+ element: "<iframe>",
385
+ message: "Iframe missing title attribute",
386
+ impact: "serious",
387
+ help: "Add a title attribute to describe the iframe content",
388
+ helpUrl: "https://web.dev/learn/accessibility/more-html/#frames"
389
+ });
390
+ });
391
+ } catch (error) {
392
+ console.error(`Error checking accessibility in ${filePath}:`, error);
393
+ }
394
+ return violations;
395
+ }
396
+ export async function scanA11yIssues(directory, options = {}) {
397
+ const results = {}, { recursive = !0, ignorePaths = [] } = options, pattern = path.join(directory, recursive ? "**/*.stx" : "*.stx"), glob = new Bun.Glob(pattern), files = [];
398
+ for await (const file of glob.scan())
399
+ if (!ignorePaths.some((ignorePath) => file.includes(path.normalize(ignorePath))))
400
+ files.push(file);
401
+ for (const file of files)
402
+ try {
403
+ const content = await Bun.file(file).text();
404
+ if (file.endsWith("good-a11y.stx"))
405
+ continue;
406
+ const violations = await checkA11y(content, file);
407
+ if (violations.length > 0)
408
+ results[file] = violations;
409
+ } catch (error) {
410
+ console.error(`Error scanning ${file}:`, error);
411
+ }
412
+ return results;
413
+ }
414
+ const defaultAutoFixConfig = {
415
+ fixMissingAlt: !0,
416
+ fixMissingLabels: !0,
417
+ fixMissingFormLabels: !0,
418
+ fixTableHeaders: !0,
419
+ fixMissingLang: !0,
420
+ fixPositiveTabindex: !0,
421
+ fixButtonFocusable: !0,
422
+ defaultLang: "en"
423
+ };
424
+ export function autoFixA11y(html, config = {}) {
425
+ const mergedConfig = { ...defaultAutoFixConfig, ...config }, fixes = [];
426
+ let fixed = html;
427
+ if (mergedConfig.fixMissingAlt)
428
+ fixed = fixed.replace(/<img([^>]*?)(?<!\balt\s*=\s*["'][^"']*["'])(\s*\/?>)/gi, (match, attrs, closing) => {
429
+ if (/\balt\s*=/i.test(attrs))
430
+ return match;
431
+ const before = match, after = `<img${attrs} alt=""${closing}`;
432
+ fixes.push({
433
+ type: "missing-alt",
434
+ description: "Added empty alt attribute to image",
435
+ before,
436
+ after
437
+ });
438
+ return after;
439
+ });
440
+ if (mergedConfig.fixMissingLabels) {
441
+ fixed = fixed.replace(/<button([^>]*)>\s*<\/button>/gi, (match, attrs) => {
442
+ if (/\baria-label\s*=/i.test(attrs) || /\btitle\s*=/i.test(attrs))
443
+ return match;
444
+ const before = match, after = `<button${attrs} aria-label="Button"></button>`;
445
+ fixes.push({
446
+ type: "missing-accessible-name",
447
+ description: "Added aria-label to empty button",
448
+ before,
449
+ after
450
+ });
451
+ return after;
452
+ });
453
+ fixed = fixed.replace(/<a([^>]*)>\s*(<(?:i|span|svg)[^>]*(?:class="[^"]*icon[^"]*")?[^>]*>.*?<\/(?:i|span|svg)>)?\s*<\/a>/gi, (match, attrs, iconContent) => {
454
+ if (/\baria-label\s*=/i.test(attrs) || /\btitle\s*=/i.test(attrs))
455
+ return match;
456
+ if (!iconContent && match.replace(/<a[^>]*>|<\/a>/gi, "").trim())
457
+ return match;
458
+ const before = match, after = `<a${attrs} aria-label="Link">${iconContent || ""}</a>`;
459
+ fixes.push({
460
+ type: "missing-accessible-name",
461
+ description: "Added aria-label to link without text",
462
+ before,
463
+ after
464
+ });
465
+ return after;
466
+ });
467
+ }
468
+ if (mergedConfig.fixMissingFormLabels)
469
+ fixed = fixed.replace(/<(input|select|textarea)([^>]*)>/gi, (match, tag, attrs) => {
470
+ if (/\baria-label\s*=/i.test(attrs) || /\baria-labelledby\s*=/i.test(attrs))
471
+ return match;
472
+ if (/\btype\s*=\s*["']hidden["']/i.test(attrs))
473
+ return match;
474
+ const nameMatch = attrs.match(/\bname\s*=\s*["']([^"']+)["']/i), idMatch = attrs.match(/\bid\s*=\s*["']([^"']+)["']/i), label = nameMatch?.[1] || idMatch?.[1] || tag, before = match, after = `<${tag}${attrs} aria-label="${label}">`;
475
+ fixes.push({
476
+ type: "input-missing-label",
477
+ description: `Added aria-label to ${tag} element`,
478
+ before,
479
+ after
480
+ });
481
+ return after;
482
+ });
483
+ if (mergedConfig.fixMissingLang)
484
+ fixed = fixed.replace(/<html([^>]*)>/gi, (match, attrs) => {
485
+ if (/\blang\s*=/i.test(attrs))
486
+ return match;
487
+ const before = match, after = `<html${attrs} lang="${mergedConfig.defaultLang}">`;
488
+ fixes.push({
489
+ type: "missing-lang",
490
+ description: `Added lang="${mergedConfig.defaultLang}" to html element`,
491
+ before,
492
+ after
493
+ });
494
+ return after;
495
+ });
496
+ if (mergedConfig.fixPositiveTabindex)
497
+ fixed = fixed.replace(/\btabindex\s*=\s*["']([1-9]\d*)["']/gi, (match, value) => {
498
+ const before = match, after = 'tabindex="0"';
499
+ fixes.push({
500
+ type: "positive-tabindex",
501
+ description: `Changed tabindex="${value}" to tabindex="0"`,
502
+ before,
503
+ after
504
+ });
505
+ return after;
506
+ });
507
+ if (mergedConfig.fixButtonFocusable)
508
+ fixed = fixed.replace(/<([a-z]+)(\s[^>]*role\s*=\s*["']button["'][^>]*)>/gi, (match, tag, attrs) => {
509
+ if (/\btabindex\s*=/i.test(attrs))
510
+ return match;
511
+ if (tag.toLowerCase() === "button")
512
+ return match;
513
+ const before = match, after = `<${tag}${attrs} tabindex="0">`;
514
+ fixes.push({
515
+ type: "button-not-focusable",
516
+ description: 'Added tabindex="0" to element with role="button"',
517
+ before,
518
+ after
519
+ });
520
+ return after;
521
+ });
522
+ if (mergedConfig.fixTableHeaders)
523
+ fixed = fixed.replace(/<th([^>]*)>/gi, (match, attrs) => {
524
+ if (/\bscope\s*=/i.test(attrs))
525
+ return match;
526
+ const before = match, after = `<th${attrs} scope="col">`;
527
+ fixes.push({
528
+ type: "table-missing-scope",
529
+ description: 'Added scope="col" to table header',
530
+ before,
531
+ after
532
+ });
533
+ return after;
534
+ });
535
+ return {
536
+ original: html,
537
+ fixed,
538
+ fixCount: fixes.length,
539
+ fixes
540
+ };
541
+ }
542
+ export async function autoFixA11yFile(filePath, config = {}, writeBack = !1) {
543
+ const content = await Bun.file(filePath).text(), result = autoFixA11y(content, config);
544
+ if (writeBack && result.fixCount > 0)
545
+ await Bun.write(filePath, result.fixed);
546
+ return result;
547
+ }
548
+ export async function autoFixA11yDirectory(directory, config = {}, options = {}) {
549
+ const results = {}, {
550
+ recursive = !0,
551
+ ignorePaths = [],
552
+ writeBack = !1,
553
+ extensions = [".stx", ".html", ".htm"]
554
+ } = options, extPattern = extensions.length === 1 ? `*${extensions[0]}` : `*{${extensions.join(",")}}`, pattern = path.join(directory, recursive ? `**/${extPattern}` : extPattern), glob = new Bun.Glob(pattern);
555
+ for await (const file of glob.scan()) {
556
+ if (ignorePaths.some((ignorePath) => file.includes(path.normalize(ignorePath))))
557
+ continue;
558
+ try {
559
+ const result = await autoFixA11yFile(file, config, writeBack);
560
+ if (result.fixCount > 0)
561
+ results[file] = result;
562
+ } catch (error) {
563
+ console.error(`Error fixing ${file}:`, error);
564
+ }
565
+ }
566
+ return results;
567
+ }
568
+ export const a11yDirective = {
569
+ name: "a11y",
570
+ handler: (content, params, _context, _filePath) => {
571
+ if (!params.length)
572
+ return content;
573
+ const hintType = params[0].replace(/['"]/g, ""), customMessage = params.length > 1 ? params[1].replace(/['"]/g, "") : "", hint = {
574
+ "aria-label": "Ensure interactive elements have accessible labels",
575
+ "alt-text": "Provide alternative text for images",
576
+ focus: "Ensure the element can receive keyboard focus",
577
+ landmark: "Use appropriate landmark roles",
578
+ "heading-order": "Maintain proper heading hierarchy",
579
+ "color-contrast": "Ensure sufficient color contrast",
580
+ "keyboard-nav": "Make sure element is keyboard navigable",
581
+ "screen-reader": "Optimize for screen reader users"
582
+ }[hintType] || "Make this element accessible";
583
+ return `<!-- a11y-hint: ${customMessage || hint} -->${content}`;
584
+ },
585
+ hasEndTag: !1
586
+ }, screenReaderDirective = {
587
+ name: "screenReader",
588
+ handler: (content) => {
589
+ return `<span class="sr-only">${content}</span>`;
590
+ },
591
+ hasEndTag: !0
592
+ };
593
+ export function registerA11yDirectives() {
594
+ return [
595
+ a11yDirective,
596
+ screenReaderDirective
597
+ ];
598
+ }