@birdapi/velinstyle 0.7.0 → 0.9.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 (336) hide show
  1. package/README.de.md +135 -224
  2. package/README.md +134 -223
  3. package/cli/blueprint.js +8 -0
  4. package/cli/blueprints/bottom-nav-mobile.html +17 -0
  5. package/cli/blueprints/cookie-consent.html +9 -0
  6. package/cli/blueprints/empty-state.html +5 -0
  7. package/cli/blueprints/filter-bar.html +15 -0
  8. package/cli/blueprints/notification-center.html +13 -0
  9. package/cli/blueprints/onboarding.html +23 -0
  10. package/cli/blueprints/pricing-table.html +20 -0
  11. package/cli/blueprints/settings-panel.html +20 -0
  12. package/cli/cli-manifest.json +97 -0
  13. package/cli/docgen/extract-a11y.js +89 -0
  14. package/cli/docgen/extract-attributes.js +95 -0
  15. package/cli/docgen/extract-cli.js +50 -0
  16. package/cli/docgen/extract-components.js +175 -0
  17. package/cli/docgen/extract-meta.js +32 -0
  18. package/cli/docgen/extract-rules.js +76 -0
  19. package/cli/docgen/extract-tokens.js +79 -0
  20. package/cli/docgen/extract-utilities.js +75 -0
  21. package/cli/docgen/markdown.js +43 -0
  22. package/cli/docs-generate.js +196 -0
  23. package/cli/index.js +236 -5
  24. package/cli/layout-audit.js +325 -0
  25. package/cli/meta.js +97 -0
  26. package/cli/perf-audit.js +174 -0
  27. package/cli/pii-scanner.js +134 -0
  28. package/cli/scaffold-recipes.json +70 -0
  29. package/cli/scaffold.js +155 -0
  30. package/cli/scanner-rules-data.js +62 -0
  31. package/cli/scanner.js +136 -1
  32. package/cli/search-index.js +163 -0
  33. package/cli/tokens-build.js +21 -1
  34. package/cli/tokens-validate.js +69 -0
  35. package/components/a11y-entry.js +42 -0
  36. package/components/a11y-utils.js +71 -0
  37. package/components/focus-manager.js +45 -8
  38. package/components/index.js +40 -11
  39. package/components/runtime/component-loaders.js +43 -0
  40. package/components/runtime/index.js +77 -0
  41. package/components/runtime-entry.js +10 -0
  42. package/components/sanitize.js +135 -28
  43. package/components/shadow-a11y-styles.js +18 -0
  44. package/components/velin-accordion.js +12 -0
  45. package/components/velin-announcer.js +35 -0
  46. package/components/velin-bottom-nav.js +108 -0
  47. package/components/velin-carousel.js +2 -2
  48. package/components/velin-code-block.js +142 -0
  49. package/components/velin-combobox.js +149 -0
  50. package/components/velin-command.js +142 -0
  51. package/components/velin-copy.js +18 -5
  52. package/components/velin-counter.js +155 -0
  53. package/components/velin-dialog.js +9 -1
  54. package/components/velin-email.js +94 -0
  55. package/components/velin-flip.js +220 -0
  56. package/components/velin-icon.js +99 -22
  57. package/components/velin-lightbox.js +8 -3
  58. package/components/velin-live-dot.js +90 -0
  59. package/components/velin-menubar.js +83 -0
  60. package/components/velin-modal.js +6 -3
  61. package/components/velin-popover.js +34 -2
  62. package/components/velin-rating.js +91 -0
  63. package/components/velin-reveal.js +22 -0
  64. package/components/velin-scroll-top.js +1 -1
  65. package/components/velin-search.js +267 -0
  66. package/components/velin-secure-field.js +99 -0
  67. package/components/velin-segmented-control.js +108 -0
  68. package/components/velin-sheet.js +107 -0
  69. package/components/velin-sparkline.js +227 -0
  70. package/components/{velin-stepper-wc.js → velin-stepper.js} +37 -8
  71. package/components/velin-theme-toggle.js +284 -60
  72. package/components/velin-toast.js +4 -0
  73. package/components/{velin-tooltip-wc.js → velin-tooltip.js} +22 -3
  74. package/core/a11y/component-contracts.json +221 -0
  75. package/core/attributes/index.js +6 -0
  76. package/core/attributes/registry.js +268 -0
  77. package/core/highlight/highlight.js +114 -0
  78. package/core/highlight/index.js +29 -0
  79. package/core/highlight/languages/_utils.js +52 -0
  80. package/core/highlight/languages/blade.js +16 -0
  81. package/core/highlight/languages/css.js +26 -0
  82. package/core/highlight/languages/html.js +17 -0
  83. package/core/highlight/languages/js.js +58 -0
  84. package/core/highlight/languages/json.js +14 -0
  85. package/core/highlight/languages/markdown.js +16 -0
  86. package/core/highlight/languages/php.js +39 -0
  87. package/core/highlight/languages/plain.js +7 -0
  88. package/core/highlight/languages/shell.js +33 -0
  89. package/core/highlight/languages/sql.js +20 -0
  90. package/core/highlight/languages/typescript.js +28 -0
  91. package/core/highlight/observe.js +53 -0
  92. package/core/highlight/registry.js +107 -0
  93. package/core/highlight/render.js +35 -0
  94. package/core/highlight/types.js +28 -0
  95. package/core/meta/build.js +293 -0
  96. package/core/meta/index.js +17 -0
  97. package/core/meta/schema.js +49 -0
  98. package/core/motion/effects.js +54 -0
  99. package/core/motion/index.js +76 -0
  100. package/core/motion/scheduler.js +72 -0
  101. package/core/motion/scroll.js +32 -0
  102. package/core/motion/stagger.js +24 -0
  103. package/core/search/docs-url.js +96 -0
  104. package/core/search/engine.js +139 -0
  105. package/core/search/highlight.js +48 -0
  106. package/core/search/index.js +126 -0
  107. package/core/search/providers.js +36 -0
  108. package/core/search/types.js +61 -0
  109. package/core/search/worker-client.js +56 -0
  110. package/core/search/worker.js +20 -0
  111. package/dist/chunks/a11y-utils-IRC7LOPF.js +16 -0
  112. package/dist/chunks/attributes-3BZLI7XF.js +364 -0
  113. package/dist/chunks/attributes-4N5JP4CG.js +364 -0
  114. package/dist/chunks/attributes-5Q2WXGRC.js +374 -0
  115. package/dist/chunks/attributes-AIR7SVLK.js +364 -0
  116. package/dist/chunks/attributes-BGRN5XZO.js +364 -0
  117. package/dist/chunks/attributes-BVSQAYLR.js +364 -0
  118. package/dist/chunks/attributes-CDYFUY7Y.js +364 -0
  119. package/dist/chunks/attributes-JMYJZBPE.js +364 -0
  120. package/dist/chunks/attributes-R5JY3X4O.js +374 -0
  121. package/dist/chunks/attributes-STYCS3O5.js +391 -0
  122. package/dist/chunks/attributes-TNSPQTHX.js +374 -0
  123. package/dist/chunks/attributes-TPANLMLF.js +391 -0
  124. package/dist/chunks/blade-LIQLVKZQ.js +19 -0
  125. package/dist/chunks/browser-MRKYZPEH.js +1149 -0
  126. package/dist/chunks/chunk-2354NEBP.js +109 -0
  127. package/dist/chunks/chunk-2VNA7G7S.js +109 -0
  128. package/dist/chunks/chunk-42VVPW6N.js +132 -0
  129. package/dist/chunks/chunk-7FFAMRFV.js +44 -0
  130. package/dist/chunks/chunk-7MCGPHVC.js +69 -0
  131. package/dist/chunks/chunk-AQLRJSGG.js +109 -0
  132. package/dist/chunks/chunk-EWPSDMQT.js +109 -0
  133. package/dist/chunks/chunk-F7OLHTGX.js +22 -0
  134. package/dist/chunks/chunk-J472ERN2.js +242 -0
  135. package/dist/chunks/chunk-LA7264K4.js +85 -0
  136. package/dist/chunks/chunk-M5CHQVP6.js +61 -0
  137. package/dist/chunks/chunk-MKZP2TBH.js +89 -0
  138. package/dist/chunks/chunk-QTJJ3DPO.js +109 -0
  139. package/dist/chunks/chunk-RDE3QE7Z.js +89 -0
  140. package/dist/chunks/chunk-RSMRR27R.js +109 -0
  141. package/dist/chunks/chunk-RZQVWFHW.js +109 -0
  142. package/dist/chunks/chunk-SRL6EWHP.js +109 -0
  143. package/dist/chunks/chunk-U4XHMZ7D.js +109 -0
  144. package/dist/chunks/chunk-V5YIUA6G.js +109 -0
  145. package/dist/chunks/chunk-XIET2VSZ.js +109 -0
  146. package/dist/chunks/chunk-XYLJ2GCB.js +205 -0
  147. package/dist/chunks/chunk-Z4JYQ2XX.js +51 -0
  148. package/dist/chunks/chunk-ZPSPKUYD.js +109 -0
  149. package/dist/chunks/css-MQ5YU77P.js +28 -0
  150. package/dist/chunks/highlight-GJHHV4KM.js +37 -0
  151. package/dist/chunks/highlight-XTHRKBA3.js +37 -0
  152. package/dist/chunks/html-ZODC4DLQ.js +20 -0
  153. package/dist/chunks/js-MNSNYTJU.js +7 -0
  154. package/dist/chunks/json-VEM2HFH3.js +17 -0
  155. package/dist/chunks/markdown-E7OPGS3S.js +19 -0
  156. package/dist/chunks/php-MLL7T3LT.js +41 -0
  157. package/dist/chunks/plain-LJJDC5TN.js +8 -0
  158. package/dist/chunks/runtime-entry.js +14 -0
  159. package/dist/chunks/shell-QTRK4U4E.js +35 -0
  160. package/dist/chunks/sql-PPWLHGJ2.js +23 -0
  161. package/dist/chunks/typescript-JT3CCYWL.js +30 -0
  162. package/dist/chunks/velin-accordion-FBIPAEXG.js +105 -0
  163. package/dist/chunks/velin-accordion-QAQO7BI7.js +117 -0
  164. package/dist/chunks/velin-announcer-PVTXXCWR.js +33 -0
  165. package/dist/chunks/velin-bottom-nav-2N2TYWOF.js +86 -0
  166. package/dist/chunks/velin-bottom-nav-7GEMPIM6.js +86 -0
  167. package/dist/chunks/velin-bottom-nav-CTU6FFZV.js +101 -0
  168. package/dist/chunks/velin-bottom-nav-N3DFQR66.js +86 -0
  169. package/dist/chunks/velin-carousel-Y5VCOABZ.js +213 -0
  170. package/dist/chunks/velin-carousel-ZTBANFQQ.js +213 -0
  171. package/dist/chunks/velin-code-block-ASUBTAQV.js +119 -0
  172. package/dist/chunks/velin-code-block-CIAURDRJ.js +132 -0
  173. package/dist/chunks/velin-code-block-TSUKPY4C.js +123 -0
  174. package/dist/chunks/velin-code-block-Y6CM726Q.js +119 -0
  175. package/dist/chunks/velin-collapse-5XYBUIID.js +80 -0
  176. package/dist/chunks/velin-combobox-2KDTCQ7N.js +155 -0
  177. package/dist/chunks/velin-combobox-NXS4QB4R.js +155 -0
  178. package/dist/chunks/velin-combobox-UGA56HP3.js +155 -0
  179. package/dist/chunks/velin-command-CKDNO4BW.js +148 -0
  180. package/dist/chunks/velin-command-M7RNHUPR.js +136 -0
  181. package/dist/chunks/velin-command-ONKO2A3J.js +136 -0
  182. package/dist/chunks/velin-command-TMLSRGIU.js +136 -0
  183. package/dist/chunks/velin-copy-G2TZ5YBB.js +81 -0
  184. package/dist/chunks/velin-copy-NYDBOKXT.js +81 -0
  185. package/dist/chunks/velin-copy-T5KDTDXP.js +81 -0
  186. package/dist/chunks/velin-countdown-4ZVDGK4R.js +101 -0
  187. package/dist/chunks/velin-countdown-5XSTN3BH.js +101 -0
  188. package/dist/chunks/velin-countdown-7AIY66CU.js +101 -0
  189. package/dist/chunks/velin-counter-ISCTEAHI.js +118 -0
  190. package/dist/chunks/velin-counter-L5FYJF7A.js +121 -0
  191. package/dist/chunks/velin-dialog-D2GUHSCD.js +144 -0
  192. package/dist/chunks/velin-dialog-ELFOZIXZ.js +152 -0
  193. package/dist/chunks/velin-dialog-GTTZI564.js +147 -0
  194. package/dist/chunks/velin-dialog-IJLFDXAJ.js +144 -0
  195. package/dist/chunks/velin-dialog-TNS3WXMB.js +144 -0
  196. package/dist/chunks/velin-drawer-BE6TYN3H.js +130 -0
  197. package/dist/chunks/velin-drawer-DLL2GLT6.js +130 -0
  198. package/dist/chunks/velin-drawer-MJS6WCF7.js +130 -0
  199. package/dist/chunks/velin-dropdown-PLUIFA5M.js +172 -0
  200. package/dist/chunks/velin-email-N5B5ZYTE.js +90 -0
  201. package/dist/chunks/velin-email-NTM6DG3V.js +90 -0
  202. package/dist/chunks/velin-email-RBX6ZR4S.js +90 -0
  203. package/dist/chunks/velin-haptic-4QQTM3RK.js +50 -0
  204. package/dist/chunks/velin-icon-7M76DOPB.js +164 -0
  205. package/dist/chunks/velin-icon-KZO3IEHG.js +164 -0
  206. package/dist/chunks/velin-icon-WTFPG2DD.js +191 -0
  207. package/dist/chunks/velin-icon-ZTSKUOVN.js +193 -0
  208. package/dist/chunks/velin-lightbox-6E7CAATP.js +149 -0
  209. package/dist/chunks/velin-lightbox-I75U6JF4.js +140 -0
  210. package/dist/chunks/velin-lightbox-QOTB4PRL.js +140 -0
  211. package/dist/chunks/velin-lightbox-UCD6N7HF.js +140 -0
  212. package/dist/chunks/velin-live-dot-RJHX2DGY.js +74 -0
  213. package/dist/chunks/velin-live-dot-XHUZCIDZ.js +67 -0
  214. package/dist/chunks/velin-menubar-I426AED2.js +86 -0
  215. package/dist/chunks/velin-menubar-J66JXRWW.js +86 -0
  216. package/dist/chunks/velin-menubar-SFEXJE56.js +86 -0
  217. package/dist/chunks/velin-modal-2HOBXE6F.js +176 -0
  218. package/dist/chunks/velin-modal-5HYNNNUI.js +176 -0
  219. package/dist/chunks/velin-modal-AEOTZ67O.js +177 -0
  220. package/dist/chunks/velin-modal-GLI2XZZB.js +176 -0
  221. package/dist/chunks/velin-persist-DFPL3QP4.js +110 -0
  222. package/dist/chunks/velin-popover-EXINRIGJ.js +145 -0
  223. package/dist/chunks/velin-popover-HQW6Q2Y6.js +172 -0
  224. package/dist/chunks/velin-popover-OXX7MRZ6.js +145 -0
  225. package/dist/chunks/velin-popover-T72HK3DF.js +151 -0
  226. package/dist/chunks/velin-popover-YKCCROJG.js +145 -0
  227. package/dist/chunks/velin-progress-ring-E4YRLZHH.js +66 -0
  228. package/dist/chunks/velin-rating-6CDBI6DG.js +91 -0
  229. package/dist/chunks/velin-rating-N4DI2XNL.js +91 -0
  230. package/dist/chunks/velin-rating-XRQJV4LO.js +91 -0
  231. package/dist/chunks/velin-scroll-top-F2FCZNYD.js +58 -0
  232. package/dist/chunks/velin-scroll-top-OHYVVHHY.js +58 -0
  233. package/dist/chunks/velin-scrollspy-OKCT4FDV.js +50 -0
  234. package/dist/chunks/velin-search-2XRQFBCS.js +556 -0
  235. package/dist/chunks/velin-search-4YHJWYSS.js +556 -0
  236. package/dist/chunks/velin-search-7B4KJ6TX.js +557 -0
  237. package/dist/chunks/velin-search-LWHY23Q5.js +474 -0
  238. package/dist/chunks/velin-secure-field-6PV7RZDJ.js +95 -0
  239. package/dist/chunks/velin-secure-field-H7FSBUJW.js +95 -0
  240. package/dist/chunks/velin-secure-field-OFNAXCDP.js +95 -0
  241. package/dist/chunks/velin-segmented-control-EKL4E3BL.js +109 -0
  242. package/dist/chunks/velin-segmented-control-GYD5BIXQ.js +109 -0
  243. package/dist/chunks/velin-segmented-control-PQX6LKOJ.js +109 -0
  244. package/dist/chunks/velin-sheet-3OGI4HD7.js +119 -0
  245. package/dist/chunks/velin-sheet-OUK6572T.js +119 -0
  246. package/dist/chunks/velin-sheet-R2Y67X6H.js +119 -0
  247. package/dist/chunks/velin-sparkline-GVEANJVW.js +184 -0
  248. package/dist/chunks/velin-sparkline-KDA3GQAN.js +162 -0
  249. package/dist/chunks/velin-sparkline-XVTFC6GE.js +181 -0
  250. package/dist/chunks/velin-stepper-2ZIHLKGM.js +141 -0
  251. package/dist/chunks/velin-stepper-7ECRUYHD.js +148 -0
  252. package/dist/chunks/velin-stepper-FYEUEWE6.js +141 -0
  253. package/dist/chunks/velin-stepper-X54WGHDG.js +141 -0
  254. package/dist/chunks/velin-stepper-wc-QU3KRVQR.js +133 -0
  255. package/dist/chunks/velin-tabs-5UQ5ZVMV.js +138 -0
  256. package/dist/chunks/velin-theme-toggle-32J2CBNC.js +291 -0
  257. package/dist/chunks/velin-theme-toggle-BNNS7WLV.js +285 -0
  258. package/dist/chunks/velin-theme-toggle-NO7V4TWI.js +285 -0
  259. package/dist/chunks/velin-theme-toggle-QELCJM2Q.js +291 -0
  260. package/dist/chunks/velin-toast-OMMOA2DK.js +109 -0
  261. package/dist/chunks/velin-toast-RCZ4CSUC.js +109 -0
  262. package/dist/chunks/velin-toast-RSF2IHT3.js +113 -0
  263. package/dist/chunks/velin-toast-WEUBTJG6.js +109 -0
  264. package/dist/chunks/velin-tooltip-664IOHZA.js +112 -0
  265. package/dist/chunks/velin-tooltip-BDHGRTQB.js +112 -0
  266. package/dist/chunks/velin-tooltip-HVUOKNVX.js +112 -0
  267. package/dist/chunks/velin-tooltip-wc-LXDVT6DE.js +103 -0
  268. package/dist/chunks/worker-client-R6DBYPFT.js +46 -0
  269. package/dist/llms.test.txt +40 -0
  270. package/dist/llms.txt +40 -0
  271. package/dist/search-index.json +1773 -0
  272. package/dist/search-index.test.json +1773 -0
  273. package/dist/themes/brutalist.min.css +1 -1
  274. package/dist/themes/midnight.min.css +1 -1
  275. package/dist/themes/pastel.min.css +1 -1
  276. package/dist/themes/retro.min.css +1 -1
  277. package/dist/themes/sunset.min.css +1 -1
  278. package/dist/velin-agent.json +684 -0
  279. package/dist/velin-agent.test.json +684 -0
  280. package/dist/velinstyle-components.iife.js +7959 -2199
  281. package/dist/velinstyle-components.js +7982 -2174
  282. package/dist/velinstyle-components.min.js +521 -90
  283. package/dist/velinstyle.css +1290 -282
  284. package/dist/velinstyle.d.ts +54 -0
  285. package/dist/velinstyle.min.css +1 -1
  286. package/examples/search-index.schema.json +33 -0
  287. package/package.json +57 -10
  288. package/src/a11y/authentication.css +37 -0
  289. package/src/a11y/consistent-help.css +22 -0
  290. package/src/a11y/dragging-alternatives.css +30 -0
  291. package/src/a11y/focus-appearance.css +20 -0
  292. package/src/a11y/high-contrast-aaa.css +16 -26
  293. package/src/a11y/security.css +18 -0
  294. package/src/a11y/skip-link.css +3 -1
  295. package/src/a11y/sr-only.css +1 -1
  296. package/src/base/reset.css +0 -25
  297. package/src/base/wc-placeholder.css +102 -0
  298. package/src/components/attributes.css +42 -0
  299. package/src/components/highlight.css +182 -0
  300. package/src/components/input-group.css +1 -2
  301. package/src/components/nav.css +151 -151
  302. package/src/components/search.css +95 -0
  303. package/src/components/stepper.css +2 -4
  304. package/src/components/timeline.css +1 -2
  305. package/src/components/tooltip.css +2 -4
  306. package/src/layout/container.css +5 -5
  307. package/src/layout/grid.css +8 -8
  308. package/src/layout/patterns.css +5 -5
  309. package/src/themes/brutalist.css +2 -11
  310. package/src/themes/corporate.css +0 -9
  311. package/src/themes/earth.css +0 -9
  312. package/src/themes/forest.css +0 -9
  313. package/src/themes/midnight.css +1 -10
  314. package/src/themes/neon.css +0 -9
  315. package/src/themes/nordic.css +0 -9
  316. package/src/themes/ocean.css +0 -9
  317. package/src/themes/pastel.css +1 -10
  318. package/src/themes/retro.css +2 -11
  319. package/src/themes/sharp.css +0 -7
  320. package/src/themes/soft.css +0 -7
  321. package/src/themes/sunset.css +1 -10
  322. package/src/tokens/color.css +45 -46
  323. package/src/tokens/fonts.css +10 -0
  324. package/src/tokens/motion.css +7 -0
  325. package/src/tokens/typography.css +4 -5
  326. package/src/utilities/animation.css +99 -3
  327. package/src/utilities/chart-animation.css +101 -0
  328. package/src/utilities/display.css +3 -3
  329. package/src/utilities/divide.css +2 -6
  330. package/src/utilities/filter-effects.css +103 -0
  331. package/src/utilities/responsive.css +4 -4
  332. package/src/utilities/safe-area.css +39 -0
  333. package/src/utilities/scroll-animation.css +34 -0
  334. package/src/utilities/spacing.css +17 -8
  335. package/src/utilities/text.css +4 -1
  336. package/src/velinstyle.css +12 -0
@@ -0,0 +1,79 @@
1
+ import { readFileSync, readdirSync, existsSync } from 'fs';
2
+ import { join, basename } from 'path';
3
+ import { banner, heading, table, sortByKey } from './markdown.js';
4
+
5
+ const VAR_RE = /(--velin-[\w-]+)\s*:\s*([^;]+);/g;
6
+
7
+ export function parseTokenCss(content) {
8
+ const tokens = [];
9
+ let m;
10
+ const re = new RegExp(VAR_RE.source, 'g');
11
+ while ((m = re.exec(content)) !== null) {
12
+ tokens.push({ name: m[1], value: m[2].trim() });
13
+ }
14
+ return tokens;
15
+ }
16
+
17
+ export function extractTokens(srcDir) {
18
+ const tokensDir = join(srcDir, 'tokens');
19
+ if (!existsSync(tokensDir)) return { categories: [], byCategory: {} };
20
+
21
+ const files = readdirSync(tokensDir).filter((f) => f.endsWith('.css')).sort();
22
+ const byCategory = {};
23
+
24
+ for (const file of files) {
25
+ const content = readFileSync(join(tokensDir, file), 'utf-8');
26
+ const category = basename(file, '.css');
27
+ const tokens = sortByKey(parseTokenCss(content), 'name');
28
+ byCategory[category] = { file: `src/tokens/${file}`, tokens };
29
+ }
30
+
31
+ return { categories: Object.keys(byCategory).sort(), byCategory };
32
+ }
33
+
34
+ export function renderTokenCategory(category, data) {
35
+ let md = banner(`src/tokens/${category}.css`);
36
+ md += heading(1, `Tokens: ${category}`);
37
+ md += `\nSource: \`${data.file}\`\n\n`;
38
+ if (!data.tokens.length) {
39
+ md += '_No \`--velin-*\` variables found._\n';
40
+ return md;
41
+ }
42
+ md += table(
43
+ ['Token', 'Value'],
44
+ data.tokens.map((t) => [`\`${t.name}\``, `\`${t.value}\``]),
45
+ );
46
+ if (category === 'color') {
47
+ md += '\n## Contrast (WCAG 2.2 AAA)\n\n';
48
+ md += 'VelinStyle defaults target **7:1** for body text on `--velin-color-surface-bright` and semantic text tokens. ';
49
+ md += 'CI runs `npm run test:contrast` across `:root`, dark mode, and all 13 theme presets.\n\n';
50
+ md += 'For **AA (4.5:1)** body text (migration from pre-0.9 palettes), set `data-velin-contrast="aa"` on `<html>` ';
51
+ md += '(see `src/a11y/high-contrast-aaa.css`). AAA remains the default when the attribute is omitted.\n\n';
52
+ md += 'See [WCAG 2.2 AAA matrix](../a11y/wcag22-aaa-matrix.md) and [Accessibility guide](../../../docs/a11y.html).\n';
53
+ }
54
+ return md;
55
+ }
56
+
57
+ export function renderTokensIndex(extracted) {
58
+ let md = banner('src/tokens/*.css');
59
+ md += heading(1, 'Design tokens');
60
+ md += '\nCSS custom properties from `src/tokens/`. Use with `var(--velin-*, fallback)`.\n\n';
61
+ md += 'See also: [`examples/tokens.full.json`](../../examples/tokens.full.json) for JSON `tokens build` input.\n\n';
62
+ md += table(
63
+ ['Category', 'Variables', 'Reference'],
64
+ extracted.categories.map((cat) => {
65
+ const n = extracted.byCategory[cat].tokens.length;
66
+ return [cat, String(n), `[${cat}.md](./${cat}.md)`];
67
+ }),
68
+ );
69
+ return md;
70
+ }
71
+
72
+ export function renderJsonSchema(schemaPath, schemaContent) {
73
+ let md = banner(schemaPath);
74
+ md += heading(1, 'Tokens JSON schema');
75
+ md += `\nSchema file: \`${schemaPath}\`\n\n`;
76
+ md += 'Supported top-level blocks: `tokens`, `themes`, `fonts`, `motion`, `zIndex`, `displayP3`.\n\n';
77
+ md += '```json\n' + JSON.stringify(JSON.parse(schemaContent), null, 2) + '\n```\n';
78
+ return md;
79
+ }
@@ -0,0 +1,75 @@
1
+ import { readFileSync, readdirSync, existsSync } from 'fs';
2
+ import { join, basename } from 'path';
3
+ import { banner, heading, table, sortByKey } from './markdown.js';
4
+
5
+ const CLASS_RULE_RE = /\.(velin-[\w\\\/:-]+)\s*\{([^}]*)\}/g;
6
+ const NESTED_CLASS_RE = /[\s,>+~](\.velin-[\w\\\/:-]+)\s*\{([^}]*)\}/g;
7
+
8
+ function truncateCss(body, max = 120) {
9
+ const one = body.replace(/\s+/g, ' ').trim();
10
+ if (one.length <= max) return one;
11
+ return `${one.slice(0, max - 1)}…`;
12
+ }
13
+
14
+ export function parseUtilityCss(content) {
15
+ const classes = [];
16
+ let m;
17
+ const re = new RegExp(CLASS_RULE_RE.source, 'g');
18
+ while ((m = re.exec(content)) !== null) {
19
+ classes.push({ selector: m[1], output: truncateCss(m[2]) });
20
+ }
21
+ const nested = new RegExp(NESTED_CLASS_RE.source, 'g');
22
+ while ((m = nested.exec(content)) !== null) {
23
+ const sel = m[1].replace(/^\./, '');
24
+ if (!classes.some((c) => c.selector === sel)) {
25
+ classes.push({ selector: sel, output: truncateCss(m[2]) });
26
+ }
27
+ }
28
+ return classes;
29
+ }
30
+
31
+ export function extractUtilities(srcDir) {
32
+ const utilDir = join(srcDir, 'utilities');
33
+ if (!existsSync(utilDir)) return { files: [], byFile: {} };
34
+
35
+ const files = readdirSync(utilDir).filter((f) => f.endsWith('.css')).sort();
36
+ const byFile = {};
37
+
38
+ for (const file of files) {
39
+ const content = readFileSync(join(utilDir, file), 'utf-8');
40
+ const category = basename(file, '.css');
41
+ const classes = sortByKey(parseUtilityCss(content), 'selector');
42
+ byFile[category] = { file: `src/utilities/${file}`, classes };
43
+ }
44
+
45
+ return { files: Object.keys(byFile).sort(), byFile };
46
+ }
47
+
48
+ export function renderUtilityFile(category, data) {
49
+ let md = banner(data.file);
50
+ md += heading(1, `Utilities: ${category}`);
51
+ md += `\nSource: \`${data.file}\`\n\n`;
52
+ if (!data.classes.length) {
53
+ md += '_No `.velin-*` utility classes found._\n';
54
+ return md;
55
+ }
56
+ md += table(
57
+ ['Class', 'CSS output'],
58
+ data.classes.map((c) => [`\`.${c.selector}\``, `\`${c.output}\``]),
59
+ );
60
+ return md;
61
+ }
62
+
63
+ export function renderUtilitiesIndex(extracted) {
64
+ let md = banner('src/utilities/*.css');
65
+ md += heading(1, 'Utility classes');
66
+ md += '\nClasses in `@layer utilities` from `src/utilities/`.\n\n';
67
+ md += table(
68
+ ['Category', 'Classes', 'Reference'],
69
+ extracted.files.map((cat) => {
70
+ const n = extracted.byFile[cat].classes.length;
71
+ return [cat, String(n), `[${cat}.md](./${cat}.md)`];
72
+ }),
73
+ );
74
+ return md;
75
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Minimal Markdown helpers for doc generation (stable sort, escaping).
3
+ */
4
+
5
+ export function escapeCell(s) {
6
+ return String(s ?? '')
7
+ .replace(/\|/g, '\\|')
8
+ .replace(/\r?\n/g, ' ');
9
+ }
10
+
11
+ export function heading(level, text) {
12
+ const n = Math.min(6, Math.max(1, level));
13
+ return `${'#'.repeat(n)} ${text}\n`;
14
+ }
15
+
16
+ export function table(headers, rows) {
17
+ const h = headers.map(escapeCell);
18
+ const lines = [
19
+ `| ${h.join(' | ')} |`,
20
+ `| ${h.map(() => '---').join(' | ')} |`,
21
+ ];
22
+ for (const row of rows) {
23
+ lines.push(`| ${row.map(escapeCell).join(' | ')} |`);
24
+ }
25
+ return `${lines.join('\n')}\n`;
26
+ }
27
+
28
+ export function bulletList(items) {
29
+ if (!items.length) return '_None._\n';
30
+ return `${items.map((i) => `- ${i}`).join('\n')}\n`;
31
+ }
32
+
33
+ export function codeBlock(lang, code) {
34
+ return `\`\`\`${lang}\n${code}\n\`\`\`\n`;
35
+ }
36
+
37
+ export function banner(source) {
38
+ return `<!-- Auto-generated by \`velinstyle docs generate\`. Do not edit. Source: ${source} -->\n\n`;
39
+ }
40
+
41
+ export function sortByKey(arr, key) {
42
+ return [...arr].sort((a, b) => String(a[key]).localeCompare(String(b[key])));
43
+ }
@@ -0,0 +1,196 @@
1
+ import { mkdirSync, writeFileSync, readFileSync, existsSync, rmSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { extractComponents, renderComponent, renderComponentsIndex } from './docgen/extract-components.js';
5
+ import { extractTokens, renderTokenCategory, renderTokensIndex, renderJsonSchema } from './docgen/extract-tokens.js';
6
+ import { extractUtilities, renderUtilityFile, renderUtilitiesIndex } from './docgen/extract-utilities.js';
7
+ import { loadCliManifest, validateManifest, renderCliDocs } from './docgen/extract-cli.js';
8
+ import { extractA11yModules, renderScannerRules, renderA11yModules } from './docgen/extract-rules.js';
9
+ import { loadComponentContracts, renderWcagAaaMatrix } from './docgen/extract-a11y.js';
10
+ import { banner, heading } from './docgen/markdown.js';
11
+ import { buildSearchIndex } from './search-index.js';
12
+ import { writeAttributesDocs } from './docgen/extract-attributes.js';
13
+
14
+ const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ const PKG_ROOT = join(__dirname, '..');
16
+
17
+ const SCOPES = ['all', 'components', 'tokens', 'utilities', 'cli', 'rules', 'a11y', 'attributes', 'meta'];
18
+
19
+ function writeFile(path, content) {
20
+ mkdirSync(dirname(path), { recursive: true });
21
+ writeFileSync(path, content, 'utf-8');
22
+ }
23
+
24
+ function clearScopeDir(outDir, sub) {
25
+ const dir = join(outDir, sub);
26
+ if (existsSync(dir)) rmSync(dir, { recursive: true });
27
+ mkdirSync(dir, { recursive: true });
28
+ }
29
+
30
+ export async function generateDocs(options = {}) {
31
+ const scope = options.scope || 'all';
32
+ const outDir = options.outDir || join(PKG_ROOT, 'docs', 'generated');
33
+ const srcDir = join(PKG_ROOT, 'src');
34
+ const componentsDir = join(PKG_ROOT, 'components');
35
+ const written = [];
36
+
37
+ if (!SCOPES.includes(scope)) {
38
+ return { ok: false, error: `Unknown scope "${scope}". Use: ${SCOPES.join(', ')}` };
39
+ }
40
+
41
+ const run = (name) => scope === 'all' || scope === name;
42
+
43
+ if (run('components')) {
44
+ clearScopeDir(outDir, 'components');
45
+ const contracts = loadComponentContracts(PKG_ROOT);
46
+ const components = extractComponents(componentsDir);
47
+ for (const c of components) {
48
+ const p = join(outDir, 'components', `${c.tag}.md`);
49
+ writeFile(p, renderComponent(c, contracts));
50
+ written.push(p);
51
+ }
52
+ const indexPath = join(outDir, 'components', 'README.md');
53
+ writeFile(indexPath, renderComponentsIndex(components));
54
+ written.push(indexPath);
55
+ }
56
+
57
+ if (run('tokens')) {
58
+ clearScopeDir(outDir, 'tokens');
59
+ const extracted = extractTokens(srcDir);
60
+ for (const cat of extracted.categories) {
61
+ const p = join(outDir, 'tokens', `${cat}.md`);
62
+ writeFile(p, renderTokenCategory(cat, extracted.byCategory[cat]));
63
+ written.push(p);
64
+ }
65
+ const indexPath = join(outDir, 'tokens', 'README.md');
66
+ writeFile(indexPath, renderTokensIndex(extracted));
67
+ written.push(indexPath);
68
+
69
+ const schemaPath = join(PKG_ROOT, 'examples', 'tokens.schema.json');
70
+ if (existsSync(schemaPath)) {
71
+ const schemaMd = join(outDir, 'tokens', 'json-schema.md');
72
+ writeFile(
73
+ schemaMd,
74
+ renderJsonSchema('examples/tokens.schema.json', readFileSync(schemaPath, 'utf-8')),
75
+ );
76
+ written.push(schemaMd);
77
+ }
78
+ }
79
+
80
+ if (run('utilities')) {
81
+ clearScopeDir(outDir, 'utilities');
82
+ const extracted = extractUtilities(srcDir);
83
+ for (const cat of extracted.files) {
84
+ const p = join(outDir, 'utilities', `${cat}.md`);
85
+ writeFile(p, renderUtilityFile(cat, extracted.byFile[cat]));
86
+ written.push(p);
87
+ }
88
+ const indexPath = join(outDir, 'utilities', 'README.md');
89
+ writeFile(indexPath, renderUtilitiesIndex(extracted));
90
+ written.push(indexPath);
91
+ }
92
+
93
+ if (run('cli')) {
94
+ mkdirSync(join(outDir, 'cli'), { recursive: true });
95
+ const manifest = loadCliManifest();
96
+ const errors = validateManifest(manifest);
97
+ if (errors.length) {
98
+ return { ok: false, error: errors.join('; ') };
99
+ }
100
+ const p = join(outDir, 'cli', 'commands.md');
101
+ writeFile(p, renderCliDocs(manifest));
102
+ written.push(p);
103
+ }
104
+
105
+ if (run('rules')) {
106
+ mkdirSync(join(outDir, 'rules'), { recursive: true });
107
+ const p = join(outDir, 'rules', 'scanner.md');
108
+ writeFile(p, renderScannerRules());
109
+ written.push(p);
110
+ }
111
+
112
+ if (run('a11y')) {
113
+ mkdirSync(join(outDir, 'a11y'), { recursive: true });
114
+ const modules = extractA11yModules(srcDir);
115
+ const p = join(outDir, 'a11y', 'modules.md');
116
+ writeFile(p, renderA11yModules(modules));
117
+ written.push(p);
118
+ const contracts = loadComponentContracts(PKG_ROOT);
119
+ const matrixPath = join(outDir, 'a11y', 'wcag22-aaa-matrix.md');
120
+ writeFile(matrixPath, renderWcagAaaMatrix(contracts));
121
+ written.push(matrixPath);
122
+ }
123
+
124
+ if (run('attributes')) {
125
+ mkdirSync(join(outDir, 'attributes'), { recursive: true });
126
+ for (const { path: p, content } of writeAttributesDocs(outDir)) {
127
+ writeFile(p, content);
128
+ written.push(p);
129
+ }
130
+ }
131
+
132
+ if (run('meta')) {
133
+ mkdirSync(join(outDir, 'meta'), { recursive: true });
134
+ const { buildAgentBundle } = await import('../core/meta/index.js');
135
+ const { renderMetaReadme } = await import('./docgen/extract-meta.js');
136
+ const bundle = await buildAgentBundle({ pkgRoot: PKG_ROOT });
137
+ const readmePath = join(outDir, 'meta', 'README.md');
138
+ writeFile(readmePath, renderMetaReadme(bundle));
139
+ written.push(readmePath);
140
+ try {
141
+ const { buildMeta } = await import('./meta.js');
142
+ const metaOut = await buildMeta({
143
+ outFile: join(PKG_ROOT, 'dist', 'velin-agent.json'),
144
+ llmsFile: join(PKG_ROOT, 'dist', 'llms.txt'),
145
+ });
146
+ written.push(...metaOut.written);
147
+ } catch (err) {
148
+ console.warn('velin-agent.json:', err.message);
149
+ }
150
+ }
151
+
152
+ if (scope === 'all') {
153
+ let root = banner('velinstyle docs generate');
154
+ root += heading(1, 'VelinStyle generated reference');
155
+ root += '\n> **Do not edit manually.** Regenerate with `npm run docs:generate` or `velinstyle docs generate`.\n\n';
156
+ root += '| Section | Description |\n| --- | --- |\n';
157
+ root += '| [components](./components/) | Web Components API |\n';
158
+ root += '| [tokens](./tokens/) | Design tokens (`--velin-*`) |\n';
159
+ root += '| [utilities](./utilities/) | Utility classes |\n';
160
+ root += '| [cli](./cli/) | CLI commands |\n';
161
+ root += '| [rules](./rules/) | Scanner & perf rules |\n';
162
+ root += '| [a11y](./a11y/) | Accessibility CSS modules |\n';
163
+ root += '| [attributes](./attributes/) | Velin HTML attribute extensions |\n';
164
+ root += '| [meta](./meta/) | Velin-Meta agent context (AI assistants) |\n';
165
+ writeFile(join(outDir, 'README.md'), root);
166
+ written.push(join(outDir, 'README.md'));
167
+ }
168
+
169
+ if (options.searchIndex !== false && (scope === 'all' || scope === 'components' || scope === 'meta')) {
170
+ try {
171
+ const idx = buildSearchIndex({
172
+ generatedDir: outDir,
173
+ outFile: join(PKG_ROOT, 'dist', 'search-index.json'),
174
+ });
175
+ written.push(idx.outFile);
176
+ } catch (err) {
177
+ console.warn('search index:', err.message);
178
+ }
179
+ }
180
+
181
+ return { ok: true, written: written.length, paths: written };
182
+ }
183
+
184
+ export async function docsGenerateMain(argv = process.argv.slice(2)) {
185
+ const scopeIdx = argv.indexOf('--scope');
186
+ const outIdx = argv.indexOf('--out');
187
+ const scope = scopeIdx !== -1 && argv[scopeIdx + 1] ? argv[scopeIdx + 1] : 'all';
188
+ const outDir = outIdx !== -1 && argv[outIdx + 1] ? argv[outIdx + 1] : join(PKG_ROOT, 'docs', 'generated');
189
+
190
+ const result = await generateDocs({ scope, outDir });
191
+ if (!result.ok) {
192
+ console.error(result.error);
193
+ process.exit(1);
194
+ }
195
+ console.log(`Generated ${result.written} file(s) in ${outDir}`);
196
+ }